Audio plugin host https://kx.studio/carla
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.

juce_PNGLoader.cpp 20KB

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