From b9fa913d806aefc7e96be4cff1ffaeb2d3b20fe5 Mon Sep 17 00:00:00 2001 From: Luboš Luňák Date: Tue, 13 Apr 2021 13:21:26 +0200 Subject: use the bitmap buffer directly also when reading 32bit png bitmap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similarly how it's already done for rgb and gray. This saves memory and for multi-pass png's it should be also faster to do the processing just once at the end. This still leaves the split 24+8bpp case, but we'll hopefully eventually get rid of it whenever this complicated split stuff gets removed. Change-Id: Ia5e5dcd957d93cff41aa158d9bfcd25fc591e1c7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114162 Tested-by: Jenkins Reviewed-by: Luboš Luňák --- vcl/source/filter/png/PngImageReader.cxx | 51 +++++++++++++++++++------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/vcl/source/filter/png/PngImageReader.cxx b/vcl/source/filter/png/PngImageReader.cxx index c7ff5a9a8990..4136d9d9aa97 100644 --- a/vcl/source/filter/png/PngImageReader.cxx +++ b/vcl/source/filter/png/PngImageReader.cxx @@ -235,34 +235,43 @@ bool reader(SvStream& rStream, BitmapEx& rBitmapEx, bool bUseBitmap32) png_set_bgr(pPng); } - aRows = std::vector>(height); - for (auto& rRow : aRows) - rRow.resize(aRowSizeBytes, 0); - - auto const alphaFirst = (eFormat == ScanlineFormat::N32BitTcAbgr - || eFormat == ScanlineFormat::N32BitTcArgb); for (int pass = 0; pass < nNumberOfPasses; pass++) { for (png_uint_32 y = 0; y < height; y++) { Scanline pScanline = pWriteAccess->GetScanline(y); - png_bytep pRow = aRows[y].data(); - png_read_row(pPng, pRow, nullptr); - size_t iColor = 0; + png_read_row(pPng, pScanline, nullptr); + } + } + const vcl::bitmap::lookup_table& premultiply + = vcl::bitmap::get_premultiply_table(); + if (eFormat == ScanlineFormat::N32BitTcAbgr + || eFormat == ScanlineFormat::N32BitTcArgb) + { // alpha first and premultiply + for (png_uint_32 y = 0; y < height; y++) + { + Scanline pScanline = pWriteAccess->GetScanline(y); + for (size_t i = 0; i < aRowSizeBytes; i += 4) + { + const sal_uInt8 alpha = pScanline[i + 3]; + pScanline[i + 3] = premultiply[alpha][pScanline[i + 2]]; + pScanline[i + 2] = premultiply[alpha][pScanline[i + 1]]; + pScanline[i + 1] = premultiply[alpha][pScanline[i]]; + pScanline[i] = alpha; + } + } + } + else + { // keep alpha last, only premultiply + for (png_uint_32 y = 0; y < height; y++) + { + Scanline pScanline = pWriteAccess->GetScanline(y); for (size_t i = 0; i < aRowSizeBytes; i += 4) { - sal_Int8 alpha = pRow[i + 3]; - if (alphaFirst) - { - pScanline[iColor++] = alpha; - } - pScanline[iColor++] = vcl::bitmap::premultiply(pRow[i + 0], alpha); - pScanline[iColor++] = vcl::bitmap::premultiply(pRow[i + 1], alpha); - pScanline[iColor++] = vcl::bitmap::premultiply(pRow[i + 2], alpha); - if (!alphaFirst) - { - pScanline[iColor++] = alpha; - } + const sal_uInt8 alpha = pScanline[i + 3]; + pScanline[i] = premultiply[alpha][pScanline[i]]; + pScanline[i + 1] = premultiply[alpha][pScanline[i + 1]]; + pScanline[i + 2] = premultiply[alpha][pScanline[i + 2]]; } } } -- cgit