[Libreoffice-commits] core.git: framework/source include/vcl sd/qa sd/source sfx2/source sw/qa vcl/Library_vcl.mk vcl/qa vcl/source vcl/workben

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Fri Mar 12 14:38:17 UTC 2021


 framework/source/uiconfiguration/imagemanagerimpl.cxx  |    6 
 include/vcl/filter/PngImageReader.hxx                  |    4 
 include/vcl/pngread.hxx                                |   59 
 sd/qa/unit/export-tests-ooxml1.cxx                     |    6 
 sd/qa/unit/import-tests.cxx                            |   16 
 sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx |    6 
 sfx2/source/control/recentdocsview.cxx                 |    6 
 sfx2/source/control/thumbnailview.cxx                  |    6 
 sw/qa/extras/ooxmlexport/ooxmlexport10.cxx             |    6 
 vcl/Library_vcl.mk                                     |    1 
 vcl/source/app/brand.cxx                               |    7 
 vcl/source/filter/graphicfilter.cxx                    |   70 
 vcl/source/filter/png/PngImageReader.cxx               |    7 
 vcl/source/filter/png/pngread.cxx                      | 1708 -----------------
 vcl/source/treelist/transfer.cxx                       |    7 
 vcl/workben/fftester.cxx                               |    6 
 vcl/workben/pngfuzzer.cxx                              |    6 
 vcl/workben/vcldemo.cxx                                |    1 
 18 files changed, 63 insertions(+), 1865 deletions(-)

New commits:
commit e1d0846e060d2b3faedfe1a5877303037d8cf4d6
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Fri Mar 5 19:55:43 2021 +0100
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Fri Mar 12 15:37:21 2021 +0100

    drop PNGReader and use only PngImageReader
    
    PNGReader is a home-made PNG reader that does not use libpng,
    so it's more code, presumably less optimized and it apparently also
    doesn't always map colors properly.
    The only two features it has that PngImageReader doesn't are explicit
    chunk reading (used only for reading Microsoft's GIF in PNG, I
    implemented that for PngImageReader in a previous commit), and it
    loads paletted images as BitmapEx with a palette instead of
    converting to direct-color 24/32bpp or 8bpp-gray. The latter is even
    questional if nowadays that's feature or a misfeature, as it saves
    memory at the expense of speed. I can implement that if somebody
    misses it.
    I had to adjust some tests:
    - CVE-2016-0952-1.png - invalid CRC of the PNG header, neither Gimp
      nor Gwenview can display that, it should fail
    - afl-sample-Z_NEED_DICT.png - failure while decompressing data,
      but the loader considers that only a partially broken image since
      the header is correct, so it "passes" (like in Gimp or Gwenview)
    - SdImportTest::testTdf134210() and
      testPictureWithSchemeColor::Load_Verify_Reload_Verify()
      need the colors tested changed, because apparently gamma correction
      or something is now applied correctly, and it wasn't before (again
      checked the loaded images with Gimp)
    
    Change-Id: Id46f8d8a01256daf48ca64264b47c4e609183837
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/112042
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/framework/source/uiconfiguration/imagemanagerimpl.cxx b/framework/source/uiconfiguration/imagemanagerimpl.cxx
index 64cf3a53342c..8b7733aac91e 100644
--- a/framework/source/uiconfiguration/imagemanagerimpl.cxx
+++ b/framework/source/uiconfiguration/imagemanagerimpl.cxx
@@ -42,7 +42,7 @@
 #include <osl/mutex.hxx>
 #include <comphelper/sequence.hxx>
 #include <unotools/ucbstreamhelper.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
 #include <vcl/pngwrite.hxx>
 #include <rtl/instance.hxx>
 #include <memory>
@@ -333,8 +333,8 @@ void ImageManagerImpl::implts_loadUserImages(
                     BitmapEx aUserBitmap;
                     {
                         std::unique_ptr<SvStream> pSvStream(utl::UcbStreamHelper::CreateStream( xBitmapStream ));
-                        vcl::PNGReader aPngReader( *pSvStream );
-                        aUserBitmap = aPngReader.Read();
+                        vcl::PngImageReader aPngReader( *pSvStream );
+                        aUserBitmap = aPngReader.read();
                     }
 
                     // Delete old image list and create a new one from the read bitmap
diff --git a/include/vcl/filter/PngImageReader.hxx b/include/vcl/filter/PngImageReader.hxx
index 2cd57549cf49..2615fd961bd4 100644
--- a/include/vcl/filter/PngImageReader.hxx
+++ b/include/vcl/filter/PngImageReader.hxx
@@ -33,7 +33,11 @@ class VCL_DLLPUBLIC PngImageReader
 public:
     PngImageReader(SvStream& rStream);
 
+    // Returns true if image was successfully read without errors.
+    // A usable bitmap may be returned even if there were errors (e.g. incomplete image).
     bool read(BitmapEx& rBitmap);
+    // Returns a bitmap without indicating if there were errors.
+    BitmapEx read();
 
     // Returns the contents of the msOG chunk (containing a Gif image), if it exists.
     // Does not change position in the stream.
diff --git a/include/vcl/pngread.hxx b/include/vcl/pngread.hxx
deleted file mode 100644
index d3fa1942ee57..000000000000
--- a/include/vcl/pngread.hxx
+++ /dev/null
@@ -1,59 +0,0 @@
-/* -*- 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/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#ifndef INCLUDED_VCL_PNGREAD_HXX
-#define INCLUDED_VCL_PNGREAD_HXX
-
-#include <vcl/dllapi.h>
-#include <vcl/bitmapex.hxx>
-#include <memory>
-#include <vector>
-
-namespace vcl
-{
-class PNGReaderImpl;
-
-class VCL_DLLPUBLIC PNGReader
-{
-    std::unique_ptr<PNGReaderImpl> mpImpl;
-
-public:
-    /* the PNG chunks are read within the c'tor, so the stream will
-    be positioned at the end of the PNG */
-    explicit PNGReader(SvStream& rStream);
-    ~PNGReader();
-
-    /* an empty preview size hint (=default) will read the whole image
-    */
-    BitmapEx Read();
-
-    // retrieve every chunk that resides inside the PNG
-    struct ChunkData
-    {
-        sal_uInt32 nType = 0;
-        std::vector<sal_uInt8> aData;
-    };
-    const std::vector<ChunkData>& GetChunks() const;
-};
-
-} // end namespace vcl
-
-#endif // INCLUDED_VCL_PNGREAD_HXX
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sd/qa/unit/export-tests-ooxml1.cxx b/sd/qa/unit/export-tests-ooxml1.cxx
index 1e5f673428c2..4972669e4b82 100644
--- a/sd/qa/unit/export-tests-ooxml1.cxx
+++ b/sd/qa/unit/export-tests-ooxml1.cxx
@@ -54,7 +54,7 @@
 #include <svx/svdotable.hxx>
 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
 #include <rtl/uri.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
 
 using namespace css;
 
@@ -1344,8 +1344,8 @@ void SdOOXMLExportTest1::testNarrationMimeType()
     OUString aImageRelName;
     CPPUNIT_ASSERT(aImageAbsName.startsWith("file:///", &aImageRelName));
     std::unique_ptr<SvStream> pImageStream = parseExportStream(aTempFile, aImageRelName);
-    vcl::PNGReader aReader(*pImageStream);
-    BitmapEx aBitmapEx = aReader.Read();
+    vcl::PngImageReader aReader(*pImageStream);
+    BitmapEx aBitmapEx = aReader.read();
     // Without the accompanying fix in place, this test would have failed with:
     // - Expected: 256
     // - Actual  : 120
diff --git a/sd/qa/unit/import-tests.cxx b/sd/qa/unit/import-tests.cxx
index 12560e90d586..cce54cb16e4f 100644
--- a/sd/qa/unit/import-tests.cxx
+++ b/sd/qa/unit/import-tests.cxx
@@ -92,7 +92,7 @@
 #include <comphelper/sequenceashashmap.hxx>
 #include <comphelper/graphicmimetype.hxx>
 #include <comphelper/lok.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
 #include <vcl/BitmapReadAccess.hxx>
 #include <vcl/dibtools.hxx>
 #include <svx/svdograf.hxx>
@@ -1614,8 +1614,8 @@ void SdImportTest::testTdf113163()
     xGraphicExporter->filter(aDescriptor);
 
     SvFileStream aFileStream(aTempFile.GetURL(), StreamMode::READ);
-    vcl::PNGReader aPNGReader(aFileStream);
-    BitmapEx aBMPEx = aPNGReader.Read();
+    vcl::PngImageReader aPNGReader(aFileStream);
+    BitmapEx aBMPEx = aPNGReader.read();
 
     // make sure the bitmap is not empty and correct size (PNG export->import was successful)
     CPPUNIT_ASSERT_EQUAL(Size(100, 100), aBMPEx.GetSizePixel());
@@ -1665,8 +1665,8 @@ void SdImportTest::testTdf93124()
     xGraphicExporter->filter(aDescriptor);
 
     SvFileStream aFileStream(aTempFile.GetURL(), StreamMode::READ);
-    vcl::PNGReader aPNGReader(aFileStream);
-    BitmapEx aBMPEx = aPNGReader.Read();
+    vcl::PngImageReader aPNGReader(aFileStream);
+    BitmapEx aBMPEx = aPNGReader.read();
 
     // make sure the bitmap is not empty and correct size (PNG export->import was successful)
     CPPUNIT_ASSERT_EQUAL(Size(320, 180), aBMPEx.GetSizePixel());
@@ -1730,8 +1730,8 @@ void SdImportTest::testTdf99729()
         xGraphicExporter->filter(aDescriptor);
 
         SvFileStream aFileStream(aTempFile.GetURL(), StreamMode::READ);
-        vcl::PNGReader aPNGReader(aFileStream);
-        BitmapEx aBMPEx = aPNGReader.Read();
+        vcl::PngImageReader aPNGReader(aFileStream);
+        BitmapEx aBMPEx = aPNGReader.read();
         Bitmap aBMP = aBMPEx.GetBitmap();
         Bitmap::ScopedReadAccess pRead(aBMP);
         for (tools::Long nX = 154; nX < (154 + 12); ++nX)
@@ -2768,7 +2768,7 @@ void SdImportTest::testTdf134210()
 
     Graphic aGraphic(xGraphic);
     BitmapEx aBitmap(aGraphic.GetBitmapEx());
-    CPPUNIT_ASSERT_EQUAL( Color(6708292), aBitmap.GetPixelColor( 0, 0 ));
+    CPPUNIT_ASSERT_EQUAL( Color(6313534), aBitmap.GetPixelColor( 0, 0 ));
 
     xDocShRef->DoClose();
 }
diff --git a/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx
index 04b99dbf6c15..d4da935ddd0c 100644
--- a/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx
+++ b/sd/source/ui/slidesorter/cache/SlsBitmapCompressor.cxx
@@ -21,7 +21,7 @@
 
 #include <tools/stream.hxx>
 #include <vcl/bitmapex.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
 #include <vcl/pngwrite.hxx>
 
 namespace sd::slidesorter::cache {
@@ -180,8 +180,8 @@ BitmapEx PngCompression::Decompress (
     if (pData != nullptr)
     {
         SvMemoryStream aStream (pData->mpData, pData->mnDataSize, StreamMode::READ);
-        vcl::PNGReader aReader (aStream);
-        aResult = aReader.Read().GetBitmap();
+        vcl::PngImageReader aReader (aStream);
+        aResult = aReader.read().GetBitmap();
     }
 
     return aResult;
diff --git a/sfx2/source/control/recentdocsview.cxx b/sfx2/source/control/recentdocsview.cxx
index d137d366837c..ca822d0c3487 100644
--- a/sfx2/source/control/recentdocsview.cxx
+++ b/sfx2/source/control/recentdocsview.cxx
@@ -24,7 +24,7 @@
 #include <tools/diagnose_ex.h>
 #include <unotools/historyoptions.hxx>
 #include <vcl/event.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
 #include <vcl/ptrstyle.hxx>
 #include <vcl/svapp.hxx>
 #include <tools/stream.hxx>
@@ -264,8 +264,8 @@ void RecentDocsView::Reload()
                     comphelper::Base64::decode(aDecoded, aBase64);
 
                     SvMemoryStream aStream(aDecoded.getArray(), aDecoded.getLength(), StreamMode::READ);
-                    vcl::PNGReader aReader(aStream);
-                    aThumbnail = aReader.Read();
+                    vcl::PngImageReader aReader(aStream);
+                    aThumbnail = aReader.read();
                 } else
                 {
                     INetURLObject aUrl(aURL);
diff --git a/sfx2/source/control/thumbnailview.cxx b/sfx2/source/control/thumbnailview.cxx
index 071e73f54c9c..f9624027755e 100644
--- a/sfx2/source/control/thumbnailview.cxx
+++ b/sfx2/source/control/thumbnailview.cxx
@@ -30,7 +30,7 @@
 #include <vcl/svapp.hxx>
 #include <vcl/settings.hxx>
 #include <vcl/event.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
 
 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
 #include <com/sun/star/embed/ElementModes.hpp>
@@ -138,8 +138,8 @@ BitmapEx ThumbnailView::readThumbnail(const OUString &msURL)
     {
         std::unique_ptr<SvStream> pStream (
             ::utl::UcbStreamHelper::CreateStream (xIStream));
-        vcl::PNGReader aReader (*pStream);
-        aThumbnail = aReader.Read ();
+        vcl::PngImageReader aReader (*pStream);
+        aThumbnail = aReader.read ();
     }
 
     // Note that the preview is returned without scaling it to the desired
diff --git a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
index 45f9a46000e1..c33f99cb4322 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlexport10.cxx
@@ -453,10 +453,8 @@ DECLARE_OOXMLEXPORT_TEST(testPictureWithSchemeColor, "picture-with-schemecolor.d
     BitmapEx aBitmap(aVclGraphic.GetBitmapEx());
     CPPUNIT_ASSERT_EQUAL(tools::Long(341), aBitmap.GetSizePixel().Width());
     CPPUNIT_ASSERT_EQUAL(tools::Long(181), aBitmap.GetSizePixel().Height());
-    Color aColor(aBitmap.GetPixelColor(120, 30));
-    CPPUNIT_ASSERT_EQUAL(aColor, Color( 0xb1, 0xc8, 0xdd ));
-    aColor = aBitmap.GetPixelColor(260, 130);
-    CPPUNIT_ASSERT_EQUAL(aColor, Color( 0xb1, 0xc8, 0xdd ));
+    CPPUNIT_ASSERT_EQUAL(Color( 0xad, 0xc5, 0xdb ), aBitmap.GetPixelColor(120, 30));
+    CPPUNIT_ASSERT_EQUAL(Color( 0xad, 0xc5, 0xdb ), aBitmap.GetPixelColor(260, 130));
 }
 
 DECLARE_OOXMLEXPORT_TEST(testFdo69656, "Table_cell_auto_width_fdo69656.docx")
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 00c2971df58a..17ddf83fe961 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -476,7 +476,6 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/filter/wmf/wmfexternal \
     vcl/source/filter/wmf/wmfwr \
     vcl/source/filter/png/PngImageReader \
-    vcl/source/filter/png/pngread \
     vcl/source/filter/png/pngwrite \
     vcl/source/font/Feature \
     vcl/source/font/FeatureCollector \
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/pass/CVE-2016-0952-1.png b/vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0952-1.png
similarity index 100%
rename from vcl/qa/cppunit/graphicfilter/data/png/pass/CVE-2016-0952-1.png
rename to vcl/qa/cppunit/graphicfilter/data/png/fail/CVE-2016-0952-1.png
diff --git a/vcl/qa/cppunit/graphicfilter/data/png/fail/afl-sample-Z_NEED_DICT.png b/vcl/qa/cppunit/graphicfilter/data/png/pass/afl-sample-Z_NEED_DICT.png
similarity index 100%
rename from vcl/qa/cppunit/graphicfilter/data/png/fail/afl-sample-Z_NEED_DICT.png
rename to vcl/qa/cppunit/graphicfilter/data/png/pass/afl-sample-Z_NEED_DICT.png
diff --git a/vcl/source/app/brand.cxx b/vcl/source/app/brand.cxx
index 269d141de3fe..ed4cccff4031 100644
--- a/vcl/source/app/brand.cxx
+++ b/vcl/source/app/brand.cxx
@@ -29,7 +29,8 @@
 #include <tools/urlobj.hxx>
 #include <tools/stream.hxx>
 #include <i18nlangtag/languagetag.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
+#include <vcl/bitmapex.hxx>
 #include <vcl/svapp.hxx>
 
 namespace {
@@ -38,8 +39,8 @@ namespace {
         INetURLObject aObj( rPath );
         SvFileStream aStrm( aObj.PathToFileName(), StreamMode::STD_READ );
         if ( !aStrm.GetError() ) {
-            vcl::PNGReader aReader( aStrm );
-            rBitmap = aReader.Read();
+            vcl::PngImageReader aReader( aStrm );
+            rBitmap = aReader.read();
             return !rBitmap.IsEmpty();
         }
         else
diff --git a/vcl/source/filter/graphicfilter.cxx b/vcl/source/filter/graphicfilter.cxx
index f6349d9923a9..e482f0f5d213 100644
--- a/vcl/source/filter/graphicfilter.cxx
+++ b/vcl/source/filter/graphicfilter.cxx
@@ -32,7 +32,7 @@
 #include <vcl/dibtools.hxx>
 #include <fltcall.hxx>
 #include <vcl/salctype.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
 #include <vcl/pngwrite.hxx>
 #include <vcl/vectorgraphicdata.hxx>
 #include <vcl/virdev.hxx>
@@ -87,8 +87,6 @@
 #include <graphic/GraphicFormatDetector.hxx>
 #include <graphic/GraphicReader.hxx>
 
-#define PMGCHUNG_msOG       0x6d734f47      // Microsoft Office Animated GIF
-
 typedef ::std::vector< GraphicFilter* > FilterList_impl;
 static FilterList_impl* pFilterHdlList = nullptr;
 
@@ -755,35 +753,12 @@ Graphic GraphicFilter::ImportUnloadedGraphic(SvStream& rIStream, sal_uInt64 size
         }
         else if (aFilterName.equalsIgnoreAsciiCase(IMP_PNG))
         {
-            vcl::PNGReader aPNGReader(rIStream);
-
             // check if this PNG contains a GIF chunk!
-            const std::vector<vcl::PNGReader::ChunkData>& rChunkData = aPNGReader.GetChunks();
-            for (auto const& chunk : rChunkData)
-            {
-                // Microsoft Office is storing Animated GIFs in following chunk
-                if (chunk.nType == PMGCHUNG_msOG)
-                {
-                    sal_uInt32 nChunkSize = chunk.aData.size();
-
-                    if (nChunkSize > 11)
-                    {
-                        const std::vector<sal_uInt8>& rData = chunk.aData;
-                        nGraphicContentSize = nChunkSize - 11;
-                        SvMemoryStream aIStrm(const_cast<sal_uInt8*>(&rData[11]), nGraphicContentSize, StreamMode::READ);
-                        pGraphicContent.reset(new sal_uInt8[nGraphicContentSize]);
-                        sal_uInt64 aCurrentPosition = aIStrm.Tell();
-                        aIStrm.ReadBytes(pGraphicContent.get(), nGraphicContentSize);
-                        aIStrm.Seek(aCurrentPosition);
-                        eLinkType = GfxLinkType::NativeGif;
-                        break;
-                    }
-                }
-            }
-            if (eLinkType == GfxLinkType::NONE)
-            {
+            pGraphicContent = vcl::PngImageReader::getMicrosoftGifChunk(rIStream, &nGraphicContentSize);
+            if( pGraphicContent )
+                eLinkType = GfxLinkType::NativeGif;
+            else
                 eLinkType = GfxLinkType::NativePng;
-            }
         }
         else if (aFilterName.equalsIgnoreAsciiCase(IMP_JPEG))
         {
@@ -955,36 +930,19 @@ ErrCode GraphicFilter::readPNG(SvStream & rStream, Graphic & rGraphic, GfxLinkTy
 {
     ErrCode aReturnCode = ERRCODE_NONE;
 
-    vcl::PNGReader aPNGReader(rStream);
+    // check if this PNG contains a GIF chunk!
+    rpGraphicContent = vcl::PngImageReader::getMicrosoftGifChunk(rStream, &rGraphicContentSize);
+    if( rpGraphicContent )
     {
-        // check if this PNG contains a GIF chunk!
-        const std::vector<vcl::PNGReader::ChunkData>& rChunkData = aPNGReader.GetChunks();
-        for (auto const& chunk : rChunkData)
-        {
-            // Microsoft Office is storing Animated GIFs in following chunk
-            if (chunk.nType == PMGCHUNG_msOG)
-            {
-                sal_uInt32 nChunkSize = chunk.aData.size();
-
-                if (nChunkSize > 11)
-                {
-                    const std::vector<sal_uInt8>& rData = chunk.aData;
-                    rGraphicContentSize = nChunkSize - 11;
-                    SvMemoryStream aIStrm(const_cast<sal_uInt8*>(&rData[11]), rGraphicContentSize, StreamMode::READ);
-                    rpGraphicContent.reset(new sal_uInt8[rGraphicContentSize]);
-                    sal_uInt64 aCurrentPosition = aIStrm.Tell();
-                    aIStrm.ReadBytes(rpGraphicContent.get(), rGraphicContentSize);
-                    aIStrm.Seek(aCurrentPosition);
-                    ImportGIF(aIStrm, rGraphic);
-                    rLinkType = GfxLinkType::NativeGif;
-                    return aReturnCode;
-                }
-            }
-        }
+        SvMemoryStream aIStrm(rpGraphicContent.get(), rGraphicContentSize, StreamMode::READ);
+        ImportGIF(aIStrm, rGraphic);
+        rLinkType = GfxLinkType::NativeGif;
+        return aReturnCode;
     }
 
     // PNG has no GIF chunk
-    BitmapEx aBitmapEx(aPNGReader.Read());
+    vcl::PngImageReader aPNGReader(rStream);
+    BitmapEx aBitmapEx(aPNGReader.read());
     if (!aBitmapEx.IsEmpty())
     {
         rGraphic = aBitmapEx;
diff --git a/vcl/source/filter/png/PngImageReader.cxx b/vcl/source/filter/png/PngImageReader.cxx
index 829f3dd45bca..1f1b632bbd0d 100644
--- a/vcl/source/filter/png/PngImageReader.cxx
+++ b/vcl/source/filter/png/PngImageReader.cxx
@@ -425,6 +425,13 @@ bool PngImageReader::read(BitmapEx& rBitmapEx)
     return reader(mrStream, rBitmapEx, bSupportsBitmap32);
 }
 
+BitmapEx PngImageReader::read()
+{
+    BitmapEx bitmap;
+    read(bitmap);
+    return bitmap;
+}
+
 std::unique_ptr<sal_uInt8[]> PngImageReader::getMicrosoftGifChunk(SvStream& rStream,
                                                                   sal_Int32* chunkSize)
 {
diff --git a/vcl/source/filter/png/pngread.cxx b/vcl/source/filter/png/pngread.cxx
deleted file mode 100644
index 8b3f777c6ac5..000000000000
--- a/vcl/source/filter/png/pngread.cxx
+++ /dev/null
@@ -1,1708 +0,0 @@
-/* -*- 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/.
- *
- * This file incorporates work covered by the following license notice:
- *
- *   Licensed to the Apache Software Foundation (ASF) under one or more
- *   contributor license agreements. See the NOTICE file distributed
- *   with this work for additional information regarding copyright
- *   ownership. The ASF licenses this file to you under the Apache
- *   License, Version 2.0 (the "License"); you may not use this file
- *   except in compliance with the License. You may obtain a copy of
- *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#include <sal/config.h>
-#include <sal/log.hxx>
-#include <o3tl/safeint.hxx>
-#include <osl/diagnose.h>
-
-#include <cassert>
-#include <memory>
-#include <unotools/configmgr.hxx>
-#include <vcl/pngread.hxx>
-
-#include <cmath>
-#include <rtl/crc.h>
-#include <tools/zcodec.hxx>
-#include <tools/stream.hxx>
-#include <vcl/alpha.hxx>
-#include <osl/endian.h>
-
-#include <bitmap/BitmapWriteAccess.hxx>
-
-namespace vcl
-{
-
-#define PNGCHUNK_IHDR       0x49484452
-#define PNGCHUNK_PLTE       0x504c5445
-#define PNGCHUNK_IDAT       0x49444154
-#define PNGCHUNK_IEND       0x49454e44
-#define PNGCHUNK_bKGD       0x624b4744
-#define PNGCHUNK_gAMA       0x67414d41
-#define PNGCHUNK_pHYs       0x70485973
-#define PNGCHUNK_tRNS       0x74524e53
-
-#define VIEWING_GAMMA       2.35
-#define DISPLAY_GAMMA       1.0
-
-
-const sal_uInt8 mpDefaultColorTable[ 256 ] =
-{   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
-    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
-    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-    0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
-    0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
-    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
-    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
-    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
-    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
-    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
-    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
-    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
-    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
-    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
-};
-
-class PNGReaderImpl
-{
-private:
-    SvStream&           mrPNGStream;
-    SvStreamEndian      mnOrigStreamMode;
-
-    std::vector<vcl::PNGReader::ChunkData> maChunkSeq;
-    std::vector<vcl::PNGReader::ChunkData>::iterator maChunkIter;
-    std::vector<sal_uInt8>::iterator maDataIter;
-
-    std::unique_ptr<Bitmap>    mpBmp;
-    BitmapScopedWriteAccess  mxAcc;
-    std::unique_ptr<Bitmap>    mpMaskBmp;
-    BitmapScopedWriteAccess    mxMaskAcc;
-    std::unique_ptr<AlphaMask> mpAlphaMask;
-    AlphaScopedWriteAccess     mxAlphaAcc;
-    BitmapWriteAccess*         mpMaskAcc;
-
-    ZCodec              mpZCodec;
-    std::unique_ptr<sal_uInt8[]>
-                        mpInflateInBuf; // as big as the size of a scanline + alphachannel + 1
-    std::unique_ptr<sal_uInt8[]>
-                        mpScanPrior;    // pointer to the latest scanline
-    std::unique_ptr<sal_uInt8[]>
-                        mpTransTab;     // for transparency in images with palette colortype
-    sal_uInt8*          mpScanCurrent;  // pointer into the current scanline
-    sal_uInt8*          mpColorTable;
-    std::size_t         mnStreamSize;   // estimate of PNG file size
-    sal_uInt32          mnChunkType;    // Type of current PNG chunk
-    sal_Int32           mnChunkLen;     // Length of current PNG chunk
-    Size                maOrigSize;     // pixel size of the full image
-    Size                maTargetSize;   // pixel size of the result image
-    Size                maPhysSize;     // preferred size in MapUnit::Map100thMM units
-    sal_uInt32          mnBPP;          // number of bytes per pixel
-    sal_uInt32          mnScansize;     // max size of scanline
-    sal_uInt32          mnYpos;         // latest y position in full image
-    int                 mnPass;         // if interlaced the latest pass ( 1..7 ) else 7
-    sal_uInt32          mnXStart;       // the starting X for the current pass
-    sal_uInt32          mnXAdd;         // the increment for input images X coords for the current pass
-    sal_uInt32          mnYAdd;         // the increment for input images Y coords for the current pass
-    int                 mnPreviewShift; // shift to convert orig image coords into preview image coords
-    int                 mnPreviewMask;  // == ((1 << mnPreviewShift) - 1)
-    sal_uInt16          mnTargetDepth;      // pixel depth of target bitmap
-    sal_uInt8           mnTransRed;
-    sal_uInt8           mnTransGreen;
-    sal_uInt8           mnTransBlue;
-    sal_uInt8           mnPngDepth;     // pixel depth of PNG data
-    sal_uInt8           mnColorType;
-    sal_uInt8           mnCompressionType;
-    sal_uInt8           mnFilterType;
-    sal_uInt8           mnInterlaceType;
-    const BitmapColor   mcTranspColor;  // transparency mask's transparency "color"
-    const BitmapColor   mcOpaqueColor;  // transparency mask's opaque "color"
-    bool                mbTransparent : 1;  // graphic includes a tRNS Chunk or an alpha Channel
-    bool                mbAlphaChannel : 1; // is true for ColorType 4 and 6
-    bool                mbRGBTriple : 1;
-    bool                mbPalette : 1;      // false if we need a Palette
-    bool                mbGrayScale : 1;
-    bool                mbzCodecInUse : 1;
-    bool                mbStatus : 1;
-    bool                mbIDATStarted : 1;  // true if IDAT seen
-    bool                mbIDATComplete : 1; // true if finished with enough IDAT chunks
-    bool                mbpHYs : 1;         // true if physical size of pixel available
-    bool                mbIgnoreCRC : 1; // skip checking CRCs while fuzzing
-
-#if OSL_DEBUG_LEVEL > 0
-    // do some checks in debug mode
-    sal_Int32           mnAllocSizeScanline;
-    sal_Int32           mnAllocSizeScanlineAlpha;
-#endif
-    // the temporary Scanline (and alpha) for direct scanline copy to Bitmap
-    std::unique_ptr<sal_uInt8[]>
-                        mpScanline;
-    std::unique_ptr<sal_uInt8[]>
-                        mpScanlineAlpha;
-
-    bool                ReadNextChunk();
-
-    void                ImplSetPixel( sal_uInt32 y, sal_uInt32 x, const BitmapColor & );
-    void                ImplSetPixel( sal_uInt32 y, sal_uInt32 x, sal_uInt8 nPalIndex );
-    void                ImplSetTranspPixel( sal_uInt32 y, sal_uInt32 x, const BitmapColor &, bool bTrans );
-    void                ImplSetAlphaPixel( sal_uInt32 y, sal_uInt32 x, sal_uInt8 nPalIndex, sal_uInt8 nAlpha );
-    void                ImplSetAlphaPixel( sal_uInt32 y, sal_uInt32 x, const BitmapColor&, sal_uInt8 nAlpha );
-    void                ImplReadIDAT();
-    bool                ImplPreparePass();
-    void                ImplApplyFilter();
-    void                ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd );
-    bool                ImplReadTransparent();
-    void                ImplGetGamma();
-    void                ImplGetBackground();
-    sal_uInt8           ImplScaleColor();
-    bool                ImplReadHeader();
-    bool                ImplReadPalette();
-    void                ImplGetGrayPalette( sal_uInt16 );
-    sal_uInt32          ImplReadsal_uInt32();
-
-public:
-
-    explicit PNGReaderImpl( SvStream& );
-    ~PNGReaderImpl();
-
-    BitmapEx            GetBitmapEx();
-    const std::vector<vcl::PNGReader::ChunkData>& GetAllChunks();
-};
-
-PNGReaderImpl::PNGReaderImpl( SvStream& rPNGStream )
-:   mrPNGStream( rPNGStream ),
-    mpMaskAcc       ( nullptr ),
-    mpScanCurrent   ( nullptr ),
-    mpColorTable    ( const_cast<sal_uInt8*>(mpDefaultColorTable) ),
-    mnChunkType     ( 0 ),
-    mnChunkLen      ( 0 ),
-    mnBPP           ( 0 ),
-    mnScansize      ( 0 ),
-    mnYpos          ( 0 ),
-    mnPass          ( 0 ),
-    mnXStart        ( 0 ),
-    mnXAdd          ( 0 ),
-    mnYAdd          ( 0 ),
-    mnTargetDepth   ( 0 ),
-    mnTransRed      ( 0 ),
-    mnTransGreen    ( 0 ),
-    mnTransBlue     ( 0 ),
-    mnPngDepth      ( 0 ),
-    mnColorType     ( 0 ),
-    mnCompressionType( 0 ),
-    mnFilterType    ( 0 ),
-    mnInterlaceType ( 0 ),
-    mcTranspColor   ( BitmapColor( 0xFF )),
-    mcOpaqueColor   ( BitmapColor( 0x00 )),
-    mbTransparent( false ),
-    mbAlphaChannel( false ),
-    mbRGBTriple( false ),
-    mbPalette( false ),
-    mbGrayScale( false ),
-    mbzCodecInUse   ( false ),
-    mbStatus( true ),
-    mbIDATStarted( false ),
-    mbIDATComplete( false ),
-    mbpHYs              ( false ),
-    mbIgnoreCRC( utl::ConfigManager::IsFuzzing() )
-#if OSL_DEBUG_LEVEL > 0
-    ,mnAllocSizeScanline(0),
-    mnAllocSizeScanlineAlpha(0)
-#endif
-{
-    // prepare the PNG data stream
-    mnOrigStreamMode = mrPNGStream.GetEndian();
-    mrPNGStream.SetEndian( SvStreamEndian::BIG );
-
-    // prepare the chunk reader
-    maChunkSeq.reserve( 16 );
-    maChunkIter = maChunkSeq.begin();
-
-    // estimate PNG file size (to allow sanity checks)
-    mnStreamSize = mrPNGStream.TellEnd();
-
-    // check the PNG header magic
-    sal_uInt32 nDummy = 0;
-    mrPNGStream.ReadUInt32( nDummy );
-    mbStatus = (nDummy == 0x89504e47);
-    mrPNGStream.ReadUInt32( nDummy );
-    mbStatus = (nDummy == 0x0d0a1a0a) && mbStatus;
-
-    mnPreviewShift = 0;
-    mnPreviewMask = (1 << mnPreviewShift) - 1;
-}
-
-PNGReaderImpl::~PNGReaderImpl()
-{
-    mrPNGStream.SetEndian( mnOrigStreamMode );
-
-    if ( mbzCodecInUse )
-        mpZCodec.EndCompression();
-
-    if( mpColorTable != mpDefaultColorTable )
-        delete[] mpColorTable;
-}
-
-bool PNGReaderImpl::ReadNextChunk()
-{
-    if( maChunkIter == maChunkSeq.end() )
-    {
-        // get the next chunk from the stream
-
-        // unless we are at the end of the PNG stream
-        if (!mrPNGStream.good() || mrPNGStream.remainingSize() < 8)
-            return false;
-        if( !maChunkSeq.empty() && (maChunkSeq.back().nType == PNGCHUNK_IEND) )
-            return false;
-
-        PNGReader::ChunkData aDummyChunk;
-        maChunkIter = maChunkSeq.insert( maChunkSeq.end(), aDummyChunk );
-        PNGReader::ChunkData& rChunkData = *maChunkIter;
-
-        // read the chunk header
-        mnChunkLen = 0;
-        mnChunkType = 0;
-        mrPNGStream.ReadInt32( mnChunkLen ).ReadUInt32( mnChunkType );
-        rChunkData.nType = mnChunkType;
-
-        // fdo#61847 truncate over-long, trailing chunks
-        const std::size_t nStreamPos = mrPNGStream.Tell();
-        if( mnChunkLen < 0 || nStreamPos + mnChunkLen >= mnStreamSize )
-            mnChunkLen = mnStreamSize - nStreamPos;
-
-        // calculate chunktype CRC (swap it back to original byte order)
-        sal_uInt32 nChunkType = mnChunkType;
-        #if defined(__LITTLEENDIAN) || defined(OSL_LITENDIAN)
-        nChunkType = OSL_SWAPDWORD( nChunkType );
-        #endif
-        sal_uInt32 nCRC32 = rtl_crc32( 0, &nChunkType, 4 );
-
-        // read the chunk data and check the CRC
-        if( mnChunkLen && !mrPNGStream.eof() )
-        {
-            rChunkData.aData.resize( mnChunkLen );
-
-            sal_Int32 nBytesRead = 0;
-            do
-            {
-                sal_uInt8& rPtr = rChunkData.aData[nBytesRead];
-                nBytesRead += mrPNGStream.ReadBytes(&rPtr, mnChunkLen - nBytesRead);
-            } while (nBytesRead < mnChunkLen && mrPNGStream.good());
-
-            nCRC32 = rtl_crc32( nCRC32, rChunkData.aData.data(), mnChunkLen );
-            maDataIter = rChunkData.aData.begin();
-        }
-        sal_uInt32 nCheck(0);
-        mrPNGStream.ReadUInt32( nCheck );
-        if (!mbIgnoreCRC && nCRC32 != nCheck)
-            return false;
-    }
-    else
-    {
-        // the next chunk was already read
-        mnChunkType = (*maChunkIter).nType;
-        mnChunkLen = (*maChunkIter).aData.size();
-        maDataIter = (*maChunkIter).aData.begin();
-    }
-
-    ++maChunkIter;
-    return mnChunkType != PNGCHUNK_IEND;
-}
-
-const std::vector< vcl::PNGReader::ChunkData >& PNGReaderImpl::GetAllChunks()
-{
-    // read the remaining chunks from mrPNGStream
-    while( ReadNextChunk() ) ;
-    return maChunkSeq;
-}
-
-BitmapEx PNGReaderImpl::GetBitmapEx()
-{
-    // reset to the first chunk
-    maChunkIter = maChunkSeq.begin();
-
-    // first chunk must be IDHR
-    if( mbStatus && ReadNextChunk() )
-    {
-        if (mnChunkType == PNGCHUNK_IHDR)
-            mbStatus = ImplReadHeader();
-        else
-            mbStatus = false;
-    }
-
-    // parse the remaining chunks
-    while (mbStatus && !mbIDATComplete && ReadNextChunk())
-    {
-        switch( mnChunkType )
-        {
-            case PNGCHUNK_IHDR :
-            {
-                mbStatus = false; //IHDR should only appear as the first chunk
-            }
-            break;
-
-            case PNGCHUNK_gAMA :                                // the gamma chunk must precede
-            {                                                   // the 'IDAT' and also the 'PLTE'(if available )
-                if (!mbIDATComplete)
-                    ImplGetGamma();
-            }
-            break;
-
-            case PNGCHUNK_PLTE :
-            {
-                if (!mbPalette && !mbIDATStarted)
-                    mbStatus = ImplReadPalette();
-            }
-            break;
-
-            case PNGCHUNK_tRNS :
-            {
-                if (!mbIDATComplete)                            // the tRNS chunk must precede the IDAT
-                    mbStatus = ImplReadTransparent();
-            }
-            break;
-
-            case PNGCHUNK_bKGD :                                // the background chunk must appear
-            {
-                if (!mbIDATComplete && mbPalette)               // before the 'IDAT' and after the
-                    ImplGetBackground();                        // PLTE(if available ) chunk.
-            }
-            break;
-
-            case PNGCHUNK_IDAT :
-            {
-                if ( !mpInflateInBuf )  // taking care that the header has properly been read
-                    mbStatus = false;
-                else if (!mbIDATComplete) // the gfx is finished, but there may be left a zlibCRC of about 4Bytes
-                    ImplReadIDAT();
-            }
-            break;
-
-            case PNGCHUNK_pHYs :
-            {
-                if (!mbIDATComplete && mnChunkLen == 9)
-                {
-                    sal_uInt32 nXPixelPerMeter = ImplReadsal_uInt32();
-                    sal_uInt32 nYPixelPerMeter = ImplReadsal_uInt32();
-
-                    sal_uInt8 nUnitSpecifier = *maDataIter++;
-                    if( (nUnitSpecifier == 1) && nXPixelPerMeter && nYPixelPerMeter )
-                    {
-                        mbpHYs = true;
-
-                        // convert into MapUnit::Map100thMM
-                        maPhysSize.setWidth( static_cast<sal_Int32>( (100000.0 * maOrigSize.Width()) / nXPixelPerMeter ) );
-                        maPhysSize.setHeight( static_cast<sal_Int32>( (100000.0 * maOrigSize.Height()) / nYPixelPerMeter ) );
-                    }
-                }
-            }
-            break;
-
-            case PNGCHUNK_IEND:
-                mbStatus = mbIDATComplete;  // there is a problem if the image is not complete yet
-            break;
-        }
-    }
-
-    // release write access of the bitmaps
-    mxAcc.reset();
-    mxMaskAcc.reset();
-    mxAlphaAcc.reset();
-    mpMaskAcc = nullptr;
-
-    // return the resulting BitmapEx
-    BitmapEx aRet;
-
-    if (!mbStatus || !mbIDATComplete)
-        aRet.Clear();
-    else
-    {
-        if ( mpAlphaMask )
-            aRet = BitmapEx( *mpBmp, *mpAlphaMask );
-        else if ( mpMaskBmp )
-            aRet = BitmapEx( *mpBmp, *mpMaskBmp );
-        else
-            aRet = *mpBmp;
-
-        if ( mbpHYs && maPhysSize.Width() && maPhysSize.Height() )
-        {
-            aRet.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
-            aRet.SetPrefSize( maPhysSize );
-        }
-    }
-    return aRet;
-}
-
-bool PNGReaderImpl::ImplReadHeader()
-{
-    if( mnChunkLen < 13 )
-        return false;
-
-    maOrigSize.setWidth( ImplReadsal_uInt32() );
-    maOrigSize.setHeight( ImplReadsal_uInt32() );
-
-    if (maOrigSize.IsEmpty())
-        return false;
-
-    mnPngDepth = *(maDataIter++);
-    mnColorType = *(maDataIter++);
-
-    mnCompressionType = *(maDataIter++);
-    if( mnCompressionType != 0 )    // unknown compression type
-        return false;
-
-    mnFilterType = *(maDataIter++);
-    if( mnFilterType != 0 )         // unknown filter type
-        return false;
-
-    mnInterlaceType = *(maDataIter++);
-    switch ( mnInterlaceType ) // filter type valid ?
-    {
-        case 0 :  // progressive image
-            mnPass = 7;
-            break;
-        case 1 :  // Adam7-interlaced image
-            mnPass = 0;
-            break;
-        default:
-            return false;
-    }
-
-    mbPalette = true;
-    mbIDATStarted = mbIDATComplete = mbAlphaChannel = mbTransparent = false;
-    mbGrayScale = mbRGBTriple = false;
-    mnTargetDepth = mnPngDepth;
-    sal_uInt64 nScansize64 = ( ( static_cast< sal_uInt64 >( maOrigSize.Width() ) * mnPngDepth ) + 7 ) >> 3;
-
-    // valid color types are 0,2,3,4 & 6
-    switch ( mnColorType )
-    {
-        case 0 :    // each pixel is a grayscale
-        {
-            switch ( mnPngDepth )
-            {
-                case 2 : // 2bit target not available -> use four bits
-                    mnTargetDepth = 4;  // we have to expand the bitmap
-                    mbGrayScale = true;
-                    break;
-                case 16 :
-                    mnTargetDepth = 8;  // we have to reduce the bitmap
-                    [[fallthrough]];
-                case 1 :
-                case 4 :
-                case 8 :
-                    mbGrayScale = true;
-                    break;
-                default :
-                    return false;
-            }
-        }
-        break;
-
-        case 2 :    // each pixel is an RGB triple
-        {
-            mbRGBTriple = true;
-            nScansize64 *= 3;
-            switch ( mnPngDepth )
-            {
-                case 16 :           // we have to reduce the bitmap
-                case 8 :
-                    mnTargetDepth = 24;
-                    break;
-                default :
-                    return false;
-            }
-        }
-        break;
-
-        case 3 :    // each pixel is a palette index
-        {
-            switch ( mnPngDepth )
-            {
-                case 2 :
-                    mnTargetDepth = 4;  // we have to expand the bitmap
-                    mbPalette = false;
-                    break;
-                case 1 :
-                case 4 :
-                case 8 :
-                    mbPalette = false;
-                    break;
-                default :
-                    return false;
-            }
-        }
-        break;
-
-        case 4 :    // each pixel is a grayscale sample followed by an alpha sample
-        {
-            nScansize64 *= 2;
-            mbAlphaChannel = true;
-            switch ( mnPngDepth )
-            {
-                case 16 :
-                    mnTargetDepth = 8;  // we have to reduce the bitmap
-                    [[fallthrough]];
-                case 8 :
-                    mbGrayScale = true;
-                    break;
-                default :
-                    return false;
-            }
-        }
-        break;
-
-        case 6 :    // each pixel is an RGB triple followed by an alpha sample
-        {
-            mbRGBTriple = true;
-            nScansize64 *= 4;
-            mbAlphaChannel = true;
-            switch (mnPngDepth )
-            {
-                case 16 :           // we have to reduce the bitmap
-                case 8 :
-                    mnTargetDepth = 24;
-                    break;
-                default :
-                    return false;
-            }
-        }
-        break;
-
-        default :
-            return false;
-    }
-
-    mnBPP = static_cast< sal_uInt32 >( nScansize64 / maOrigSize.Width() );
-    if ( !mnBPP )
-        mnBPP = 1;
-
-    nScansize64++;       // each scanline includes one filterbyte
-
-    if ( nScansize64 > SAL_MAX_UINT32 )
-        return false;
-
-    // assume max theoretical compression of 1:1032
-    sal_uInt64 nMinSizeRequired = (nScansize64 * maOrigSize.Height()) / 1032;
-    if (nMinSizeRequired > mnStreamSize)
-    {
-        SAL_WARN("vcl.gdi", "overlarge png dimensions: " <<
-                 maOrigSize.Width() << " x " << maOrigSize.Height() << " depth: " << static_cast<int>(mnPngDepth) <<
-                 " couldn't be supplied by file length " << mnStreamSize << " at least " << nMinSizeRequired << " needed ");
-        return false;
-    }
-
-    mnScansize = static_cast< sal_uInt32 >( nScansize64 );
-
-    maTargetSize.setWidth( (maOrigSize.Width() + mnPreviewMask) >> mnPreviewShift );
-    maTargetSize.setHeight( (maOrigSize.Height() + mnPreviewMask) >> mnPreviewShift );
-
-    //round bits up to nearest multiple of 8 and divide by 8 to get num of bytes per pixel
-    int nBytesPerPixel = ((mnTargetDepth + 7) & ~7)/8;
-
-    //stupidly big, forget about it
-    if (maTargetSize.Width() >= SAL_MAX_INT32 / nBytesPerPixel / maTargetSize.Height())
-    {
-        SAL_WARN( "vcl.gdi", "overlarge png dimensions: " <<
-            maTargetSize.Width() << " x " << maTargetSize.Height() << " depth: " << mnTargetDepth);
-        return false;
-    }
-
-    // TODO: switch between both scanlines instead of copying
-    mpInflateInBuf.reset( new (std::nothrow) sal_uInt8[ mnScansize ] );
-    mpScanCurrent = mpInflateInBuf.get();
-    mpScanPrior.reset( new (std::nothrow) sal_uInt8[ mnScansize ] );
-
-    if ( !mpInflateInBuf || !mpScanPrior )
-        return false;
-
-    mpBmp = std::make_unique<Bitmap>( maTargetSize, mnTargetDepth );
-    mxAcc = BitmapScopedWriteAccess(*mpBmp);
-    if (!mxAcc)
-        return false;
-
-    if ( mbAlphaChannel )
-    {
-        mpAlphaMask = std::make_unique<AlphaMask>( maTargetSize );
-        mpAlphaMask->Erase( 128 );
-        mxAlphaAcc = AlphaScopedWriteAccess(*mpAlphaMask);
-        mpMaskAcc = mxAlphaAcc.get();
-        if (!mpMaskAcc)
-            return false;
-    }
-
-    if ( mbGrayScale )
-        ImplGetGrayPalette( mnPngDepth );
-
-    ImplPreparePass();
-
-    return true;
-}
-
-void PNGReaderImpl::ImplGetGrayPalette( sal_uInt16 nBitDepth )
-{
-    if( nBitDepth > 8 )
-        nBitDepth = 8;
-
-    sal_uInt16  nPaletteEntryCount = 1 << nBitDepth;
-    sal_uInt32  nAdd = nBitDepth ? 256 / (nPaletteEntryCount - 1) : 0;
-
-    // no bitdepth==2 available
-    // but bitdepth==4 with two unused bits is close enough
-    if( nBitDepth == 2 )
-        nPaletteEntryCount = 16;
-
-    mxAcc->SetPaletteEntryCount( nPaletteEntryCount );
-    for ( sal_uInt32 i = 0, nStart = 0; nStart < 256; i++, nStart += nAdd )
-        mxAcc->SetPaletteColor( static_cast<sal_uInt16>(i), BitmapColor( mpColorTable[ nStart ],
-            mpColorTable[ nStart ], mpColorTable[ nStart ] ) );
-}
-
-bool PNGReaderImpl::ImplReadPalette()
-{
-    sal_uInt16 nCount = static_cast<sal_uInt16>( mnChunkLen / 3 );
-
-    if ( ( ( mnChunkLen % 3 ) == 0 ) && ( ( 0 < nCount ) && ( nCount <= 256 ) ) && mxAcc )
-    {
-        mbPalette = true;
-        mxAcc->SetPaletteEntryCount( nCount );
-
-        for ( sal_uInt16 i = 0; i < nCount; i++ )
-        {
-            sal_uInt8 nRed =   mpColorTable[ *maDataIter++ ];
-            sal_uInt8 nGreen = mpColorTable[ *maDataIter++ ];
-            sal_uInt8 nBlue =  mpColorTable[ *maDataIter++ ];
-            mxAcc->SetPaletteColor( i, Color( nRed, nGreen, nBlue ) );
-        }
-    }
-    else
-        mbStatus = false;
-
-    return mbStatus;
-}
-
-bool PNGReaderImpl::ImplReadTransparent()
-{
-    bool bNeedAlpha = false;
-
-    if ( mpTransTab == nullptr )
-    {
-        switch ( mnColorType )
-        {
-            case 0 :
-            {
-                if ( mnChunkLen == 2 )
-                {
-                    mpTransTab.reset( new sal_uInt8[ 256 ] );
-                    memset( mpTransTab.get(), 0xff, 256);
-                    // color type 0 and 4 is always greyscale,
-                    // so the return value can be used as index
-                    sal_uInt8 nIndex = ImplScaleColor();
-                    mpTransTab[ nIndex ] = 0;
-                    mbTransparent = true;
-                }
-            }
-            break;
-
-            case 2 :
-            {
-                if ( mnChunkLen == 6 )
-                {
-                    mnTransRed = ImplScaleColor();
-                    mnTransGreen = ImplScaleColor();
-                    mnTransBlue = ImplScaleColor();
-                    mbTransparent = true;
-                }
-            }
-            break;
-
-            case 3 :
-            {
-                if ( mnChunkLen <= 256 )
-                {
-                    mbTransparent = true;
-                    mpTransTab.reset( new sal_uInt8 [ 256 ] );
-                    memset( mpTransTab.get(), 0xff, 256 );
-                    if (mnChunkLen > 0)
-                    {
-                        memcpy( mpTransTab.get(), &(*maDataIter), mnChunkLen );
-                        maDataIter += mnChunkLen;
-                        // need alpha transparency if not on/off masking
-                        for( int i = 0; i < mnChunkLen; ++i )
-                           bNeedAlpha |= (mpTransTab[i]!=0x00) && (mpTransTab[i]!=0xFF);
-                    }
-                }
-            }
-            break;
-        }
-    }
-
-    if( mbTransparent && !mbAlphaChannel && !mpMaskBmp )
-    {
-        if( bNeedAlpha)
-        {
-            mpAlphaMask = std::make_unique<AlphaMask>( maTargetSize );
-            mxAlphaAcc = AlphaScopedWriteAccess(*mpAlphaMask);
-            mpMaskAcc = mxAlphaAcc.get();
-        }
-        else
-        {
-            mpMaskBmp = std::make_unique<Bitmap>( maTargetSize, 1 );
-            mxMaskAcc = BitmapScopedWriteAccess(*mpMaskBmp);
-            mpMaskAcc = mxMaskAcc.get();
-        }
-        mbTransparent = (mpMaskAcc != nullptr);
-        if( !mbTransparent )
-            return false;
-        mpMaskAcc->Erase( Color(0,0,0) );
-    }
-
-    return true;
-}
-
-void PNGReaderImpl::ImplGetGamma()
-{
-    if( mnChunkLen < 4 )
-        return;
-
-    sal_uInt32  nGammaValue = ImplReadsal_uInt32();
-    double      fGamma = ( VIEWING_GAMMA / DISPLAY_GAMMA ) * ( static_cast<double>(nGammaValue) / 100000 );
-    double      fInvGamma = ( fGamma <= 0.0 || fGamma > 10.0 ) ? 1.0 : ( 1.0 / fGamma );
-
-    if ( fInvGamma != 1.0 )
-    {
-        if ( mpColorTable == mpDefaultColorTable )
-            mpColorTable = new sal_uInt8[ 256 ];
-
-        for ( sal_Int32 i = 0; i < 256; i++ )
-            mpColorTable[ i ] = static_cast<sal_uInt8>(pow(static_cast<double>(i)/255.0, fInvGamma) * 255.0 + 0.5);
-
-        if ( mbGrayScale )
-            ImplGetGrayPalette( mnPngDepth );
-    }
-}
-
-void PNGReaderImpl::ImplGetBackground()
-{
-    switch (mnColorType)
-    {
-        case 3:
-        {
-            if (mnChunkLen == 1)
-            {
-                sal_uInt16 nCol = *maDataIter++;
-
-                if (nCol < mxAcc->GetPaletteEntryCount())
-                {
-                    mxAcc->Erase(mxAcc->GetPaletteColor(static_cast<sal_uInt8>(nCol)));
-                    break;
-                }
-            }
-        }
-        break;
-
-        case 0:
-        case 4:
-        {
-            if (mnChunkLen == 2)
-            {
-                // the color type 0 and 4 is always greyscale,
-                // so the return value can be used as index
-                mxAcc->Erase(mxAcc->GetPaletteColor(ImplScaleColor()));
-            }
-        }
-        break;
-
-        case 2:
-        case 6:
-        {
-            if (mnChunkLen == 6)
-            {
-                sal_uInt8 nRed = ImplScaleColor();
-                sal_uInt8 nGreen = ImplScaleColor();
-                sal_uInt8 nBlue = ImplScaleColor();
-                // ofz#18653 slow and uninteresting
-                if (utl::ConfigManager::IsFuzzing())
-                    return;
-                mxAcc->Erase(Color(nRed, nGreen, nBlue));
-            }
-        }
-        break;
-    }
-}
-
-// for color type 0 and 4 (greyscale) the return value is always index to the color
-//                2 and 6 (RGB)       the return value is always the 8 bit color component
-sal_uInt8 PNGReaderImpl::ImplScaleColor()
-{
-    sal_uInt32 nMask = ( 1 << mnPngDepth ) - 1;
-    sal_uInt16 nCol = ( *maDataIter++ << 8 );
-
-    nCol += *maDataIter++ & static_cast<sal_uInt16>(nMask);
-
-    if ( mnPngDepth > 8 )   // convert 16bit graphics to 8
-        nCol >>= 8;
-
-    return static_cast<sal_uInt8>(nCol);
-}
-
-// ImplReadIDAT reads as much image data as needed
-
-void PNGReaderImpl::ImplReadIDAT()
-{
-    //when fuzzing with a max len set, max decompress to 250 times that limit
-    static size_t nMaxAllowedDecompression = [](const char* pEnv) { size_t nRet = pEnv ? std::atoi(pEnv) : 0; return nRet * 250; }(std::getenv("FUZZ_MAX_INPUT_LEN"));
-    size_t nTotalDataRead = 0;
-
-    if( mnChunkLen > 0 )
-    {
-        mbIDATStarted = true;
-
-        if ( !mbzCodecInUse )
-        {
-            mbzCodecInUse = true;
-            mpZCodec.BeginCompression( ZCODEC_NO_COMPRESSION );
-        }
-        mpZCodec.SetBreak( mnChunkLen );
-        SvMemoryStream aIStrm( &(*maDataIter), mnChunkLen, StreamMode::READ );
-
-        while ( mpZCodec.GetBreak() )
-        {
-            // get bytes needed to fill the current scanline
-            sal_Int32 nToRead = mnScansize - (mpScanCurrent - mpInflateInBuf.get());
-            sal_Int32 nRead = mpZCodec.ReadAsynchron( aIStrm, mpScanCurrent, nToRead );
-            if ( nRead < 0 )
-            {
-                mbStatus = false;
-                break;
-            }
-            nTotalDataRead += nRead;
-            if (nMaxAllowedDecompression && nTotalDataRead > nMaxAllowedDecompression)
-            {
-                mbStatus = false;
-                break;
-            }
-            if ( nRead < nToRead )
-            {
-                mpScanCurrent += nRead; // more ZStream data in the next IDAT chunk
-                break;
-            }
-            else  // this scanline is Finished
-            {
-                mpScanCurrent = mpInflateInBuf.get();
-                ImplApplyFilter();
-
-                ImplDrawScanline( mnXStart, mnXAdd );
-                mnYpos += mnYAdd;
-            }
-
-            if ( mnYpos >= o3tl::make_unsigned(maOrigSize.Height()) )
-            {
-                if( (mnPass < 7) && mnInterlaceType )
-                    if( ImplPreparePass() )
-                        continue;
-                mbIDATComplete = true;
-                break;
-            }
-        }
-    }
-
-    if (mbIDATComplete)
-    {
-        mpZCodec.EndCompression();
-        mbzCodecInUse = false;
-    }
-}
-
-bool PNGReaderImpl::ImplPreparePass()
-{
-    struct InterlaceParams{ int mnXStart, mnYStart, mnXAdd, mnYAdd; };
-    static const InterlaceParams aInterlaceParams[8] =
-    {
-        // non-interlaced
-        { 0, 0, 1, 1 },
-        // Adam7-interlaced
-        { 0, 0, 8, 8 },    // pass 1
-        { 4, 0, 8, 8 },    // pass 2
-        { 0, 4, 4, 8 },    // pass 3
-        { 2, 0, 4, 4 },    // pass 4
-        { 0, 2, 2, 4 },    // pass 5
-        { 1, 0, 2, 2 },    // pass 6
-        { 0, 1, 1, 2 }     // pass 7
-    };
-
-    const InterlaceParams* pParam = &aInterlaceParams[ 0 ];
-    if( mnInterlaceType )
-    {
-        while( ++mnPass <= 7 )
-        {
-            pParam = &aInterlaceParams[ mnPass ];
-
-            // skip this pass if the original image is too small for it
-            if( (pParam->mnXStart < maOrigSize.Width())
-            &&  (pParam->mnYStart < maOrigSize.Height()) )
-                break;
-        }
-        if( mnPass > 7 )
-            return false;
-
-        // skip the last passes if possible (for scaled down target images)
-        if( mnPreviewMask & (pParam->mnXStart | pParam->mnYStart) )
-            return false;
-    }
-
-    mnYpos      = pParam->mnYStart;
-    mnXStart    = pParam->mnXStart;
-    mnXAdd      = pParam->mnXAdd;
-    mnYAdd      = pParam->mnYAdd;
-
-    // in Interlace mode the size of scanline is not constant
-    // so first we calculate the number of entries
-    tools::Long nScanWidth = (maOrigSize.Width() - mnXStart + mnXAdd - 1) / mnXAdd;
-    mnScansize = nScanWidth;
-
-    if( mbRGBTriple )
-        mnScansize = 3 * nScanWidth;
-
-    if( mbAlphaChannel )
-        mnScansize += nScanWidth;
-
-    // convert to width in bytes
-    mnScansize = ( mnScansize*mnPngDepth + 7 ) >> 3;
-
-    ++mnScansize; // scan size also needs room for the filtertype byte
-    memset( mpScanPrior.get(), 0, mnScansize );
-
-    return true;
-}
-
-// ImplApplyFilter writes the complete Scanline (nY)
-// in interlace mode the parameter nXStart and nXAdd are non-zero
-
-void PNGReaderImpl::ImplApplyFilter()
-{
-    OSL_ASSERT( mnScansize >= mnBPP + 1 );
-    const sal_uInt8* const pScanEnd = mpInflateInBuf.get() + mnScansize;
-
-    sal_uInt8 nFilterType = mpInflateInBuf[0]; // the filter type may change each scanline
-    switch ( nFilterType )
-    {
-        default: // unknown Scanline Filter Type
-        case 0: // Filter Type "None"
-            // we let the pixels pass and display the data unfiltered
-            break;
-
-        case 1: // Scanline Filter Type "Sub"
-        {
-            sal_uInt8* p1 = mpInflateInBuf.get() + 1;
-            const sal_uInt8* p2 = p1;
-            p1 += mnBPP;
-
-            // use left pixels
-            while (p1 < pScanEnd)
-            {
-                *p1 = static_cast<sal_uInt8>( *p1 + *(p2++) );
-                ++p1;
-            }
-        }
-        break;
-
-        case 2: // Scanline Filter Type "Up"
-        {
-            sal_uInt8* p1 = mpInflateInBuf.get() + 1;
-            const sal_uInt8* p2 = mpScanPrior.get() + 1;
-
-            // use pixels from prior line
-            while( p1 < pScanEnd )
-            {
-                *p1 = static_cast<sal_uInt8>( *p1 + *(p2++) );
-                ++p1;
-            }
-        }
-        break;
-
-        case 3: // Scanline Filter Type "Average"
-        {
-            sal_uInt8* p1 = mpInflateInBuf.get() + 1;
-            const sal_uInt8* p2 = mpScanPrior.get() + 1;
-            const sal_uInt8* p3 = p1;
-
-            // use one pixel from prior line
-            for( int n = mnBPP; --n >= 0; ++p1, ++p2)
-                *p1 = static_cast<sal_uInt8>( *p1 + (*p2 >> 1) );
-
-            // predict by averaging the left and prior line pixels
-            while( p1 < pScanEnd )
-            {
-                *p1 = static_cast<sal_uInt8>( *p1 + ((*(p2++) + *(p3++)) >> 1) );
-                ++p1;
-            }
-        }
-        break;
-
-        case 4: // Scanline Filter Type "PathPredictor"
-        {
-            sal_uInt8* p1 = mpInflateInBuf.get() + 1;
-            const sal_uInt8* p2 = mpScanPrior.get() + 1;
-            const sal_uInt8* p3 = p1;
-            const sal_uInt8* p4 = p2;
-
-            // use one pixel from prior line
-            for( int n = mnBPP; --n >= 0; ++p1)
-                *p1 = static_cast<sal_uInt8>( *p1 + *(p2++) );
-
-            // predict by using the left and the prior line pixels
-            while( p1 < pScanEnd )
-            {
-                int na = *(p2++);
-                int nb = *(p3++);
-                int nc = *(p4++);
-
-                int npa = nb - nc;
-                int npb = na - nc;
-                int npc = npa + npb;
-
-                if( npa < 0 )
-                    npa =-npa;
-                if( npb < 0 )
-                    npb =-npb;
-                if( npc < 0 )
-                    npc =-npc;
-
-                if( npa > npb )
-                {
-                    na = nb;
-                    npa = npb;
-                }
-                if( npa > npc )
-                    na = nc;
-
-                *p1 = static_cast<sal_uInt8>( *p1 + na );
-                ++p1;
-            }
-        }
-        break;
-    }
-
-    memcpy( mpScanPrior.get(), mpInflateInBuf.get(), mnScansize );
-}
-
-namespace
-{
-    sal_uInt8 SanitizePaletteIndex(sal_uInt8 nIndex, sal_uInt16 nPaletteEntryCount)
-    {
-        if (nIndex >= nPaletteEntryCount)
-        {
-            auto nSanitizedIndex = nIndex % nPaletteEntryCount;
-            SAL_WARN_IF(nIndex != nSanitizedIndex, "vcl", "invalid colormap index: "
-                        << static_cast<unsigned int>(nIndex) << ", colormap len is: "
-                        << nPaletteEntryCount);
-            nIndex = nSanitizedIndex;
-        }
-        return nIndex;
-    }
-
-    void SanitizePaletteIndexes(sal_uInt8* pEntries, int nLen, const BitmapScopedWriteAccess& rAcc)
-    {
-        sal_uInt16 nPaletteEntryCount = rAcc->GetPaletteEntryCount();
-        for (int nX = 0; nX < nLen; ++nX)
-        {
-            if (pEntries[nX] >= nPaletteEntryCount)
-            {
-                SAL_WARN("vcl.gdi", "invalid colormap index: "
-                          << static_cast<unsigned int>(pEntries[nX]) << ", colormap len is: "
-                          << nPaletteEntryCount);
-                pEntries[nX] = pEntries[nX] % nPaletteEntryCount;
-            }
-        }
-    }
-}
-
-// ImplDrawScanlines draws the complete Scanline (nY) into the target bitmap
-// In interlace mode the parameter nXStart and nXAdd append to the currently used pass
-
-void PNGReaderImpl::ImplDrawScanline( sal_uInt32 nXStart, sal_uInt32 nXAdd )
-{
-    // optimization for downscaling
-    if( mnYpos & mnPreviewMask )
-        return;
-    if( nXStart & mnPreviewMask )
-        return;
-
-    // convert nY to pixel units in the target image
-    // => TODO; also do this for nX here instead of in the ImplSet*Pixel() methods
-    const sal_uInt32 nY = mnYpos >> mnPreviewShift;
-
-    sal_uInt8* pTmp = mpInflateInBuf.get() + 1;
-    if ( mxAcc->HasPalette() ) // alphachannel is not allowed by pictures including palette entries
-    {
-        switch ( mxAcc->GetBitCount() )
-        {
-            case 1 :
-            {
-                if ( mbTransparent )
-                {
-                    for ( tools::Long nX = nXStart, nShift = 0; nX < maOrigSize.Width(); nX += nXAdd )
-                    {
-                        sal_uInt8 nCol;
-                        nShift = (nShift - 1) & 7;
-                        if ( nShift == 0 )
-                            nCol = *(pTmp++);
-                        else
-                            nCol = static_cast<sal_uInt8>( *pTmp >> nShift );
-                        nCol &= 1;
-
-                        ImplSetAlphaPixel( nY, nX, nCol, mpTransTab[ nCol ] );
-                    }
-                }
-                else
-                {   // ScanlineFormat::N1BitMsbPal
-                    for ( tools::Long nX = nXStart, nShift = 0; nX < maOrigSize.Width(); nX += nXAdd )
-                    {
-                        nShift = (nShift - 1) & 7;
-
-                        sal_uInt8 nCol;
-                        if ( nShift == 0 )
-                            nCol = *(pTmp++);
-                        else
-                            nCol = static_cast<sal_uInt8>( *pTmp >> nShift );
-                        nCol &= 1;
-
-                        ImplSetPixel( nY, nX, nCol );
-                    }
-                }
-            }
-            break;
-
-            case 4 :
-            {
-                if ( mbTransparent )
-                {
-                    if ( mnPngDepth == 4 )  // check if source has a two bit pixel format
-                    {
-                        for ( tools::Long nX = nXStart, nXIndex = 0; nX < maOrigSize.Width(); nX += nXAdd, ++nXIndex )
-                        {
-                            if( nXIndex & 1 )
-                            {
-                                ImplSetAlphaPixel( nY, nX, *pTmp & 0x0f, mpTransTab[ *pTmp & 0x0f ] );
-                                pTmp++;
-                            }
-                            else
-                            {
-                                ImplSetAlphaPixel( nY, nX, ( *pTmp >> 4 ) & 0x0f, mpTransTab[ *pTmp >> 4 ] );
-                            }
-                        }
-                    }
-                    else // if ( mnPngDepth == 2 )
-                    {
-                        for ( tools::Long nX = nXStart, nXIndex = 0; nX < maOrigSize.Width(); nX += nXAdd, nXIndex++ )
-                        {
-                            sal_uInt8 nCol;
-                            switch( nXIndex & 3 )
-                            {
-                                case 0 :
-                                    nCol = *pTmp >> 6;
-                                break;
-
-                                case 1 :
-                                    nCol = ( *pTmp >> 4 ) & 0x03 ;
-                                break;
-
-                                case 2 :
-                                    nCol = ( *pTmp >> 2 ) & 0x03;
-                                break;
-
-                                case 3 :
-                                    nCol = ( *pTmp++ ) & 0x03;
-                                break;
-
-                                default:    // get rid of nCol uninitialized warning
-                                    nCol = 0;
-                                    break;
-                            }
-
-                            ImplSetAlphaPixel( nY, nX, nCol, mpTransTab[ nCol ] );
-                        }
-                    }
-                }
-                else
-                {
-                    if ( mnPngDepth == 4 )  // maybe the source is a two bitmap graphic
-                    {   // ScanlineFormat::N4BitLsnPal
-                        for ( tools::Long nX = nXStart, nXIndex = 0; nX < maOrigSize.Width(); nX += nXAdd, nXIndex++ )
-                        {
-                            if( nXIndex & 1 )
-                                ImplSetPixel( nY, nX, *pTmp++ & 0x0f );
-                            else
-                                ImplSetPixel( nY, nX, ( *pTmp >> 4 ) & 0x0f );
-                        }
-                    }
-                    else // if ( mnPngDepth == 2 )
-                    {
-                        for ( tools::Long nX = nXStart, nXIndex = 0; nX < maOrigSize.Width(); nX += nXAdd, nXIndex++ )
-                        {
-                            switch( nXIndex & 3 )
-                            {
-                                case 0 :
-                                    ImplSetPixel( nY, nX, *pTmp >> 6 );
-                                break;
-
-                                case 1 :
-                                    ImplSetPixel( nY, nX, ( *pTmp >> 4 ) & 0x03 );
-                                break;
-
-                                case 2 :
-                                    ImplSetPixel( nY, nX, ( *pTmp >> 2 ) & 0x03 );
-                                break;
-
-                                case 3 :
-                                    ImplSetPixel( nY, nX, *pTmp++ & 0x03 );
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-            break;
-
-            case 8 :
-            {
-                if ( mbAlphaChannel )
-                {
-                    if ( mnPngDepth == 8 )  // maybe the source is a 16 bit grayscale
-                    {
-                        for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 2 )
-                            ImplSetAlphaPixel( nY, nX, pTmp[ 0 ], pTmp[ 1 ] );
-                    }
-                    else
-                    {
-                        assert(mnPngDepth == 16);
-                        for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
-                            ImplSetAlphaPixel( nY, nX, pTmp[ 0 ], pTmp[ 2 ] );
-                    }
-                }
-                else if ( mbTransparent )
-                {
-                    if ( mnPngDepth == 8 )  // maybe the source is a 16 bit grayscale
-                    {
-                        for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp++ )
-                            ImplSetAlphaPixel( nY, nX, *pTmp, mpTransTab[ *pTmp ] );
-                    }
-                    else if (mnPngDepth == 1 )
-                    {
-                        for ( tools::Long nX = nXStart, nShift = 0; nX < maOrigSize.Width(); nX += nXAdd )
-                        {
-                            nShift = (nShift - 1) & 7;
-
-                            sal_uInt8 nCol;
-                            if ( nShift == 0 )
-                                nCol = *(pTmp++);
-                            else
-                                nCol = static_cast<sal_uInt8>( *pTmp >> nShift );
-                            nCol &= 1;
-
-                            ImplSetAlphaPixel( nY, nX, nCol, mpTransTab[ nCol ] );
-                        }
-                    }
-                    else
-                    {
-                        for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 2 )
-                            ImplSetAlphaPixel( nY, nX, *pTmp, mpTransTab[ *pTmp ] );
-                    }
-                }
-                else // neither alpha nor transparency
-                {
-                    if ( mnPngDepth == 8 )  // maybe the source is a 16 bit grayscale or 1 bit indexed
-                    {
-                        if( nXAdd == 1 && mnPreviewShift == 0 )  // copy raw line data if possible
-                        {
-                            int nLineBytes = maOrigSize.Width();
-                            if (mbPalette)
-                                SanitizePaletteIndexes(pTmp, nLineBytes, mxAcc);
-                            mxAcc->CopyScanline( nY, pTmp, ScanlineFormat::N8BitPal, nLineBytes );
-                        }
-                        else
-                        {
-                            for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd )
-                                ImplSetPixel( nY, nX, *pTmp++ );
-                        }
-                    }
-                    else if (mnPngDepth == 1 )
-                    {
-                        for ( tools::Long nX = nXStart, nShift = 0; nX < maOrigSize.Width(); nX += nXAdd )
-                        {
-                            nShift = (nShift - 1) & 7;
-
-                            sal_uInt8 nCol;
-                            if ( nShift == 0 )
-                                nCol = *(pTmp++);
-                            else
-                                nCol = static_cast<sal_uInt8>( *pTmp >> nShift );
-                            nCol &= 1;
-
-                            ImplSetPixel( nY, nX, nCol );
-                        }
-                    }
-                    else
-                    {
-                        for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 2 )
-                            ImplSetPixel( nY, nX, *pTmp );
-                    }
-                }
-            }
-            break;
-
-            default :
-                mbStatus = false;
-            break;
-        }
-    }
-    else // no palette => truecolor
-    {
-        if( mbAlphaChannel )
-        {
-            // has RGB + alpha
-            if ( mnPngDepth == 8 )  // maybe the source has 16 bit per sample
-            {
-                // ScanlineFormat::N32BitTcRgba
-                // only use DirectScanline when we have no preview shifting stuff and accesses to content and alpha
-                const bool bDoDirectScanline(
-                    !nXStart && 1 == nXAdd && !mnPreviewShift && mpMaskAcc);
-                const bool bCustomColorTable(mpColorTable != mpDefaultColorTable);
-
-                if(bDoDirectScanline)
-                {
-                    // allocate scanlines on demand, reused for next line
-                    if(!mpScanline)
-                    {
-#if OSL_DEBUG_LEVEL > 0
-                        mnAllocSizeScanline = maOrigSize.Width() * 3;
-#endif
-                        mpScanline.reset( new sal_uInt8[maOrigSize.Width() * 3] );
-                    }
-
-                    if(!mpScanlineAlpha)
-                    {
-#if OSL_DEBUG_LEVEL > 0
-                        mnAllocSizeScanlineAlpha = maOrigSize.Width();
-#endif
-                        mpScanlineAlpha.reset( new sal_uInt8[maOrigSize.Width()] );
-                    }
-                }
-
-                if(bDoDirectScanline)
-                {
-                    OSL_ENSURE(mpScanline, "No Scanline allocated (!)");
-                    OSL_ENSURE(mpScanlineAlpha, "No ScanlineAlpha allocated (!)");
-#if OSL_DEBUG_LEVEL > 0
-                    OSL_ENSURE(mnAllocSizeScanline >= maOrigSize.Width() * 3, "Allocated Scanline too small (!)");
-                    OSL_ENSURE(mnAllocSizeScanlineAlpha >= maOrigSize.Width(), "Allocated ScanlineAlpha too small (!)");
-#endif
-                    sal_uInt8* pScanline(mpScanline.get());
-                    sal_uInt8* pScanlineAlpha(mpScanlineAlpha.get());
-
-                    for (tools::Long nX(0); nX < maOrigSize.Width(); nX++, pTmp += 4)
-                    {
-                        // prepare content line as BGR by reordering when copying
-                        // do not forget to invert alpha (source is alpha, target is opacity)
-                        if(bCustomColorTable)
-                        {
-                            *pScanline++ = mpColorTable[pTmp[2]];
-                            *pScanline++ = mpColorTable[pTmp[1]];
-                            *pScanline++ = mpColorTable[pTmp[0]];
-                            *pScanlineAlpha++ = ~pTmp[3];
-                        }
-                        else
-                        {
-                            *pScanline++ = pTmp[2];
-                            *pScanline++ = pTmp[1];
-                            *pScanline++ = pTmp[0];
-                            *pScanlineAlpha++ = ~pTmp[3];
-                        }
-                    }
-
-                    // copy scanlines directly to bitmaps for content and alpha; use the formats which
-                    // are able to copy directly to BitmapBuffer
-                    mxAcc->CopyScanline(nY, mpScanline.get(), ScanlineFormat::N24BitTcBgr, maOrigSize.Width() * 3);
-                    mpMaskAcc->CopyScanline(nY, mpScanlineAlpha.get(), ScanlineFormat::N8BitPal, maOrigSize.Width());
-                }
-                else
-                {
-                    for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 4 )
-                    {
-                        if(bCustomColorTable)
-                        {
-                            ImplSetAlphaPixel(
-                                nY,
-                                nX,
-                                BitmapColor(
-                                    mpColorTable[ pTmp[ 0 ] ],
-                                    mpColorTable[ pTmp[ 1 ] ],
-                                    mpColorTable[ pTmp[ 2 ] ]),
-                                pTmp[ 3 ]);
-                        }
-                        else
-                        {
-                            ImplSetAlphaPixel(
-                                nY,
-                                nX,
-                                BitmapColor(
-                                    pTmp[0],
-                                    pTmp[1],
-                                    pTmp[2]),
-                                pTmp[3]);
-                        }
-                    }
-                }
-            }
-            else
-            {
-                // BMP_FORMAT_64BIT_TC_RGBA
-                for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 8 )
-                {
-                    ImplSetAlphaPixel(
-                        nY,
-                        nX,
-                        BitmapColor(
-                            mpColorTable[ pTmp[ 0 ] ],
-                            mpColorTable[ pTmp[ 2 ] ],
-                            mpColorTable[ pTmp[ 4 ] ]),
-                        pTmp[6]);
-                }
-            }
-        }
-        else if( mbTransparent ) // has RGB + transparency
-        {
-            // ScanlineFormat::N24BitTcRgb
-            // no support currently for DirectScanline, found no real usages in current PNGs, may be added on demand
-            if ( mnPngDepth == 8 )  // maybe the source has 16 bit per sample
-            {
-                for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
-                {
-                    sal_uInt8 nRed = pTmp[ 0 ];
-                    sal_uInt8 nGreen = pTmp[ 1 ];
-                    sal_uInt8 nBlue = pTmp[ 2 ];
-                    bool bTransparent = ( ( nRed == mnTransRed )
-                                        && ( nGreen == mnTransGreen )
-                                        && ( nBlue == mnTransBlue ) );
-
-                    ImplSetTranspPixel( nY, nX, BitmapColor( mpColorTable[ nRed ],
-                                                        mpColorTable[ nGreen ],
-                                                        mpColorTable[ nBlue ] ), bTransparent );
-                }
-            }
-            else
-            {
-                // BMP_FORMAT_48BIT_TC_RGB
-                for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 6 )
-                {
-                    sal_uInt8 nRed = pTmp[ 0 ];
-                    sal_uInt8 nGreen = pTmp[ 2 ];
-                    sal_uInt8 nBlue = pTmp[ 4 ];
-                    bool bTransparent = ( ( nRed == mnTransRed )
-                                        && ( nGreen == mnTransGreen )
-                                        && ( nBlue == mnTransBlue ) );
-
-                    ImplSetTranspPixel( nY, nX, BitmapColor( mpColorTable[ nRed ],
-                                                        mpColorTable[ nGreen ],
-                                                        mpColorTable[ nBlue ] ), bTransparent );
-                }
-            }
-        }
-        else  // has RGB but neither alpha nor transparency
-        {
-            // ScanlineFormat::N24BitTcRgb
-            // only use DirectScanline when we have no preview shifting stuff and access to content
-            const bool bDoDirectScanline(
-                !nXStart && 1 == nXAdd && !mnPreviewShift);
-            const bool bCustomColorTable(mpColorTable != mpDefaultColorTable);
-
-            if(bDoDirectScanline && !mpScanline)
-            {
-                // allocate scanlines on demand, reused for next line
-#if OSL_DEBUG_LEVEL > 0
-                mnAllocSizeScanline = maOrigSize.Width() * 3;
-#endif
-                mpScanline.reset( new sal_uInt8[maOrigSize.Width() * 3] );
-            }
-
-            if ( mnPngDepth == 8 )   // maybe the source has 16 bit per sample
-            {
-                if(bDoDirectScanline)
-                {
-                    OSL_ENSURE(mpScanline, "No Scanline allocated (!)");
-#if OSL_DEBUG_LEVEL > 0
-                    OSL_ENSURE(mnAllocSizeScanline >= maOrigSize.Width() * 3, "Allocated Scanline too small (!)");
-#endif
-                    sal_uInt8* pScanline(mpScanline.get());
-
-                    for (tools::Long nX(0); nX < maOrigSize.Width(); nX++, pTmp += 3)
-                    {
-                        // prepare content line as BGR by reordering when copying
-                        if(bCustomColorTable)
-                        {
-                            *pScanline++ = mpColorTable[pTmp[2]];
-                            *pScanline++ = mpColorTable[pTmp[1]];
-                            *pScanline++ = mpColorTable[pTmp[0]];
-                        }
-                        else
-                        {
-                            *pScanline++ = pTmp[2];
-                            *pScanline++ = pTmp[1];
-                            *pScanline++ = pTmp[0];
-                        }
-                    }
-
-                    // copy scanline directly to bitmap for content; use the format which is able to
-                    // copy directly to BitmapBuffer
-                    mxAcc->CopyScanline(nY, mpScanline.get(), ScanlineFormat::N24BitTcBgr, maOrigSize.Width() * 3);
-                }
-                else
-                {
-                    for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 3 )
-                    {
-                        if(bCustomColorTable)
-                        {
-                            ImplSetPixel(
-                                nY,
-                                nX,
-                                BitmapColor(
-                                    mpColorTable[ pTmp[ 0 ] ],
-                                    mpColorTable[ pTmp[ 1 ] ],
-                                    mpColorTable[ pTmp[ 2 ] ]));
-                        }
-                        else
-                        {
-                            ImplSetPixel(
-                                nY,
-                                nX,
-                                BitmapColor(
-                                    pTmp[0],
-                                    pTmp[1],
-                                    pTmp[2]));
-                        }
-                    }
-                }
-            }
-            else
-            {
-                // BMP_FORMAT_48BIT_TC_RGB
-                // no support currently for DirectScanline, found no real usages in current PNGs, may be added on demand
-                for ( tools::Long nX = nXStart; nX < maOrigSize.Width(); nX += nXAdd, pTmp += 6 )
-                {
-                    ImplSetPixel(
-                        nY,
-                        nX,
-                        BitmapColor(
-                            mpColorTable[ pTmp[ 0 ] ],
-                            mpColorTable[ pTmp[ 2 ] ],
-                            mpColorTable[ pTmp[ 4 ] ]));
-                }
-            }
-        }
-    }
-}
-
-void PNGReaderImpl::ImplSetPixel( sal_uInt32 nY, sal_uInt32 nX, const BitmapColor& rBitmapColor )
-{
-    // TODO: get preview mode checks out of inner loop
-    if( nX & mnPreviewMask )
-        return;
-    nX >>= mnPreviewShift;
-
-    mxAcc->SetPixel( nY, nX, rBitmapColor );
-}
-
-void PNGReaderImpl::ImplSetPixel( sal_uInt32 nY, sal_uInt32 nX, sal_uInt8 nPalIndex )
-{
-    // TODO: get preview mode checks out of inner loop
-    if( nX & mnPreviewMask )
-        return;
-    nX >>= mnPreviewShift;
-
-    mxAcc->SetPixelIndex(nY, nX, SanitizePaletteIndex(nPalIndex, mxAcc->GetPaletteEntryCount()));
-}
-
-void PNGReaderImpl::ImplSetTranspPixel( sal_uInt32 nY, sal_uInt32 nX, const BitmapColor& rBitmapColor, bool bTrans )
-{
-    // TODO: get preview mode checks out of inner loop
-    if( nX & mnPreviewMask )
-        return;
-    nX >>= mnPreviewShift;
-
-    mxAcc->SetPixel( nY, nX, rBitmapColor );
-
-    if ( bTrans )
-        mpMaskAcc->SetPixel( nY, nX, mcTranspColor );
-    else
-        mpMaskAcc->SetPixel( nY, nX, mcOpaqueColor );
-}
-
-void PNGReaderImpl::ImplSetAlphaPixel( sal_uInt32 nY, sal_uInt32 nX,
-    sal_uInt8 nPalIndex, sal_uInt8 nAlpha )
-{
-    // TODO: get preview mode checks out of inner loop
-    if( nX & mnPreviewMask )
-        return;
-    nX >>= mnPreviewShift;
-
-    mxAcc->SetPixelIndex(nY, nX, SanitizePaletteIndex(nPalIndex, mxAcc->GetPaletteEntryCount()));
-    mpMaskAcc->SetPixel(nY, nX, BitmapColor(~nAlpha));
-}
-
-void PNGReaderImpl::ImplSetAlphaPixel( sal_uInt32 nY, sal_uInt32 nX,
-    const BitmapColor& rBitmapColor, sal_uInt8 nAlpha )
-{
-    // TODO: get preview mode checks out of inner loop
-    if( nX & mnPreviewMask )
-        return;
-    nX >>= mnPreviewShift;
-
-    mxAcc->SetPixel( nY, nX, rBitmapColor );
-    if (!mpMaskAcc)
-        return;
-    mpMaskAcc->SetPixel(nY, nX, BitmapColor(~nAlpha));
-}
-
-sal_uInt32 PNGReaderImpl::ImplReadsal_uInt32()
-{
-    sal_uInt32 nRet;
-    nRet = *maDataIter++;
-    nRet <<= 8;
-    nRet |= *maDataIter++;
-    nRet <<= 8;
-    nRet |= *maDataIter++;
-    nRet <<= 8;
-    nRet |= *maDataIter++;
-    return nRet;
-}
-
-PNGReader::PNGReader(SvStream& rIStream) :
-    mpImpl(new vcl::PNGReaderImpl(rIStream))
-{
-}
-
-PNGReader::~PNGReader()
-{
-}
-
-BitmapEx PNGReader::Read()
-{
-    return mpImpl->GetBitmapEx();
-}
-
-const std::vector< vcl::PNGReader::ChunkData >& PNGReader::GetChunks() const
-{
-    return mpImpl->GetAllChunks();
-}
-
-} // namespace vcl
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/treelist/transfer.cxx b/vcl/source/treelist/transfer.cxx
index bee628edc60b..e659eef56c04 100644
--- a/vcl/source/treelist/transfer.cxx
+++ b/vcl/source/treelist/transfer.cxx
@@ -60,7 +60,7 @@
 #include <rtl/strbuf.hxx>
 #include <cstdio>
 #include <vcl/dibtools.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
 #include <vcl/pngwrite.hxx>
 #include <vcl/graphicfilter.hxx>
 #include <memory>
@@ -1590,9 +1590,8 @@ bool TransferableDataHelper::GetBitmapEx( const DataFlavor& rFlavor, BitmapEx& r
         if(!bSuppressPNG && rFlavor.MimeType.equalsIgnoreAsciiCase("image/png"))
         {
             // it's a PNG, import to BitmapEx
-            vcl::PNGReader aPNGReader(*xStm);
-
-            rBmpEx = aPNGReader.Read();
+            vcl::PngImageReader aPNGReader(*xStm);
+            rBmpEx = aPNGReader.read();
         }
         else if(!bSuppressJPEG && rFlavor.MimeType.equalsIgnoreAsciiCase("image/jpeg"))
         {
diff --git a/vcl/workben/fftester.cxx b/vcl/workben/fftester.cxx
index 640bd1f54832..7d165d5a5957 100644
--- a/vcl/workben/fftester.cxx
+++ b/vcl/workben/fftester.cxx
@@ -41,7 +41,7 @@
 #include <vcl/dibtools.hxx>
 #include <vcl/event.hxx>
 #include <vcl/graphicfilter.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/wmf.hxx>
 #include <vcl/wrkwin.hxx>
@@ -155,8 +155,8 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS(argc, argv)
         else if (strcmp(argv[2], "png") == 0)
         {
             SvFileStream aFileStream(out, StreamMode::READ);
-            vcl::PNGReader aReader(aFileStream);
-            ret = static_cast<int>(!!aReader.Read());
+            vcl::PngImageReader aReader(aFileStream);
+            ret = static_cast<int>(!!aReader.read());
         }
         else if (strcmp(argv[2], "bmp") == 0)
         {
diff --git a/vcl/workben/pngfuzzer.cxx b/vcl/workben/pngfuzzer.cxx
index 2a3357830007..e5e3c9e8a239 100644
--- a/vcl/workben/pngfuzzer.cxx
+++ b/vcl/workben/pngfuzzer.cxx
@@ -8,7 +8,7 @@
  */
 
 #include <tools/stream.hxx>
-#include <vcl/pngread.hxx>
+#include <vcl/filter/PngImageReader.hxx>
 #include "commonfuzzer.hxx"
 
 #include <config_features.h>
@@ -48,8 +48,8 @@ extern "C" void* lo_get_custom_widget_func(const char*)
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
 {
     SvMemoryStream aStream(const_cast<uint8_t*>(data), size, StreamMode::READ);
-    vcl::PNGReader aReader(aStream);
-    (void)aReader.Read();
+    vcl::PngImageReader aReader(aStream);
+    (void)aReader.read();
     return 0;
 }
 
diff --git a/vcl/workben/vcldemo.cxx b/vcl/workben/vcldemo.cxx
index e9df921c293e..e37ac96eba9b 100644
--- a/vcl/workben/vcldemo.cxx
+++ b/vcl/workben/vcldemo.cxx
@@ -39,7 +39,6 @@
 #include <tools/urlobj.hxx>
 #include <tools/stream.hxx>
 #include <vcl/svapp.hxx>
-#include <vcl/pngread.hxx>
 #include <vcl/wrkwin.hxx>
 #include <vcl/virdev.hxx>
 #include <vcl/graphicfilter.hxx>


More information about the Libreoffice-commits mailing list