filter/source/pdf/pdfexport.cxx | 2 include/vcl/pdfextoutdevdata.hxx | 22 +++++++--- vcl/Package_opengl.mk | 1 vcl/inc/impbmp.hxx | 1 vcl/inc/opengl/salbmp.hxx | 1 vcl/inc/salbmp.hxx | 4 + vcl/opengl/greyscaleFragmentShader.glsl | 18 ++++++++ vcl/opengl/salbmp.cxx | 36 ++++++++++++++++ vcl/source/gdi/bitmap3.cxx | 17 +++++++ vcl/source/gdi/impbmp.cxx | 10 ++++ vcl/source/gdi/pdfextoutdevdata.cxx | 69 ++++++++++++++++++++++++++++---- vcl/workben/vcldemo.cxx | 13 ++++++ 12 files changed, 182 insertions(+), 12 deletions(-)
New commits: commit bff3f3f3fd40f0ce302b6af166e7cc432c249d5b Author: Michael Meeks <[email protected]> Date: Mon Feb 8 23:09:13 2016 +0000 Convert cleanups - avoid converting already converted bitmaps. Change-Id: I4cb79dc3b798e301c31c8440a1d1210d7bbdfc4b diff --git a/vcl/opengl/greyscaleFragmentShader.glsl b/vcl/opengl/greyscaleFragmentShader.glsl index 5117c488..758109e 100644 --- a/vcl/opengl/greyscaleFragmentShader.glsl +++ b/vcl/opengl/greyscaleFragmentShader.glsl @@ -12,7 +12,7 @@ uniform sampler2D sampler; void main() { vec4 texel = texture2D(sampler, tex_coord); - gl_FragColor = vec4(vec3(dot(texel.rgb, vec3(0.302, 0.592, 0.109))), 1.0); + gl_FragColor = vec4(vec3(dot(texel.rgb, vec3(0.301, 0.591, 0.108))), 1.0); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx index 8814372..7f0d66b 100644 --- a/vcl/opengl/salbmp.cxx +++ b/vcl/opengl/salbmp.cxx @@ -905,7 +905,8 @@ bool OpenGLSalBitmap::ConvertToGreyscale() { VCL_GL_INFO("::ConvertToGreyscale"); - if (false) + // avoid re-converting to 8bits. + if ( mnBits == 8 && maPalette == Bitmap::GetGreyPalette(256) ) return false; OpenGLZone aZone; @@ -922,7 +923,6 @@ bool OpenGLSalBitmap::ConvertToGreyscale() OpenGLTexture aNewTex(mnWidth, mnHeight); pFramebuffer = xContext->AcquireFramebuffer(aNewTex); - pProgram->ApplyMatrix(mnWidth, mnHeight); pProgram->SetTexture("sampler", maTexture); pProgram->DrawTexture(maTexture); pProgram->Clean(); @@ -930,19 +930,7 @@ bool OpenGLSalBitmap::ConvertToGreyscale() OpenGLContext::ReleaseFramebuffer( pFramebuffer ); maTexture = aNewTex; mnBits = 8; - - static BitmapPalette aGreyPalette256; - if (!aGreyPalette256.GetEntryCount()) - { - aGreyPalette256.SetEntryCount(256); - - for (sal_uInt16 i = 0; i < 256; i++) - { - sal_uInt8 nValue = sal_uInt8(i); - aGreyPalette256[i] = BitmapColor(nValue, nValue, nValue); - } - } - maPalette = aGreyPalette256; + maPalette = Bitmap::GetGreyPalette(256); CHECK_GL_ERROR(); return true; diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx index 30a4f92..b4f1000 100644 --- a/vcl/source/gdi/bitmap3.cxx +++ b/vcl/source/gdi/bitmap3.cxx @@ -259,8 +259,6 @@ bool Bitmap::Convert( BmpConversion eConversion ) { ImplSetImpBitmap(pImpBmp); SAL_INFO( "vcl.opengl", "Ref count: " << mpImpBmp->ImplGetRefCount() ); - //maPrefMapMode = MapMode(MAP_PIXEL); - //maPrefSize = pImpBmp->ImplGetSize(); return true; } else diff --git a/vcl/workben/vcldemo.cxx b/vcl/workben/vcldemo.cxx index 3a91d44..00a1181 100644 --- a/vcl/workben/vcldemo.cxx +++ b/vcl/workben/vcldemo.cxx @@ -1070,6 +1070,19 @@ public: aBelow.Move(0,aResult.GetSizePixel().Height()); rDev.DrawBitmapEx(aBelow, aResult); + // mini convert test. + aBelow.Move(aResult.GetSizePixel().Width()+4,0); + rDev.DrawBitmapEx(aBelow, aResult); + + Bitmap aGrey = aSrc.GetBitmap(); + aGrey.Convert(BMP_CONVERSION_8BIT_GREYS); + rDev.DrawBitmap(aBelow, aGrey); + + aBelow.Move(aGrey.GetSizePixel().Width(),0); + BitmapEx aGreyMask(aSrc.GetBitmap(), + AlphaMask(aSrc.GetMask())); + rDev.DrawBitmapEx(aBelow, aGreyMask); + aLocation.Move(aSrc.GetSizePixel().Width()*6,0); if (aLocation.X() > r.Right()) aLocation = Point(0,aLocation.Y()+aSrc.GetSizePixel().Height()*3+4); commit 1a2b22645a5d1d42a07d6d5db67d3e3dfc617f33 Author: Michael Meeks <[email protected]> Date: Mon Feb 8 14:24:15 2016 +0000 tdf#97662 - Try to preserve original compressed JPEGs harder. Avoiding de-compressing and re-compressing them saves lots of time too. Change-Id: Ie8eb68554627581b2f0584a55bbbdb43c9482bed diff --git a/filter/source/pdf/pdfexport.cxx b/filter/source/pdf/pdfexport.cxx index 5a67041..457b55f 100644 --- a/filter/source/pdf/pdfexport.cxx +++ b/filter/source/pdf/pdfexport.cxx @@ -817,6 +817,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 477f668..0e81584 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 8212f85..e84191b 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: */ commit c2eaaf89ae7d31940a2c60fb9ccbdcb7e998ab54 Author: Tomaž Vajngerl <[email protected]> Date: Mon Feb 8 22:25:59 2016 +0100 opengl: convert the bitmap to 8bit grays using GL shader Change-Id: I4d48d29ab752814f71c697a201e70a26ae937775 diff --git a/vcl/Package_opengl.mk b/vcl/Package_opengl.mk index 9d42502..b8851df 100644 --- a/vcl/Package_opengl.mk +++ b/vcl/Package_opengl.mk @@ -17,6 +17,7 @@ $(eval $(call gb_Package_add_files,vcl_opengl_shader,$(LIBO_ETC_FOLDER)/opengl,\ blendedTextureVertexShader.glsl \ dumbVertexShader.glsl \ diffTextureFragmentShader.glsl \ + greyscaleFragmentShader.glsl \ invert50FragmentShader.glsl \ convolutionFragmentShader.glsl \ linearGradientFragmentShader.glsl \ diff --git a/vcl/inc/impbmp.hxx b/vcl/inc/impbmp.hxx index f2bd27d..9527c5d 100644 --- a/vcl/inc/impbmp.hxx +++ b/vcl/inc/impbmp.hxx @@ -74,6 +74,7 @@ public: bool ImplScale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag ); bool ImplReplace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ); + bool ImplConvert( BmpConversion eConversion ); }; #endif // INCLUDED_VCL_INC_IMPBMP_HXX diff --git a/vcl/inc/opengl/salbmp.hxx b/vcl/inc/opengl/salbmp.hxx index 7d1efa3..4b34027 100644 --- a/vcl/inc/opengl/salbmp.hxx +++ b/vcl/inc/opengl/salbmp.hxx @@ -82,6 +82,7 @@ public: bool Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag ) override; bool Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ) override; + bool ConvertToGreyscale() override; public: diff --git a/vcl/inc/salbmp.hxx b/vcl/inc/salbmp.hxx index 49d2657..49b8319 100644 --- a/vcl/inc/salbmp.hxx +++ b/vcl/inc/salbmp.hxx @@ -71,6 +71,10 @@ public: virtual bool Scale( const double& rScaleX, const double& rScaleY, BmpScaleFlag nScaleFlag ) = 0; virtual bool Replace( const Color& rSearchColor, const Color& rReplaceColor, sal_uLong nTol ) = 0; + virtual bool ConvertToGreyscale() + { + return false; + } bool GetChecksum(ChecksumType& rChecksum) const { diff --git a/vcl/opengl/greyscaleFragmentShader.glsl b/vcl/opengl/greyscaleFragmentShader.glsl new file mode 100644 index 0000000..5117c488 --- /dev/null +++ b/vcl/opengl/greyscaleFragmentShader.glsl @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +varying vec2 tex_coord; +uniform sampler2D sampler; + +void main() { + vec4 texel = texture2D(sampler, tex_coord); + gl_FragColor = vec4(vec3(dot(texel.rgb, vec3(0.302, 0.592, 0.109))), 1.0); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/opengl/salbmp.cxx b/vcl/opengl/salbmp.cxx index 03497dc..8814372 100644 --- a/vcl/opengl/salbmp.cxx +++ b/vcl/opengl/salbmp.cxx @@ -900,4 +900,52 @@ bool OpenGLSalBitmap::Replace( const Color& rSearchColor, const Color& rReplaceC return true; } +// Convert texture to greyscale and adjust bitmap metadata +bool OpenGLSalBitmap::ConvertToGreyscale() +{ + VCL_GL_INFO("::ConvertToGreyscale"); + + if (false) + return false; + + OpenGLZone aZone; + rtl::Reference<OpenGLContext> xContext = OpenGLContext::getVCLContext(); + + OpenGLFramebuffer* pFramebuffer; + OpenGLProgram* pProgram; + + GetTexture(); + pProgram = xContext->UseProgram("textureVertexShader", "greyscaleFragmentShader"); + + if (!pProgram) + return false; + + OpenGLTexture aNewTex(mnWidth, mnHeight); + pFramebuffer = xContext->AcquireFramebuffer(aNewTex); + pProgram->ApplyMatrix(mnWidth, mnHeight); + pProgram->SetTexture("sampler", maTexture); + pProgram->DrawTexture(maTexture); + pProgram->Clean(); + + OpenGLContext::ReleaseFramebuffer( pFramebuffer ); + maTexture = aNewTex; + mnBits = 8; + + static BitmapPalette aGreyPalette256; + if (!aGreyPalette256.GetEntryCount()) + { + aGreyPalette256.SetEntryCount(256); + + for (sal_uInt16 i = 0; i < 256; i++) + { + sal_uInt8 nValue = sal_uInt8(i); + aGreyPalette256[i] = BitmapColor(nValue, nValue, nValue); + } + } + maPalette = aGreyPalette256; + + CHECK_GL_ERROR(); + return true; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/gdi/bitmap3.cxx b/vcl/source/gdi/bitmap3.cxx index 9359fb9..30a4f92 100644 --- a/vcl/source/gdi/bitmap3.cxx +++ b/vcl/source/gdi/bitmap3.cxx @@ -250,6 +250,25 @@ void ImplCreateDitherMatrix( sal_uInt8 (*pDitherMatrix)[16][16] ) bool Bitmap::Convert( BmpConversion eConversion ) { + // try to convert in backend + if (mpImpBmp) + { + ImpBitmap* pImpBmp = new ImpBitmap; + + if (pImpBmp->ImplCreate(*mpImpBmp) && pImpBmp->ImplConvert(eConversion)) + { + ImplSetImpBitmap(pImpBmp); + SAL_INFO( "vcl.opengl", "Ref count: " << mpImpBmp->ImplGetRefCount() ); + //maPrefMapMode = MapMode(MAP_PIXEL); + //maPrefSize = pImpBmp->ImplGetSize(); + return true; + } + else + { + delete pImpBmp; + } + } + const sal_uInt16 nBitCount = GetBitCount (); bool bRet = false; diff --git a/vcl/source/gdi/impbmp.cxx b/vcl/source/gdi/impbmp.cxx index b79b0d4..ea9a859 100644 --- a/vcl/source/gdi/impbmp.cxx +++ b/vcl/source/gdi/impbmp.cxx @@ -114,4 +114,14 @@ bool ImpBitmap::ImplReplace( const Color& rSearchColor, const Color& rReplaceCol return mpSalBitmap->Replace( rSearchColor, rReplaceColor, nTol ); } +bool ImpBitmap::ImplConvert( BmpConversion eConversion ) +{ + // avoid large chunk of obsolete and hopefully rarely used conversions. + if (eConversion != BMP_CONVERSION_8BIT_GREYS) + return false; + + // frequently used conversion for creating alpha masks + return mpSalBitmap->ConvertToGreyscale(); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
_______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
