The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

655 lines
21KB

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