From e9e1b0f4505d4e90727900caf6ed5053fc6c30f3 Mon Sep 17 00:00:00 2001 From: Thorsten Behrens Date: Mon, 20 Apr 2020 21:40:10 +0200 Subject: pdf export: be a bit less wasteful when jpeg-optimising bitmaps Before, code was test-compressing every single bitmap coming along. Let's buffer those SvMemStreams, and keep the last 15 around in case the same image comes along again. Change-Id: Ic8da32725ea46b01bd6beacc389abf8f52845d36 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/93058 Tested-by: Jenkins Reviewed-by: Thorsten Behrens --- vcl/source/gdi/pdfwriter_impl2.cxx | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'vcl') diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx b/vcl/source/gdi/pdfwriter_impl2.cxx index f08067f356f5..f84ab684c24c 100644 --- a/vcl/source/gdi/pdfwriter_impl2.cxx +++ b/vcl/source/gdi/pdfwriter_impl2.cxx @@ -43,6 +43,7 @@ #include #include +#include #include #include @@ -54,6 +55,9 @@ using namespace com::sun::star::beans; static bool lcl_canUsePDFAxialShading(const Gradient& rGradient); +/// Cache some last 15 bitmaps we've exported, in case we encounter them again.. +static o3tl::lru_map> lcl_PDFBmpCache(15); + void PDFWriterImpl::implWriteGradient( const tools::PolyPolygon& i_rPolyPoly, const Gradient& i_rGradient, VirtualDevice* i_pDummyVDev, const vcl::PDFWriter::PlayMetafileContext& i_rContext ) { @@ -168,13 +172,25 @@ void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSiz if ( bIsPng || ( aSizePixel.Width() < 32 ) || ( aSizePixel.Height() < 32 ) ) bUseJPGCompression = false; - SvMemoryStream aStrm; - Bitmap aMask; + auto pStrm=std::make_shared(); + Bitmap aMask; bool bTrueColorJPG = true; if ( bUseJPGCompression ) { - + // TODO this checks could be done much earlier, saving us + // from trying conversion & stores before... + if ( !aBitmapEx.IsTransparent() ) + { + const auto& rCacheEntry=lcl_PDFBmpCache.find( + aBitmapEx.GetChecksum()); + if ( rCacheEntry != lcl_PDFBmpCache.end() ) + { + m_rOuterFace.DrawJPGBitmap( *rCacheEntry->second, true, aSizePixel, + tools::Rectangle( aPoint, aSize ), aMask, i_Graphic ); + return; + } + } sal_uInt32 nZippedFileSize = 0; // sj: we will calculate the filesize of a zipped bitmap if ( !bIsJpeg ) // to determine if jpeg compression is useful { @@ -201,7 +217,7 @@ void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSiz try { - uno::Reference < io::XStream > xStream = new utl::OStreamWrapper( aStrm ); + uno::Reference < io::XStream > xStream = new utl::OStreamWrapper( *pStrm ); uno::Reference< io::XSeekable > xSeekable( xStream, UNO_QUERY_THROW ); uno::Reference< uno::XComponentContext > xContext( comphelper::getProcessComponentContext() ); uno::Reference< graphic::XGraphicProvider > xGraphicProvider( graphic::GraphicProvider::create(xContext) ); @@ -222,7 +238,7 @@ void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSiz } else { - aStrm.Seek( STREAM_SEEK_TO_END ); + pStrm->Seek( STREAM_SEEK_TO_END ); xSeekable->seek( 0 ); Sequence< PropertyValue > aArgs( 1 ); @@ -245,7 +261,15 @@ void PDFWriterImpl::implWriteBitmapEx( const Point& i_rPoint, const Size& i_rSiz } } if ( bUseJPGCompression ) - m_rOuterFace.DrawJPGBitmap( aStrm, bTrueColorJPG, aSizePixel, tools::Rectangle( aPoint, aSize ), aMask, i_Graphic ); + { + m_rOuterFace.DrawJPGBitmap( *pStrm, bTrueColorJPG, aSizePixel, tools::Rectangle( aPoint, aSize ), aMask, i_Graphic ); + if (!aBitmapEx.IsTransparent() && bTrueColorJPG) + { + // Cache last jpeg export + lcl_PDFBmpCache.insert( + {aBitmapEx.GetChecksum(), pStrm}); + } + } else if ( aBitmapEx.IsTransparent() ) m_rOuterFace.DrawBitmapEx( aPoint, aSize, aBitmapEx ); else -- cgit