[Libreoffice-commits] core.git: include/vcl vcl/qa vcl/source

Luke Deller (via logerrit) logerrit at kemper.freedesktop.org
Thu Oct 31 07:52:25 UTC 2019


 include/vcl/graphicfilter.hxx        |    8 +++
 vcl/qa/cppunit/GraphicTest.cxx       |   55 ++++++++++++++++++++++----
 vcl/source/filter/graphicfilter2.cxx |   72 ++++++++++++++++++++---------------
 vcl/source/gdi/impgraph.cxx          |   16 ++++---
 4 files changed, 106 insertions(+), 45 deletions(-)

New commits:
commit ef3dabd1f814d1b005efc5d5144978c1d26a8e73
Author:     Luke Deller <luke at deller.id.au>
AuthorDate: Thu Oct 31 01:36:22 2019 +1100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Thu Oct 31 08:51:49 2019 +0100

    Fix IsTransparent() for unloaded graphics
    
    Fix Graphic::IsAlpha() and Graphic::IsTransparent() for unloaded
    graphics. This fixes tdf#118036.
    
    GraphicDescriptor::Detect(true) is currently used to read the image size
    from the header of images which are not being fully loaded yet.  This
    change extends GraphicDescriptor to also report whether the image
    supports transparency or alpha, implemented only for PNG format so far.
    
    Change-Id: I1753c0d11491f1dc518e23da8d7b3842945770cb
    Reviewed-on: https://gerrit.libreoffice.org/81785
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmiklos at collabora.com>

diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx
index eea2e9ac8b7d..45fe8e261f9e 100644
--- a/include/vcl/graphicfilter.hxx
+++ b/include/vcl/graphicfilter.hxx
@@ -145,6 +145,8 @@ class VCL_DLLPUBLIC GraphicDescriptor final
     GraphicFileFormat   nFormat;
     bool const          bOwnStream;
     sal_uInt8 mnNumberOfImageComponents;
+    bool                bIsTransparent;
+    bool                bIsAlpha;
 
     void                ImpConstruct();
 
@@ -214,6 +216,12 @@ public:
     /** @return number of color channels */
     sal_uInt8 GetNumberOfImageComponents() const { return mnNumberOfImageComponents; }
 
+    /** @return whether image supports transparency */
+    bool IsTransparent() const { return bIsTransparent; }
+
+    /** @return whether image supports alpha values for translucent colours */
+    bool IsAlpha() const { return bIsAlpha; }
+
     /** @return filter number that is needed by the GraphFilter to read this format */
     static OUString GetImportFormatShortName( GraphicFileFormat nFormat );
 };
diff --git a/vcl/qa/cppunit/GraphicTest.cxx b/vcl/qa/cppunit/GraphicTest.cxx
index af5985b01f99..56e05c8bf3de 100644
--- a/vcl/qa/cppunit/GraphicTest.cxx
+++ b/vcl/qa/cppunit/GraphicTest.cxx
@@ -28,25 +28,40 @@ class GraphicTest : public CppUnit::TestFixture
     void testUnloadedGraphic();
     void testUnloadedGraphicLoading();
     void testUnloadedGraphicWmf();
+    void testUnloadedGraphicAlpha();
 
     CPPUNIT_TEST_SUITE(GraphicTest);
     CPPUNIT_TEST(testUnloadedGraphic);
     CPPUNIT_TEST(testUnloadedGraphicLoading);
     CPPUNIT_TEST(testUnloadedGraphicWmf);
+    CPPUNIT_TEST(testUnloadedGraphicAlpha);
     CPPUNIT_TEST_SUITE_END();
 };
 
-BitmapEx createBitmap()
+BitmapEx createBitmap(bool alpha = false)
 {
-    Bitmap aBitmap(Size(100, 100), 24);
+    Bitmap aBitmap(Size(120, 100), 24);
     aBitmap.Erase(COL_LIGHTRED);
 
-    return BitmapEx(aBitmap);
+    aBitmap.SetPrefSize(Size(6000, 5000));
+    aBitmap.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
+
+    if (alpha)
+    {
+        sal_uInt8 uAlphaValue = 0x80;
+        AlphaMask aAlphaMask(Size(120, 100), &uAlphaValue);
+
+        return BitmapEx(aBitmap, aAlphaMask);
+    }
+    else
+    {
+        return BitmapEx(aBitmap);
+    }
 }
 
-void createBitmapAndExportForType(SvStream& rStream, OUString const& sType)
+void createBitmapAndExportForType(SvStream& rStream, OUString const& sType, bool alpha)
 {
-    BitmapEx aBitmapEx = createBitmap();
+    BitmapEx aBitmapEx = createBitmap(alpha);
 
     uno::Sequence<beans::PropertyValue> aFilterData;
     GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
@@ -56,11 +71,11 @@ void createBitmapAndExportForType(SvStream& rStream, OUString const& sType)
     rStream.Seek(STREAM_SEEK_TO_BEGIN);
 }
 
