summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2016-02-08 14:24:15 +0000
committerMichael Meeks <michael.meeks@collabora.com>2016-02-09 00:09:08 +0000
commit76ec54e8c9f3580450bca85236a4f5af0c328588 (patch)
tree1c4d36e921be16426fc8a61c7a85bdc006e0fafa
parente07ffae5046e9c91ef96026435cab84c3bcb4534 (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.cxx2
-rw-r--r--include/vcl/pdfextoutdevdata.hxx22
-rw-r--r--vcl/source/gdi/pdfextoutdevdata.cxx69
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: */