pngset.c 46 KB

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