-Graphic makeUnloadedGraphic(OUString const& sType)
+Graphic makeUnloadedGraphic(OUString const& sType, bool alpha = false)
 {
     SvMemoryStream aStream;
     GraphicFilter& rGraphicFilter = GraphicFilter::GetGraphicFilter();
-    createBitmapAndExportForType(aStream, sType);
+    createBitmapAndExportForType(aStream, sType, alpha);
     return rGraphicFilter.ImportUnloadedGraphic(aStream);
 }
 
@@ -81,10 +96,15 @@ void GraphicTest::testUnloadedGraphic()
     // check GetSizePixel doesn't load graphic
     aGraphic = makeUnloadedGraphic("png");
     CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
-    CPPUNIT_ASSERT_EQUAL(100L, aGraphic.GetSizePixel().Width());
+    CPPUNIT_ASSERT_EQUAL(120L, aGraphic.GetSizePixel().Width());
     CPPUNIT_ASSERT_EQUAL(100L, aGraphic.GetSizePixel().Height());
     CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
 
+    // check GetPrefSize doesn't load graphic
+    CPPUNIT_ASSERT_EQUAL(6000L, aGraphic.GetPrefSize().Width());
+    CPPUNIT_ASSERT_EQUAL(5000L, aGraphic.GetPrefSize().Height());
+    CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
     // check GetSizeBytes loads graphic
     CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
     CPPUNIT_ASSERT(aGraphic.GetSizeBytes() > 0);
@@ -101,7 +121,7 @@ void GraphicTest::testUnloadedGraphicLoading()
 
         // check available
         CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
-        CPPUNIT_ASSERT_EQUAL(100L, aGraphic.GetSizePixel().Width());
+        CPPUNIT_ASSERT_EQUAL(120L, aGraphic.GetSizePixel().Width());
         CPPUNIT_ASSERT_EQUAL(100L, aGraphic.GetSizePixel().Height());
         CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
         CPPUNIT_ASSERT(aGraphic.GetSizeBytes() > 0);
@@ -157,6 +177,23 @@ void GraphicTest::testUnloadedGraphicWmf()
     CPPUNIT_ASSERT_EQUAL(Size(42, 42), aGraphic.GetPrefSize());
 }
 
+void GraphicTest::testUnloadedGraphicAlpha()
+{
+    // make unloaded test graphic with alpha
+    Graphic aGraphic = makeUnloadedGraphic("png", true);
+
+    CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsAlpha());
+    CPPUNIT_ASSERT_EQUAL(true, aGraphic.IsTransparent());
+    CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+
+    // make unloaded test graphic without alpha
+    aGraphic = makeUnloadedGraphic("png", false);
+
+    CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsAlpha());
+    CPPUNIT_ASSERT_EQUAL(false, aGraphic.IsTransparent());
+    CPPUNIT_ASSERT_EQUAL(false, aGraphic.isAvailable());
+}
+
 } // namespace
 
 CPPUNIT_TEST_SUITE_REGISTRATION(GraphicTest);
diff --git a/vcl/source/filter/graphicfilter2.cxx b/vcl/source/filter/graphicfilter2.cxx
index 03e1ac228067..5640e7c96ed2 100644
--- a/vcl/source/filter/graphicfilter2.cxx
+++ b/vcl/source/filter/graphicfilter2.cxx
@@ -99,6 +99,8 @@ void GraphicDescriptor::ImpConstruct()
     nBitsPerPixel = 0;
     nPlanes = 0;
     mnNumberOfImageComponents = 0;
+    bIsTransparent = false;
+    bIsAlpha = false;
 }
 
 bool GraphicDescriptor::ImpDetectBMP( SvStream& rStm, bool bExtendedInfo )
@@ -548,6 +550,11 @@ bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, bool bExtendedInfo )
                 rStm.ReadUChar( cByte );
                 nBitsPerPixel = cByte;
 
+                // Colour type - check whether it supports alpha values
+                sal_uInt8 cColType = 0;
+                rStm.ReadUChar( cColType );
+                bIsAlpha = bIsTransparent = ( cColType == 4 || cColType == 6 );
+
                 // Planes always 1;
                 // compression always
                 nPlanes = 1;
@@ -555,46 +562,53 @@ bool GraphicDescriptor::ImpDetectPNG( SvStream& rStm, bool bExtendedInfo )
                 sal_uInt32  nLen32 = 0;
                 nTemp32 = 0;
 
-                rStm.SeekRel( 8 );
+                rStm.SeekRel( 7 );
 
