summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2016-06-26 11:13:13 +0800
committerTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2016-11-16 11:10:27 +0100
commit05b751d5af4a65b5ec7ef23e9a0d6802d5445826 (patch)
tree8a46c0cb796995df2ff8137470d67a99b804adbf
parent411694e6d4f9b7df9859c8f00243878b49389635 (diff)
vcl: PngReader which uses libpng for PNG decoding
We already need libpng for some of the dependencies and in LO itself (splash). However in vcl we have our own implementation for reading and writing PNG images. This adds a PNG reader that uses libpng and always decodes to a 32-bit RGBA bitmap, however it doesn't replace the existing PNGReader - yet. Change-Id: I95663886ea599603bb3d18826b0a640596ce3724
-rw-r--r--include/vcl/filter/PngReader.hxx40
-rw-r--r--vcl/Library_vcl.mk2
-rw-r--r--vcl/source/filter/png/PngReader.cxx180
3 files changed, 222 insertions, 0 deletions
diff --git a/include/vcl/filter/PngReader.hxx b/include/vcl/filter/PngReader.hxx
new file mode 100644
index 000000000000..957539c8cf39
--- /dev/null
+++ b/include/vcl/filter/PngReader.hxx
@@ -0,0 +1,40 @@
+/* -*- 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>
+
+#ifndef INCLUDED_VCL_SOURCE_FILTER_PNG_PNGREADER_HXX
+#define INCLUDED_VCL_SOURCE_FILTER_PNG_PNGREADER_HXX
+
+namespace vcl
+{
+
+class VCL_DLLPUBLIC PngReader
+{
+ SvStream& mrStream;
+ css::uno::Reference< css::task::XStatusIndicator > mxStatusIndicator;
+
+public:
+ PngReader(SvStream& rStream);
+
+ virtual ~PngReader()
+ {}
+
+ bool Read(BitmapEx& rBitmap);
+ bool Read(Graphic& rGraphic);
+};
+
+} // namespace vcl
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 8b158fb57178..bf958f37df4d 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -122,6 +122,7 @@ $(eval $(call gb_Library_use_externals,vcl,\
icuuc \
lcms2 \
mdds_headers \
+ png \
))
ifeq ($(ENABLE_HEADLESS),)
$(eval $(call gb_Library_use_externals,vcl,\
@@ -373,6 +374,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/filter/jpeg/JpegReader \
vcl/source/filter/jpeg/JpegWriter \
vcl/source/filter/jpeg/JpegTransform \
+ vcl/source/filter/png/PngReader \
vcl/source/filter/wmf/emfwr \
vcl/source/filter/wmf/enhwmf \
vcl/source/filter/wmf/winmtf \
diff --git a/vcl/source/filter/png/PngReader.cxx b/vcl/source/filter/png/PngReader.cxx
new file mode 100644
index 000000000000..6470aa1fadd9
--- /dev/null
+++ b/vcl/source/filter/png/PngReader.cxx
@@ -0,0 +1,180 @@
+/* -*- 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/PngReader.hxx>
+
+#include <png.h>
+
+#include <vcl/bitmapaccess.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 = reinterpret_cast<SvStream*>(pIO);
+
+ sal_Size nBytesRead = pStream->ReadBytes(pOutBytes, nBytesToRead);
+
+ if (nBytesRead != nBytesToRead)
+ png_error(pPng, "Error reading");
+}
+
+bool reader(SvStream& rStream, Bitmap& rBitmap)
+{
+ 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), 32);
+
+ 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);
+ }
+
+ 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;
+ }
+
+ {
+ Bitmap::ScopedWriteAccess pWriteAccess(aBitmap);
+
+ for (int pass = 0; pass < nNumberOfPasses; pass++)
+ {
+ for (png_uint_32 y = 0; y < height; y++)
+ {
+ Scanline pScanline = pWriteAccess->GetScanline(y);
+ png_read_rows(pPng, &pScanline, nullptr, 1);
+ }
+ }
+ }
+
+ png_read_end(pPng, pInfo);
+
+ png_destroy_read_struct(&pPng, &pInfo, nullptr);
+
+ rBitmap = aBitmap;
+
+ return true;
+}
+
+} // anonymous namespace
+
+namespace vcl
+{
+
+PngReader::PngReader(SvStream& rStream)
+ : mrStream(rStream)
+{}
+
+bool PngReader::Read(BitmapEx& rBitmap)
+{
+ Bitmap aBitmap;
+ if (!reader(mrStream, aBitmap))
+ return false;
+ rBitmap = BitmapEx(aBitmap);
+ return true;
+}
+
+bool PngReader::Read(Graphic& rGraphic)
+{
+ Bitmap aBitmap;
+ if (!reader(mrStream, aBitmap))
+ return false;
+ rGraphic = Graphic(aBitmap);
+ return true;
+}
+
+} // namespace vcl
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */