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.

1607 lines
48KB

  1. /* pngset.c - storage of image information into info struct
  2. *
  3. * Last changed in libpng 1.6.1 [March 28, 2013]
  4. * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  5. * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  6. * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  7. *
  8. * This code is released under the libpng license.
  9. * For conditions of distribution and use, see the disclaimer
  10. * and license in png.h
  11. *
  12. * The functions here are used during reads to store data from the file
  13. * into the info struct, and during writes to store application data
  14. * into the info struct for writing into the file. This abstracts the
  15. * info struct and allows us to change the structure in the future.
  16. */
  17. #include "pngpriv.h"
  18. #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
  19. #ifdef PNG_bKGD_SUPPORTED
  20. void PNGAPI
  21. png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
  22. png_const_color_16p background)
  23. {
  24. png_debug1(1, "in %s storage function", "bKGD");
  25. if (png_ptr == NULL || info_ptr == NULL || background == NULL)
  26. return;
  27. info_ptr->background = *background;
  28. info_ptr->valid |= PNG_INFO_bKGD;
  29. }
  30. #endif
  31. #ifdef PNG_cHRM_SUPPORTED
  32. void PNGFAPI
  33. png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
  34. png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
  35. png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
  36. png_fixed_point blue_x, png_fixed_point blue_y)
  37. {
  38. png_xy xy;
  39. png_debug1(1, "in %s storage function", "cHRM fixed");
  40. if (png_ptr == NULL || info_ptr == NULL)
  41. return;
  42. xy.redx = red_x;
  43. xy.redy = red_y;
  44. xy.greenx = green_x;
  45. xy.greeny = green_y;
  46. xy.bluex = blue_x;
  47. xy.bluey = blue_y;
  48. xy.whitex = white_x;
  49. xy.whitey = white_y;
  50. if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
  51. 2/* override with app values*/))
  52. info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
  53. png_colorspace_sync_info(png_ptr, info_ptr);
  54. }
  55. void PNGFAPI
  56. png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
  57. png_fixed_point int_red_X, png_fixed_point int_red_Y,
  58. png_fixed_point int_red_Z, png_fixed_point int_green_X,
  59. png_fixed_point int_green_Y, png_fixed_point int_green_Z,
  60. png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
  61. png_fixed_point int_blue_Z)
  62. {
  63. png_XYZ XYZ;
  64. png_debug1(1, "in %s storage function", "cHRM XYZ fixed");
  65. if (png_ptr == NULL || info_ptr == NULL)
  66. return;
  67. XYZ.red_X = int_red_X;
  68. XYZ.red_Y = int_red_Y;
  69. XYZ.red_Z = int_red_Z;
  70. XYZ.green_X = int_green_X;
  71. XYZ.green_Y = int_green_Y;
  72. XYZ.green_Z = int_green_Z;
  73. XYZ.blue_X = int_blue_X;
  74. XYZ.blue_Y = int_blue_Y;
  75. XYZ.blue_Z = int_blue_Z;
  76. if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace, &XYZ, 2))
  77. info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
  78. png_colorspace_sync_info(png_ptr, info_ptr);
  79. }
  80. # ifdef PNG_FLOATING_POINT_SUPPORTED
  81. void PNGAPI
  82. png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
  83. double white_x, double white_y, double red_x, double red_y,
  84. double green_x, double green_y, double blue_x, double blue_y)
  85. {
  86. png_set_cHRM_fixed(png_ptr, info_ptr,
  87. png_fixed(png_ptr, white_x, "cHRM White X"),
  88. png_fixed(png_ptr, white_y, "cHRM White Y"),
  89. png_fixed(png_ptr, red_x, "cHRM Red X"),
  90. png_fixed(png_ptr, red_y, "cHRM Red Y"),
  91. png_fixed(png_ptr, green_x, "cHRM Green X"),
  92. png_fixed(png_ptr, green_y, "cHRM Green Y"),
  93. png_fixed(png_ptr, blue_x, "cHRM Blue X"),
  94. png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
  95. }
  96. void PNGAPI
  97. png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
  98. double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
  99. double blue_X, double blue_Y, double blue_Z)
  100. {
  101. png_set_cHRM_XYZ_fixed(png_ptr, info_ptr,
  102. png_fixed(png_ptr, red_X, "cHRM Red X"),
  103. png_fixed(png_ptr, red_Y, "cHRM Red Y"),
  104. png_fixed(png_ptr, red_Z, "cHRM Red Z"),
  105. png_fixed(png_ptr, green_X, "cHRM Red X"),
  106. png_fixed(png_ptr, green_Y, "cHRM Red Y"),
  107. png_fixed(png_ptr, green_Z, "cHRM Red Z"),
  108. png_fixed(png_ptr, blue_X, "cHRM Red X"),
  109. png_fixed(png_ptr, blue_Y, "cHRM Red Y"),
  110. png_fixed(png_ptr, blue_Z, "cHRM Red Z"));
  111. }
  112. # endif /* PNG_FLOATING_POINT_SUPPORTED */
  113. #endif /* PNG_cHRM_SUPPORTED */
  114. #ifdef PNG_gAMA_SUPPORTED
  115. void PNGFAPI
  116. png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
  117. png_fixed_point file_gamma)
  118. {
  119. png_debug1(1, "in %s storage function", "gAMA");
  120. if (png_ptr == NULL || info_ptr == NULL)
  121. return;
  122. png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
  123. png_colorspace_sync_info(png_ptr, info_ptr);
  124. }
  125. # ifdef PNG_FLOATING_POINT_SUPPORTED
  126. void PNGAPI
  127. png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma)
  128. {
  129. png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
  130. "png_set_gAMA"));
  131. }
  132. # endif
  133. #endif
  134. #ifdef PNG_hIST_SUPPORTED
  135. void PNGAPI
  136. png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
  137. png_const_uint_16p hist)
  138. {
  139. int i;
  140. png_debug1(1, "in %s storage function", "hIST");
  141. if (png_ptr == NULL || info_ptr == NULL)
  142. return;
  143. if (info_ptr->num_palette == 0 || info_ptr->num_palette
  144. > PNG_MAX_PALETTE_LENGTH)
  145. {
  146. png_warning(png_ptr,
  147. "Invalid palette size, hIST allocation skipped");
  148. return;
  149. }
  150. png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
  151. /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
  152. * version 1.2.1
  153. */
  154. info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr,
  155. PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16))));
  156. if (info_ptr->hist == NULL)
  157. {
  158. png_warning(png_ptr, "Insufficient memory for hIST chunk data");
  159. return;
  160. }
  161. info_ptr->free_me |= PNG_FREE_HIST;
  162. for (i = 0; i < info_ptr->num_palette; i++)
  163. info_ptr->hist[i] = hist[i];
  164. info_ptr->valid |= PNG_INFO_hIST;
  165. }
  166. #endif
  167. void PNGAPI
  168. png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
  169. png_uint_32 width, png_uint_32 height, int bit_depth,
  170. int color_type, int interlace_type, int compression_type,
  171. int filter_type)
  172. {
  173. png_debug1(1, "in %s storage function", "IHDR");
  174. if (png_ptr == NULL || info_ptr == NULL)
  175. return;
  176. info_ptr->width = width;
  177. info_ptr->height = height;
  178. info_ptr->bit_depth = (png_byte)bit_depth;
  179. info_ptr->color_type = (png_byte)color_type;
  180. info_ptr->compression_type = (png_byte)compression_type;
  181. info_ptr->filter_type = (png_byte)filter_type;
  182. info_ptr->interlace_type = (png_byte)interlace_type;
  183. png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
  184. info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
  185. info_ptr->compression_type, info_ptr->filter_type);
  186. if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  187. info_ptr->channels = 1;
  188. else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
  189. info_ptr->channels = 3;
  190. else
  191. info_ptr->channels = 1;
  192. if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
  193. info_ptr->channels++;
  194. info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
  195. /* Check for potential overflow */
  196. if (width >
  197. (PNG_UINT_32_MAX >> 3) /* 8-byte RRGGBBAA pixels */
  198. - 48 /* bigrowbuf hack */
  199. - 1 /* filter byte */
  200. - 7*8 /* rounding of width to multiple of 8 pixels */
  201. - 8) /* extra max_pixel_depth pad */
  202. info_ptr->rowbytes = 0;
  203. else
  204. info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
  205. }
  206. #ifdef PNG_oFFs_SUPPORTED
  207. void PNGAPI
  208. png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr,
  209. png_int_32 offset_x, png_int_32 offset_y, int unit_type)
  210. {
  211. png_debug1(1, "in %s storage function", "oFFs");
  212. if (png_ptr == NULL || info_ptr == NULL)
  213. return;
  214. info_ptr->x_offset = offset_x;
  215. info_ptr->y_offset = offset_y;
  216. info_ptr->offset_unit_type = (png_byte)unit_type;
  217. info_ptr->valid |= PNG_INFO_oFFs;
  218. }
  219. #endif
  220. #ifdef PNG_pCAL_SUPPORTED
  221. void PNGAPI
  222. png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
  223. png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
  224. int nparams, png_const_charp units, png_charpp params)
  225. {
  226. png_size_t length;
  227. int i;
  228. png_debug1(1, "in %s storage function", "pCAL");
  229. if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
  230. || (nparams > 0 && params == NULL))
  231. return;
  232. length = strlen(purpose) + 1;
  233. png_debug1(3, "allocating purpose for info (%lu bytes)",
  234. (unsigned long)length);
  235. /* TODO: validate format of calibration name and unit name */
  236. /* Check that the type matches the specification. */
  237. if (type < 0 || type > 3)
  238. png_error(png_ptr, "Invalid pCAL equation type");
  239. if (nparams < 0 || nparams > 255)
  240. png_error(png_ptr, "Invalid pCAL parameter count");
  241. /* Validate params[nparams] */
  242. for (i=0; i<nparams; ++i)
  243. if (params[i] == NULL ||
  244. !png_check_fp_string(params[i], strlen(params[i])))
  245. png_error(png_ptr, "Invalid format for pCAL parameter");
  246. info_ptr->pcal_purpose = png_voidcast(png_charp,
  247. png_malloc_warn(png_ptr, length));
  248. if (info_ptr->pcal_purpose == NULL)
  249. {
  250. png_warning(png_ptr, "Insufficient memory for pCAL purpose");
  251. return;
  252. }
  253. memcpy(info_ptr->pcal_purpose, purpose, length);
  254. png_debug(3, "storing X0, X1, type, and nparams in info");
  255. info_ptr->pcal_X0 = X0;
  256. info_ptr->pcal_X1 = X1;
  257. info_ptr->pcal_type = (png_byte)type;
  258. info_ptr->pcal_nparams = (png_byte)nparams;
  259. length = strlen(units) + 1;
  260. png_debug1(3, "allocating units for info (%lu bytes)",
  261. (unsigned long)length);
  262. info_ptr->pcal_units = png_voidcast(png_charp,
  263. png_malloc_warn(png_ptr, length));
  264. if (info_ptr->pcal_units == NULL)
  265. {
  266. png_warning(png_ptr, "Insufficient memory for pCAL units");
  267. return;
  268. }
  269. memcpy(info_ptr->pcal_units, units, length);
  270. info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
  271. (png_size_t)((nparams + 1) * (sizeof (png_charp)))));
  272. if (info_ptr->pcal_params == NULL)
  273. {
  274. png_warning(png_ptr, "Insufficient memory for pCAL params");
  275. return;
  276. }
  277. memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp)));
  278. for (i = 0; i < nparams; i++)
  279. {
  280. length = strlen(params[i]) + 1;
  281. png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
  282. (unsigned long)length);
  283. info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
  284. if (info_ptr->pcal_params[i] == NULL)
  285. {
  286. png_warning(png_ptr, "Insufficient memory for pCAL parameter");
  287. return;
  288. }
  289. memcpy(info_ptr->pcal_params[i], params[i], length);
  290. }
  291. info_ptr->valid |= PNG_INFO_pCAL;
  292. info_ptr->free_me |= PNG_FREE_PCAL;
  293. }
  294. #endif
  295. #ifdef PNG_sCAL_SUPPORTED
  296. void PNGAPI
  297. png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
  298. int unit, png_const_charp swidth, png_const_charp sheight)
  299. {
  300. png_size_t lengthw = 0, lengthh = 0;
  301. png_debug1(1, "in %s storage function", "sCAL");
  302. if (png_ptr == NULL || info_ptr == NULL)
  303. return;
  304. /* Double check the unit (should never get here with an invalid
  305. * unit unless this is an API call.)
  306. */
  307. if (unit != 1 && unit != 2)
  308. png_error(png_ptr, "Invalid sCAL unit");
  309. if (swidth == NULL || (lengthw = strlen(swidth)) == 0 ||
  310. swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
  311. png_error(png_ptr, "Invalid sCAL width");
  312. if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
  313. sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
  314. png_error(png_ptr, "Invalid sCAL height");
  315. info_ptr->scal_unit = (png_byte)unit;
  316. ++lengthw;
  317. png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw);
  318. info_ptr->scal_s_width = png_voidcast(png_charp,
  319. png_malloc_warn(png_ptr, lengthw));
  320. if (info_ptr->scal_s_width == NULL)
  321. {
  322. png_warning(png_ptr, "Memory allocation failed while processing sCAL");
  323. return;
  324. }
  325. memcpy(info_ptr->scal_s_width, swidth, lengthw);
  326. ++lengthh;
  327. png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh);
  328. info_ptr->scal_s_height = png_voidcast(png_charp,
  329. png_malloc_warn(png_ptr, lengthh));
  330. if (info_ptr->scal_s_height == NULL)
  331. {
  332. png_free (png_ptr, info_ptr->scal_s_width);
  333. info_ptr->scal_s_width = NULL;
  334. png_warning(png_ptr, "Memory allocation failed while processing sCAL");
  335. return;
  336. }
  337. memcpy(info_ptr->scal_s_height, sheight, lengthh);
  338. info_ptr->valid |= PNG_INFO_sCAL;
  339. info_ptr->free_me |= PNG_FREE_SCAL;
  340. }
  341. # ifdef PNG_FLOATING_POINT_SUPPORTED
  342. void PNGAPI
  343. png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
  344. double width, double height)
  345. {
  346. png_debug1(1, "in %s storage function", "sCAL");
  347. /* Check the arguments. */
  348. if (width <= 0)
  349. png_warning(png_ptr, "Invalid sCAL width ignored");
  350. else if (height <= 0)
  351. png_warning(png_ptr, "Invalid sCAL height ignored");
  352. else
  353. {
  354. /* Convert 'width' and 'height' to ASCII. */
  355. char swidth[PNG_sCAL_MAX_DIGITS+1];
  356. char sheight[PNG_sCAL_MAX_DIGITS+1];
  357. png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
  358. PNG_sCAL_PRECISION);
  359. png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
  360. PNG_sCAL_PRECISION);
  361. png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
  362. }
  363. }
  364. # endif
  365. # ifdef PNG_FIXED_POINT_SUPPORTED
  366. void PNGAPI
  367. png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
  368. png_fixed_point width, png_fixed_point height)
  369. {
  370. png_debug1(1, "in %s storage function", "sCAL");
  371. /* Check the arguments. */
  372. if (width <= 0)
  373. png_warning(png_ptr, "Invalid sCAL width ignored");
  374. else if (height <= 0)
  375. png_warning(png_ptr, "Invalid sCAL height ignored");
  376. else
  377. {
  378. /* Convert 'width' and 'height' to ASCII. */
  379. char swidth[PNG_sCAL_MAX_DIGITS+1];
  380. char sheight[PNG_sCAL_MAX_DIGITS+1];
  381. png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width);
  382. png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height);
  383. png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
  384. }
  385. }
  386. # endif
  387. #endif
  388. #ifdef PNG_pHYs_SUPPORTED
  389. void PNGAPI
  390. png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr,
  391. png_uint_32 res_x, png_uint_32 res_y, int unit_type)
  392. {
  393. png_debug1(1, "in %s storage function", "pHYs");
  394. if (png_ptr == NULL || info_ptr == NULL)
  395. return;
  396. info_ptr->x_pixels_per_unit = res_x;
  397. info_ptr->y_pixels_per_unit = res_y;
  398. info_ptr->phys_unit_type = (png_byte)unit_type;
  399. info_ptr->valid |= PNG_INFO_pHYs;
  400. }
  401. #endif
  402. void PNGAPI
  403. png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
  404. png_const_colorp palette, int num_palette)
  405. {
  406. png_debug1(1, "in %s storage function", "PLTE");
  407. if (png_ptr == NULL || info_ptr == NULL)
  408. return;
  409. if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
  410. {
  411. if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
  412. png_error(png_ptr, "Invalid palette length");
  413. else
  414. {
  415. png_warning(png_ptr, "Invalid palette length");
  416. return;
  417. }
  418. }
  419. if ((num_palette > 0 && palette == NULL) ||
  420. (num_palette == 0
  421. # ifdef PNG_MNG_FEATURES_SUPPORTED
  422. && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
  423. # endif
  424. ))
  425. {
  426. png_chunk_report(png_ptr, "Invalid palette", PNG_CHUNK_ERROR);
  427. return;
  428. }
  429. /* It may not actually be necessary to set png_ptr->palette here;
  430. * we do it for backward compatibility with the way the png_handle_tRNS
  431. * function used to do the allocation.
  432. *
  433. * 1.6.0: the above statement appears to be incorrect; something has to set
  434. * the palette inside png_struct on read.
  435. */
  436. png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
  437. /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
  438. * of num_palette entries, in case of an invalid PNG file that has
  439. * too-large sample values.
  440. */
  441. png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
  442. PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
  443. if (num_palette > 0)
  444. memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
  445. info_ptr->palette = png_ptr->palette;
  446. info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
  447. info_ptr->free_me |= PNG_FREE_PLTE;
  448. info_ptr->valid |= PNG_INFO_PLTE;
  449. }
  450. #ifdef PNG_sBIT_SUPPORTED
  451. void PNGAPI
  452. png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
  453. png_const_color_8p sig_bit)
  454. {
  455. png_debug1(1, "in %s storage function", "sBIT");
  456. if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
  457. return;
  458. info_ptr->sig_bit = *sig_bit;
  459. info_ptr->valid |= PNG_INFO_sBIT;
  460. }
  461. #endif
  462. #ifdef PNG_sRGB_SUPPORTED
  463. void PNGAPI
  464. png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
  465. {
  466. png_debug1(1, "in %s storage function", "sRGB");
  467. if (png_ptr == NULL || info_ptr == NULL)
  468. return;
  469. (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
  470. png_colorspace_sync_info(png_ptr, info_ptr);
  471. }
  472. void PNGAPI
  473. png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
  474. int srgb_intent)
  475. {
  476. png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
  477. if (png_ptr == NULL || info_ptr == NULL)
  478. return;
  479. if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent))
  480. {
  481. /* This causes the gAMA and cHRM to be written too */
  482. info_ptr->colorspace.flags |=
  483. PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
  484. }
  485. png_colorspace_sync_info(png_ptr, info_ptr);
  486. }
  487. #endif /* sRGB */
  488. #ifdef PNG_iCCP_SUPPORTED
  489. void PNGAPI
  490. png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
  491. png_const_charp name, int compression_type,
  492. png_const_bytep profile, png_uint_32 proflen)
  493. {
  494. png_charp new_iccp_name;
  495. png_bytep new_iccp_profile;
  496. png_size_t length;
  497. png_debug1(1, "in %s storage function", "iCCP");
  498. if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
  499. return;
  500. if (compression_type != PNG_COMPRESSION_TYPE_BASE)
  501. png_app_error(png_ptr, "Invalid iCCP compression method");
  502. /* Set the colorspace first because this validates the profile; do not
  503. * override previously set app cHRM or gAMA here (because likely as not the
  504. * application knows better than libpng what the correct values are.) Pass
  505. * the info_ptr color_type field to png_colorspace_set_ICC because in the
  506. * write case it has not yet been stored in png_ptr.
  507. */
  508. {
  509. int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
  510. proflen, profile, info_ptr->color_type);
  511. png_colorspace_sync_info(png_ptr, info_ptr);
  512. /* Don't do any of the copying if the profile was bad, or inconsistent. */
  513. if (!result)
  514. return;
  515. /* But do write the gAMA and cHRM chunks from the profile. */
  516. info_ptr->colorspace.flags |=
  517. PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
  518. }
  519. length = strlen(name)+1;
  520. new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
  521. if (new_iccp_name == NULL)
  522. {
  523. png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");
  524. return;
  525. }
  526. memcpy(new_iccp_name, name, length);
  527. new_iccp_profile = png_voidcast(png_bytep,
  528. png_malloc_warn(png_ptr, proflen));
  529. if (new_iccp_profile == NULL)
  530. {
  531. png_free(png_ptr, new_iccp_name);
  532. png_benign_error(png_ptr,
  533. "Insufficient memory to process iCCP profile");
  534. return;
  535. }
  536. memcpy(new_iccp_profile, profile, proflen);
  537. png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
  538. info_ptr->iccp_proflen = proflen;
  539. info_ptr->iccp_name = new_iccp_name;
  540. info_ptr->iccp_profile = new_iccp_profile;
  541. info_ptr->free_me |= PNG_FREE_ICCP;
  542. info_ptr->valid |= PNG_INFO_iCCP;
  543. }
  544. #endif
  545. #ifdef PNG_TEXT_SUPPORTED
  546. void PNGAPI
  547. png_set_text(png_const_structrp png_ptr, png_inforp info_ptr,
  548. png_const_textp text_ptr, int num_text)
  549. {
  550. int ret;
  551. ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
  552. if (ret)
  553. png_error(png_ptr, "Insufficient memory to store text");
  554. }
  555. int /* PRIVATE */
  556. png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
  557. png_const_textp text_ptr, int num_text)
  558. {
  559. int i;
  560. png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" :
  561. (unsigned long)png_ptr->chunk_name);
  562. if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
  563. return(0);
  564. /* Make sure we have enough space in the "text" array in info_struct
  565. * to hold all of the incoming text_ptr objects. This compare can't overflow
  566. * because max_text >= num_text (anyway, subtract of two positive integers
  567. * can't overflow in any case.)
  568. */
  569. if (num_text > info_ptr->max_text - info_ptr->num_text)
  570. {
  571. int old_num_text = info_ptr->num_text;
  572. int max_text;
  573. png_textp new_text = NULL;
  574. /* Calculate an appropriate max_text, checking for overflow. */
  575. max_text = old_num_text;
  576. if (num_text <= INT_MAX - max_text)
  577. {
  578. max_text += num_text;
  579. /* Round up to a multiple of 8 */
  580. if (max_text < INT_MAX-8)
  581. max_text = (max_text + 8) & ~0x7;
  582. else
  583. max_text = INT_MAX;
  584. /* Now allocate a new array and copy the old members in, this does all
  585. * the overflow checks.
  586. */
  587. new_text = png_voidcast(png_textp,png_realloc_array(png_ptr,
  588. info_ptr->text, old_num_text, max_text-old_num_text,
  589. sizeof *new_text));
  590. }
  591. if (new_text == NULL)
  592. {
  593. png_chunk_report(png_ptr, "too many text chunks",
  594. PNG_CHUNK_WRITE_ERROR);
  595. return 1;
  596. }
  597. png_free(png_ptr, info_ptr->text);
  598. info_ptr->text = new_text;
  599. info_ptr->free_me |= PNG_FREE_TEXT;
  600. info_ptr->max_text = max_text;
  601. /* num_text is adjusted below as the entries are copied in */
  602. png_debug1(3, "allocated %d entries for info_ptr->text", max_text);
  603. }
  604. for (i = 0; i < num_text; i++)
  605. {
  606. size_t text_length, key_len;
  607. size_t lang_len, lang_key_len;
  608. png_textp textp = &(info_ptr->text[info_ptr->num_text]);
  609. if (text_ptr[i].key == NULL)
  610. continue;
  611. if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
  612. text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
  613. {
  614. png_chunk_report(png_ptr, "text compression mode is out of range",
  615. PNG_CHUNK_WRITE_ERROR);
  616. continue;
  617. }
  618. key_len = strlen(text_ptr[i].key);
  619. if (text_ptr[i].compression <= 0)
  620. {
  621. lang_len = 0;
  622. lang_key_len = 0;
  623. }
  624. else
  625. # ifdef PNG_iTXt_SUPPORTED
  626. {
  627. /* Set iTXt data */
  628. if (text_ptr[i].lang != NULL)
  629. lang_len = strlen(text_ptr[i].lang);
  630. else
  631. lang_len = 0;
  632. if (text_ptr[i].lang_key != NULL)
  633. lang_key_len = strlen(text_ptr[i].lang_key);
  634. else
  635. lang_key_len = 0;
  636. }
  637. # else /* PNG_iTXt_SUPPORTED */
  638. {
  639. png_chunk_report(png_ptr, "iTXt chunk not supported",
  640. PNG_CHUNK_WRITE_ERROR);
  641. continue;
  642. }
  643. # endif
  644. if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
  645. {
  646. text_length = 0;
  647. # ifdef PNG_iTXt_SUPPORTED
  648. if (text_ptr[i].compression > 0)
  649. textp->compression = PNG_ITXT_COMPRESSION_NONE;
  650. else
  651. # endif
  652. textp->compression = PNG_TEXT_COMPRESSION_NONE;
  653. }
  654. else
  655. {
  656. text_length = strlen(text_ptr[i].text);
  657. textp->compression = text_ptr[i].compression;
  658. }
  659. textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr,
  660. key_len + text_length + lang_len + lang_key_len + 4));
  661. if (textp->key == NULL)
  662. {
  663. png_chunk_report(png_ptr, "text chunk: out of memory",
  664. PNG_CHUNK_WRITE_ERROR);
  665. return 1;
  666. }
  667. png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
  668. (unsigned long)(png_uint_32)
  669. (key_len + lang_len + lang_key_len + text_length + 4),
  670. textp->key);
  671. memcpy(textp->key, text_ptr[i].key, key_len);
  672. *(textp->key + key_len) = '\0';
  673. if (text_ptr[i].compression > 0)
  674. {
  675. textp->lang = textp->key + key_len + 1;
  676. memcpy(textp->lang, text_ptr[i].lang, lang_len);
  677. *(textp->lang + lang_len) = '\0';
  678. textp->lang_key = textp->lang + lang_len + 1;
  679. memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
  680. *(textp->lang_key + lang_key_len) = '\0';
  681. textp->text = textp->lang_key + lang_key_len + 1;
  682. }
  683. else
  684. {
  685. textp->lang=NULL;
  686. textp->lang_key=NULL;
  687. textp->text = textp->key + key_len + 1;
  688. }
  689. if (text_length)
  690. memcpy(textp->text, text_ptr[i].text, text_length);
  691. *(textp->text + text_length) = '\0';
  692. # ifdef PNG_iTXt_SUPPORTED
  693. if (textp->compression > 0)
  694. {
  695. textp->text_length = 0;
  696. textp->itxt_length = text_length;
  697. }
  698. else
  699. # endif
  700. {
  701. textp->text_length = text_length;
  702. textp->itxt_length = 0;
  703. }
  704. info_ptr->num_text++;
  705. png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
  706. }
  707. return(0);
  708. }
  709. #endif
  710. #ifdef PNG_tIME_SUPPORTED
  711. void PNGAPI
  712. png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
  713. png_const_timep mod_time)
  714. {
  715. png_debug1(1, "in %s storage function", "tIME");
  716. if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
  717. (png_ptr->mode & PNG_WROTE_tIME))
  718. return;
  719. if (mod_time->month == 0 || mod_time->month > 12 ||
  720. mod_time->day == 0 || mod_time->day > 31 ||
  721. mod_time->hour > 23 || mod_time->minute > 59 ||
  722. mod_time->second > 60)
  723. {
  724. png_warning(png_ptr, "Ignoring invalid time value");
  725. return;
  726. }
  727. info_ptr->mod_time = *mod_time;
  728. info_ptr->valid |= PNG_INFO_tIME;
  729. }
  730. #endif
  731. #ifdef PNG_tRNS_SUPPORTED
  732. void PNGAPI
  733. png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
  734. png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
  735. {
  736. png_debug1(1, "in %s storage function", "tRNS");
  737. if (png_ptr == NULL || info_ptr == NULL)
  738. return;
  739. if (trans_alpha != NULL)
  740. {
  741. /* It may not actually be necessary to set png_ptr->trans_alpha here;
  742. * we do it for backward compatibility with the way the png_handle_tRNS
  743. * function used to do the allocation.
  744. *
  745. * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
  746. * relies on png_set_tRNS storing the information in png_struct
  747. * (otherwise it won't be there for the code in pngrtran.c).
  748. */
  749. png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
  750. /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
  751. png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep,
  752. png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
  753. if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
  754. memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
  755. }
  756. if (trans_color != NULL)
  757. {
  758. int sample_max = (1 << info_ptr->bit_depth);
  759. if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
  760. trans_color->gray > sample_max) ||
  761. (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
  762. (trans_color->red > sample_max ||
  763. trans_color->green > sample_max ||
  764. trans_color->blue > sample_max)))
  765. png_warning(png_ptr,
  766. "tRNS chunk has out-of-range samples for bit_depth");
  767. info_ptr->trans_color = *trans_color;
  768. if (num_trans == 0)
  769. num_trans = 1;
  770. }
  771. info_ptr->num_trans = (png_uint_16)num_trans;
  772. if (num_trans != 0)
  773. {
  774. info_ptr->valid |= PNG_INFO_tRNS;
  775. info_ptr->free_me |= PNG_FREE_TRNS;
  776. }
  777. }
  778. #endif
  779. #ifdef PNG_sPLT_SUPPORTED
  780. void PNGAPI
  781. png_set_sPLT(png_const_structrp png_ptr,
  782. png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
  783. /*
  784. * entries - array of png_sPLT_t structures
  785. * to be added to the list of palettes
  786. * in the info structure.
  787. *
  788. * nentries - number of palette structures to be
  789. * added.
  790. */
  791. {
  792. png_sPLT_tp np;
  793. if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
  794. return;
  795. /* Use the internal realloc function, which checks for all the possible
  796. * overflows. Notice that the parameters are (int) and (size_t)
  797. */
  798. np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr,
  799. info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
  800. sizeof *np));
  801. if (np == NULL)
  802. {
  803. /* Out of memory or too many chunks */
  804. png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);
  805. return;
  806. }
  807. png_free(png_ptr, info_ptr->splt_palettes);
  808. info_ptr->splt_palettes = np;
  809. info_ptr->free_me |= PNG_FREE_SPLT;
  810. np += info_ptr->splt_palettes_num;
  811. do
  812. {
  813. png_size_t length;
  814. /* Skip invalid input entries */
  815. if (entries->name == NULL || entries->entries == NULL)
  816. {
  817. /* png_handle_sPLT doesn't do this, so this is an app error */
  818. png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
  819. /* Just skip the invalid entry */
  820. continue;
  821. }
  822. np->depth = entries->depth;
  823. /* In the even of out-of-memory just return - there's no point keeping on
  824. * trying to add sPLT chunks.
  825. */
  826. length = strlen(entries->name) + 1;
  827. np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length));
  828. if (np->name == NULL)
  829. break;
  830. memcpy(np->name, entries->name, length);
  831. /* IMPORTANT: we have memory now that won't get freed if something else
  832. * goes wrong, this code must free it. png_malloc_array produces no
  833. * warnings, use a png_chunk_report (below) if there is an error.
  834. */
  835. np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr,
  836. entries->nentries, sizeof (png_sPLT_entry)));
  837. if (np->entries == NULL)
  838. {
  839. png_free(png_ptr, np->name);
  840. break;
  841. }
  842. np->nentries = entries->nentries;
  843. /* This multiply can't overflow because png_malloc_array has already
  844. * checked it when doing the allocation.
  845. */
  846. memcpy(np->entries, entries->entries,
  847. entries->nentries * sizeof (png_sPLT_entry));
  848. /* Note that 'continue' skips the advance of the out pointer and out
  849. * count, so an invalid entry is not added.
  850. */
  851. info_ptr->valid |= PNG_INFO_sPLT;
  852. ++(info_ptr->splt_palettes_num);
  853. ++np;
  854. }
  855. while (++entries, --nentries);
  856. if (nentries > 0)
  857. png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
  858. }
  859. #endif /* PNG_sPLT_SUPPORTED */
  860. #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
  861. static png_byte
  862. check_location(png_const_structrp png_ptr, int location)
  863. {
  864. location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
  865. /* New in 1.6.0; copy the location and check it. This is an API
  866. * change, previously the app had to use the
  867. * png_set_unknown_chunk_location API below for each chunk.
  868. */
  869. if (location == 0 && !(png_ptr->mode & PNG_IS_READ_STRUCT))
  870. {
  871. /* Write struct, so unknown chunks come from the app */
  872. png_app_warning(png_ptr,
  873. "png_set_unknown_chunks now expects a valid location");
  874. /* Use the old behavior */
  875. location = (png_byte)(png_ptr->mode &
  876. (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
  877. }
  878. /* This need not be an internal error - if the app calls
  879. * png_set_unknown_chunks on a read pointer it must get the location right.
  880. */
  881. if (location == 0)
  882. png_error(png_ptr, "invalid location in png_set_unknown_chunks");
  883. /* Now reduce the location to the top-most set bit by removing each least
  884. * significant bit in turn.
  885. */
  886. while (location != (location & -location))
  887. location &= ~(location & -location);
  888. /* The cast is safe because 'location' is a bit mask and only the low four
  889. * bits are significant.
  890. */
  891. return (png_byte)location;
  892. }
  893. void PNGAPI
  894. png_set_unknown_chunks(png_const_structrp png_ptr,
  895. png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
  896. {
  897. png_unknown_chunkp np;
  898. if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
  899. unknowns == NULL)
  900. return;
  901. /* Check for the failure cases where support has been disabled at compile
  902. * time. This code is hardly ever compiled - it's here because
  903. * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
  904. * code) but may be meaningless if the read or write handling of unknown
  905. * chunks is not compiled in.
  906. */
  907. # if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
  908. defined(PNG_READ_SUPPORTED)
  909. if (png_ptr->mode & PNG_IS_READ_STRUCT)
  910. {
  911. png_app_error(png_ptr, "no unknown chunk support on read");
  912. return;
  913. }
  914. # endif
  915. # if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
  916. defined(PNG_WRITE_SUPPORTED)
  917. if (!(png_ptr->mode & PNG_IS_READ_STRUCT))
  918. {
  919. png_app_error(png_ptr, "no unknown chunk support on write");
  920. return;
  921. }
  922. # endif
  923. /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
  924. * unknown critical chunks could be lost with just a warning resulting in
  925. * undefined behavior. Now png_chunk_report is used to provide behavior
  926. * appropriate to read or write.
  927. */
  928. np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr,
  929. info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
  930. sizeof *np));
  931. if (np == NULL)
  932. {
  933. png_chunk_report(png_ptr, "too many unknown chunks",
  934. PNG_CHUNK_WRITE_ERROR);
  935. return;
  936. }
  937. png_free(png_ptr, info_ptr->unknown_chunks);
  938. info_ptr->unknown_chunks = np; /* safe because it is initialized */
  939. info_ptr->free_me |= PNG_FREE_UNKN;
  940. np += info_ptr->unknown_chunks_num;
  941. /* Increment unknown_chunks_num each time round the loop to protect the
  942. * just-allocated chunk data.
  943. */
  944. for (; num_unknowns > 0; --num_unknowns, ++unknowns)
  945. {
  946. memcpy(np->name, unknowns->name, (sizeof np->name));
  947. np->name[(sizeof np->name)-1] = '\0';
  948. np->location = check_location(png_ptr, unknowns->location);
  949. if (unknowns->size == 0)
  950. {
  951. np->data = NULL;
  952. np->size = 0;
  953. }
  954. else
  955. {
  956. np->data = png_voidcast(png_bytep,
  957. png_malloc_base(png_ptr, unknowns->size));
  958. if (np->data == NULL)
  959. {
  960. png_chunk_report(png_ptr, "unknown chunk: out of memory",
  961. PNG_CHUNK_WRITE_ERROR);
  962. /* But just skip storing the unknown chunk */
  963. continue;
  964. }
  965. memcpy(np->data, unknowns->data, unknowns->size);
  966. np->size = unknowns->size;
  967. }
  968. /* These increments are skipped on out-of-memory for the data - the
  969. * unknown chunk entry gets overwritten if the png_chunk_report returns.
  970. * This is correct in the read case (the chunk is just dropped.)
  971. */
  972. ++np;
  973. ++(info_ptr->unknown_chunks_num);
  974. }
  975. }
  976. void PNGAPI
  977. png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
  978. int chunk, int location)
  979. {
  980. /* This API is pretty pointless in 1.6.0 because the location can be set
  981. * before the call to png_set_unknown_chunks.
  982. *
  983. * TODO: add a png_app_warning in 1.7
  984. */
  985. if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
  986. chunk < info_ptr->unknown_chunks_num)
  987. {
  988. if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
  989. {
  990. png_app_error(png_ptr, "invalid unknown chunk location");
  991. /* Fake out the pre 1.6.0 behavior: */
  992. if ((location & PNG_HAVE_IDAT)) /* undocumented! */
  993. location = PNG_AFTER_IDAT;
  994. else
  995. location = PNG_HAVE_IHDR; /* also undocumented */
  996. }
  997. info_ptr->unknown_chunks[chunk].location =
  998. check_location(png_ptr, location);
  999. }
  1000. }
  1001. #endif
  1002. #ifdef PNG_MNG_FEATURES_SUPPORTED
  1003. png_uint_32 PNGAPI
  1004. png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
  1005. {
  1006. png_debug(1, "in png_permit_mng_features");
  1007. if (png_ptr == NULL)
  1008. return 0;
  1009. png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
  1010. return png_ptr->mng_features_permitted;
  1011. }
  1012. #endif
  1013. #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
  1014. static unsigned int
  1015. add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep)
  1016. {
  1017. unsigned int i;
  1018. /* Utility function: update the 'keep' state of a chunk if it is already in
  1019. * the list, otherwise add it to the list.
  1020. */
  1021. for (i=0; i<count; ++i, list += 5) if (memcmp(list, add, 4) == 0)
  1022. {
  1023. list[4] = (png_byte)keep;
  1024. return count;
  1025. }
  1026. if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
  1027. {
  1028. ++count;
  1029. memcpy(list, add, 4);
  1030. list[4] = (png_byte)keep;
  1031. }
  1032. return count;
  1033. }
  1034. void PNGAPI
  1035. png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
  1036. png_const_bytep chunk_list, int num_chunks_in)
  1037. {
  1038. png_bytep new_list;
  1039. unsigned int num_chunks, old_num_chunks;
  1040. if (png_ptr == NULL)
  1041. return;
  1042. if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
  1043. {
  1044. png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
  1045. return;
  1046. }
  1047. if (num_chunks_in <= 0)
  1048. {
  1049. png_ptr->unknown_default = keep;
  1050. /* '0' means just set the flags, so stop here */
  1051. if (num_chunks_in == 0)
  1052. return;
  1053. }
  1054. if (num_chunks_in < 0)
  1055. {
  1056. /* Ignore all unknown chunks and all chunks recognized by
  1057. * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
  1058. */
  1059. static PNG_CONST png_byte chunks_to_ignore[] = {
  1060. 98, 75, 71, 68, '\0', /* bKGD */
  1061. 99, 72, 82, 77, '\0', /* cHRM */
  1062. 103, 65, 77, 65, '\0', /* gAMA */
  1063. 104, 73, 83, 84, '\0', /* hIST */
  1064. 105, 67, 67, 80, '\0', /* iCCP */
  1065. 105, 84, 88, 116, '\0', /* iTXt */
  1066. 111, 70, 70, 115, '\0', /* oFFs */
  1067. 112, 67, 65, 76, '\0', /* pCAL */
  1068. 112, 72, 89, 115, '\0', /* pHYs */
  1069. 115, 66, 73, 84, '\0', /* sBIT */
  1070. 115, 67, 65, 76, '\0', /* sCAL */
  1071. 115, 80, 76, 84, '\0', /* sPLT */
  1072. 115, 84, 69, 82, '\0', /* sTER */
  1073. 115, 82, 71, 66, '\0', /* sRGB */
  1074. 116, 69, 88, 116, '\0', /* tEXt */
  1075. 116, 73, 77, 69, '\0', /* tIME */
  1076. 122, 84, 88, 116, '\0' /* zTXt */
  1077. };
  1078. chunk_list = chunks_to_ignore;
  1079. num_chunks = (sizeof chunks_to_ignore)/5;
  1080. }
  1081. else /* num_chunks_in > 0 */
  1082. {
  1083. if (chunk_list == NULL)
  1084. {
  1085. /* Prior to 1.6.0 this was silently ignored, now it is an app_error
  1086. * which can be switched off.
  1087. */
  1088. png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
  1089. return;
  1090. }
  1091. num_chunks = num_chunks_in;
  1092. }
  1093. old_num_chunks = png_ptr->num_chunk_list;
  1094. if (png_ptr->chunk_list == NULL)
  1095. old_num_chunks = 0;
  1096. /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
  1097. */
  1098. if (num_chunks + old_num_chunks > UINT_MAX/5)
  1099. {
  1100. png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
  1101. return;
  1102. }
  1103. /* If these chunks are being reset to the default then no more memory is
  1104. * required because add_one_chunk above doesn't extend the list if the 'keep'
  1105. * parameter is the default.
  1106. */
  1107. if (keep)
  1108. {
  1109. new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
  1110. 5 * (num_chunks + old_num_chunks)));
  1111. if (old_num_chunks > 0)
  1112. memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
  1113. }
  1114. else if (old_num_chunks > 0)
  1115. new_list = png_ptr->chunk_list;
  1116. else
  1117. new_list = NULL;
  1118. /* Add the new chunks together with each one's handling code. If the chunk
  1119. * already exists the code is updated, otherwise the chunk is added to the
  1120. * end. (In libpng 1.6.0 order no longer matters because this code enforces
  1121. * the earlier convention that the last setting is the one that is used.)
  1122. */
  1123. if (new_list != NULL)
  1124. {
  1125. png_const_bytep inlist;
  1126. png_bytep outlist;
  1127. unsigned int i;
  1128. for (i=0; i<num_chunks; ++i)
  1129. old_num_chunks = add_one_chunk(new_list, old_num_chunks,
  1130. chunk_list+5*i, keep);
  1131. /* Now remove any spurious 'default' entries. */
  1132. num_chunks = 0;
  1133. for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5)
  1134. if (inlist[4])
  1135. {
  1136. if (outlist != inlist)
  1137. memcpy(outlist, inlist, 5);
  1138. outlist += 5;
  1139. ++num_chunks;
  1140. }
  1141. /* This means the application has removed all the specialized handling. */
  1142. if (num_chunks == 0)
  1143. {
  1144. if (png_ptr->chunk_list != new_list)
  1145. png_free(png_ptr, new_list);
  1146. new_list = NULL;
  1147. }
  1148. }
  1149. else
  1150. num_chunks = 0;
  1151. png_ptr->num_chunk_list = num_chunks;
  1152. if (png_ptr->chunk_list != new_list)
  1153. {
  1154. if (png_ptr->chunk_list != NULL)
  1155. png_free(png_ptr, png_ptr->chunk_list);
  1156. png_ptr->chunk_list = new_list;
  1157. }
  1158. }
  1159. #endif
  1160. #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
  1161. void PNGAPI
  1162. png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
  1163. png_user_chunk_ptr read_user_chunk_fn)
  1164. {
  1165. png_debug(1, "in png_set_read_user_chunk_fn");
  1166. if (png_ptr == NULL)
  1167. return;
  1168. png_ptr->read_user_chunk_fn = read_user_chunk_fn;
  1169. png_ptr->user_chunk_ptr = user_chunk_ptr;
  1170. }
  1171. #endif
  1172. #ifdef PNG_INFO_IMAGE_SUPPORTED
  1173. void PNGAPI
  1174. png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
  1175. png_bytepp row_pointers)
  1176. {
  1177. png_debug1(1, "in %s storage function", "rows");
  1178. if (png_ptr == NULL || info_ptr == NULL)
  1179. return;
  1180. if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
  1181. png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
  1182. info_ptr->row_pointers = row_pointers;
  1183. if (row_pointers)
  1184. info_ptr->valid |= PNG_INFO_IDAT;
  1185. }
  1186. #endif
  1187. void PNGAPI
  1188. png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
  1189. {
  1190. if (png_ptr == NULL)
  1191. return;
  1192. if (size == 0 || size > PNG_UINT_31_MAX)
  1193. png_error(png_ptr, "invalid compression buffer size");
  1194. # ifdef PNG_SEQUENTIAL_READ_SUPPORTED
  1195. if (png_ptr->mode & PNG_IS_READ_STRUCT)
  1196. {
  1197. png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
  1198. return;
  1199. }
  1200. # endif
  1201. # ifdef PNG_WRITE_SUPPORTED
  1202. if (!(png_ptr->mode & PNG_IS_READ_STRUCT))
  1203. {
  1204. if (png_ptr->zowner != 0)
  1205. {
  1206. png_warning(png_ptr,
  1207. "Compression buffer size cannot be changed because it is in use");
  1208. return;
  1209. }
  1210. if (size > ZLIB_IO_MAX)
  1211. {
  1212. png_warning(png_ptr,
  1213. "Compression buffer size limited to system maximum");
  1214. size = ZLIB_IO_MAX; /* must fit */
  1215. }
  1216. else if (size < 6)
  1217. {
  1218. /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
  1219. * if this is permitted.
  1220. */
  1221. png_warning(png_ptr,
  1222. "Compression buffer size cannot be reduced below 6");
  1223. return;
  1224. }
  1225. if (png_ptr->zbuffer_size != size)
  1226. {
  1227. png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
  1228. png_ptr->zbuffer_size = (uInt)size;
  1229. }
  1230. }
  1231. # endif
  1232. }
  1233. void PNGAPI
  1234. png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
  1235. {
  1236. if (png_ptr && info_ptr)
  1237. info_ptr->valid &= ~mask;
  1238. }
  1239. #ifdef PNG_SET_USER_LIMITS_SUPPORTED
  1240. /* This function was added to libpng 1.2.6 */
  1241. void PNGAPI
  1242. png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
  1243. png_uint_32 user_height_max)
  1244. {
  1245. /* Images with dimensions larger than these limits will be
  1246. * rejected by png_set_IHDR(). To accept any PNG datastream
  1247. * regardless of dimensions, set both limits to 0x7ffffffL.
  1248. */
  1249. if (png_ptr == NULL)
  1250. return;
  1251. png_ptr->user_width_max = user_width_max;
  1252. png_ptr->user_height_max = user_height_max;
  1253. }
  1254. /* This function was added to libpng 1.4.0 */
  1255. void PNGAPI
  1256. png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
  1257. {
  1258. if (png_ptr)
  1259. png_ptr->user_chunk_cache_max = user_chunk_cache_max;
  1260. }
  1261. /* This function was added to libpng 1.4.1 */
  1262. void PNGAPI
  1263. png_set_chunk_malloc_max (png_structrp png_ptr,
  1264. png_alloc_size_t user_chunk_malloc_max)
  1265. {
  1266. if (png_ptr)
  1267. png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
  1268. }
  1269. #endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
  1270. #ifdef PNG_BENIGN_ERRORS_SUPPORTED
  1271. void PNGAPI
  1272. png_set_benign_errors(png_structrp png_ptr, int allowed)
  1273. {
  1274. png_debug(1, "in png_set_benign_errors");
  1275. /* If allowed is 1, png_benign_error() is treated as a warning.
  1276. *
  1277. * If allowed is 0, png_benign_error() is treated as an error (which
  1278. * is the default behavior if png_set_benign_errors() is not called).
  1279. */
  1280. if (allowed)
  1281. png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN |
  1282. PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
  1283. else
  1284. png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
  1285. PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
  1286. }
  1287. #endif /* PNG_BENIGN_ERRORS_SUPPORTED */
  1288. #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
  1289. /* Whether to report invalid palette index; added at libng-1.5.10.
  1290. * It is possible for an indexed (color-type==3) PNG file to contain
  1291. * pixels with invalid (out-of-range) indexes if the PLTE chunk has
  1292. * fewer entries than the image's bit-depth would allow. We recover
  1293. * from this gracefully by filling any incomplete palette with zeroes
  1294. * (opaque black). By default, when this occurs libpng will issue
  1295. * a benign error. This API can be used to override that behavior.
  1296. */
  1297. void PNGAPI
  1298. png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
  1299. {
  1300. png_debug(1, "in png_set_check_for_invalid_index");
  1301. if (allowed > 0)
  1302. png_ptr->num_palette_max = 0;
  1303. else
  1304. png_ptr->num_palette_max = -1;
  1305. }
  1306. #endif
  1307. #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */