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

Tomaž Vajngerl (via logerrit) logerrit at kemper.freedesktop.org
Wed Apr 3 09:57:34 UTC 2019


 include/vcl/BitmapTools.hxx                     |    5 
 vcl/headless/svpgdi.cxx                         |   12 -
 vcl/headless/svpinst.cxx                        |    7 +
 vcl/inc/backend/BackendCapabilities.hxx         |   28 ++++
 vcl/inc/headless/svpinst.hxx                    |    2 
 vcl/inc/salinst.hxx                             |    7 +
 vcl/qa/cppunit/BitmapTest.cxx                   |   64 +++++++++-
 vcl/qa/cppunit/png/PngFilterTest.cxx            |  135 +++++++++++++--------
 vcl/source/bitmap/BitmapDisabledImageFilter.cxx |    2 
 vcl/source/bitmap/BitmapTools.cxx               |   43 ++++++
 vcl/source/bitmap/bitmap.cxx                    |   14 +-
 vcl/source/filter/png/PngImageReader.cxx        |  148 ++++++++++++++++--------
 vcl/source/filter/png/pngwrite.cxx              |   39 ++++--
 vcl/source/gdi/bmpacc2.cxx                      |  129 ++++++++++++--------
 14 files changed, 459 insertions(+), 176 deletions(-)

New commits:
commit 86ea64f216819696cd86d1926aff0a138ace2baf
Author:     Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Fri Feb 15 13:14:32 2019 +0100
Commit:     Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Wed Apr 3 11:57:08 2019 +0200

    Support for native 32bit Bitmap in VCL and SVP (cairo) backend
    
    This adds basic support for 32bit bitmaps for the SVP backend. For
    other backends the support is disabled for now as we need to add it for
    each backend separately and enable support.
    
    When this patch is applied it is possible to a Bitmap with bit count
    32, but currently no input filter uses this with the exception of the
    new PngImageReader(libpng based), which is used only for the icons.
    
    For a general support more things need to be implemented and tested:
    - conversion back and fourth between 32-bit and 24-bit + 8bit alpha (or
    other supported pairs)
    - 'raw' export of the bitmap needs to be handeled properly (like in
    SVM import/export) so it creates the correct image.
    - input filters need to be checked and converted if this is necessary
    - look for possible bugs when drawing transparent bitmaps
    - check of UNO API
    
    Change-Id: I7a7be0e6134dfdd9a7aeaef897131bb6e710ae7e
    Reviewed-on: https://gerrit.libreoffice.org/69289
    Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
    Tested-by: Tomaž Vajngerl <quikee at gmail.com>

diff --git a/include/vcl/BitmapTools.hxx b/include/vcl/BitmapTools.hxx
index ff431783ad24..0099358476c0 100644
--- a/include/vcl/BitmapTools.hxx
+++ b/include/vcl/BitmapTools.hxx
@@ -33,6 +33,9 @@ typedef sal_uInt8 (*lookup_table)[256];
 lookup_table VCL_DLLPUBLIC get_premultiply_table();
 lookup_table VCL_DLLPUBLIC get_unpremultiply_table();
 
+VCL_DLLPUBLIC sal_uInt8 unpremultiply(sal_uInt8 c, sal_uInt8 a);
+VCL_DLLPUBLIC sal_uInt8 premultiply(sal_uInt8 c, sal_uInt8 a);
+
 /**
  * Intended to be used to feed into CreateFromData to create a BitmapEx. RGB data format.
  */
@@ -124,6 +127,8 @@ VCL_DLLPUBLIC css::uno::Sequence< sal_Int8 > CanvasExtractBitmapData(BitmapEx co
 BitmapEx VCL_DLLPUBLIC createHistorical8x8FromArray(std::array<sal_uInt8,64> const & pArray, Color aColorPix, Color aColorBack);
 bool VCL_DLLPUBLIC isHistorical8x8(const BitmapEx& rBitmapEx, BitmapColor& o_rBack, BitmapColor& o_rFront);
 
+VCL_DLLPUBLIC bool convertBitmap32To24Plus8(BitmapEx const & rInput, BitmapEx & rResult);
+
 }} // end vcl::bitmap
 
 #endif // INCLUDED_VCL_BITMAP_TOOLS_HXX
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
index 08cb2bfec940..3ec663c8706b 100644
--- a/vcl/headless/svpgdi.cxx
+++ b/vcl/headless/svpgdi.cxx
@@ -1624,7 +1624,7 @@ void SvpSalGraphics::drawBitmap(const SalTwoRect& rTR, const SalBitmap& rSourceB
 {
     SourceHelper aSurface(rSourceBitmap);
     cairo_surface_t* source = aSurface.getSurface();
-    copySource(rTR, source);
+    copyWithOperator(rTR, source, CAIRO_OPERATOR_OVER);
 }
 
 void SvpSalGraphics::drawBitmap(const SalTwoRect& rTR, const BitmapBuffer* pBuffer, cairo_operator_t eOp)
@@ -1749,11 +1749,10 @@ std::shared_ptr<SalBitmap> SvpSalGraphics::getBitmap( long nX, long nY, long nWi
 Color SvpSalGraphics::getPixel( long nX, long nY )
 {
 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 12, 0)
-    cairo_surface_t *target = cairo_surface_create_similar_image(m_pSurface,
+    cairo_surface_t *target = cairo_surface_create_similar_image(m_pSurface, CAIRO_FORMAT_ARGB32, 1, 1);
 #else
-    cairo_surface_t *target = cairo_image_surface_create(
+    cairo_surface_t *target = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
 #endif
-            CAIRO_FORMAT_ARGB32, 1, 1);
 
     cairo_t* cr = cairo_create(target);
 
@@ -1769,11 +1768,10 @@ Color SvpSalGraphics::getPixel( long nX, long nY )
     sal_uInt8 b = unpremultiply_table[a][data[SVP_CAIRO_BLUE]];
     sal_uInt8 g = unpremultiply_table[a][data[SVP_CAIRO_GREEN]];
     sal_uInt8 r = unpremultiply_table[a][data[SVP_CAIRO_RED]];
-    Color nRet = Color(r, g, b);
-
+    Color aColor(0xFF - a, r, g, b);
     cairo_surface_destroy(target);
 
-    return nRet;
+    return aColor;
 }
 
 namespace
diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index 49a64c7fa8bf..324d976cb95e 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -537,6 +537,13 @@ void SvpSalInstance::AddToRecentDocumentList(const OUString&, const OUString&, c
 {
 }
 
+std::shared_ptr<vcl::BackendCapabilities> SvpSalInstance::GetBackendCapabilities()
+{
+    auto pBackendCapabilities = SalInstance::GetBackendCapabilities();
+    pBackendCapabilities->mbSupportsBitmap32 = true;
+    return pBackendCapabilities;
+}
+
 //obviously doesn't actually do anything, it's just a nonfunctional stub
 
 #ifdef LIBO_HEADLESS
diff --git a/vcl/inc/backend/BackendCapabilities.hxx b/vcl/inc/backend/BackendCapabilities.hxx
new file mode 100644
index 000000000000..89879ee492e1
--- /dev/null
+++ b/vcl/inc/backend/BackendCapabilities.hxx
@@ -0,0 +1,28 @@
+/* -*- 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/.
+ *
+ */
+
+#ifndef INCLUDED_VCL_INC_BACKENDCAPABILITIES_HXX
+#define INCLUDED_VCL_INC_BACKENDCAPABILITIES_HXX
+
+namespace vcl
+{
+struct BackendCapabilities
+{
+    bool mbSupportsBitmap32;
+    BackendCapabilities()
+        : mbSupportsBitmap32(false)
+    {
+    }
+};
+}
+
+#endif // INCLUDED_VCL_INC_BACKENDCAPABILITIES_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx
index 684abde290fa..dcdd29fc8f07 100644
--- a/vcl/inc/headless/svpinst.hxx
+++ b/vcl/inc/headless/svpinst.hxx
@@ -167,6 +167,8 @@ public:
     // SalBitmap
     virtual std::shared_ptr<SalBitmap> CreateSalBitmap() override;
 
+    std::shared_ptr<vcl::BackendCapabilities> GetBackendCapabilities() override;
+
     // wait next event and dispatch
     // must returned by UserEvent (SalFrame::PostEvent)
     // and timer
diff --git a/vcl/inc/salinst.hxx b/vcl/inc/salinst.hxx
index e35cd78df4fb..4acb0315de4c 100644
--- a/vcl/inc/salinst.hxx
+++ b/vcl/inc/salinst.hxx
@@ -28,6 +28,8 @@
 #include <osl/thread.hxx>
 #include <vcl/vclenum.hxx>
 
+#include "backend/BackendCapabilities.hxx"
+
 #include "displayconnectiondispatch.hxx"
 
 #include <com/sun/star/uno/XComponentContext.hpp>
@@ -134,6 +136,11 @@ public:
     virtual SalSystem*      CreateSalSystem() = 0;
     // SalBitmap
     virtual std::shared_ptr<SalBitmap> CreateSalBitmap() = 0;
+    // BackendCapabilities
+    virtual std::shared_ptr<vcl::BackendCapabilities> GetBackendCapabilities()
+    {
+        return std::make_shared<vcl::BackendCapabilities>();
+    }
 
     // YieldMutex
     comphelper::SolarMutex* GetYieldMutex();
diff --git a/vcl/qa/cppunit/BitmapTest.cxx b/vcl/qa/cppunit/BitmapTest.cxx
index 986ce3532487..11cfea33f2d6 100644
--- a/vcl/qa/cppunit/BitmapTest.cxx
+++ b/vcl/qa/cppunit/BitmapTest.cxx
@@ -30,6 +30,9 @@
 #include <BitmapSymmetryCheck.hxx>
 #include <bitmapwriteaccess.hxx>
 
+#include <svdata.hxx>
+#include <salinst.hxx>
+
 namespace
 {
 class BitmapTest : public CppUnit::TestFixture
@@ -44,6 +47,8 @@ class BitmapTest : public CppUnit::TestFixture
     void testCRC();
     void testGreyPalette();
     void testCustom8BitPalette();
+    void testErase();
+    void testBitmap32();
 
     CPPUNIT_TEST_SUITE(BitmapTest);
     CPPUNIT_TEST(testCreation);
@@ -56,6 +61,8 @@ class BitmapTest : public CppUnit::TestFixture
     CPPUNIT_TEST(testCRC);
     CPPUNIT_TEST(testGreyPalette);
     CPPUNIT_TEST(testCustom8BitPalette);
+    CPPUNIT_TEST(testErase);
+    CPPUNIT_TEST(testBitmap32);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -151,6 +158,10 @@ void BitmapTest::testCreation()
                                      aBmp.GetSizeBytes());
     }
 
+    // Check backend capabilities and return from the test successfully
+    // if the backend doesn't support 32-bit bitmap
+    auto pBackendCapabilities = ImplGetSVData()->mpDefInst->GetBackendCapabilities();
+    if (pBackendCapabilities->mbSupportsBitmap32)
     {
         Bitmap aBmp(Size(10, 10), 32);
         Size aSize = aBmp.GetSizePixel();
@@ -158,12 +169,11 @@ void BitmapTest::testCreation()
         CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong height", static_cast<long>(10), aSize.Height());
         CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong pref size", Size(), aBmp.GetPrefSize());
         CPPUNIT_ASSERT_MESSAGE("Empty bitmap", !aBmp.IsEmpty());
-        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", static_cast<sal_uInt16>(24),
-                                     aBmp.GetBitCount());
-        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", static_cast<sal_uLong>(16777216),
-                                     aBmp.GetColorCount());
-        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", static_cast<sal_uLong>(300),
-                                     aBmp.GetSizeBytes());
+
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong bit count", sal_uInt16(32), aBmp.GetBitCount());
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong color count", sal_Int64(4294967296U),
+                                     sal_Int64(aBmp.GetColorCount()));
+        CPPUNIT_ASSERT_EQUAL_MESSAGE("Wrong byte size", sal_uLong(400), aBmp.GetSizeBytes());
     }
 }
 
@@ -599,6 +609,48 @@ void BitmapTest::testCustom8BitPalette()
     }
 }
 
+void BitmapTest::testErase()
+{
+    Bitmap aBitmap(Size(3, 3), 24);
+    {
+        BitmapScopedWriteAccess pWriteAccess(aBitmap);
+        pWriteAccess->Erase(Color(0x11, 0x22, 0x33));
+    }
+    {
+        Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+        BitmapColor aColor(pReadAccess->GetPixel(0, 0));
+        CPPUNIT_ASSERT_EQUAL(BitmapColor(0x11, 0x22, 0x33, 0x00), aColor);
+    }
+}
+
+void BitmapTest::testBitmap32()
+{
+    // Check backend capabilities and return from the test successfully
+    // if the backend doesn't support 32-bit bitmap
+    auto pBackendCapabilities = ImplGetSVData()->mpDefInst->GetBackendCapabilities();
+    if (!pBackendCapabilities->mbSupportsBitmap32)
+        return;
+
+    Bitmap aBitmap(Size(3, 3), 32);
+    {
+        BitmapScopedWriteAccess pWriteAccess(aBitmap);
+        pWriteAccess->Erase(Color(0xFF, 0x11, 0x22, 0x33));
+        pWriteAccess->SetPixel(1, 1, BitmapColor(0x44, 0xFF, 0xBB, 0x00));
+        pWriteAccess->SetPixel(2, 2, BitmapColor(0x99, 0x77, 0x66, 0x55));
+    }
+    {
+        Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+        BitmapColor aColor = pReadAccess->GetPixel(0, 0);
+        CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0xFF), aColor);
+
+        aColor = pReadAccess->GetPixel(1, 1);
+        CPPUNIT_ASSERT_EQUAL(BitmapColor(0x44, 0xFF, 0xBB, 0x00), aColor);
+
+        aColor = pReadAccess->GetPixel(2, 2);
+        CPPUNIT_ASSERT_EQUAL(BitmapColor(0x99, 0x77, 0x66, 0x55), aColor);
+    }
+}
+
 } // namespace
 
 CPPUNIT_TEST_SUITE_REGISTRATION(BitmapTest);
diff --git a/vcl/qa/cppunit/png/PngFilterTest.cxx b/vcl/qa/cppunit/png/PngFilterTest.cxx
index 1a9dd0a4cead..fdb61f976cff 100644
--- a/vcl/qa/cppunit/png/PngFilterTest.cxx
+++ b/vcl/qa/cppunit/png/PngFilterTest.cxx
@@ -60,19 +60,25 @@ void PngFilterTest::testPng()
         Bitmap aBitmap = aBitmapEx.GetBitmap();
         {
             Bitmap::ScopedReadAccess pAccess(aBitmap);
-            CPPUNIT_ASSERT_EQUAL(sal_uInt16(24), pAccess->GetBitCount());
             CPPUNIT_ASSERT_EQUAL(4L, pAccess->Width());
             CPPUNIT_ASSERT_EQUAL(4L, pAccess->Height());
 
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 0));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 3));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 0));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 3));
-
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0x00), pAccess->GetPixel(1, 1));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0x00), pAccess->GetPixel(1, 2));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0x00), pAccess->GetPixel(2, 1));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0x00), pAccess->GetPixel(2, 2));
+            if (pAccess->GetBitCount() == 24 || pAccess->GetBitCount() == 32)
+            {
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 0));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 3));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 0));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 3));
+
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0x00), pAccess->GetPixel(1, 1));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0x00), pAccess->GetPixel(1, 2));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0x00), pAccess->GetPixel(2, 1));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x00, 0x00), pAccess->GetPixel(2, 2));
+            }
+            else
+            {
+                CPPUNIT_ASSERT_MESSAGE("Bitmap is not 24 or 32 bit.", false);
+            }
         }
     }
     for (const OUString& aFileName :
@@ -87,19 +93,24 @@ void PngFilterTest::testPng()
         Bitmap aBitmap = aBitmapEx.GetBitmap();
         {
             Bitmap::ScopedReadAccess pAccess(aBitmap);
-            CPPUNIT_ASSERT_EQUAL(sal_uInt16(24), pAccess->GetBitCount());
             CPPUNIT_ASSERT_EQUAL(4L, pAccess->Width());
             CPPUNIT_ASSERT_EQUAL(4L, pAccess->Height());
-
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 0));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 3));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 0));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 3));
-
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0x00, 0x00, 0x00), pAccess->GetPixel(1, 1));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0xFF, 0x00, 0x00), pAccess->GetPixel(1, 2));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0xFF, 0x00), pAccess->GetPixel(2, 1));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0x00, 0x00), pAccess->GetPixel(2, 2));
+            if (pAccess->GetBitCount() == 24 || pAccess->GetBitCount() == 32)
+            {
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 0));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 3));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 0));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 3));
+
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0x00, 0x00, 0x00), pAccess->GetPixel(1, 1));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0xFF, 0x00, 0x00), pAccess->GetPixel(1, 2));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0xFF, 0x00), pAccess->GetPixel(2, 1));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0x00, 0x00), pAccess->GetPixel(2, 2));
+            }
+            else
+            {
+                CPPUNIT_ASSERT_MESSAGE("Bitmap is not 24 or 32 bit.", false);
+            }
         }
     }
     for (const OUString& aFileName : { OUString("alpha-rect-8bit-RGBA.png") })
@@ -113,39 +124,65 @@ void PngFilterTest::testPng()
         Bitmap aBitmap = aBitmapEx.GetBitmap();
         {
             Bitmap::ScopedReadAccess pAccess(aBitmap);
-            CPPUNIT_ASSERT_EQUAL(sal_uInt16(24), pAccess->GetBitCount());
-            CPPUNIT_ASSERT_EQUAL(4L, pAccess->Width());
-            CPPUNIT_ASSERT_EQUAL(4L, pAccess->Height());
-
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 0));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 3));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 0));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 3));
-
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0x00, 0x00, 0x00), pAccess->GetPixel(1, 1));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0xFF, 0x00, 0x00), pAccess->GetPixel(1, 2));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0xFF, 0x00), pAccess->GetPixel(2, 1));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0x00, 0x00), pAccess->GetPixel(2, 2));
-        }
-        AlphaMask aAlpha = aBitmapEx.GetAlpha();
-        {
-            AlphaMask::ScopedReadAccess pAccess(aAlpha);
-            CPPUNIT_ASSERT_EQUAL(sal_uInt16(8), pAccess->GetBitCount());
             CPPUNIT_ASSERT_EQUAL(4L, pAccess->Width());
             CPPUNIT_ASSERT_EQUAL(4L, pAccess->Height());
 
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x80, 0x00), pAccess->GetPixel(0, 0));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x80, 0x00), pAccess->GetPixel(3, 3));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x80, 0x00), pAccess->GetPixel(3, 0));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x80, 0x00), pAccess->GetPixel(0, 3));
-
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x40, 0x00), pAccess->GetPixel(1, 1));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0xC0, 0x00), pAccess->GetPixel(1, 2));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0xC0, 0x00), pAccess->GetPixel(2, 1));
-            CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x40, 0x00), pAccess->GetPixel(2, 2));
+            if (pAccess->GetBitCount() == 24)
+            {
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 0));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 3));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(3, 0));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x00), pAccess->GetPixel(0, 3));
+
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0x00, 0x00, 0x00), pAccess->GetPixel(1, 1));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0xFF, 0x00, 0x00), pAccess->GetPixel(1, 2));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0xFF, 0x00), pAccess->GetPixel(2, 1));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0x00, 0x00), pAccess->GetPixel(2, 2));
+
+                AlphaMask aAlpha = aBitmapEx.GetAlpha();
+                {
+                    AlphaMask::ScopedReadAccess pAlphaAccess(aAlpha);
+                    CPPUNIT_ASSERT_EQUAL(sal_uInt16(8), pAlphaAccess->GetBitCount());
+                    CPPUNIT_ASSERT_EQUAL(4L, pAlphaAccess->Width());
+                    CPPUNIT_ASSERT_EQUAL(4L, pAlphaAccess->Height());
+
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x80, 0x00),
+                                         pAlphaAccess->GetPixel(0, 0));
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x80, 0x00),
+                                         pAlphaAccess->GetPixel(3, 3));
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x80, 0x00),
+                                         pAlphaAccess->GetPixel(3, 0));
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x80, 0x00),
+                                         pAlphaAccess->GetPixel(0, 3));
+
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x40, 0x00),
+                                         pAlphaAccess->GetPixel(1, 1));
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0xC0, 0x00),
+                                         pAlphaAccess->GetPixel(1, 2));
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0xC0, 0x00),
+                                         pAlphaAccess->GetPixel(2, 1));
+                    CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0x40, 0x00),
+                                         pAlphaAccess->GetPixel(2, 2));
+                }
+            }
+            else if (pAccess->GetBitCount() == 32)
+            {
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x80), pAccess->GetPixel(0, 0));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x80), pAccess->GetPixel(3, 3));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x80), pAccess->GetPixel(3, 0));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0xFF, 0x80), pAccess->GetPixel(0, 3));
+
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0x00, 0x00, 0x40), pAccess->GetPixel(1, 1));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0xFF, 0x00, 0xC0), pAccess->GetPixel(1, 2));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0x00, 0x00, 0xFF, 0xC0), pAccess->GetPixel(2, 1));
+                CPPUNIT_ASSERT_EQUAL(BitmapColor(0xFF, 0xFF, 0x00, 0x40), pAccess->GetPixel(2, 2));
+            }
+            else
+            {
+                CPPUNIT_ASSERT_MESSAGE("Bitmap is not 24 or 32 bit.", false);
+            }
         }
     }
-    // CPPUNIT_ASSERT(false);
 }
 
 CPPUNIT_TEST_SUITE_REGISTRATION(PngFilterTest);
diff --git a/vcl/source/bitmap/BitmapDisabledImageFilter.cxx b/vcl/source/bitmap/BitmapDisabledImageFilter.cxx
index 56f46b313159..6c13e6133f32 100644
--- a/vcl/source/bitmap/BitmapDisabledImageFilter.cxx
+++ b/vcl/source/bitmap/BitmapDisabledImageFilter.cxx
@@ -44,7 +44,7 @@ BitmapEx BitmapDisabledImageFilter::execute(BitmapEx const& rBitmapEx) const
                 // Get the luminance from RGB color and remap the value from 0-255 to 160-224
                 const BitmapColor aColor = pRead->GetPixelFromData(pReadScan, nX);
                 sal_uInt8 nLum(aColor.GetLuminance() / 4 + 160);
-                BitmapColor aGreyValue(nLum, nLum, nLum);
+                BitmapColor aGreyValue(nLum, nLum, nLum, aColor.GetAlpha());
                 pGrey->SetPixelOnData(pGreyScan, nX, aGreyValue);
             }
         }
diff --git a/vcl/source/bitmap/BitmapTools.cxx b/vcl/source/bitmap/BitmapTools.cxx
index 9762c27280cd..6f14c3526d42 100644
--- a/vcl/source/bitmap/BitmapTools.cxx
+++ b/vcl/source/bitmap/BitmapTools.cxx
@@ -1041,12 +1041,12 @@ void CanvasCairoExtractBitmapData( BitmapEx const & aBmpEx, Bitmap & aBitmap, un
         return bRet;
     }
 
-    static sal_uInt8 unpremultiply(sal_uInt8 c, sal_uInt8 a)
+    sal_uInt8 unpremultiply(sal_uInt8 c, sal_uInt8 a)
     {
         return (a == 0) ? 0 : (c * 255 + a / 2) / a;
     }
 
-    static sal_uInt8 premultiply(sal_uInt8 c, sal_uInt8 a)
+    sal_uInt8 premultiply(sal_uInt8 c, sal_uInt8 a)
     {
         return (c * a + 127) / 255;
     }
@@ -1083,6 +1083,45 @@ void CanvasCairoExtractBitmapData( BitmapEx const & aBmpEx, Bitmap & aBitmap, un
         return premultiply_table;
     }
 
+bool convertBitmap32To24Plus8(BitmapEx const & rInput, BitmapEx & rResult)
+{
+    Bitmap aBitmap(rInput.GetBitmap());
+    if (aBitmap.GetBitCount() != 32)
+        return false;
+
+    Size aSize = aBitmap.GetSizePixel();
+    Bitmap aResultBitmap(aSize, 24);
+    AlphaMask aResultAlpha(aSize);
+    {
+        BitmapScopedWriteAccess pResultBitmapAccess(aResultBitmap);
+        AlphaScopedWriteAccess pResultAlphaAccess(aResultAlpha);
+
+        Bitmap::ScopedReadAccess pReadAccess(aBitmap);
+
+        for (long nY = 0; nY < aSize.Height(); ++nY)
+        {
+            Scanline aResultScan = pResultBitmapAccess->GetScanline(nY);
+            Scanline aResultScanAlpha = pResultAlphaAccess->GetScanline(nY);
+
+            Scanline aReadScan = pReadAccess->GetScanline(nY);
+
+            for (long nX = 0; nX < aSize.Width(); ++nX)
+            {
+                const BitmapColor aColor = pReadAccess->GetPixelFromData(aReadScan, nX);
+                BitmapColor aResultColor(aColor.GetRed(), aColor.GetGreen(), aColor.GetBlue());
+                BitmapColor aResultColorAlpha(aColor.GetAlpha(), aColor.GetAlpha(), aColor.GetAlpha());
+
+                pResultBitmapAccess->SetPixelOnData(aResultScan, nX, aResultColor);
+                pResultAlphaAccess->SetPixelOnData(aResultScanAlpha, nX, aResultColorAlpha);
+            }
+        }
+    }
+    if (rInput.IsTransparent())
+        rResult = BitmapEx(aResultBitmap, rInput.GetAlpha());
+    else
+        rResult = BitmapEx(aResultBitmap, aResultAlpha);
+    return true;
+}
 
 }} // end vcl::bitmap
 
diff --git a/vcl/source/bitmap/bitmap.cxx b/vcl/source/bitmap/bitmap.cxx
index c26cf89c3b66..bf391f339750 100644
--- a/vcl/source/bitmap/bitmap.cxx
+++ b/vcl/source/bitmap/bitmap.cxx
@@ -260,9 +260,19 @@ sal_uInt16 Bitmap::GetBitCount() const
 {
     if (!mxSalBmp)
         return 0;
+
     sal_uInt16 nBitCount = mxSalBmp->GetBitCount();
-    return ( nBitCount <= 4 ) ? ( ( nBitCount <= 1 ) ? 1 : 4 ):
-                                ( ( nBitCount <= 8 ) ? 8 : 24);
+    if (nBitCount <= 1)
+        return 1;
+    if (nBitCount <= 4)
+        return 4;
+    if (nBitCount <= 8)
+        return 8;
+    if (nBitCount <= 24)
+        return 24;
+    if (nBitCount <= 32)
+        return 32;
+    return 0;
 }
 
 bool Bitmap::HasGreyPalette() const
diff --git a/vcl/source/filter/png/PngImageReader.cxx b/vcl/source/filter/png/PngImageReader.cxx
index 2c83f890e91a..be506874b667 100644
--- a/vcl/source/filter/png/PngImageReader.cxx
+++ b/vcl/source/filter/png/PngImageReader.cxx
@@ -14,6 +14,9 @@
 #include <bitmapwriteaccess.hxx>
 #include <vcl/bitmap.hxx>
 #include <vcl/alpha.hxx>
+#include <vcl/BitmapTools.hxx>
+#include <svdata.hxx>
+#include <salinst.hxx>
 
 namespace
 {
@@ -32,13 +35,14 @@ void lclReadStream(png_structp pPng, png_bytep pOutBytes, png_size_t nBytesToRea
         png_error(pPng, "Error reading");
 }
 
-bool reader(SvStream& rStream, BitmapEx& rBitmapEx)
+bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32)
 {
     enum
     {
         PNG_SIGNATURE_SIZE = 8
     };
 
+    // Check signature bytes
     sal_uInt8 aHeader[PNG_SIGNATURE_SIZE];
     rStream.ReadBytes(aHeader, PNG_SIGNATURE_SIZE);
 
@@ -62,9 +66,11 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx)
         return false;
     }
 
+    png_set_option(pPng, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON);
+
     png_set_read_fn(pPng, &rStream, lclReadStream);
 
-    png_set_crc_action(pPng, PNG_CRC_WARN_USE, PNG_CRC_WARN_DISCARD);
+    png_set_crc_action(pPng, PNG_CRC_ERROR_QUIT, PNG_CRC_WARN_DISCARD);
 
     png_set_sig_bytes(pPng, PNG_SIGNATURE_SIZE);
 
@@ -85,9 +91,6 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx)
         return false;
     }
 
-    Bitmap aBitmap(Size(width, height), 24);
-    AlphaMask aBitmapAlpha(Size(width, height), nullptr);
-
     if (colorType == PNG_COLOR_TYPE_PALETTE)
         png_set_palette_to_rgb(pPng);
 
