28void lclReadStream(png_structp pPng, png_bytep pOutBytes, png_size_t nBytesToRead)
30 png_voidp pIO = png_get_io_ptr(pPng);
37 sal_Size nBytesRead = pStream->
ReadBytes(pOutBytes, nBytesToRead);
39 if (nBytesRead != nBytesToRead)
42 png_error(pPng,
"Error reading");
46 memset(pOutBytes + nBytesRead, 0, nBytesToRead - nBytesRead);
47 png_warning(pPng,
"Short read");
52constexpr int PNG_SIGNATURE_SIZE = 8;
58 if (rStream.
ReadBytes(aHeader, PNG_SIGNATURE_SIZE) != PNG_SIGNATURE_SIZE)
60 return png_sig_cmp(aHeader, 0, PNG_SIGNATURE_SIZE) == 0;
65 ~PngDestructor() { png_destroy_read_struct(&pPng, &pInfo,
nullptr); }
70#if defined __GNUC__ && __GNUC__ == 8 && !defined __clang__
71#pragma GCC diagnostic push
72#pragma GCC diagnostic ignored "-Wclobbered"
82 png_structp pPng = png_create_read_struct(PNG_LIBPNG_VER_STRING,
nullptr,
nullptr,
nullptr);
86 png_infop pInfo = png_create_info_struct(pPng);
89 png_destroy_read_struct(&pPng,
nullptr,
nullptr);
93 PngDestructor pngDestructor = { pPng, pInfo };
105 const bool bOnlyCreateBitmap
107 const bool bUseExistingBitmap
110 if (setjmp(png_jmpbuf(pPng)))
112 if (!bUseExistingBitmap)
116 pWriteAccessInstance.
reset();
117 pWriteAccessAlphaInstance.
reset();
119 rBitmapEx =
BitmapEx(aBitmap, aBitmapAlpha);
131 png_set_option(pPng, PNG_MAXIMUM_INFLATE_WINDOW, PNG_OPTION_ON);
133 png_set_read_fn(pPng, &rStream, lclReadStream);
136 png_set_crc_action(pPng, PNG_CRC_ERROR_QUIT, PNG_CRC_WARN_DISCARD);
138 png_set_crc_action(pPng, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
140 png_set_sig_bytes(pPng, PNG_SIGNATURE_SIZE);
142 png_read_info(pPng, pInfo);
144 png_uint_32 width = 0;
145 png_uint_32 height = 0;
150 png_uint_32 returnValue = png_get_IHDR(pPng, pInfo, &width, &height, &bitDepth, &colorType,
151 &interlace,
nullptr,
nullptr);
153 if (returnValue != 1)
156 if (colorType == PNG_COLOR_TYPE_PALETTE)
157 png_set_palette_to_rgb(pPng);
159 if (colorType == PNG_COLOR_TYPE_GRAY)
160 png_set_expand_gray_1_2_4_to_8(pPng);
162 if (png_get_valid(pPng, pInfo, PNG_INFO_tRNS))
163 png_set_tRNS_to_alpha(pPng);
166 png_set_scale_16(pPng);
169 png_set_packing(pPng);
172 if (colorType == PNG_COLOR_TYPE_GRAY_ALPHA
173 || (colorType == PNG_COLOR_TYPE_GRAY && png_get_valid(pPng, pInfo, PNG_INFO_tRNS)))
175 png_set_gray_to_rgb(pPng);
181 int nNumberOfPasses = png_set_interlace_handling(pPng);
183 png_read_update_info(pPng, pInfo);
184 returnValue = png_get_IHDR(pPng, pInfo, &width, &height, &bitDepth, &colorType,
nullptr,
187 if (returnValue != 1)
191 || (colorType != PNG_COLOR_TYPE_RGB && colorType != PNG_COLOR_TYPE_RGB_ALPHA
192 && colorType != PNG_COLOR_TYPE_GRAY))
197 png_uint_32 res_x = 0;
198 png_uint_32 res_y = 0;
200 if (png_get_pHYs(pPng, pInfo, &res_x, &res_y, &unit_type) != 0
201 && unit_type == PNG_RESOLUTION_METER && res_x && res_y)
204 prefSize =
Size(
static_cast<sal_Int32
>((100000.0 * width) / res_x),
205 static_cast<sal_Int32
>((100000.0 * height) / res_y));
208 if (!bUseExistingBitmap)
212 case PNG_COLOR_TYPE_RGB:
215 case PNG_COLOR_TYPE_RGBA:
216 if (bSupportsBitmap32)
224 case PNG_COLOR_TYPE_GRAY:
232 if (bOnlyCreateBitmap)
235 rBitmapEx =
BitmapEx(aBitmap, aBitmapAlpha);
247 if (!pWriteAccessInstance)
252 if (!pWriteAccessAlphaInstance)
258 = pAlphaAccess ? *pAlphaAccess : pWriteAccessAlphaInstance;
260 if (colorType == PNG_COLOR_TYPE_RGB)
266 for (
int pass = 0;
pass < nNumberOfPasses;
pass++)
268 for (png_uint_32 y = 0;
y < height;
y++)
270 Scanline pScanline = pWriteAccess->GetScanline(y);
271 png_read_row(pPng, pScanline,
nullptr);
275 else if (colorType == PNG_COLOR_TYPE_RGB_ALPHA)
277 size_t aRowSizeBytes = png_get_rowbytes(pPng, pInfo);
279 if (bSupportsBitmap32)
285 for (
int pass = 0;
pass < nNumberOfPasses;
pass++)
287 for (png_uint_32 y = 0;
y < height;
y++)
289 Scanline pScanline = pWriteAccess->GetScanline(y);
290 png_read_row(pPng, pScanline,
nullptr);
293#if !ENABLE_WASM_STRIP_PREMULTIPLY
298 for (png_uint_32 y = 0;
y < height;
y++)
300 Scanline pScanline = pWriteAccess->GetScanline(y);
301 for (
size_t i = 0;
i < aRowSizeBytes;
i += 4)
304#if ENABLE_WASM_STRIP_PREMULTIPLY
313 pScanline[
i] = alpha;
319 for (png_uint_32 y = 0;
y < height;
y++)
321 Scanline pScanline = pWriteAccess->GetScanline(y);
322 for (
size_t i = 0;
i < aRowSizeBytes;
i += 4)
325#if ENABLE_WASM_STRIP_PREMULTIPLY
344 if (nNumberOfPasses == 1)
347 std::vector<png_byte> aRow(aRowSizeBytes, 0);
348 for (png_uint_32 y = 0;
y < height;
y++)
350 Scanline pScanline = pWriteAccess->GetScanline(y);
351 Scanline pScanAlpha = pWriteAccessAlpha->GetScanline(y);
352 png_bytep pRow = aRow.data();
353 png_read_row(pPng, pRow,
nullptr);
356 for (
size_t i = 0;
i < aRowSizeBytes;
i += 4)
358 pScanline[iColor++] = pRow[
i + 0];
359 pScanline[iColor++] = pRow[
i + 1];
360 pScanline[iColor++] = pRow[
i + 2];
361 pScanAlpha[iAlpha++] = 0xFF - pRow[
i + 3];
367 std::vector<std::vector<png_byte>> aRows(height);
368 for (
auto& rRow : aRows)
369 rRow.resize(aRowSizeBytes, 0);
370 for (
int pass = 0;
pass < nNumberOfPasses;
pass++)
372 for (png_uint_32 y = 0;
y < height;
y++)
374 Scanline pScanline = pWriteAccess->GetScanline(y);
375 Scanline pScanAlpha = pWriteAccessAlpha->GetScanline(y);
376 png_bytep pRow = aRows[
y].data();
377 png_read_row(pPng, pRow,
nullptr);
380 for (
size_t i = 0;
i < aRowSizeBytes;
i += 4)
382 pScanline[iColor++] = pRow[
i + 0];
383 pScanline[iColor++] = pRow[
i + 1];
384 pScanline[iColor++] = pRow[
i + 2];
385 pScanAlpha[iAlpha++] = 0xFF - pRow[
i + 3];
392 else if (colorType == PNG_COLOR_TYPE_GRAY)
394 for (
int pass = 0;
pass < nNumberOfPasses;
pass++)
396 for (png_uint_32 y = 0;
y < height;
y++)
398 Scanline pScanline = pWriteAccess->GetScanline(y);
399 png_read_row(pPng, pScanline,
nullptr);
404 png_read_end(pPng, pInfo);
406 if (!bUseExistingBitmap)
408 pWriteAccess.
reset();
409 pWriteAccessAlpha.
reset();
411 rBitmapEx =
BitmapEx(aBitmap, aBitmapAlpha);
440 constexpr sal_uInt32 PNGCHUNK_msOG = 0x6d734f47;
441 constexpr sal_uInt64 MSGifHeaderSize = 11;
442 if (type == PNGCHUNK_msOG && length > MSGifHeaderSize)
445 sal_uInt32 typeForCrc =
type;
446#if defined(__LITTLEENDIAN) || defined(OSL_LITENDIAN)
447 typeForCrc = OSL_SWAPDWORD(typeForCrc);
449 sal_uInt32 computedCrc = rtl_crc32(0, &typeForCrc, 4);
450 const sal_uInt64
pos = rStream.
Tell();
451 if (pos + length >= rStream.
TellEnd())
454 char msHeader[MSGifHeaderSize];
455 if (rStream.
ReadBytes(msHeader, MSGifHeaderSize) != MSGifHeaderSize)
457 computedCrc = rtl_crc32(computedCrc, msHeader, MSGifHeaderSize);
458 length -= MSGifHeaderSize;
463 computedCrc = rtl_crc32(computedCrc, chunk.getData(), chunk.getSize());
465 if (!ignoreCrc && crc != computedCrc)
473 constexpr sal_uInt32 PNGCHUNK_IEND = 0x49454e44;
474 if (type == PNGCHUNK_IEND)
478#if defined __GNUC__ && __GNUC__ == 8 && !defined __clang__
479#pragma GCC diagnostic pop
502 sal_uInt64 originalPosition = rStream.
Tell();
505 auto chunk = getMsGifChunk(rStream);
507 rStream.
Seek(originalPosition);
516 if (reader(
rInputStream, bitmap, nImportFlags, pAccess, pAlphaAccess))
vcl::ScopedBitmapAccess< BitmapWriteAccess, AlphaMask, &AlphaMask::AcquireAlphaWriteAccess > AlphaScopedWriteAccess
vcl::ScopedBitmapAccess< BitmapWriteAccess, Bitmap, &Bitmap::AcquireWriteAccess > BitmapScopedWriteAccess
Container for the binary data, whose responsibility is to manage the make it as simple as possible to...
void SetPrefMapMode(const MapMode &rPrefMapMode)
void SetPrefSize(const Size &rPrefSize)
static const BitmapPalette & GetGreyPalette(int nEntries)
bool supportsBitmap32() const
void SetEndian(SvStreamEndian SvStreamEndian)
virtual sal_uInt64 TellEnd()
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
SvStreamEndian GetEndian() const
sal_uInt64 Seek(sal_uInt64 nPos)
std::size_t ReadBytes(void *pData, std::size_t nSize)
sal_uInt64 SeekRel(sal_Int64 nPos)
sal_uInt64 remainingSize()
PngImageReader(SvStream &rStream)
static BinaryDataContainer getMicrosoftGifChunk(SvStream &rStream)
This template handles BitmapAccess the RAII way.
Reference< XInputStream > rInputStream
@ UseExistingBitmap
Read pixel data into an existing bitmap.
@ OnlyCreateBitmap
Only create a bitmap, do not read pixel data.
sal_uInt8 premultiply(sal_uInt8 c, sal_uInt8 a)
lookup_table const & get_premultiply_table()
std::array< std::array< sal_uInt8, 256 >, 256 > lookup_table
bool ImportPNG(SvStream &rInputStream, Graphic &rGraphic, GraphicFilterImportFlags nImportFlags, BitmapScopedWriteAccess *pAccess, AlphaScopedWriteAccess *pAlphaAccess)
ImplSVData * ImplGetSVData()