1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2020 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11 Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12
13 End User License Agreement: www.juce.com/juce-6-licence
14 Privacy Policy: www.juce.com/juce-privacy-policy
15
16 Or: You may also use this code under the terms of the GPL v3 (see
17 www.gnu.org/licenses).
18
19 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21 DISCLAIMED.
22
23 ==============================================================================
24 */
25
26 namespace juce
27 {
28
29 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4390 4611 4365 4267 4616 2544 2545)
30
31 namespace zlibNamespace
32 {
33 #if JUCE_INCLUDE_ZLIB_CODE
34 #undef OS_CODE
35 #undef fdopen
36 #define ZLIB_INTERNAL
37 #define NO_DUMMY_DECL
38 #include <juce_core/zip/zlib/zlib.h>
39 #undef OS_CODE
40 #else
41 #include JUCE_ZLIB_INCLUDE_PATH
42 #endif
43 }
44
45 #if ! defined (jmp_buf) || ! defined (longjmp)
46 #include <setjmp.h>
47 #endif
48
49 namespace pnglibNamespace
50 {
51 using namespace zlibNamespace;
52
53 #if JUCE_INCLUDE_PNGLIB_CODE || ! defined (JUCE_INCLUDE_PNGLIB_CODE)
54
55 #if _MSC_VER != 1310
56 using std::calloc; // (causes conflict in VS.NET 2003)
57 using std::malloc;
58 using std::free;
59 #endif
60
61 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wsign-conversion",
62 "-Wimplicit-fallthrough",
63 "-Wtautological-constant-out-of-range-compare",
64 "-Wzero-as-null-pointer-constant",
65 "-Wcomma")
66
67 #undef check
68 using std::abs;
69 #define NO_DUMMY_DECL
70 #define PNGLCONF_H 1
71
72 #if JUCE_ANDROID
73 #define PNG_ARM_NEON_SUPPORTED
74 #endif
75
76 #define PNG_16BIT_SUPPORTED
77 #define PNG_ALIGNED_MEMORY_SUPPORTED
78 #define PNG_BENIGN_ERRORS_SUPPORTED
79 #define PNG_BENIGN_READ_ERRORS_SUPPORTED
80 #define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
81 #define PNG_COLORSPACE_SUPPORTED
82 #define PNG_CONSOLE_IO_SUPPORTED
83 #define PNG_EASY_ACCESS_SUPPORTED
84 #define PNG_FIXED_POINT_SUPPORTED
85 #define PNG_FLOATING_ARITHMETIC_SUPPORTED
86 #define PNG_FLOATING_POINT_SUPPORTED
87 #define PNG_FORMAT_AFIRST_SUPPORTED
88 #define PNG_FORMAT_BGR_SUPPORTED
89 #define PNG_GAMMA_SUPPORTED
90 #define PNG_GET_PALETTE_MAX_SUPPORTED
91 #define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
92 #define PNG_INCH_CONVERSIONS_SUPPORTED
93 #define PNG_INFO_IMAGE_SUPPORTED
94 #define PNG_IO_STATE_SUPPORTED
95 #define PNG_POINTER_INDEXING_SUPPORTED
96 #define PNG_PROGRESSIVE_READ_SUPPORTED
97 #define PNG_READ_16BIT_SUPPORTED
98 #define PNG_READ_ALPHA_MODE_SUPPORTED
99 #define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
100 #define PNG_READ_BACKGROUND_SUPPORTED
101 #define PNG_READ_BGR_SUPPORTED
102 #define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
103 #define PNG_READ_COMPOSITE_NODIV_SUPPORTED
104 #define PNG_READ_COMPRESSED_TEXT_SUPPORTED
105 #define PNG_READ_EXPAND_16_SUPPORTED
106 #define PNG_READ_EXPAND_SUPPORTED
107 #define PNG_READ_FILLER_SUPPORTED
108 #define PNG_READ_GAMMA_SUPPORTED
109 #define PNG_READ_GET_PALETTE_MAX_SUPPORTED
110 #define PNG_READ_GRAY_TO_RGB_SUPPORTED
111 #define PNG_READ_INTERLACING_SUPPORTED
112 #define PNG_READ_INT_FUNCTIONS_SUPPORTED
113 #define PNG_READ_INVERT_ALPHA_SUPPORTED
114 #define PNG_READ_INVERT_SUPPORTED
115 #define PNG_READ_OPT_PLTE_SUPPORTED
116 #define PNG_READ_PACKSWAP_SUPPORTED
117 #define PNG_READ_PACK_SUPPORTED
118 #define PNG_READ_QUANTIZE_SUPPORTED
119 #define PNG_READ_RGB_TO_GRAY_SUPPORTED
120 #define PNG_READ_SCALE_16_TO_8_SUPPORTED
121 #define PNG_READ_SHIFT_SUPPORTED
122 #define PNG_READ_STRIP_16_TO_8_SUPPORTED
123 #define PNG_READ_STRIP_ALPHA_SUPPORTED
124 #define PNG_READ_SUPPORTED
125 #define PNG_READ_SWAP_ALPHA_SUPPORTED
126 #define PNG_READ_SWAP_SUPPORTED
127 #define PNG_READ_TEXT_SUPPORTED
128 #define PNG_READ_TRANSFORMS_SUPPORTED
129 #define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
130 #define PNG_READ_USER_CHUNKS_SUPPORTED
131 #define PNG_READ_USER_TRANSFORM_SUPPORTED
132 #define PNG_READ_bKGD_SUPPORTED
133 #define PNG_READ_cHRM_SUPPORTED
134 #define PNG_READ_gAMA_SUPPORTED
135 #define PNG_READ_hIST_SUPPORTED
136 #define PNG_READ_iCCP_SUPPORTED
137 #define PNG_READ_iTXt_SUPPORTED
138 #define PNG_READ_oFFs_SUPPORTED
139 #define PNG_READ_pCAL_SUPPORTED
140 #define PNG_READ_pHYs_SUPPORTED
141 #define PNG_READ_sBIT_SUPPORTED
142 #define PNG_READ_sCAL_SUPPORTED
143 #define PNG_READ_sPLT_SUPPORTED
144 #define PNG_READ_sRGB_SUPPORTED
145 #define PNG_READ_tEXt_SUPPORTED
146 #define PNG_READ_tIME_SUPPORTED
147 #define PNG_READ_tRNS_SUPPORTED
148 #define PNG_READ_zTXt_SUPPORTED
149 #define PNG_SAVE_INT_32_SUPPORTED
150 #define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
151 #define PNG_SEQUENTIAL_READ_SUPPORTED
152 #define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
153 #define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
154 #define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
155 #define PNG_SET_USER_LIMITS_SUPPORTED
156 #define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
157 #define PNG_SIMPLIFIED_READ_BGR_SUPPORTED
158 #define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
159 #define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
160 #define PNG_STDIO_SUPPORTED
161 #define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
162 #define PNG_TEXT_SUPPORTED
163 #define PNG_TIME_RFC1123_SUPPORTED
164 #define PNG_UNKNOWN_CHUNKS_SUPPORTED
165 #define PNG_USER_CHUNKS_SUPPORTED
166 #define PNG_USER_LIMITS_SUPPORTED
167 #define PNG_USER_TRANSFORM_INFO_SUPPORTED
168 #define PNG_USER_TRANSFORM_PTR_SUPPORTED
169 #define PNG_WARNINGS_SUPPORTED
170 #define PNG_WRITE_16BIT_SUPPORTED
171 #define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
172 #define PNG_WRITE_BGR_SUPPORTED
173 #define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
174 #define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
175 #define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
176 #define PNG_WRITE_FILLER_SUPPORTED
177 #define PNG_WRITE_FILTER_SUPPORTED
178 #define PNG_WRITE_FLUSH_SUPPORTED
179 #define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED
180 #define PNG_WRITE_INTERLACING_SUPPORTED
181 #define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
182 #define PNG_WRITE_INVERT_ALPHA_SUPPORTED
183 #define PNG_WRITE_INVERT_SUPPORTED
184 #define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
185 #define PNG_WRITE_PACKSWAP_SUPPORTED
186 #define PNG_WRITE_PACK_SUPPORTED
187 #define PNG_WRITE_SHIFT_SUPPORTED
188 #define PNG_WRITE_SUPPORTED
189 #define PNG_WRITE_SWAP_ALPHA_SUPPORTED
190 #define PNG_WRITE_SWAP_SUPPORTED
191 #define PNG_WRITE_TEXT_SUPPORTED
192 #define PNG_WRITE_TRANSFORMS_SUPPORTED
193 #define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
194 #define PNG_WRITE_USER_TRANSFORM_SUPPORTED
195 #define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
196 #define PNG_WRITE_bKGD_SUPPORTED
197 #define PNG_WRITE_cHRM_SUPPORTED
198 #define PNG_WRITE_gAMA_SUPPORTED
199 #define PNG_WRITE_hIST_SUPPORTED
200 #define PNG_WRITE_iCCP_SUPPORTED
201 #define PNG_WRITE_iTXt_SUPPORTED
202 #define PNG_WRITE_oFFs_SUPPORTED
203 #define PNG_WRITE_pCAL_SUPPORTED
204 #define PNG_WRITE_pHYs_SUPPORTED
205 #define PNG_WRITE_sBIT_SUPPORTED
206 #define PNG_WRITE_sCAL_SUPPORTED
207 #define PNG_WRITE_sPLT_SUPPORTED
208 #define PNG_WRITE_sRGB_SUPPORTED
209 #define PNG_WRITE_tEXt_SUPPORTED
210 #define PNG_WRITE_tIME_SUPPORTED
211 #define PNG_WRITE_tRNS_SUPPORTED
212 #define PNG_WRITE_zTXt_SUPPORTED
213 #define PNG_bKGD_SUPPORTED
214 #define PNG_cHRM_SUPPORTED
215 #define PNG_gAMA_SUPPORTED
216 #define PNG_hIST_SUPPORTED
217 #define PNG_iCCP_SUPPORTED
218 #define PNG_iTXt_SUPPORTED
219 #define PNG_oFFs_SUPPORTED
220 #define PNG_pCAL_SUPPORTED
221 #define PNG_pHYs_SUPPORTED
222 #define PNG_sBIT_SUPPORTED
223 #define PNG_sCAL_SUPPORTED
224 #define PNG_sPLT_SUPPORTED
225 #define PNG_sRGB_SUPPORTED
226 #define PNG_tEXt_SUPPORTED
227 #define PNG_tIME_SUPPORTED
228 #define PNG_tRNS_SUPPORTED
229 #define PNG_zTXt_SUPPORTED
230
231 #define PNG_STRING_COPYRIGHT "";
232 #define PNG_STRING_NEWLINE "\n"
233 #define PNG_LITERAL_SHARP 0x23
234 #define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b
235 #define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d
236
237 #define PNG_API_RULE 0
238 #define PNG_CALLOC_SUPPORTED
239 #define PNG_COST_SHIFT 3
240 #define PNG_DEFAULT_READ_MACROS 1
241 #define PNG_GAMMA_THRESHOLD_FIXED 5000
242 #define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
243 #define PNG_INFLATE_BUF_SIZE 1024
244 #define PNG_MAX_GAMMA_8 11
245 #define PNG_QUANTIZE_BLUE_BITS 5
246 #define PNG_QUANTIZE_GREEN_BITS 5
247 #define PNG_QUANTIZE_RED_BITS 5
248 #define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1)
249 #define PNG_TEXT_Z_DEFAULT_STRATEGY 0
250 #define PNG_WEIGHT_SHIFT 8
251 #define PNG_ZBUF_SIZE 8192
252 #define PNG_Z_DEFAULT_COMPRESSION (-1)
253 #define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
254 #define PNG_Z_DEFAULT_STRATEGY 1
255 #define PNG_sCAL_PRECISION 5
256 #define PNG_sRGB_PROFILE_CHECKS 2
257
258 #define PNG_LINKAGE_API
259 #define PNG_LINKAGE_FUNCTION
260
261 #define PNG_ARM_NEON_OPT 0
262
263 #if ! defined (PNG_USER_WIDTH_MAX)
264 #define PNG_USER_WIDTH_MAX 1000000
265 #endif
266
267 #if ! defined (PNG_USER_HEIGHT_MAX)
268 #define PNG_USER_HEIGHT_MAX 1000000
269 #endif
270
271 #define png_debug(a, b)
272 #define png_debug1(a, b, c)
273 #define png_debug2(a, b, c, d)
274
275 #include "pnglib/png.h"
276 #include "pnglib/pngconf.h"
277
278 #define PNG_NO_EXTERN
279 #include "pnglib/png.c"
280 #include "pnglib/pngerror.c"
281 #include "pnglib/pngget.c"
282 #include "pnglib/pngmem.c"
283 #include "pnglib/pngread.c"
284 #include "pnglib/pngpread.c"
285 #include "pnglib/pngrio.c"
286
287 void png_do_expand_palette (png_row_infop, png_bytep, png_const_colorp, png_const_bytep, int);
288 void png_do_expand (png_row_infop, png_bytep, png_const_color_16p);
289 void png_do_chop (png_row_infop, png_bytep);
290 void png_do_quantize (png_row_infop, png_bytep, png_const_bytep, png_const_bytep);
291 void png_do_gray_to_rgb (png_row_infop, png_bytep);
292 void png_do_unshift (png_row_infop, png_bytep, png_const_color_8p);
293 void png_do_unpack (png_row_infop, png_bytep);
294 int png_do_rgb_to_gray (png_structrp, png_row_infop, png_bytep);
295 void png_do_compose (png_row_infop, png_bytep, png_structrp);
296 void png_do_gamma (png_row_infop, png_bytep, png_structrp);
297 void png_do_encode_alpha (png_row_infop, png_bytep, png_structrp);
298 void png_do_scale_16_to_8 (png_row_infop, png_bytep);
299 void png_do_expand_16 (png_row_infop, png_bytep);
300 void png_do_read_filler (png_row_infop, png_bytep, png_uint_32, png_uint_32);
301 void png_do_read_invert_alpha (png_row_infop, png_bytep);
302 void png_do_read_swap_alpha (png_row_infop, png_bytep);
303
304 #include "pnglib/pngrtran.c"
305 #include "pnglib/pngrutil.c"
306 #include "pnglib/pngset.c"
307 #include "pnglib/pngtrans.c"
308 #include "pnglib/pngwio.c"
309 #include "pnglib/pngwrite.c"
310 #include "pnglib/pngwtran.c"
311 #include "pnglib/pngwutil.c"
312
313 JUCE_END_IGNORE_WARNINGS_GCC_LIKE
314
315 #else
316 extern "C"
317 {
318 #include <png.h>
319 #include <pngconf.h>
320 }
321 #endif
322 }
323
324 #undef max
325 #undef min
326 #undef fdopen
327
328 JUCE_END_IGNORE_WARNINGS_MSVC
329
330 //==============================================================================
331 namespace PNGHelpers
332 {
333 using namespace pnglibNamespace;
334
writeDataCallback(png_structp png,png_bytep data,png_size_t length)335 static void JUCE_CDECL writeDataCallback (png_structp png, png_bytep data, png_size_t length)
336 {
337 static_cast<OutputStream*> (png_get_io_ptr (png))->write (data, length);
338 }
339
340 #if ! JUCE_USING_COREIMAGE_LOADER
readCallback(png_structp png,png_bytep data,png_size_t length)341 static void JUCE_CDECL readCallback (png_structp png, png_bytep data, png_size_t length)
342 {
343 static_cast<InputStream*> (png_get_io_ptr (png))->read (data, (int) length);
344 }
345
346 struct PNGErrorStruct {};
347
errorCallback(png_structp p,png_const_charp)348 static void JUCE_CDECL errorCallback (png_structp p, png_const_charp)
349 {
350 #ifdef PNG_SETJMP_SUPPORTED
351 setjmp(png_jmpbuf(p));
352 #else
353 longjmp (*(jmp_buf*) p->error_ptr, 1);
354 #endif
355 }
356
warningCallback(png_structp,png_const_charp)357 static void JUCE_CDECL warningCallback (png_structp, png_const_charp) {}
358
359 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4611)
360
readHeader(InputStream & in,png_structp pngReadStruct,png_infop pngInfoStruct,jmp_buf & errorJumpBuf,png_uint_32 & width,png_uint_32 & height,int & bitDepth,int & colorType,int & interlaceType)361 static bool readHeader (InputStream& in, png_structp pngReadStruct, png_infop pngInfoStruct, jmp_buf& errorJumpBuf,
362 png_uint_32& width, png_uint_32& height, int& bitDepth, int& colorType, int& interlaceType) noexcept
363 {
364 if (setjmp (errorJumpBuf) == 0)
365 {
366 // read the header..
367 png_set_read_fn (pngReadStruct, &in, readCallback);
368
369 png_read_info (pngReadStruct, pngInfoStruct);
370
371 png_get_IHDR (pngReadStruct, pngInfoStruct,
372 &width, &height,
373 &bitDepth, &colorType,
374 &interlaceType, nullptr, nullptr);
375
376 if (bitDepth == 16)
377 png_set_strip_16 (pngReadStruct);
378
379 if (colorType == PNG_COLOR_TYPE_PALETTE)
380 png_set_expand (pngReadStruct);
381
382 if (bitDepth < 8)
383 png_set_expand (pngReadStruct);
384
385 if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA)
386 png_set_gray_to_rgb (pngReadStruct);
387
388 return true;
389 }
390
391 return false;
392 }
393
readImageData(png_structp pngReadStruct,png_infop pngInfoStruct,jmp_buf & errorJumpBuf,png_bytepp rows)394 static bool readImageData (png_structp pngReadStruct, png_infop pngInfoStruct, jmp_buf& errorJumpBuf, png_bytepp rows) noexcept
395 {
396 if (setjmp (errorJumpBuf) == 0)
397 {
398 if (png_get_valid (pngReadStruct, pngInfoStruct, PNG_INFO_tRNS))
399 png_set_expand (pngReadStruct);
400
401 png_set_add_alpha (pngReadStruct, 0xff, PNG_FILLER_AFTER);
402
403 png_read_image (pngReadStruct, rows);
404 png_read_end (pngReadStruct, pngInfoStruct);
405 return true;
406 }
407
408 return false;
409 }
410
411 JUCE_END_IGNORE_WARNINGS_MSVC
412
createImageFromData(bool hasAlphaChan,int width,int height,png_bytepp rows)413 static Image createImageFromData (bool hasAlphaChan, int width, int height, png_bytepp rows)
414 {
415 // now convert the data to a juce image format..
416 Image image (hasAlphaChan ? Image::ARGB : Image::RGB, width, height, hasAlphaChan);
417
418 image.getProperties()->set ("originalImageHadAlpha", image.hasAlphaChannel());
419 hasAlphaChan = image.hasAlphaChannel(); // (the native image creator may not give back what we expect)
420
421 const Image::BitmapData destData (image, Image::BitmapData::writeOnly);
422
423 for (int y = 0; y < (int) height; ++y)
424 {
425 const uint8* src = rows[y];
426 uint8* dest = destData.getLinePointer (y);
427
428 if (hasAlphaChan)
429 {
430 for (int i = (int) width; --i >= 0;)
431 {
432 ((PixelARGB*) dest)->setARGB (src[3], src[0], src[1], src[2]);
433 ((PixelARGB*) dest)->premultiply();
434 dest += destData.pixelStride;
435 src += 4;
436 }
437 }
438 else
439 {
440 for (int i = (int) width; --i >= 0;)
441 {
442 ((PixelRGB*) dest)->setARGB (0, src[0], src[1], src[2]);
443 dest += destData.pixelStride;
444 src += 4;
445 }
446 }
447 }
448
449 return image;
450 }
451
readImage(InputStream & in,png_structp pngReadStruct,png_infop pngInfoStruct)452 static Image readImage (InputStream& in, png_structp pngReadStruct, png_infop pngInfoStruct)
453 {
454 jmp_buf errorJumpBuf;
455 png_set_error_fn (pngReadStruct, &errorJumpBuf, errorCallback, warningCallback);
456
457 png_uint_32 width = 0, height = 0;
458 int bitDepth = 0, colorType = 0, interlaceType = 0;
459
460 if (readHeader (in, pngReadStruct, pngInfoStruct, errorJumpBuf,
461 width, height, bitDepth, colorType, interlaceType))
462 {
463 // Load the image into a temp buffer..
464 const size_t lineStride = width * 4;
465 HeapBlock<uint8> tempBuffer (height * lineStride);
466 HeapBlock<png_bytep> rows (height);
467
468 for (size_t y = 0; y < height; ++y)
469 rows[y] = (png_bytep) (tempBuffer + lineStride * y);
470
471 png_bytep trans_alpha = nullptr;
472 png_color_16p trans_color = nullptr;
473 int num_trans = 0;
474 png_get_tRNS (pngReadStruct, pngInfoStruct, &trans_alpha, &num_trans, &trans_color);
475
476 if (readImageData (pngReadStruct, pngInfoStruct, errorJumpBuf, rows))
477 return createImageFromData ((colorType & PNG_COLOR_MASK_ALPHA) != 0 || num_trans != 0,
478 (int) width, (int) height, rows);
479 }
480
481 return Image();
482 }
483
readImage(InputStream & in)484 static Image readImage (InputStream& in)
485 {
486 if (png_structp pngReadStruct = png_create_read_struct (PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr))
487 {
488 if (png_infop pngInfoStruct = png_create_info_struct (pngReadStruct))
489 {
490 Image image (readImage (in, pngReadStruct, pngInfoStruct));
491 png_destroy_read_struct (&pngReadStruct, &pngInfoStruct, nullptr);
492 return image;
493 }
494
495 png_destroy_read_struct (&pngReadStruct, nullptr, nullptr);
496 }
497
498 return Image();
499 }
500 #endif
501 }
502
503 //==============================================================================
PNGImageFormat()504 PNGImageFormat::PNGImageFormat() {}
~PNGImageFormat()505 PNGImageFormat::~PNGImageFormat() {}
506
getFormatName()507 String PNGImageFormat::getFormatName() { return "PNG"; }
usesFileExtension(const File & f)508 bool PNGImageFormat::usesFileExtension (const File& f) { return f.hasFileExtension ("png"); }
509
canUnderstand(InputStream & in)510 bool PNGImageFormat::canUnderstand (InputStream& in)
511 {
512 const int bytesNeeded = 4;
513 char header [bytesNeeded];
514
515 return in.read (header, bytesNeeded) == bytesNeeded
516 && header[1] == 'P'
517 && header[2] == 'N'
518 && header[3] == 'G';
519 }
520
521 #if JUCE_USING_COREIMAGE_LOADER
522 Image juce_loadWithCoreImage (InputStream&);
523 #endif
524
decodeImage(InputStream & in)525 Image PNGImageFormat::decodeImage (InputStream& in)
526 {
527 #if JUCE_USING_COREIMAGE_LOADER
528 return juce_loadWithCoreImage (in);
529 #else
530 return PNGHelpers::readImage (in);
531 #endif
532 }
533
writeImageToStream(const Image & image,OutputStream & out)534 bool PNGImageFormat::writeImageToStream (const Image& image, OutputStream& out)
535 {
536 using namespace pnglibNamespace;
537 auto width = image.getWidth();
538 auto height = image.getHeight();
539
540 auto pngWriteStruct = png_create_write_struct (PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
541
542 if (pngWriteStruct == nullptr)
543 return false;
544
545 auto pngInfoStruct = png_create_info_struct (pngWriteStruct);
546
547 if (pngInfoStruct == nullptr)
548 {
549 png_destroy_write_struct (&pngWriteStruct, nullptr);
550 return false;
551 }
552
553 png_set_write_fn (pngWriteStruct, &out, PNGHelpers::writeDataCallback, nullptr);
554
555 png_set_IHDR (pngWriteStruct, pngInfoStruct, (png_uint_32) width, (png_uint_32) height, 8,
556 image.hasAlphaChannel() ? PNG_COLOR_TYPE_RGB_ALPHA
557 : PNG_COLOR_TYPE_RGB,
558 PNG_INTERLACE_NONE,
559 PNG_COMPRESSION_TYPE_BASE,
560 PNG_FILTER_TYPE_BASE);
561
562 HeapBlock<uint8> rowData (width * 4);
563
564 png_color_8 sig_bit;
565 sig_bit.red = 8;
566 sig_bit.green = 8;
567 sig_bit.blue = 8;
568 sig_bit.gray = 0;
569 sig_bit.alpha = 8;
570 png_set_sBIT (pngWriteStruct, pngInfoStruct, &sig_bit);
571
572 png_write_info (pngWriteStruct, pngInfoStruct);
573
574 png_set_shift (pngWriteStruct, &sig_bit);
575 png_set_packing (pngWriteStruct);
576
577 const Image::BitmapData srcData (image, Image::BitmapData::readOnly);
578
579 for (int y = 0; y < height; ++y)
580 {
581 uint8* dst = rowData;
582 const uint8* src = srcData.getLinePointer (y);
583
584 if (image.hasAlphaChannel())
585 {
586 for (int i = width; --i >= 0;)
587 {
588 PixelARGB p (*(const PixelARGB*) src);
589 p.unpremultiply();
590
591 *dst++ = p.getRed();
592 *dst++ = p.getGreen();
593 *dst++ = p.getBlue();
594 *dst++ = p.getAlpha();
595 src += srcData.pixelStride;
596 }
597 }
598 else
599 {
600 for (int i = width; --i >= 0;)
601 {
602 *dst++ = ((const PixelRGB*) src)->getRed();
603 *dst++ = ((const PixelRGB*) src)->getGreen();
604 *dst++ = ((const PixelRGB*) src)->getBlue();
605 src += srcData.pixelStride;
606 }
607 }
608
609 png_bytep rowPtr = rowData;
610 png_write_rows (pngWriteStruct, &rowPtr, 1);
611 }
612
613 png_write_end (pngWriteStruct, pngInfoStruct);
614 png_destroy_write_struct (&pngWriteStruct, &pngInfoStruct);
615
616 return true;
617 }
618
619 } // namespace juce
620