diff options
author | Michael Meeks <michael.meeks@collabora.com> | 2016-02-08 14:24:15 +0000 |
---|---|---|
committer | Michael Meeks <michael.meeks@collabora.com> | 2016-02-09 00:09:08 +0000 |
commit | 76ec54e8c9f3580450bca85236a4f5af0c328588 (patch) | |
tree | 1c4d36e921be16426fc8a61c7a85bdc006e0fafa | |
parent | e07ffae5046e9c91ef96026435cab84c3bcb4534 (diff) |
tdf#97662 - Try to preserve original compressed JPEGs harder.
Avoiding de-compressing and re-compressing them saves lots of time too.
Change-Id: Ie8eb68554627581b2f0584a55bbbdb43c9482bed
Reviewed-on: https://gerrit.libreoffice.org/22219
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
Tested-by: Michael Meeks <michael.meeks@collabora.com>
-rw-r--r-- | filter/source/pdf/pdfexport.cxx | 2 | ||||
-rw-r--r-- | include/vcl/pdfextoutdevdata.hxx | 22 | ||||
-rw-r--r-- | vcl/source/gdi/pdfextoutdevdata.cxx | 69 |
3 files changed, 81 insertions, 12 deletions
diff --git a/filter/source/pdf/pdfexport.cxx b/filter/source/pdf/pdfexport.cxx index 1a749eb67637..d0f5796694cb 100644 --- a/filter/source/pdf/pdfexport.cxx +++ b/filter/source/pdf/pdfexport.cxx @@ -818,6 +818,8 @@ bool PDFExport::Export( const OUString& rFile, const Sequence< PropertyValue >& pPDFExtOutDevData->SetIsExportBookmarks( mbExportBookmarks ); pPDFExtOutDevData->SetIsExportHiddenSlides( mbExportHiddenSlides ); pPDFExtOutDevData->SetIsLosslessCompression( mbUseLosslessCompression ); + pPDFExtOutDevData->SetCompressionQuality( mnQuality ); + pPDFExtOutDevData->SetMaxImageResolution( mnMaxImageResolution ); pPDFExtOutDevData->SetIsReduceImageResolution( mbReduceImageResolution ); pPDFExtOutDevData->SetIsExportNamedDestinations( mbExportBmkToDest ); diff --git a/include/vcl/pdfextoutdevdata.hxx b/include/vcl/pdfextoutdevdata.hxx index 265a5b328a76..d681ab072730 100644 --- a/include/vcl/pdfextoutdevdata.hxx +++ b/include/vcl/pdfextoutdevdata.hxx @@ -86,6 +86,8 @@ class VCL_DLLPUBLIC PDFExtOutDevData : public ExtOutDevData bool mbExportNDests; //i56629 sal_Int32 mnFormsFormat; sal_Int32 mnPage; + sal_Int32 mnCompressionQuality; + sal_Int32 mnMaxImageResolution; css::lang::Locale maDocLocale; PageSyncData* mpPageSyncData; @@ -103,8 +105,6 @@ public: void PlayGlobalActions( PDFWriter& rWriter ); - - bool GetIsExportNotes() const { return mbExportNotes;} void SetIsExportNotes( const bool bExportNotes ); @@ -135,10 +135,16 @@ public: sal_Int32 GetCurrentPageNumber() const { return mnPage;} void SetCurrentPageNumber( const sal_Int32 nPage ); - bool GetIsLosslessCompression() const { return mbUseLosslessCompression;} + bool GetIsLosslessCompression() const { return mbUseLosslessCompression;} void SetIsLosslessCompression( const bool bLosslessCompression ); - bool GetIsReduceImageResolution() const { return mbReduceImageResolution;} + sal_Int32 GetCompressionQuality() const { return mnCompressionQuality; } + void SetCompressionQuality( const sal_Int32 nQuality ); + + sal_Int32 GetMaxImageResolution() const { return mnMaxImageResolution; } + void SetMaxImageResolution( const sal_Int32 nQuality ); + + bool GetIsReduceImageResolution() const { return mbReduceImageResolution;} void SetIsReduceImageResolution( const bool bReduceImageResolution ); const css::lang::Locale& GetDocumentLocale() const { return maDocLocale;} @@ -176,9 +182,15 @@ public: rOutputRect, e.g. for cropped graphics. */ void EndGroup( const Graphic& rGraphic, - sal_uInt8 nTransparency, + sal_uInt8 nTransparency, const Rectangle& rOutputRect, const Rectangle& rVisibleOutputRect ); + + /// Detect if stream is compressed enough to avoid de-compress / scale & re-compress + bool HasAdequateCompression( const Graphic &rGraphic, + const Rectangle &rOutputRect, + const Rectangle &rVisibleOutputRect ) const; + //--->i56629 /** Create a new named destination to be used in a link to this document from another PDF document (see PDF spec 1.4, 8.2.1) diff --git a/vcl/source/gdi/pdfextoutdevdata.cxx b/vcl/source/gdi/pdfextoutdevdata.cxx index 78304facf2f8..2030b3a011f6 100644 --- a/vcl/source/gdi/pdfextoutdevdata.cxx +++ b/vcl/source/gdi/pdfextoutdevdata.cxx @@ -305,6 +305,7 @@ struct PageSyncData void PushAction( const OutputDevice& rOutDev, const PDFExtOutDevDataSync::Action eAct ); bool PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAction, const PDFExtOutDevData& rOutDevData ); }; + void PageSyncData::PushAction( const OutputDevice& rOutDev, const PDFExtOutDevDataSync::Action eAct ) { GDIMetaFile* pMtf = rOutDev.GetConnectMetaFile(); @@ -403,13 +404,14 @@ bool PageSyncData::PlaySyncPageAct( PDFWriter& rWriter, sal_uInt32& rCurGDIMtfAc } else if ( aBeg->eAct == PDFExtOutDevDataSync::EndGroupGfxLink ) { - if ( rOutDevData.GetIsLosslessCompression() && !rOutDevData.GetIsReduceImageResolution() ) + Graphic& rGraphic = mGraphics.front(); + if ( rGraphic.IsLink() && + rGraphic.GetLink().GetType() == GFX_LINK_TYPE_NATIVE_JPG && + mParaRects.size() >= 2 ) { - Graphic& rGraphic = mGraphics.front(); - if ( rGraphic.IsLink() && rGraphic.GetLink().GetType() == GFX_LINK_TYPE_NATIVE_JPG ) - { - mbGroupIgnoreGDIMtfActions = true; - } + mbGroupIgnoreGDIMtfActions = + rOutDevData.HasAdequateCompression( + rGraphic, mParaRects[0], mParaRects[1]); } break; } @@ -504,6 +506,8 @@ PDFExtOutDevData::PDFExtOutDevData( const OutputDevice& rOutDev ) : mbExportNDests ( false ), mnFormsFormat ( 0 ), mnPage ( -1 ), + mnCompressionQuality ( 90 ), + mnMaxImageResolution ( 300 ), mpPageSyncData ( nullptr ), mpGlobalSyncData ( new GlobalSyncData() ) { @@ -528,6 +532,14 @@ void PDFExtOutDevData::SetIsLosslessCompression( const bool bUseLosslessCompress { mbUseLosslessCompression = bUseLosslessCompression; } +void PDFExtOutDevData::SetCompressionQuality( const sal_Int32 nQuality ) +{ + mnCompressionQuality = nQuality; +} +void PDFExtOutDevData::SetMaxImageResolution( const sal_Int32 nMaxImageResolution ) +{ + mnMaxImageResolution = nMaxImageResolution; +} void PDFExtOutDevData::SetIsReduceImageResolution( const bool bReduceImageResolution ) { mbReduceImageResolution = bReduceImageResolution; @@ -748,7 +760,7 @@ void PDFExtOutDevData::BeginGroup() } void PDFExtOutDevData::EndGroup( const Graphic& rGraphic, - sal_uInt8 nTransparency, + sal_uInt8 nTransparency, const Rectangle& rOutputRect, const Rectangle& rVisibleOutputRect ) { @@ -759,6 +771,49 @@ void PDFExtOutDevData::EndGroup( const Graphic& rGraphic, mpPageSyncData->mParaRects.push_back( rVisibleOutputRect ); } +// Avoids expensive de-compression and re-compression of large images. +bool PDFExtOutDevData::HasAdequateCompression( const Graphic &rGraphic, + const Rectangle & /* rOutputRect */, + const Rectangle & /* rVisibleOutputRect */ ) const +{ + bool bReduceResolution = false; + + assert( rGraphic.IsLink() && rGraphic.GetLink().GetType() == GFX_LINK_TYPE_NATIVE_JPG ); + + // small items better off as PNG anyway + if ( rGraphic.GetSizePixel().Width() < 32 && + rGraphic.GetSizePixel().Height() < 32 ) + return false; + + // FIXME: ideally we'd also pre-empt the DPI related scaling too. + + Size aSize = rGraphic.GetSizePixel(); + sal_Int32 nCurrentRatio = (100 * aSize.Width() * aSize.Height() * 4) / + rGraphic.GetLink().GetDataSize(); + + if ( GetIsLosslessCompression() ) + return !bReduceResolution && !GetIsReduceImageResolution(); + else + { + static const struct { + sal_Int32 mnQuality; + sal_Int32 mnRatio; + } aRatios[] = { // minium tolerable compression ratios + { 100, 400 }, { 95, 700 }, { 90, 1000 }, { 85, 1200 }, + { 80, 1500 }, { 75, 1700 } + }; + sal_Int32 nTargetRatio = 10000; + for ( size_t i = 0 ; i < SAL_N_ELEMENTS( aRatios ); ++i ) + { + if ( mnCompressionQuality > aRatios[i].mnQuality ) + break; + nTargetRatio = aRatios[i].mnRatio; + } + + return nCurrentRatio > nTargetRatio; + } +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |