summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2019-02-08 21:30:39 +0100
committerTomaž Vajngerl <quikee@gmail.com>2019-02-09 11:57:48 +0100
commit34a6e8443312c5f9aa0a1bb055fac50d722a90ff (patch)
tree41c1c25c6c639d6c6ce4d29d117138bad61e5358
parentebc6cfbb323d2f933336f7e2f4a775098c4f4341 (diff)
add PngImageFilter that uses libpng for PNG loading
This adds loading of PNG images that uses libpng instead of our own solution. It always loaded the image as either RGB or RGBA image and if the source PNG is using something else, libpng converts to either RGB or RGBA. In addition this adds tests for loading of various PNG files to make sure the resulting bitmaps are using pixel data as expected. (especially needed to check the RGBA bitmaps) Change-Id: I194321caf76c2ec2365bb6075c79c5e84983658a Reviewed-on: https://gerrit.libreoffice.org/67571 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
-rw-r--r--include/vcl/filter/PngImageReader.hxx39
-rw-r--r--vcl/CppunitTest_vcl_png_test.mk52
-rw-r--r--vcl/Library_vcl.mk2
-rw-r--r--vcl/Module_vcl.mk1
-rw-r--r--vcl/qa/cppunit/png/PngFilterTest.cxx155
-rw-r--r--vcl/qa/cppunit/png/data/alpha-rect-8bit-RGBA.pngbin0 -> 158 bytes
-rw-r--r--vcl/qa/cppunit/png/data/color-rect-4bit-pal.pngbin0 -> 104 bytes
-rw-r--r--vcl/qa/cppunit/png/data/color-rect-8bit-RGB.pngbin0 -> 90 bytes
-rw-r--r--vcl/qa/cppunit/png/data/rect-1bit-pal.pngbin0 -> 89 bytes
-rw-r--r--vcl/source/filter/png/PngImageReader.cxx214
10 files changed, 463 insertions, 0 deletions
diff --git a/include/vcl/filter/PngImageReader.hxx b/include/vcl/filter/PngImageReader.hxx
new file mode 100644
index 000000000000..f555939a4836
--- /dev/null
+++ b/include/vcl/filter/PngImageReader.hxx
@@ -0,0 +1,39 @@
+/* -*- 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/.
+ *
+ */
+
+#include <vcl/graph.hxx>
+#include <vcl/dllapi.h>
+#include <com/sun/star/task/XStatusIndicator.hpp>
+#include <tools/stream.hxx>
+#include <vcl/bitmapex.hxx>
+
+#ifndef INCLUDED_VCL_SOURCE_FILTER_PNG_PNGIMAGEREADER_HXX
+#define INCLUDED_VCL_SOURCE_FILTER_PNG_PNGIMAGEREADER_HXX
+
+namespace vcl
+{
+class VCL_DLLPUBLIC PngImageReader
+{
+ SvStream& mrStream;
+ css::uno::Reference<css::task::XStatusIndicator> mxStatusIndicator;
+
+public:
+ PngImageReader(SvStream& rStream);
+
+ virtual ~PngImageReader() {}
+
+ bool read(BitmapEx& rBitmap);
+};
+
+} // namespace vcl
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/CppunitTest_vcl_png_test.mk b/vcl/CppunitTest_vcl_png_test.mk
new file mode 100644
index 000000000000..1f88209313a0
--- /dev/null
+++ b/vcl/CppunitTest_vcl_png_test.mk
@@ -0,0 +1,52 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# 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/.
+#
+
+$(eval $(call gb_CppunitTest_CppunitTest,vcl_png_test))
+
+$(eval $(call gb_CppunitTest_add_exception_objects,vcl_png_test, \
+ vcl/qa/cppunit/png/PngFilterTest \
+))
+
+$(eval $(call gb_CppunitTest_set_include,vcl_png_test,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/vcl/inc \
+))
+
+$(eval $(call gb_CppunitTest_use_libraries,vcl_png_test, \
+ comphelper \
+ cppu \
+ cppuhelper \
+ sal \
+ svt \
+ test \
+ tl \
+ unotest \
+ vcl \
+ utl \
+ $(gb_UWINAPI) \
+))
+
+$(eval $(call gb_CppunitTest_use_api,vcl_png_test,\
+ udkapi \
+ offapi \
+))
+
+$(eval $(call gb_CppunitTest_use_ure,vcl_png_test))
+$(eval $(call gb_CppunitTest_use_vcl,vcl_png_test))
+
+$(eval $(call gb_CppunitTest_use_components,vcl_png_test,\
+ configmgr/source/configmgr \
+ i18npool/util/i18npool \
+ ucb/source/core/ucb1 \
+ unotools/util/utl \
+))
+
+$(eval $(call gb_CppunitTest_use_configuration,vcl_png_test))
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 31e677b9e37d..0178ffc809df 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -66,6 +66,7 @@ $(eval $(call gb_Library_use_custom_headers,vcl,\
$(eval $(call gb_Library_use_externals,vcl,\
libjpeg \
libeot \
+ libpng \
$(if $(filter PDFIUM,$(BUILD_TYPE)),pdfium) \
))
@@ -407,6 +408,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/filter/wmf/wmf \
vcl/source/filter/wmf/wmfexternal \
vcl/source/filter/wmf/wmfwr \
+ vcl/source/filter/png/PngImageReader \
vcl/source/font/Feature \
vcl/source/font/FeatureCollector \
vcl/source/font/FeatureParser \
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index 95dd579c38de..14e3eacf1bf5 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -205,6 +205,7 @@ $(eval $(call gb_Module_add_check_targets,vcl,\
CppunitTest_vcl_errorhandler \
CppunitTest_vcl_bitmap_render_test \
CppunitTest_vcl_apitests \
+ CppunitTest_vcl_png_test \
))
ifneq (,$(filter PDFIUM,$(BUILD_TYPE)))
diff --git a/vcl/qa/cppunit/png/PngFilterTest.cxx b/vcl/qa/cppunit/png/PngFilterTest.cxx
new file mode 100644
index 000000000000..1a9dd0a4cead
--- /dev/null
+++ b/vcl/qa/cppunit/png/PngFilterTest.cxx
@@ -0,0 +1,155 @@
+/* -*- 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 <test/bootstrapfixture.hxx>
+#include <vcl/filter/PngImageReader.hxx>
+#include <vcl/bitmapaccess.hxx>
+#include <vcl/alpha.hxx>
+
+using namespace css;
+
+class PngFilterTest : public test::BootstrapFixture
+{
+ OUString maDataUrl;
+
+ OUString getFullUrl(const OUString& sFileName)
+ {
+ return m_directories.getURLFromSrc(maDataUrl) + sFileName;
+ }
+
+public:
+ PngFilterTest()
+ : BootstrapFixture(true, false)
+ , maDataUrl("/vcl/qa/cppunit/png/data/")
+ {
+ }
+
+ void testPng();
+
+ CPPUNIT_TEST_SUITE(PngFilterTest);
+ CPPUNIT_TEST(testPng);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void PngFilterTest::testPng()
+{
+ for (const OUString& aFileName : { OUString("rect-1bit-pal.png") })
+ {
+ SvFileStream aFileStream(getFullUrl(aFileName), StreamMode::READ);
+
+ vcl::PngImageReader aPngReader(aFileStream);
+ BitmapEx aBitmapEx;
+ aPngReader.read(aBitmapEx);
+
+ 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));
+ }
+ }
+ for (const OUString& aFileName :
+ { OUString("color-rect-8bit-RGB.png"), OUString("color-rect-4bit-pal.png") })
+ {
+ SvFileStream aFileStream(getFullUrl(aFileName), StreamMode::READ);
+
+ vcl::PngImageReader aPngReader(aFileStream);
+ BitmapEx aBitmapEx;
+ aPngReader.read(aBitmapEx);
+
+ 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));
+ }
+ }
+ for (const OUString& aFileName : { OUString("alpha-rect-8bit-RGBA.png") })
+ {
+ SvFileStream aFileStream(getFullUrl(aFileName), StreamMode::READ);
+
+ vcl::PngImageReader aPngReader(aFileStream);
+ BitmapEx aBitmapEx;
+ aPngReader.read(aBitmapEx);
+
+ 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));
+ }
+ }
+ // CPPUNIT_ASSERT(false);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(PngFilterTest);
+
+CPPUNIT_PLUGIN_IMPLEMENT();
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/png/data/alpha-rect-8bit-RGBA.png b/vcl/qa/cppunit/png/data/alpha-rect-8bit-RGBA.png
new file mode 100644
index 000000000000..1e90e1a6cfed
--- /dev/null
+++ b/vcl/qa/cppunit/png/data/alpha-rect-8bit-RGBA.png
Binary files differ
diff --git a/vcl/qa/cppunit/png/data/color-rect-4bit-pal.png b/vcl/qa/cppunit/png/data/color-rect-4bit-pal.png
new file mode 100644
index 000000000000..740eede512d1
--- /dev/null
+++ b/vcl/qa/cppunit/png/data/color-rect-4bit-pal.png
Binary files differ
diff --git a/vcl/qa/cppunit/png/data/color-rect-8bit-RGB.png b/vcl/qa/cppunit/png/data/color-rect-8bit-RGB.png
new file mode 100644
index 000000000000..727859d8a7c1
--- /dev/null
+++ b/vcl/qa/cppunit/png/data/color-rect-8bit-RGB.png
Binary files differ
diff --git a/vcl/qa/cppunit/png/data/rect-1bit-pal.png b/vcl/qa/cppunit/png/data/rect-1bit-pal.png
new file mode 100644
index 000000000000..cf7ac3e7c31b
--- /dev/null
+++ b/vcl/qa/cppunit/png/data/rect-1bit-pal.png
Binary files differ
diff --git a/vcl/source/filter/png/PngImageReader.cxx b/vcl/source/filter/png/PngImageReader.cxx
new file mode 100644
index 000000000000..790336654714
--- /dev/null
+++ b/vcl/source/filter/png/PngImageReader.cxx
@@ -0,0 +1,214 @@
+/* -*- 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/.
+ *
+ */
+
+#include <vcl/filter/PngImageReader.hxx>
+#include <png.h>
+#include <vcl/bitmapaccess.hxx>
+#include <bitmapwriteaccess.hxx>
+#include <vcl/bitmap.hxx>
+#include <vcl/alpha.hxx>
+
+namespace
+{
+void lclReadStream(png_structp pPng, png_bytep pOutBytes, png_size_t nBytesToRead)
+{
+ png_voidp pIO = png_get_io_ptr(pPng);
+
+ if (pIO == nullptr)
+ return;
+
+ SvStream* pStream = static_cast<SvStream*>(pIO);
+
+ sal_Size nBytesRead = pStream->ReadBytes(pOutBytes, nBytesToRead);
+
+ if (nBytesRead != nBytesToRead)
+ png_error(pPng, "Error reading");
+}
+
+bool reader(SvStream& rStream, BitmapEx& rBitmapEx)
+{
+ enum
+ {
+ PNG_SIGNATURE_SIZE = 8
+ };
+
+ sal_uInt8 aHeader[PNG_SIGNATURE_SIZE];
+ rStream.ReadBytes(aHeader, PNG_SIGNATURE_SIZE);
+
+ if (png_sig_cmp(aHeader, 0, PNG_SIGNATURE_SIZE))
+ return false;
+
+ png_structp pPng = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
+ if (!pPng)
+ return false;
+
+ png_infop pInfo = png_create_info_struct(pPng);
+ if (!pInfo)
+ {
+ png_destroy_read_struct(&pPng, nullptr, nullptr);
+ return false;
+ }
+
+ if (setjmp(png_jmpbuf(pPng)))
+ {
+ png_destroy_read_struct(&pPng, &pInfo, nullptr);
+ return false;
+ }
+
+ png_set_read_fn(pPng, &rStream, lclReadStream);
+
+ png_set_crc_action(pPng, PNG_CRC_WARN_USE, PNG_CRC_WARN_DISCARD);
+
+ png_set_sig_bytes(pPng, PNG_SIGNATURE_SIZE);
+
+ png_read_info(pPng, pInfo);
+
+ png_uint_32 width = 0;
+ png_uint_32 height = 0;
+ int bitDepth = 0;
+ int colorType = -1;
+ int interlace = -1;
+
+ png_uint_32 returnValue = png_get_IHDR(pPng, pInfo, &width, &height, &bitDepth, &colorType,
+ &interlace, nullptr, nullptr);
+
+ if (returnValue != 1)
+ {
+ png_destroy_read_struct(&pPng, &pInfo, nullptr);
+ return false;
+ }
+
+ Bitmap aBitmap(Size(width, height), 24);
+ AlphaMask aBitmapAlpha(Size(width, height), nullptr);
+
+ png_set_bgr(pPng);
+
+ if (colorType == PNG_COLOR_TYPE_PALETTE)
+ png_set_palette_to_rgb(pPng);
+
+ if (colorType == PNG_COLOR_TYPE_GRAY)
+ png_set_expand_gray_1_2_4_to_8(pPng);
+
+ if (png_get_valid(pPng, pInfo, PNG_INFO_tRNS))
+ png_set_tRNS_to_alpha(pPng);
+
+ if (bitDepth == 16)
+ png_set_scale_16(pPng);
+
+ if (bitDepth < 8)
+ png_set_packing(pPng);
+
+ if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
+ {
+ png_set_gray_to_rgb(pPng);
+ }
+
+ // Sets the filler byte - if RGB it converts to RGBA
+ // png_set_filler(pPng, 0xFF, PNG_FILLER_AFTER);
+
+ int nNumberOfPasses = png_set_interlace_handling(pPng);
+
+ png_read_update_info(pPng, pInfo);
+ returnValue = png_get_IHDR(pPng, pInfo, &width, &height, &bitDepth, &colorType, nullptr,
+ nullptr, nullptr);
+
+ if (returnValue != 1)
+ {
+ png_destroy_read_struct(&pPng, &pInfo, nullptr);
+ return false;
+ }
+
+ if (bitDepth != 8
+ || !(colorType == PNG_COLOR_TYPE_RGB || colorType == PNG_COLOR_TYPE_RGB_ALPHA))
+ {
+ png_destroy_read_struct(&pPng, &pInfo, nullptr);
+ return false;
+ }
+
+ {
+ if (colorType == PNG_COLOR_TYPE_RGB)
+ {
+ size_t aRowSizeBytes = png_get_rowbytes(pPng, pInfo);
+
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+
+ std::vector<png_byte> aRow(aRowSizeBytes, 0);
+
+ for (int pass = 0; pass < nNumberOfPasses; pass++)
+ {
+ for (png_uint_32 y = 0; y < height; y++)
+ {
+ 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)
+ {
+ pScanline[iColor++] = pRow[i + 0];
+ pScanline[iColor++] = pRow[i + 1];
+ pScanline[iColor++] = pRow[i + 2];
+ }
+ }
+ }
+ }
+ else if (colorType == PNG_COLOR_TYPE_RGB_ALPHA)
+ {
+ size_t aRowSizeBytes = png_get_rowbytes(pPng, pInfo);
+
+ BitmapScopedWriteAccess pWriteAccess(aBitmap);
+ AlphaScopedWriteAccess pWriteAccessAlpha(aBitmapAlpha);
+
+ std::vector<png_byte> aRow(aRowSizeBytes, 0);
+
+ for (int pass = 0; pass < nNumberOfPasses; pass++)
+ {
+ for (png_uint_32 y = 0; y < height; y++)
+ {
+ 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)
+ {
+ pScanline[iColor++] = pRow[i + 0];
+ pScanline[iColor++] = pRow[i + 1];
+ pScanline[iColor++] = pRow[i + 2];
+ pScanAlpha[iAlpha++] = 0xFF - pRow[i + 3];
+ }
+ }
+ }
+ }
+ }
+
+ png_read_end(pPng, pInfo);
+
+ png_destroy_read_struct(&pPng, &pInfo, nullptr);
+
+ rBitmapEx = BitmapEx(aBitmap, aBitmapAlpha);
+
+ return true;
+}
+
+} // anonymous namespace
+
+namespace vcl
+{
+PngImageReader::PngImageReader(SvStream& rStream)
+ : mrStream(rStream)
+{
+}
+
+bool PngImageReader::read(BitmapEx& rBitmapEx) { return reader(mrStream, rBitmapEx); }
+
+} // namespace vcl
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */