From be3ef7b0e5e51c1d97309ce3b6d5cac1fbd025d0 Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Wed, 2 May 2018 17:22:30 +0200 Subject: tdf#109143 PDF export: don't reuse compressed bitmaps for cropped images PDF wants to loose the pixels masked out by cropping, so the "reuse original compressed image" optimization should not be used in that case. Change-Id: Ifdf2cc4ff6bff0ed456a2159395314817c1cf417 Reviewed-on: https://gerrit.libreoffice.org/53743 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- include/vcl/pdfextoutdevdata.hxx | 4 ++- vcl/qa/cppunit/pdfexport/data/tdf109143.odt | Bin 0 -> 68155 bytes vcl/qa/cppunit/pdfexport/pdfexport.cxx | 42 ++++++++++++++++++++++++++++ vcl/source/gdi/pdfextoutdevdata.cxx | 12 ++++++-- 4 files changed, 54 insertions(+), 4 deletions(-) create mode 100644 vcl/qa/cppunit/pdfexport/data/tdf109143.odt diff --git a/include/vcl/pdfextoutdevdata.hxx b/include/vcl/pdfextoutdevdata.hxx index e9a2ad04fb04..c260f8461fa7 100644 --- a/include/vcl/pdfextoutdevdata.hxx +++ b/include/vcl/pdfextoutdevdata.hxx @@ -183,7 +183,9 @@ public: const tools::Rectangle& rVisibleOutputRect ); /// Detect if stream is compressed enough to avoid de-compress / scale & re-compress - bool HasAdequateCompression( const Graphic &rGraphic ) const; + bool HasAdequateCompression( const Graphic &rGraphic, + const tools::Rectangle &rOutputRect, + const tools::Rectangle &rVisibleOutputRect ) const; //--->i56629 /** Create a new named destination to be used in a link to this document from another PDF document diff --git a/vcl/qa/cppunit/pdfexport/data/tdf109143.odt b/vcl/qa/cppunit/pdfexport/data/tdf109143.odt new file mode 100644 index 000000000000..7d9afa3789e5 Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/tdf109143.odt differ diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx b/vcl/qa/cppunit/pdfexport/pdfexport.cxx index 1f527239dea7..62e1713a14cf 100644 --- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx +++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx @@ -85,6 +85,7 @@ public: void testTdf66597_3(); #endif #endif + void testTdf109143(); CPPUNIT_TEST_SUITE(PdfExportTest); #if HAVE_FEATURE_PDFIUM @@ -112,6 +113,7 @@ public: CPPUNIT_TEST(testTdf66597_3); #endif #endif + CPPUNIT_TEST(testTdf109143); CPPUNIT_TEST_SUITE_END(); }; @@ -436,6 +438,46 @@ void PdfExportTest::testTdf106206() CPPUNIT_ASSERT(bool(it == pEnd)); } +void PdfExportTest::testTdf109143() +{ + // Import the bugdoc and export as PDF. + OUString aURL = m_directories.getURLFromSrc(DATA_DIRECTORY) + "tdf109143.odt"; + mxComponent = loadFromDesktop(aURL); + CPPUNIT_ASSERT(mxComponent.is()); + + uno::Reference xStorable(mxComponent, uno::UNO_QUERY); + utl::TempFile aTempFile; + aTempFile.EnableKillingFile(); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= OUString("writer_pdf_Export"); + xStorable->storeToURL(aTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + + // Parse the export result. + vcl::filter::PDFDocument aDocument; + SvFileStream aStream(aTempFile.GetURL(), StreamMode::READ); + CPPUNIT_ASSERT(aDocument.Read(aStream)); + + // The document has one page. + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT_EQUAL(static_cast(1), aPages.size()); + + // Get access to the only image on the only page. + vcl::filter::PDFObjectElement* pResources = aPages[0]->LookupObject("Resources"); + CPPUNIT_ASSERT(pResources); + auto pXObjects = dynamic_cast(pResources->Lookup("XObject")); + CPPUNIT_ASSERT(pXObjects); + CPPUNIT_ASSERT_EQUAL(static_cast(1), pXObjects->GetItems().size()); + vcl::filter::PDFObjectElement* pXObject = pXObjects->LookupObject(pXObjects->GetItems().begin()->first); + CPPUNIT_ASSERT(pXObject); + + // Make sure it's re-compressed. + auto pLength = dynamic_cast(pXObject->Lookup("Length")); + int nLength = pLength->GetValue(); + // This failed: cropped TIFF-in-JPEG wasn't re-compressed, so crop was + // lost. Size was 59416, now is 11827. + CPPUNIT_ASSERT(nLength < 50000); +} + void PdfExportTest::testTdf106972() { // Import the bugdoc and export as PDF. diff --git a/vcl/source/gdi/pdfextoutdevdata.cxx b/vcl/source/gdi/pdfextoutdevdata.cxx index 013cca964441..2a7e7b1f0774 100644 --- a/vcl/source/gdi/pdfextoutdevdata.cxx +++ b/vcl/source/gdi/pdfextoutdevdata.cxx @@ -403,13 +403,13 @@ bool PageSyncData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAc GfxLinkType eType = rGraphic.GetGfxLink().GetType(); if ( eType == GfxLinkType::NativeJpg ) { - mbGroupIgnoreGDIMtfActions = rOutDevData.HasAdequateCompression(rGraphic); + mbGroupIgnoreGDIMtfActions = rOutDevData.HasAdequateCompression(rGraphic, mParaRects[0], mParaRects[1]); if ( !mbGroupIgnoreGDIMtfActions ) mCurrentGraphic = rGraphic; } else if ( eType == GfxLinkType::NativePng || eType == GfxLinkType::NativePdf ) { - if ( eType == GfxLinkType::NativePdf || rOutDevData.HasAdequateCompression(rGraphic) ) + if ( eType == GfxLinkType::NativePdf || rOutDevData.HasAdequateCompression(rGraphic, mParaRects[0], mParaRects[1]) ) mCurrentGraphic = rGraphic; } } @@ -799,13 +799,19 @@ void PDFExtOutDevData::EndGroup( const Graphic& rGraphic, } // Avoids expensive de-compression and re-compression of large images. -bool PDFExtOutDevData::HasAdequateCompression( const Graphic &rGraphic ) const +bool PDFExtOutDevData::HasAdequateCompression( const Graphic &rGraphic, + const tools::Rectangle & rOutputRect, + const tools::Rectangle & rVisibleOutputRect ) const { assert(rGraphic.IsGfxLink() && (rGraphic.GetGfxLink().GetType() == GfxLinkType::NativeJpg || rGraphic.GetGfxLink().GetType() == GfxLinkType::NativePng || rGraphic.GetGfxLink().GetType() == GfxLinkType::NativePdf)); + if (rOutputRect != rVisibleOutputRect) + // rOutputRect is the crop rectangle, re-compress cropped image. + return false; + if (rGraphic.GetGfxLink().GetDataSize() == 0) return false; -- cgit v1.2.3