@@ -135,61 +138,114 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx)
         {
             size_t aRowSizeBytes = png_get_rowbytes(pPng, pInfo);
 
-            BitmapScopedWriteAccess pWriteAccess(aBitmap);
-            ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
-            if (eFormat == ScanlineFormat::N24BitTcBgr)
-                png_set_bgr(pPng);
+            Bitmap aBitmap(Size(width, height), 24);
+            {
+                BitmapScopedWriteAccess pWriteAccess(aBitmap);
+                ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
+                if (eFormat == ScanlineFormat::N24BitTcBgr)
+                    png_set_bgr(pPng);
 
-            std::vector<png_byte> aRow(aRowSizeBytes, 0);
+                std::vector<std::vector<png_byte>> aRows(height);
+                for (auto& rRow : aRows)
+                    rRow.resize(aRowSizeBytes, 0);
 
-            for (int pass = 0; pass < nNumberOfPasses; pass++)
-            {
-                for (png_uint_32 y = 0; y < height; y++)
+                for (int pass = 0; pass < nNumberOfPasses; pass++)
                 {
-                    Scanline pScanline = pWriteAccess->GetScanline(y);
-                    png_bytep pRow = aRow.data();
-                    png_read_rows(pPng, &pRow, nullptr, 1);
-                    size_t iColor = 0;
-                    for (size_t i = 0; i < aRowSizeBytes; i += 3)
+                    for (png_uint_32 y = 0; y < height; y++)
                     {
-                        pScanline[iColor++] = pRow[i + 0];
-                        pScanline[iColor++] = pRow[i + 1];
-                        pScanline[iColor++] = pRow[i + 2];
+                        Scanline pScanline = pWriteAccess->GetScanline(y);
+                        png_bytep pRow = aRows[y].data();
+                        png_read_row(pPng, pRow, nullptr);
+                        size_t iColor = 0;
+                        for (size_t i = 0; i < aRowSizeBytes; i += 3)
+                        {
+                            pScanline[iColor++] = pRow[i + 0];
+                            pScanline[iColor++] = pRow[i + 1];
+                            pScanline[iColor++] = pRow[i + 2];
+                        }
                     }
                 }
             }
+            rBitmapEx = BitmapEx(aBitmap);
         }
         else if (colorType == PNG_COLOR_TYPE_RGB_ALPHA)
         {
             size_t aRowSizeBytes = png_get_rowbytes(pPng, pInfo);
 
-            BitmapScopedWriteAccess pWriteAccess(aBitmap);
-            AlphaScopedWriteAccess pWriteAccessAlpha(aBitmapAlpha);
-
-            ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
-            if (eFormat == ScanlineFormat::N24BitTcBgr)
-                png_set_bgr(pPng);
+            if (bUseBitmap32)
+            {
+                Bitmap aBitmap(Size(width, height), 32);
+                {
+                    BitmapScopedWriteAccess pWriteAccess(aBitmap);
+                    ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
+                    if (eFormat == ScanlineFormat::N32BitTcAbgr
+                        || eFormat == ScanlineFormat::N32BitTcBgra)
+                    {
+                        png_set_bgr(pPng);
+                    }
 
-            std::vector<png_byte> aRow(aRowSizeBytes, 0);
+                    std::vector<std::vector<png_byte>> aRows(height);
+                    for (auto& rRow : aRows)
+                        rRow.resize(aRowSizeBytes, 0);
 
-            for (int pass = 0; pass < nNumberOfPasses; pass++)
+                    for (int pass = 0; pass < nNumberOfPasses; pass++)
+                    {
+                        for (png_uint_32 y = 0; y < height; y++)
+                        {
+                            Scanline pScanline = pWriteAccess->GetScanline(y);
+                            png_bytep pRow = aRows[y].data();
+                            png_read_row(pPng, pRow, nullptr);
+                            size_t iColor = 0;
+                            for (size_t i = 0; i < aRowSizeBytes; i += 4)
+                            {
+                                sal_Int8 alpha = pRow[i + 3];
+                                pScanline[iColor++] = vcl::bitmap::premultiply(pRow[i + 0], alpha);
+                                pScanline[iColor++] = vcl::bitmap::premultiply(pRow[i + 1], alpha);
+                                pScanline[iColor++] = vcl::bitmap::premultiply(pRow[i + 2], alpha);
+                                pScanline[iColor++] = alpha;
+                            }
+                        }
+                    }
+                }
+                rBitmapEx = BitmapEx(aBitmap);
+            }
+            else
             {
-                for (png_uint_32 y = 0; y < height; y++)
+                Bitmap aBitmap(Size(width, height), 24);
+                AlphaMask aBitmapAlpha(Size(width, height), nullptr);
                 {
-                    Scanline pScanAlpha = pWriteAccessAlpha->GetScanline(y);
-                    Scanline pScanline = pWriteAccess->GetScanline(y);
-                    png_bytep pRow = aRow.data();
-                    png_read_rows(pPng, &pRow, nullptr, 1);
-                    size_t iAlpha = 0;
-                    size_t iColor = 0;
-                    for (size_t i = 0; i < aRowSizeBytes; i += 4)
+                    BitmapScopedWriteAccess pWriteAccess(aBitmap);
+                    ScanlineFormat eFormat = pWriteAccess->GetScanlineFormat();
+                    if (eFormat == ScanlineFormat::N24BitTcBgr)
+                        png_set_bgr(pPng);
+
+                    AlphaScopedWriteAccess pWriteAccessAlpha(aBitmapAlpha);
+
+                    std::vector<std::vector<png_byte>> aRows(height);
+                    for (auto& rRow : aRows)
+                        rRow.resize(aRowSizeBytes, 0);
+
+                    for (int pass = 0; pass < nNumberOfPasses; pass++)
                     {
-                        pScanline[iColor++] = pRow[i + 0];
-                        pScanline[iColor++] = pRow[i + 1];
-                        pScanline[iColor++] = pRow[i + 2];
-                        pScanAlpha[iAlpha++] = 0xFF - pRow[i + 3];
+                        for (png_uint_32 y = 0; y < height; y++)
+                        {
+                            Scanline pScanline = pWriteAccess->GetScanline(y);
+                            Scanline pScanAlpha = pWriteAccessAlpha->GetScanline(y);
+                            png_bytep pRow = aRows[y].data();
+                            png_read_row(pPng, pRow, nullptr);
+                            size_t iAlpha = 0;
+                            size_t iColor = 0;
+                            for (size_t i = 0; i < aRowSizeBytes; i += 4)
+                            {
+                                pScanline[iColor++] = pRow[i + 0];
+                                pScanline[iColor++] = pRow[i + 1];
+                                pScanline[iColor++] = pRow[i + 2];
+                                pScanAlpha[iAlpha++] = 0xFF - pRow[i + 3];
+                            }
+                        }
                     }
                 }
+                rBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
             }
         }
     }
@@ -198,8 +254,6 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx)
 
     png_destroy_read_struct(&pPng, &pInfo, nullptr);
 
-    rBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
-
     return true;
 }
 
@@ -212,7 +266,13 @@ PngImageReader::PngImageReader(SvStream& rStream)
 {
 }
 
-bool PngImageReader::read(BitmapEx& rBitmapEx) { return reader(mrStream, rBitmapEx); }
+bool PngImageReader::read(BitmapEx& rBitmapEx)
+{
+    auto pBackendCapabilities = ImplGetSVData()->mpDefInst->GetBackendCapabilities();
+    bool bSupportsBitmap32 = pBackendCapabilities->mbSupportsBitmap32;
+
+    return reader(mrStream, rBitmapEx, bSupportsBitmap32);
+}
 
 } // namespace vcl
 