-                // read up to the pHYs-Chunk or the start of the image
+                // read up to the start of the image
                 rStm.ReadUInt32( nLen32 );
                 rStm.ReadUInt32( nTemp32 );
-                while( ( nTemp32 != 0x70485973 ) && ( nTemp32 != 0x49444154 )
-                       && rStm.good() )
+                while( ( nTemp32 != 0x49444154 ) && rStm.good() )
                 {
-                    rStm.SeekRel( 4 + nLen32 );
-                    rStm.ReadUInt32( nLen32 );
-                    rStm.ReadUInt32( nTemp32 );
-                }
+                    if ( nTemp32 == 0x70485973 ) // physical pixel dimensions
+                    {
+                        sal_uLong   nXRes;
+                        sal_uLong   nYRes;
 
-                if (nTemp32 == 0x70485973 && rStm.good())
-                {
-                    sal_uLong   nXRes;
-                    sal_uLong   nYRes;
+                        // horizontal resolution
+                        nTemp32 = 0;
+                        rStm.ReadUInt32( nTemp32 );
+                        nXRes = nTemp32;
 
-                    // horizontal resolution
-                    nTemp32 = 0;
-                    rStm.ReadUInt32( nTemp32 );
-                    nXRes = nTemp32;
+                        // vertical resolution
+                        nTemp32 = 0;
+                        rStm.ReadUInt32( nTemp32 );
+                        nYRes = nTemp32;
 
-                    // vertical resolution
-                    nTemp32 = 0;
-                    rStm.ReadUInt32( nTemp32 );
-                    nYRes = nTemp32;
+                        // unit
+                        cByte = 0;
+                        rStm.ReadUChar( cByte );
 
-                    // unit
-                    cByte = 0;
-                    rStm.ReadUChar( cByte );
+                        if ( cByte )
+                        {
+                            if ( nXRes )
+                                aLogSize.setWidth( (aPixSize.Width() * 100000) / nXRes );
 
-                    if ( cByte )
-                    {
-                        if ( nXRes )
-                            aLogSize.setWidth( (aPixSize.Width() * 100000) / nXRes );
+                            if ( nYRes )
+                                aLogSize.setHeight( (aPixSize.Height() * 100000) / nYRes );
+                        }
 
-                        if ( nYRes )
-                            aLogSize.setHeight( (aPixSize.Height() * 100000) / nYRes );
+                        nLen32 -= 9;
+                    }
+                    else if ( nTemp32 == 0x74524e53 ) // transparency
+                    {
+                        bIsTransparent = true;
+                        bIsAlpha = ( cColType != 0 && cColType != 2 );
                     }
+
+                    // skip forward to next chunk
+                    rStm.SeekRel( 4 + nLen32 );
+                    rStm.ReadUInt32( nLen32 );
+                    rStm.ReadUInt32( nTemp32 );
                 }
             }
         }
diff --git a/vcl/source/gdi/impgraph.cxx b/vcl/source/gdi/impgraph.cxx
index 0a215fede7b0..17c371e6d77f 100644
--- a/vcl/source/gdi/impgraph.cxx
+++ b/vcl/source/gdi/impgraph.cxx
@@ -545,10 +545,11 @@ void ImpGraphic::ImplSetPrepared(bool bAnimated, const Size* pSizeHint)
         maSwapInfo.maPrefSize = *pSizeHint;
         maSwapInfo.maPrefMapMode = MapMode(MapUnit::Map100thMM);
     }
-    else
+
+    GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
+    if (aDescriptor.Detect(true))
     {
-        GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
-        if (aDescriptor.Detect(true))
+        if (!pSizeHint)
         {
             // If we have logic size, work with that, as later pixel -> logic
             // conversion will work with the output device DPI, not the graphic
@@ -564,14 +565,15 @@ void ImpGraphic::ImplSetPrepared(bool bAnimated, const Size* pSizeHint)
                 maSwapInfo.maPrefSize = aDescriptor.GetSizePixel();
                 maSwapInfo.maPrefMapMode = MapMode(MapUnit::MapPixel);
             }
-
-            maSwapInfo.maSizePixel = aDescriptor.GetSizePixel();
         }
+
+        maSwapInfo.maSizePixel = aDescriptor.GetSizePixel();
+        maSwapInfo.mbIsTransparent = aDescriptor.IsTransparent();
+        maSwapInfo.mbIsAlpha = aDescriptor.IsAlpha();
     }
+
     maSwapInfo.mnAnimationLoopCount = 0;
     maSwapInfo.mbIsEPS = false;
-    maSwapInfo.mbIsTransparent = false;
-    maSwapInfo.mbIsAlpha = false;
     maSwapInfo.mbIsAnimated = bAnimated;
 }
 


More information about the Libreoffice-commits mailing list