diff --git a/vcl/source/filter/png/pngwrite.cxx b/vcl/source/filter/png/pngwrite.cxx
index 98dc91c3342c..38e7617bbca2 100644
--- a/vcl/source/filter/png/pngwrite.cxx
+++ b/vcl/source/filter/png/pngwrite.cxx
@@ -34,6 +34,7 @@
 #include <vcl/alpha.hxx>
 #include <osl/endian.h>
 #include <memory>
+#include <vcl/BitmapTools.hxx>
 
 #define PNG_DEF_COMPRESSION 6
 
@@ -100,7 +101,7 @@ private:
     void ImplWriteChunk(unsigned char const * pSource, sal_uInt32 nDatSize);
 };
 
-PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx,
+PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBitmapEx,
     const css::uno::Sequence<css::beans::PropertyValue>* pFilterData )
     : mnCompLevel(PNG_DEF_COMPRESSION)
     , mnInterlaced(0)
@@ -116,9 +117,21 @@ PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx,
     , mbTrueAlpha(false)
     , mnCRC(0)
 {
-    if (!rBmpEx.IsEmpty())
+    if (!rBitmapEx.IsEmpty())
     {
-        Bitmap aBmp(rBmpEx.GetBitmap());
+        BitmapEx aBitmapEx;
+
+        if (rBitmapEx.GetBitmap().GetBitCount() == 32)
+        {
+            if (!vcl::bitmap::convertBitmap32To24Plus8(rBitmapEx, aBitmapEx))
+                return;
+        }
+        else
+        {
+            aBitmapEx = rBitmapEx;
+        }
+
+        Bitmap aBmp(aBitmapEx.GetBitmap());
 
         mnMaxChunkSize = std::numeric_limits<sal_uInt32>::max();
 
@@ -141,9 +154,9 @@ PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx,
         }
         mnBitsPerPixel = static_cast<sal_uInt8>(aBmp.GetBitCount());
 
-        if (rBmpEx.IsTransparent())
+        if (aBitmapEx.IsTransparent())
         {
-            if (mnBitsPerPixel <= 8 && rBmpEx.IsAlpha())
+            if (mnBitsPerPixel <= 8 && aBitmapEx.IsAlpha())
             {
                 aBmp.Convert( BmpConversion::N24Bit );
                 mnBitsPerPixel = 24;
@@ -152,14 +165,14 @@ PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx,
             if (mnBitsPerPixel <= 8) // transparent palette
             {
                 aBmp.Convert(BmpConversion::N8BitTrans);
-                aBmp.Replace(rBmpEx.GetMask(), BMP_COL_TRANS);
+                aBmp.Replace(aBitmapEx.GetMask(), BMP_COL_TRANS);
                 mnBitsPerPixel = 8;
                 mpAccess = Bitmap::ScopedReadAccess(aBmp);
                 if (mpAccess)
                 {
                     if (ImplWriteHeader())
                     {
-                        ImplWritepHYs(rBmpEx);
+                        ImplWritepHYs(aBitmapEx);
                         ImplWritePalette();
                         ImplWriteTransparent();
                         ImplWriteIDAT();
@@ -176,16 +189,16 @@ PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx,
                 mpAccess = Bitmap::ScopedReadAccess(aBmp); // true RGB with alphachannel
                 if (mpAccess)
                 {
-                    mbTrueAlpha = rBmpEx.IsAlpha();
+                    mbTrueAlpha = aBitmapEx.IsAlpha();
                     if (mbTrueAlpha)
                     {
-                        AlphaMask aMask(rBmpEx.GetAlpha());
+                        AlphaMask aMask(aBitmapEx.GetAlpha());
                         mpMaskAccess = aMask.AcquireReadAccess();
                         if (mpMaskAccess)
                         {
                             if (ImplWriteHeader())
                             {
-                                ImplWritepHYs(rBmpEx);
+                                ImplWritepHYs(aBitmapEx);
                                 ImplWriteIDAT();
                             }
                             aMask.ReleaseAccess(mpMaskAccess);
@@ -198,13 +211,13 @@ PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx,
                     }
                     else
                     {
-                        Bitmap aMask(rBmpEx.GetMask());
+                        Bitmap aMask(aBitmapEx.GetMask());
                         mpMaskAccess = aMask.AcquireReadAccess();
                         if (mpMaskAccess)
                         {
                             if (ImplWriteHeader())
                             {
-                                ImplWritepHYs(rBmpEx);
+                                ImplWritepHYs(aBitmapEx);
                                 ImplWriteIDAT();
                             }
                             Bitmap::ReleaseAccess(mpMaskAccess);
@@ -230,7 +243,7 @@ PNGWriterImpl::PNGWriterImpl( const BitmapEx& rBmpEx,
             {
                 if (ImplWriteHeader())
                 {
-                    ImplWritepHYs(rBmpEx);
+                    ImplWritepHYs(aBitmapEx);
                     if (mpAccess->HasPalette())
                         ImplWritePalette();
 
diff --git a/vcl/source/gdi/bmpacc2.cxx b/vcl/source/gdi/bmpacc2.cxx
index 83865113234c..1b03e854ef48 100644
--- a/vcl/source/gdi/bmpacc2.cxx
+++ b/vcl/source/gdi/bmpacc2.cxx
@@ -19,6 +19,7 @@
 
 #include <vcl/salbtype.hxx>
 #include <vcl/bitmapaccess.hxx>
+#include <vcl/BitmapTools.hxx>
 
 BitmapColor BitmapReadAccess::GetPixelForN1BitMsbPal(ConstScanline pScanline, long nX, const ColorMask&)
 {
@@ -181,86 +182,110 @@ void BitmapReadAccess::SetPixelForN24BitTcRgb(Scanline pScanline, long nX, const
 
 BitmapColor BitmapReadAccess::GetPixelForN32BitTcAbgr(ConstScanline pScanline, long nX, const ColorMask&)
 {
-    BitmapColor aBitmapColor;
-
-    pScanline = pScanline + ( nX << 2 ) + 1;
-    aBitmapColor.SetBlue( *pScanline++ );
-    aBitmapColor.SetGreen( *pScanline++ );
-    aBitmapColor.SetRed( *pScanline );
-
-    return aBitmapColor;
+    pScanline = pScanline + nX * 4;
+
+    sal_uInt8 a = *pScanline++;
+    sal_uInt8 b = *pScanline++;
+    sal_uInt8 g = *pScanline++;
+    sal_uInt8 r = *pScanline;
+
+    return BitmapColor(
+            vcl::bitmap::unpremultiply(r, a),
+            vcl::bitmap::unpremultiply(g, a),
+            vcl::bitmap::unpremultiply(b, a),
+            0xFF - a);
 }
 
 void BitmapReadAccess::SetPixelForN32BitTcAbgr(Scanline pScanline, long nX, const BitmapColor& rBitmapColor, const ColorMask&)
 {
-    pScanline = pScanline + ( nX << 2 );
-    *pScanline++ = 0xFF;
-    *pScanline++ = rBitmapColor.GetBlue();
-    *pScanline++ = rBitmapColor.GetGreen();
-    *pScanline = rBitmapColor.GetRed();
+    pScanline = pScanline + nX * 4;
+
+    sal_uInt8 alpha = 0xFF - rBitmapColor.GetAlpha();
+    *pScanline++ = alpha;
+    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
+    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
+    *pScanline   = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
 }
 
 BitmapColor BitmapReadAccess::GetPixelForN32BitTcArgb(ConstScanline pScanline, long nX, const ColorMask&)
 {
-    BitmapColor aBitmapColor;
-
-    pScanline = pScanline + ( nX << 2 ) + 1;
-    aBitmapColor.SetRed( *pScanline++ );
-    aBitmapColor.SetGreen( *pScanline++ );
-    aBitmapColor.SetBlue( *pScanline );
-
-    return aBitmapColor;
+    pScanline = pScanline + nX * 4;
+
+    sal_uInt8 a = *pScanline++;
+    sal_uInt8 r = *pScanline++;
+    sal_uInt8 g = *pScanline++;
+    sal_uInt8 b = *pScanline;
+
+    return BitmapColor(
+            vcl::bitmap::unpremultiply(r, a),
+            vcl::bitmap::unpremultiply(g, a),
+            vcl::bitmap::unpremultiply(b, a),
+            0xFF - a);
 }
 
 void BitmapReadAccess::SetPixelForN32BitTcArgb(Scanline pScanline, long nX, const BitmapColor& rBitmapColor, const ColorMask&)
 {
-    pScanline = pScanline + ( nX << 2 );
-    *pScanline++ = 0xFF;
-    *pScanline++ = rBitmapColor.GetRed();
-    *pScanline++ = rBitmapColor.GetGreen();
-    *pScanline = rBitmapColor.GetBlue();
+    pScanline = pScanline + nX * 4;
+
+    sal_uInt8 alpha = 0xFF - rBitmapColor.GetAlpha();
+    *pScanline++ = alpha;
+    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
+    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
+    *pScanline   = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
 }
 
 BitmapColor BitmapReadAccess::GetPixelForN32BitTcBgra(ConstScanline pScanline, long nX, const ColorMask&)
 {
-    BitmapColor aBitmapColor;
-
-    pScanline = pScanline + ( nX << 2 );
-    aBitmapColor.SetBlue( *pScanline++ );
-    aBitmapColor.SetGreen( *pScanline++ );
-    aBitmapColor.SetRed( *pScanline );
-
-    return aBitmapColor;
+    pScanline = pScanline + nX * 4;
+
+    sal_uInt8 b = *pScanline++;
+    sal_uInt8 g = *pScanline++;
+    sal_uInt8 r = *pScanline++;
+    sal_uInt8 a = *pScanline;
+
+    return BitmapColor(
+            vcl::bitmap::unpremultiply(r, a),
+            vcl::bitmap::unpremultiply(g, a),
+            vcl::bitmap::unpremultiply(b, a),
+            0xFF - a);
 }
 
 void BitmapReadAccess::SetPixelForN32BitTcBgra(Scanline pScanline, long nX, const BitmapColor& rBitmapColor, const ColorMask&)
 {
-    pScanline = pScanline + ( nX << 2 );
-    *pScanline++ = rBitmapColor.GetBlue();
-    *pScanline++ = rBitmapColor.GetGreen();
-    *pScanline++ = rBitmapColor.GetRed();
-    *pScanline = 0xFF;
+    pScanline = pScanline + nX * 4;
+
+    sal_uInt8 alpha = 0xFF - rBitmapColor.GetAlpha();
+    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
+    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
+    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
+    *pScanline = alpha;
 }
 
 BitmapColor BitmapReadAccess::GetPixelForN32BitTcRgba(ConstScanline pScanline, long nX, const ColorMask&)
 {
-    BitmapColor aBitmapColor;
-
-    pScanline = pScanline + ( nX << 2 );
-    aBitmapColor.SetRed( *pScanline++ );
-    aBitmapColor.SetGreen( *pScanline++ );
-    aBitmapColor.SetBlue( *pScanline );
-
-    return aBitmapColor;
+    pScanline = pScanline + nX * 4;
+
+    sal_uInt8 r = *pScanline++;
+    sal_uInt8 g = *pScanline++;
+    sal_uInt8 b = *pScanline++;
+    sal_uInt8 a = *pScanline;
+
+    return BitmapColor(
+            vcl::bitmap::unpremultiply(r, a),
+            vcl::bitmap::unpremultiply(g, a),
+            vcl::bitmap::unpremultiply(b, a),
+            0xFF - a);
 }
 
 void BitmapReadAccess::SetPixelForN32BitTcRgba(Scanline pScanline, long nX, const BitmapColor& rBitmapColor, const ColorMask&)
 {
-    pScanline = pScanline + ( nX << 2 );
-    *pScanline++ = rBitmapColor.GetRed();
-    *pScanline++ = rBitmapColor.GetGreen();
-    *pScanline++ = rBitmapColor.GetBlue();
-    *pScanline = 0xFF;
+    pScanline = pScanline + nX * 4;
+
+    sal_uInt8 alpha = 0xFF - rBitmapColor.GetAlpha();
+    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetRed(), alpha);
+    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetGreen(), alpha);
+    *pScanline++ = vcl::bitmap::premultiply(rBitmapColor.GetBlue(), alpha);
+    *pScanline = alpha;
 }
 
 BitmapColor BitmapReadAccess::GetPixelForN32BitTcMask(ConstScanline pScanline, long nX, const ColorMask& rMask)


More information about the Libreoffice-commits mailing list