Cleanup: Get this rid of "this->" in fpdfsdk/
[pdfium.git] / samples / fx_lpng / lpng_v163 / fx_png.c
1 /* png.c - location for general purpose libpng functions\r
2  *\r
3  * Last changed in libpng 1.6.2 [April 25, 2013]\r
4  * Copyright (c) 1998-2013 Glenn Randers-Pehrson\r
5  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)\r
6  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)\r
7  *\r
8  * This code is released under the libpng license.\r
9  * For conditions of distribution and use, see the disclaimer\r
10  * and license in png.h\r
11  */\r
12 \r
13 #include "pngpriv.h"\r
14 \r
15 /* Generate a compiler error if there is an old png.h in the search path. */\r
16 typedef png_libpng_version_1_6_3 Your_png_h_is_not_version_1_6_3;\r
17 \r
18 /* Tells libpng that we have already handled the first "num_bytes" bytes\r
19  * of the PNG file signature.  If the PNG data is embedded into another\r
20  * stream we can set num_bytes = 8 so that libpng will not attempt to read\r
21  * or write any of the magic bytes before it starts on the IHDR.\r
22  */\r
23 \r
24 #ifdef PNG_READ_SUPPORTED\r
25 void PNGAPI\r
26 png_set_sig_bytes(png_structrp png_ptr, int num_bytes)\r
27 {\r
28    png_debug(1, "in png_set_sig_bytes");\r
29 \r
30    if (png_ptr == NULL)\r
31       return;\r
32 \r
33    if (num_bytes > 8)\r
34       png_error(png_ptr, "Too many bytes for PNG signature");\r
35 \r
36    png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes);\r
37 }\r
38 \r
39 /* Checks whether the supplied bytes match the PNG signature.  We allow\r
40  * checking less than the full 8-byte signature so that those apps that\r
41  * already read the first few bytes of a file to determine the file type\r
42  * can simply check the remaining bytes for extra assurance.  Returns\r
43  * an integer less than, equal to, or greater than zero if sig is found,\r
44  * respectively, to be less than, to match, or be greater than the correct\r
45  * PNG signature (this is the same behavior as strcmp, memcmp, etc).\r
46  */\r
47 int PNGAPI\r
48 png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check)\r
49 {\r
50    png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};\r
51 \r
52    if (num_to_check > 8)\r
53       num_to_check = 8;\r
54 \r
55    else if (num_to_check < 1)\r
56       return (-1);\r
57 \r
58    if (start > 7)\r
59       return (-1);\r
60 \r
61    if (start + num_to_check > 8)\r
62       num_to_check = 8 - start;\r
63 \r
64    return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));\r
65 }\r
66 \r
67 #endif /* PNG_READ_SUPPORTED */\r
68 \r
69 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)\r
70 /* Function to allocate memory for zlib */\r
71 PNG_FUNCTION(voidpf /* PRIVATE */,\r
72 png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)\r
73 {\r
74    png_alloc_size_t num_bytes = size;\r
75 \r
76    if (png_ptr == NULL)\r
77       return NULL;\r
78 \r
79    if (items >= (~(png_alloc_size_t)0)/size)\r
80    {\r
81       png_warning (png_voidcast(png_structrp, png_ptr),\r
82          "Potential overflow in png_zalloc()");\r
83       return NULL;\r
84    }\r
85 \r
86    num_bytes *= items;\r
87    return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes);\r
88 }\r
89 \r
90 /* Function to free memory for zlib */\r
91 void /* PRIVATE */\r
92 png_zfree(voidpf png_ptr, voidpf ptr)\r
93 {\r
94    png_free(png_voidcast(png_const_structrp,png_ptr), ptr);\r
95 }\r
96 \r
97 /* Reset the CRC variable to 32 bits of 1's.  Care must be taken\r
98  * in case CRC is > 32 bits to leave the top bits 0.\r
99  */\r
100 void /* PRIVATE */\r
101 png_reset_crc(png_structrp png_ptr)\r
102 {\r
103    /* The cast is safe because the crc is a 32 bit value. */\r
104    png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0);\r
105 }\r
106 \r
107 /* Calculate the CRC over a section of data.  We can only pass as\r
108  * much data to this routine as the largest single buffer size.  We\r
109  * also check that this data will actually be used before going to the\r
110  * trouble of calculating it.\r
111  */\r
112 void /* PRIVATE */\r
113 png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length)\r
114 {\r
115    int need_crc = 1;\r
116 \r
117    if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))\r
118    {\r
119       if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==\r
120           (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))\r
121          need_crc = 0;\r
122    }\r
123 \r
124    else /* critical */\r
125    {\r
126       if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)\r
127          need_crc = 0;\r
128    }\r
129 \r
130    /* 'uLong' is defined in zlib.h as unsigned long; this means that on some\r
131     * systems it is a 64 bit value.  crc32, however, returns 32 bits so the\r
132     * following cast is safe.  'uInt' may be no more than 16 bits, so it is\r
133     * necessary to perform a loop here.\r
134     */\r
135    if (need_crc && length > 0)\r
136    {\r
137       uLong crc = png_ptr->crc; /* Should never issue a warning */\r
138 \r
139       do\r
140       {\r
141          uInt safe_length = (uInt)length;\r
142          if (safe_length == 0)\r
143             safe_length = (uInt)-1; /* evil, but safe */\r
144 \r
145          crc = crc32(crc, ptr, safe_length);\r
146 \r
147          /* The following should never issue compiler warnings; if they do the\r
148           * target system has characteristics that will probably violate other\r
149           * assumptions within the libpng code.\r
150           */\r
151          ptr += safe_length;\r
152          length -= safe_length;\r
153       }\r
154       while (length > 0);\r
155 \r
156       /* And the following is always safe because the crc is only 32 bits. */\r
157       png_ptr->crc = (png_uint_32)crc;\r
158    }\r
159 }\r
160 \r
161 /* Check a user supplied version number, called from both read and write\r
162  * functions that create a png_struct.\r
163  */\r
164 int\r
165 png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)\r
166 {\r
167    if (user_png_ver)\r
168    {\r
169       int i = 0;\r
170 \r
171       do\r
172       {\r
173          if (user_png_ver[i] != png_libpng_ver[i])\r
174             png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;\r
175       } while (png_libpng_ver[i++]);\r
176    }\r
177 \r
178    else\r
179       png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;\r
180 \r
181    if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)\r
182    {\r
183      /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so\r
184       * we must recompile any applications that use any older library version.\r
185       * For versions after libpng 1.0, we will be compatible, so we need\r
186       * only check the first and third digits (note that when we reach version\r
187       * 1.10 we will need to check the fourth symbol, namely user_png_ver[3]).\r
188       */\r
189       if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||\r
190           (user_png_ver[0] == '1' && (user_png_ver[2] != png_libpng_ver[2] ||\r
191           user_png_ver[3] != png_libpng_ver[3])) ||\r
192           (user_png_ver[0] == '0' && user_png_ver[2] < '9'))\r
193       {\r
194 #ifdef PNG_WARNINGS_SUPPORTED\r
195          size_t pos = 0;\r
196          char m[128];\r
197 \r
198          pos = png_safecat(m, (sizeof m), pos,\r
199              "Application built with libpng-");\r
200          pos = png_safecat(m, (sizeof m), pos, user_png_ver);\r
201          pos = png_safecat(m, (sizeof m), pos, " but running with ");\r
202          pos = png_safecat(m, (sizeof m), pos, png_libpng_ver);\r
203 \r
204          png_warning(png_ptr, m);\r
205 #endif\r
206 \r
207 #ifdef PNG_ERROR_NUMBERS_SUPPORTED\r
208          png_ptr->flags = 0;\r
209 #endif\r
210 \r
211          return 0;\r
212       }\r
213    }\r
214 \r
215    /* Success return. */\r
216    return 1;\r
217 }\r
218 \r
219 /* Generic function to create a png_struct for either read or write - this\r
220  * contains the common initialization.\r
221  */\r
222 PNG_FUNCTION(png_structp /* PRIVATE */,\r
223 png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,\r
224     png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,\r
225     png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)\r
226 {\r
227    png_struct create_struct;\r
228 #  ifdef PNG_SETJMP_SUPPORTED\r
229       jmp_buf create_jmp_buf;\r
230 #  endif\r
231 \r
232    /* This temporary stack-allocated structure is used to provide a place to\r
233     * build enough context to allow the user provided memory allocator (if any)\r
234     * to be called.\r
235     */\r
236    memset(&create_struct, 0, (sizeof create_struct));\r
237 \r
238    /* Added at libpng-1.2.6 */\r
239 #  ifdef PNG_USER_LIMITS_SUPPORTED\r
240       create_struct.user_width_max = PNG_USER_WIDTH_MAX;\r
241       create_struct.user_height_max = PNG_USER_HEIGHT_MAX;\r
242 \r
243 #     ifdef PNG_USER_CHUNK_CACHE_MAX\r
244          /* Added at libpng-1.2.43 and 1.4.0 */\r
245          create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;\r
246 #     endif\r
247 \r
248 #     ifdef PNG_USER_CHUNK_MALLOC_MAX\r
249          /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists\r
250           * in png_struct regardless.\r
251           */\r
252          create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;\r
253 #     endif\r
254 #  endif\r
255 \r
256    /* The following two API calls simply set fields in png_struct, so it is safe\r
257     * to do them now even though error handling is not yet set up.\r
258     */\r
259 #  ifdef PNG_USER_MEM_SUPPORTED\r
260       png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn);\r
261 #  endif\r
262 \r
263    /* (*error_fn) can return control to the caller after the error_ptr is set,\r
264     * this will result in a memory leak unless the error_fn does something\r
265     * extremely sophisticated.  The design lacks merit but is implicit in the\r
266     * API.\r
267     */\r
268    png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn);\r
269 \r
270 #  ifdef PNG_SETJMP_SUPPORTED\r
271       if (!setjmp(create_jmp_buf))\r
272       {\r
273          /* Temporarily fake out the longjmp information until we have\r
274           * successfully completed this function.  This only works if we have\r
275           * setjmp() support compiled in, but it is safe - this stuff should\r
276           * never happen.\r
277           */\r
278          create_struct.jmp_buf_ptr = &create_jmp_buf;\r
279          create_struct.jmp_buf_size = 0; /*stack allocation*/\r
280          create_struct.longjmp_fn = longjmp;\r
281 #  else\r
282       {\r
283 #  endif\r
284          /* Call the general version checker (shared with read and write code):\r
285           */\r
286          if (png_user_version_check(&create_struct, user_png_ver))\r
287          {\r
288             png_structrp png_ptr = png_voidcast(png_structrp,\r
289                png_malloc_warn(&create_struct, (sizeof *png_ptr)));\r
290 \r
291             if (png_ptr != NULL)\r
292             {\r
293                /* png_ptr->zstream holds a back-pointer to the png_struct, so\r
294                 * this can only be done now:\r
295                 */\r
296                create_struct.zstream.zalloc = png_zalloc;\r
297                create_struct.zstream.zfree = png_zfree;\r
298                create_struct.zstream.opaque = png_ptr;\r
299 \r
300 #              ifdef PNG_SETJMP_SUPPORTED\r
301                   /* Eliminate the local error handling: */\r
302                   create_struct.jmp_buf_ptr = NULL;\r
303                   create_struct.jmp_buf_size = 0;\r
304                   create_struct.longjmp_fn = 0;\r
305 #              endif\r
306 \r
307                *png_ptr = create_struct;\r
308 \r
309                /* This is the successful return point */\r
310                return png_ptr;\r
311             }\r
312          }\r
313       }\r
314 \r
315    /* A longjmp because of a bug in the application storage allocator or a\r
316     * simple failure to allocate the png_struct.\r
317     */\r
318    return NULL;\r
319 }\r
320 \r
321 /* Allocate the memory for an info_struct for the application. */\r
322 PNG_FUNCTION(png_infop,PNGAPI\r
323 png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED)\r
324 {\r
325    png_inforp info_ptr;\r
326 \r
327    png_debug(1, "in png_create_info_struct");\r
328 \r
329    if (png_ptr == NULL)\r
330       return NULL;\r
331 \r
332    /* Use the internal API that does not (or at least should not) error out, so\r
333     * that this call always returns ok.  The application typically sets up the\r
334     * error handling *after* creating the info_struct because this is the way it\r
335     * has always been done in 'example.c'.\r
336     */\r
337    info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,\r
338       (sizeof *info_ptr)));\r
339 \r
340    if (info_ptr != NULL)\r
341       memset(info_ptr, 0, (sizeof *info_ptr));\r
342 \r
343    return info_ptr;\r
344 }\r
345 \r
346 /* This function frees the memory associated with a single info struct.\r
347  * Normally, one would use either png_destroy_read_struct() or\r
348  * png_destroy_write_struct() to free an info struct, but this may be\r
349  * useful for some applications.  From libpng 1.6.0 this function is also used\r
350  * internally to implement the png_info release part of the 'struct' destroy\r
351  * APIs.  This ensures that all possible approaches free the same data (all of\r
352  * it).\r
353  */\r
354 void PNGAPI\r
355 png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr)\r
356 {\r
357    png_inforp info_ptr = NULL;\r
358 \r
359    png_debug(1, "in png_destroy_info_struct");\r
360 \r
361    if (png_ptr == NULL)\r
362       return;\r
363 \r
364    if (info_ptr_ptr != NULL)\r
365       info_ptr = *info_ptr_ptr;\r
366 \r
367    if (info_ptr != NULL)\r
368    {\r
369       /* Do this first in case of an error below; if the app implements its own\r
370        * memory management this can lead to png_free calling png_error, which\r
371        * will abort this routine and return control to the app error handler.\r
372        * An infinite loop may result if it then tries to free the same info\r
373        * ptr.\r
374        */\r
375       *info_ptr_ptr = NULL;\r
376 \r
377       png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);\r
378       memset(info_ptr, 0, (sizeof *info_ptr));\r
379       png_free(png_ptr, info_ptr);\r
380    }\r
381 }\r
382 \r
383 /* Initialize the info structure.  This is now an internal function (0.89)\r
384  * and applications using it are urged to use png_create_info_struct()\r
385  * instead.  Use deprecated in 1.6.0, internal use removed (used internally it\r
386  * is just a memset).\r
387  *\r
388  * NOTE: it is almost inconceivable that this API is used because it bypasses\r
389  * the user-memory mechanism and the user error handling/warning mechanisms in\r
390  * those cases where it does anything other than a memset.\r
391  */\r
392 PNG_FUNCTION(void,PNGAPI\r
393 png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size),\r
394    PNG_DEPRECATED)\r
395 {\r
396    png_inforp info_ptr = *ptr_ptr;\r
397 \r
398    png_debug(1, "in png_info_init_3");\r
399 \r
400    if (info_ptr == NULL)\r
401       return;\r
402 \r
403    if ((sizeof (png_info)) > png_info_struct_size)\r
404    {\r
405       *ptr_ptr = NULL;\r
406       /* The following line is why this API should not be used: */\r
407       free(info_ptr);\r
408       info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL,\r
409          (sizeof *info_ptr)));\r
410       *ptr_ptr = info_ptr;\r
411    }\r
412 \r
413    /* Set everything to 0 */\r
414    memset(info_ptr, 0, (sizeof *info_ptr));\r
415 }\r
416 \r
417 /* The following API is not called internally */\r
418 void PNGAPI\r
419 png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,\r
420    int freer, png_uint_32 mask)\r
421 {\r
422    png_debug(1, "in png_data_freer");\r
423 \r
424    if (png_ptr == NULL || info_ptr == NULL)\r
425       return;\r
426 \r
427    if (freer == PNG_DESTROY_WILL_FREE_DATA)\r
428       info_ptr->free_me |= mask;\r
429 \r
430    else if (freer == PNG_USER_WILL_FREE_DATA)\r
431       info_ptr->free_me &= ~mask;\r
432 \r
433    else\r
434       png_error(png_ptr, "Unknown freer parameter in png_data_freer");\r
435 }\r
436 \r
437 void PNGAPI\r
438 png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,\r
439    int num)\r
440 {\r
441    png_debug(1, "in png_free_data");\r
442 \r
443    if (png_ptr == NULL || info_ptr == NULL)\r
444       return;\r
445 \r
446 #ifdef PNG_TEXT_SUPPORTED\r
447    /* Free text item num or (if num == -1) all text items */\r
448    if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)\r
449    {\r
450       if (num != -1)\r
451       {\r
452          if (info_ptr->text && info_ptr->text[num].key)\r
453          {\r
454             png_free(png_ptr, info_ptr->text[num].key);\r
455             info_ptr->text[num].key = NULL;\r
456          }\r
457       }\r
458 \r
459       else\r
460       {\r
461          int i;\r
462          for (i = 0; i < info_ptr->num_text; i++)\r
463              png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);\r
464          png_free(png_ptr, info_ptr->text);\r
465          info_ptr->text = NULL;\r
466          info_ptr->num_text=0;\r
467       }\r
468    }\r
469 #endif\r
470 \r
471 #ifdef PNG_tRNS_SUPPORTED\r
472    /* Free any tRNS entry */\r
473    if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)\r
474    {\r
475       png_free(png_ptr, info_ptr->trans_alpha);\r
476       info_ptr->trans_alpha = NULL;\r
477       info_ptr->valid &= ~PNG_INFO_tRNS;\r
478    }\r
479 #endif\r
480 \r
481 #ifdef PNG_sCAL_SUPPORTED\r
482    /* Free any sCAL entry */\r
483    if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)\r
484    {\r
485       png_free(png_ptr, info_ptr->scal_s_width);\r
486       png_free(png_ptr, info_ptr->scal_s_height);\r
487       info_ptr->scal_s_width = NULL;\r
488       info_ptr->scal_s_height = NULL;\r
489       info_ptr->valid &= ~PNG_INFO_sCAL;\r
490    }\r
491 #endif\r
492 \r
493 #ifdef PNG_pCAL_SUPPORTED\r
494    /* Free any pCAL entry */\r
495    if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)\r
496    {\r
497       png_free(png_ptr, info_ptr->pcal_purpose);\r
498       png_free(png_ptr, info_ptr->pcal_units);\r
499       info_ptr->pcal_purpose = NULL;\r
500       info_ptr->pcal_units = NULL;\r
501       if (info_ptr->pcal_params != NULL)\r
502          {\r
503             unsigned int i;\r
504             for (i = 0; i < info_ptr->pcal_nparams; i++)\r
505             {\r
506                png_free(png_ptr, info_ptr->pcal_params[i]);\r
507                info_ptr->pcal_params[i] = NULL;\r
508             }\r
509             png_free(png_ptr, info_ptr->pcal_params);\r
510             info_ptr->pcal_params = NULL;\r
511          }\r
512       info_ptr->valid &= ~PNG_INFO_pCAL;\r
513    }\r
514 #endif\r
515 \r
516 #ifdef PNG_iCCP_SUPPORTED\r
517    /* Free any profile entry */\r
518    if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)\r
519    {\r
520       png_free(png_ptr, info_ptr->iccp_name);\r
521       png_free(png_ptr, info_ptr->iccp_profile);\r
522       info_ptr->iccp_name = NULL;\r
523       info_ptr->iccp_profile = NULL;\r
524       info_ptr->valid &= ~PNG_INFO_iCCP;\r
525    }\r
526 #endif\r
527 \r
528 #ifdef PNG_sPLT_SUPPORTED\r
529    /* Free a given sPLT entry, or (if num == -1) all sPLT entries */\r
530    if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)\r
531    {\r
532       if (num != -1)\r
533       {\r
534          if (info_ptr->splt_palettes)\r
535          {\r
536             png_free(png_ptr, info_ptr->splt_palettes[num].name);\r
537             png_free(png_ptr, info_ptr->splt_palettes[num].entries);\r
538             info_ptr->splt_palettes[num].name = NULL;\r
539             info_ptr->splt_palettes[num].entries = NULL;\r
540          }\r
541       }\r
542 \r
543       else\r
544       {\r
545          if (info_ptr->splt_palettes_num)\r
546          {\r
547             int i;\r
548             for (i = 0; i < info_ptr->splt_palettes_num; i++)\r
549                png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, (int)i);\r
550 \r
551             png_free(png_ptr, info_ptr->splt_palettes);\r
552             info_ptr->splt_palettes = NULL;\r
553             info_ptr->splt_palettes_num = 0;\r
554          }\r
555          info_ptr->valid &= ~PNG_INFO_sPLT;\r
556       }\r
557    }\r
558 #endif\r
559 \r
560 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED\r
561    if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)\r
562    {\r
563       if (num != -1)\r
564       {\r
565           if (info_ptr->unknown_chunks)\r
566           {\r
567              png_free(png_ptr, info_ptr->unknown_chunks[num].data);\r
568              info_ptr->unknown_chunks[num].data = NULL;\r
569           }\r
570       }\r
571 \r
572       else\r
573       {\r
574          int i;\r
575 \r
576          if (info_ptr->unknown_chunks_num)\r
577          {\r
578             for (i = 0; i < info_ptr->unknown_chunks_num; i++)\r
579                png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, (int)i);\r
580 \r
581             png_free(png_ptr, info_ptr->unknown_chunks);\r
582             info_ptr->unknown_chunks = NULL;\r
583             info_ptr->unknown_chunks_num = 0;\r
584          }\r
585       }\r
586    }\r
587 #endif\r
588 \r
589 #ifdef PNG_hIST_SUPPORTED\r
590    /* Free any hIST entry */\r
591    if ((mask & PNG_FREE_HIST)  & info_ptr->free_me)\r
592    {\r
593       png_free(png_ptr, info_ptr->hist);\r
594       info_ptr->hist = NULL;\r
595       info_ptr->valid &= ~PNG_INFO_hIST;\r
596    }\r
597 #endif\r
598 \r
599    /* Free any PLTE entry that was internally allocated */\r
600    if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)\r
601    {\r
602       png_free(png_ptr, info_ptr->palette);\r
603       info_ptr->palette = NULL;\r
604       info_ptr->valid &= ~PNG_INFO_PLTE;\r
605       info_ptr->num_palette = 0;\r
606    }\r
607 \r
608 #ifdef PNG_INFO_IMAGE_SUPPORTED\r
609    /* Free any image bits attached to the info structure */\r
610    if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)\r
611    {\r
612       if (info_ptr->row_pointers)\r
613       {\r
614          png_uint_32 row;\r
615          for (row = 0; row < info_ptr->height; row++)\r
616          {\r
617             png_free(png_ptr, info_ptr->row_pointers[row]);\r
618             info_ptr->row_pointers[row] = NULL;\r
619          }\r
620          png_free(png_ptr, info_ptr->row_pointers);\r
621          info_ptr->row_pointers = NULL;\r
622       }\r
623       info_ptr->valid &= ~PNG_INFO_IDAT;\r
624    }\r
625 #endif\r
626 \r
627    if (num != -1)\r
628       mask &= ~PNG_FREE_MUL;\r
629 \r
630    info_ptr->free_me &= ~mask;\r
631 }\r
632 #endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */\r
633 \r
634 /* This function returns a pointer to the io_ptr associated with the user\r
635  * functions.  The application should free any memory associated with this\r
636  * pointer before png_write_destroy() or png_read_destroy() are called.\r
637  */\r
638 png_voidp PNGAPI\r
639 png_get_io_ptr(png_const_structrp png_ptr)\r
640 {\r
641    if (png_ptr == NULL)\r
642       return (NULL);\r
643 \r
644    return (png_ptr->io_ptr);\r
645 }\r
646 \r
647 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)\r
648 #  ifdef PNG_STDIO_SUPPORTED\r
649 /* Initialize the default input/output functions for the PNG file.  If you\r
650  * use your own read or write routines, you can call either png_set_read_fn()\r
651  * or png_set_write_fn() instead of png_init_io().  If you have defined\r
652  * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a\r
653  * function of your own because "FILE *" isn't necessarily available.\r
654  */\r
655 void PNGAPI\r
656 png_init_io(png_structrp png_ptr, png_FILE_p fp)\r
657 {\r
658    png_debug(1, "in png_init_io");\r
659 \r
660    if (png_ptr == NULL)\r
661       return;\r
662 \r
663    png_ptr->io_ptr = (png_voidp)fp;\r
664 }\r
665 #  endif\r
666 \r
667 #ifdef PNG_SAVE_INT_32_SUPPORTED\r
668 /* The png_save_int_32 function assumes integers are stored in two's\r
669  * complement format.  If this isn't the case, then this routine needs to\r
670  * be modified to write data in two's complement format.  Note that,\r
671  * the following works correctly even if png_int_32 has more than 32 bits\r
672  * (compare the more complex code required on read for sign extension.)\r
673  */\r
674 void PNGAPI\r
675 png_save_int_32(png_bytep buf, png_int_32 i)\r
676 {\r
677    buf[0] = (png_byte)((i >> 24) & 0xff);\r
678    buf[1] = (png_byte)((i >> 16) & 0xff);\r
679    buf[2] = (png_byte)((i >> 8) & 0xff);\r
680    buf[3] = (png_byte)(i & 0xff);\r
681 }\r
682 #endif\r
683 \r
684 #  ifdef PNG_TIME_RFC1123_SUPPORTED\r
685 /* Convert the supplied time into an RFC 1123 string suitable for use in\r
686  * a "Creation Time" or other text-based time string.\r
687  */\r
688 int PNGAPI\r
689 png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)\r
690 {\r
691    static PNG_CONST char short_months[12][4] =\r
692         {"Jan", "Feb", "Mar", "Apr", "May", "Jun",\r
693          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};\r
694 \r
695    if (out == NULL)\r
696       return 0;\r
697 \r
698    if (ptime->year > 9999 /* RFC1123 limitation */ ||\r
699        ptime->month == 0    ||  ptime->month > 12  ||\r
700        ptime->day   == 0    ||  ptime->day   > 31  ||\r
701        ptime->hour  > 23    ||  ptime->minute > 59 ||\r
702        ptime->second > 60)\r
703       return 0;\r
704 \r
705    {\r
706       size_t pos = 0;\r
707       char number_buf[5]; /* enough for a four-digit year */\r
708 \r
709 #     define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))\r
710 #     define APPEND_NUMBER(format, value)\\r
711          APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))\r
712 #     define APPEND(ch) if (pos < 28) out[pos++] = (ch)\r
713 \r
714       APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);\r
715       APPEND(' ');\r
716       APPEND_STRING(short_months[(ptime->month - 1)]);\r
717       APPEND(' ');\r
718       APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year);\r
719       APPEND(' ');\r
720       APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour);\r
721       APPEND(':');\r
722       APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute);\r
723       APPEND(':');\r
724       APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second);\r
725       APPEND_STRING(" +0000"); /* This reliably terminates the buffer */\r
726 \r
727 #     undef APPEND\r
728 #     undef APPEND_NUMBER\r
729 #     undef APPEND_STRING\r
730    }\r
731 \r
732    return 1;\r
733 }\r
734 \r
735 #     if PNG_LIBPNG_VER < 10700\r
736 /* To do: remove the following from libpng-1.7 */\r
737 /* Original API that uses a private buffer in png_struct.\r
738  * Deprecated because it causes png_struct to carry a spurious temporary\r
739  * buffer (png_struct::time_buffer), better to have the caller pass this in.\r
740  */\r
741 png_const_charp PNGAPI\r
742 png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime)\r
743 {\r
744    if (png_ptr != NULL)\r
745    {\r
746       /* The only failure above if png_ptr != NULL is from an invalid ptime */\r
747       if (!png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime))\r
748          png_warning(png_ptr, "Ignoring invalid time value");\r
749 \r
750       else\r
751          return png_ptr->time_buffer;\r
752    }\r
753 \r
754    return NULL;\r
755 }\r
756 #     endif\r
757 #  endif /* PNG_TIME_RFC1123_SUPPORTED */\r
758 \r
759 #endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */\r
760 \r
761 png_const_charp PNGAPI\r
762 png_get_copyright(png_const_structrp png_ptr)\r
763 {\r
764    PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */\r
765 #ifdef PNG_STRING_COPYRIGHT\r
766    return PNG_STRING_COPYRIGHT\r
767 #else\r
768 #  ifdef __STDC__\r
769    return PNG_STRING_NEWLINE \\r
770      "libpng version 1.6.3 - July 18, 2013" PNG_STRING_NEWLINE \\r
771      "Copyright (c) 1998-2013 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \\r
772      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \\r
773      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \\r
774      PNG_STRING_NEWLINE;\r
775 #  else\r
776       return "libpng version 1.6.3 - July 18, 2013\\r
777       Copyright (c) 1998-2013 Glenn Randers-Pehrson\\r
778       Copyright (c) 1996-1997 Andreas Dilger\\r
779       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";\r
780 #  endif\r
781 #endif\r
782 }\r
783 \r
784 /* The following return the library version as a short string in the\r
785  * format 1.0.0 through 99.99.99zz.  To get the version of *.h files\r
786  * used with your application, print out PNG_LIBPNG_VER_STRING, which\r
787  * is defined in png.h.\r
788  * Note: now there is no difference between png_get_libpng_ver() and\r
789  * png_get_header_ver().  Due to the version_nn_nn_nn typedef guard,\r
790  * it is guaranteed that png.c uses the correct version of png.h.\r
791  */\r
792 png_const_charp PNGAPI\r
793 png_get_libpng_ver(png_const_structrp png_ptr)\r
794 {\r
795    /* Version of *.c files used when building libpng */\r
796    return png_get_header_ver(png_ptr);\r
797 }\r
798 \r
799 png_const_charp PNGAPI\r
800 png_get_header_ver(png_const_structrp png_ptr)\r
801 {\r
802    /* Version of *.h files used when building libpng */\r
803    PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */\r
804    return PNG_LIBPNG_VER_STRING;\r
805 }\r
806 \r
807 png_const_charp PNGAPI\r
808 png_get_header_version(png_const_structrp png_ptr)\r
809 {\r
810    /* Returns longer string containing both version and date */\r
811    PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */\r
812 #ifdef __STDC__\r
813    return PNG_HEADER_VERSION_STRING\r
814 #  ifndef PNG_READ_SUPPORTED\r
815    "     (NO READ SUPPORT)"\r
816 #  endif\r
817    PNG_STRING_NEWLINE;\r
818 #else\r
819    return PNG_HEADER_VERSION_STRING;\r
820 #endif\r
821 }\r
822 \r
823 #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED\r
824 int PNGAPI\r
825 png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name)\r
826 {\r
827    /* Check chunk_name and return "keep" value if it's on the list, else 0 */\r
828    png_const_bytep p, p_end;\r
829 \r
830    if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0)\r
831       return PNG_HANDLE_CHUNK_AS_DEFAULT;\r
832 \r
833    p_end = png_ptr->chunk_list;\r
834    p = p_end + png_ptr->num_chunk_list*5; /* beyond end */\r
835 \r
836    /* The code is the fifth byte after each four byte string.  Historically this\r
837     * code was always searched from the end of the list, this is no longer\r
838     * necessary because the 'set' routine handles duplicate entries correcty.\r
839     */\r
840    do /* num_chunk_list > 0, so at least one */\r
841    {\r
842       p -= 5;\r
843 \r
844       if (!memcmp(chunk_name, p, 4))\r
845          return p[4];\r
846    }\r
847    while (p > p_end);\r
848 \r
849    /* This means that known chunks should be processed and unknown chunks should\r
850     * be handled according to the value of png_ptr->unknown_default; this can be\r
851     * confusing because, as a result, there are two levels of defaulting for\r
852     * unknown chunks.\r
853     */\r
854    return PNG_HANDLE_CHUNK_AS_DEFAULT;\r
855 }\r
856 \r
857 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED\r
858 int /* PRIVATE */\r
859 png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name)\r
860 {\r
861    png_byte chunk_string[5];\r
862 \r
863    PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);\r
864    return png_handle_as_unknown(png_ptr, chunk_string);\r
865 }\r
866 #endif /* READ_UNKNOWN_CHUNKS */\r
867 #endif /* SET_UNKNOWN_CHUNKS */\r
868 \r
869 #ifdef PNG_READ_SUPPORTED\r
870 /* This function, added to libpng-1.0.6g, is untested. */\r
871 int PNGAPI\r
872 png_reset_zstream(png_structrp png_ptr)\r
873 {\r
874    if (png_ptr == NULL)\r
875       return Z_STREAM_ERROR;\r
876 \r
877    /* WARNING: this resets the window bits to the maximum! */\r
878    return (inflateReset(&png_ptr->zstream));\r
879 }\r
880 #endif /* PNG_READ_SUPPORTED */\r
881 \r
882 /* This function was added to libpng-1.0.7 */\r
883 png_uint_32 PNGAPI\r
884 png_access_version_number(void)\r
885 {\r
886    /* Version of *.c files used when building libpng */\r
887    return((png_uint_32)PNG_LIBPNG_VER);\r
888 }\r
889 \r
890 \r
891 \r
892 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)\r
893 /* Ensure that png_ptr->zstream.msg holds some appropriate error message string.\r
894  * If it doesn't 'ret' is used to set it to something appropriate, even in cases\r
895  * like Z_OK or Z_STREAM_END where the error code is apparently a success code.\r
896  */\r
897 void /* PRIVATE */\r
898 png_zstream_error(png_structrp png_ptr, int ret)\r
899 {\r
900    /* Translate 'ret' into an appropriate error string, priority is given to the\r
901     * one in zstream if set.  This always returns a string, even in cases like\r
902     * Z_OK or Z_STREAM_END where the error code is a success code.\r
903     */\r
904    if (png_ptr->zstream.msg == NULL) switch (ret)\r
905    {\r
906       default:\r
907       case Z_OK:\r
908          png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code");\r
909          break;\r
910 \r
911       case Z_STREAM_END:\r
912          /* Normal exit */\r
913          png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream");\r
914          break;\r
915 \r
916       case Z_NEED_DICT:\r
917          /* This means the deflate stream did not have a dictionary; this\r
918           * indicates a bogus PNG.\r
919           */\r
920          png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary");\r
921          break;\r
922 \r
923       case Z_ERRNO:\r
924          /* gz APIs only: should not happen */\r
925          png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error");\r
926          break;\r
927 \r
928       case Z_STREAM_ERROR:\r
929          /* internal libpng error */\r
930          png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib");\r
931          break;\r
932 \r
933       case Z_DATA_ERROR:\r
934          png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream");\r
935          break;\r
936 \r
937       case Z_MEM_ERROR:\r
938          png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory");\r
939          break;\r
940 \r
941       case Z_BUF_ERROR:\r
942          /* End of input or output; not a problem if the caller is doing\r
943           * incremental read or write.\r
944           */\r
945          png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated");\r
946          break;\r
947 \r
948       case Z_VERSION_ERROR:\r
949          png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version");\r
950          break;\r
951 \r
952       case PNG_UNEXPECTED_ZLIB_RETURN:\r
953          /* Compile errors here mean that zlib now uses the value co-opted in\r
954           * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above\r
955           * and change pngpriv.h.  Note that this message is "... return",\r
956           * whereas the default/Z_OK one is "... return code".\r
957           */\r
958          png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return");\r
959          break;\r
960    }\r
961 }\r
962 \r
963 /* png_convert_size: a PNGAPI but no longer in png.h, so deleted\r
964  * at libpng 1.5.5!\r
965  */\r
966 \r
967 /* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */\r
968 #ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */\r
969 static int\r
970 png_colorspace_check_gamma(png_const_structrp png_ptr,\r
971    png_colorspacerp colorspace, png_fixed_point gAMA, int from)\r
972    /* This is called to check a new gamma value against an existing one.  The\r
973     * routine returns false if the new gamma value should not be written.\r
974     *\r
975     * 'from' says where the new gamma value comes from:\r
976     *\r
977     *    0: the new gamma value is the libpng estimate for an ICC profile\r
978     *    1: the new gamma value comes from a gAMA chunk\r
979     *    2: the new gamma value comes from an sRGB chunk\r
980     */\r
981 {\r
982    png_fixed_point gtest;\r
983 \r
984    if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&\r
985       (!png_muldiv(&gtest, colorspace->gamma, PNG_FP_1, gAMA) ||\r
986       png_gamma_significant(gtest)))\r
987    {\r
988       /* Either this is an sRGB image, in which case the calculated gamma\r
989        * approximation should match, or this is an image with a profile and the\r
990        * value libpng calculates for the gamma of the profile does not match the\r
991        * value recorded in the file.  The former, sRGB, case is an error, the\r
992        * latter is just a warning.\r
993        */\r
994       if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)\r
995       {\r
996          png_chunk_report(png_ptr, "gamma value does not match sRGB",\r
997             PNG_CHUNK_ERROR);\r
998          /* Do not overwrite an sRGB value */\r
999          return from == 2;\r
1000       }\r
1001 \r
1002       else /* sRGB tag not involved */\r
1003       {\r
1004          png_chunk_report(png_ptr, "gamma value does not match libpng estimate",\r
1005             PNG_CHUNK_WARNING);\r
1006          return from == 1;\r
1007       }\r
1008    }\r
1009 \r
1010    return 1;\r
1011 }\r
1012 \r
1013 void /* PRIVATE */\r
1014 png_colorspace_set_gamma(png_const_structrp png_ptr,\r
1015    png_colorspacerp colorspace, png_fixed_point gAMA)\r
1016 {\r
1017    /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't\r
1018     * occur.  Since the fixed point representation is assymetrical it is\r
1019     * possible for 1/gamma to overflow the limit of 21474 and this means the\r
1020     * gamma value must be at least 5/100000 and hence at most 20000.0.  For\r
1021     * safety the limits here are a little narrower.  The values are 0.00016 to\r
1022     * 6250.0, which are truly ridiculous gamma values (and will produce\r
1023     * displays that are all black or all white.)\r
1024     *\r
1025     * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk\r
1026     * handling code, which only required the value to be >0.\r
1027     */\r
1028    png_const_charp errmsg;\r
1029 \r
1030    if (gAMA < 16 || gAMA > 625000000)\r
1031       errmsg = "gamma value out of range";\r
1032 \r
1033 #  ifdef PNG_READ_gAMA_SUPPORTED\r
1034       /* Allow the application to set the gamma value more than once */\r
1035       else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&\r
1036          (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)\r
1037          errmsg = "duplicate";\r
1038 #  endif\r
1039 \r
1040    /* Do nothing if the colorspace is already invalid */\r
1041    else if (colorspace->flags & PNG_COLORSPACE_INVALID)\r
1042       return;\r
1043 \r
1044    else\r
1045    {\r
1046       if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA, 1/*from gAMA*/))\r
1047       {\r
1048          /* Store this gamma value. */\r
1049          colorspace->gamma = gAMA;\r
1050          colorspace->flags |=\r
1051             (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA);\r
1052       }\r
1053 \r
1054       /* At present if the check_gamma test fails the gamma of the colorspace is\r
1055        * not updated however the colorspace is not invalidated.  This\r
1056        * corresponds to the case where the existing gamma comes from an sRGB\r
1057        * chunk or profile.  An error message has already been output.\r
1058        */\r
1059       return;\r
1060    }\r
1061 \r
1062    /* Error exit - errmsg has been set. */\r
1063    colorspace->flags |= PNG_COLORSPACE_INVALID;\r
1064    png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);\r
1065 }\r
1066 \r
1067 void /* PRIVATE */\r
1068 png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)\r
1069 {\r
1070    if (info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID)\r
1071    {\r
1072       /* Everything is invalid */\r
1073       info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB|\r
1074          PNG_INFO_iCCP);\r
1075 \r
1076 #     ifdef PNG_COLORSPACE_SUPPORTED\r
1077          /* Clean up the iCCP profile now if it won't be used. */\r
1078          png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/);\r
1079 #     else\r
1080          PNG_UNUSED(png_ptr)\r
1081 #     endif\r
1082    }\r
1083 \r
1084    else\r
1085    {\r
1086 #     ifdef PNG_COLORSPACE_SUPPORTED\r
1087          /* Leave the INFO_iCCP flag set if the pngset.c code has already set\r
1088           * it; this allows a PNG to contain a profile which matches sRGB and\r
1089           * yet still have that profile retrievable by the application.\r
1090           */\r
1091          if (info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB)\r
1092             info_ptr->valid |= PNG_INFO_sRGB;\r
1093 \r
1094          else\r
1095             info_ptr->valid &= ~PNG_INFO_sRGB;\r
1096 \r
1097          if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS)\r
1098             info_ptr->valid |= PNG_INFO_cHRM;\r
1099 \r
1100          else\r
1101             info_ptr->valid &= ~PNG_INFO_cHRM;\r
1102 #     endif\r
1103 \r
1104       if (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA)\r
1105          info_ptr->valid |= PNG_INFO_gAMA;\r
1106 \r
1107       else\r
1108          info_ptr->valid &= ~PNG_INFO_gAMA;\r
1109    }\r
1110 }\r
1111 \r
1112 #ifdef PNG_READ_SUPPORTED\r
1113 void /* PRIVATE */\r
1114 png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)\r
1115 {\r
1116    if (info_ptr == NULL) /* reduce code size; check here not in the caller */\r
1117       return;\r
1118 \r
1119    info_ptr->colorspace = png_ptr->colorspace;\r
1120    png_colorspace_sync_info(png_ptr, info_ptr);\r
1121 }\r
1122 #endif\r
1123 #endif\r
1124 \r
1125 #ifdef PNG_COLORSPACE_SUPPORTED\r
1126 /* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for\r
1127  * cHRM, as opposed to using chromaticities.  These internal APIs return\r
1128  * non-zero on a parameter error.  The X, Y and Z values are required to be\r
1129  * positive and less than 1.0.\r
1130  */\r
1131 static int\r
1132 png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)\r
1133 {\r
1134    png_int_32 d, dwhite, whiteX, whiteY;\r
1135 \r
1136    d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;\r
1137    if (!png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d)) return 1;\r
1138    if (!png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d)) return 1;\r
1139    dwhite = d;\r
1140    whiteX = XYZ->red_X;\r
1141    whiteY = XYZ->red_Y;\r
1142 \r
1143    d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;\r
1144    if (!png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d)) return 1;\r
1145    if (!png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d)) return 1;\r
1146    dwhite += d;\r
1147    whiteX += XYZ->green_X;\r
1148    whiteY += XYZ->green_Y;\r
1149 \r
1150    d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;\r
1151    if (!png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d)) return 1;\r
1152    if (!png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d)) return 1;\r
1153    dwhite += d;\r
1154    whiteX += XYZ->blue_X;\r
1155    whiteY += XYZ->blue_Y;\r
1156 \r
1157    /* The reference white is simply the sum of the end-point (X,Y,Z) vectors,\r
1158     * thus:\r
1159     */\r
1160    if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1;\r
1161    if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1;\r
1162 \r
1163    return 0;\r
1164 }\r
1165 \r
1166 static int\r
1167 png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)\r
1168 {\r
1169    png_fixed_point red_inverse, green_inverse, blue_scale;\r
1170    png_fixed_point left, right, denominator;\r
1171 \r
1172    /* Check xy and, implicitly, z.  Note that wide gamut color spaces typically\r
1173     * have end points with 0 tristimulus values (these are impossible end\r
1174     * points, but they are used to cover the possible colors.)\r
1175     */\r
1176    if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1;\r
1177    if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;\r
1178    if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;\r
1179    if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;\r
1180    if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1;\r
1181    if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;\r
1182    if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;\r
1183    if (xy->whitey < 0 || xy->whitey > PNG_FP_1-xy->whitex) return 1;\r
1184 \r
1185    /* The reverse calculation is more difficult because the original tristimulus\r
1186     * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8\r
1187     * derived values were recorded in the cHRM chunk;\r
1188     * (red,green,blue,white)x(x,y).  This loses one degree of freedom and\r
1189     * therefore an arbitrary ninth value has to be introduced to undo the\r
1190     * original transformations.\r
1191     *\r
1192     * Think of the original end-points as points in (X,Y,Z) space.  The\r
1193     * chromaticity values (c) have the property:\r
1194     *\r
1195     *           C\r
1196     *   c = ---------\r
1197     *       X + Y + Z\r
1198     *\r
1199     * For each c (x,y,z) from the corresponding original C (X,Y,Z).  Thus the\r
1200     * three chromaticity values (x,y,z) for each end-point obey the\r
1201     * relationship:\r
1202     *\r
1203     *   x + y + z = 1\r
1204     *\r
1205     * This describes the plane in (X,Y,Z) space that intersects each axis at the\r
1206     * value 1.0; call this the chromaticity plane.  Thus the chromaticity\r
1207     * calculation has scaled each end-point so that it is on the x+y+z=1 plane\r
1208     * and chromaticity is the intersection of the vector from the origin to the\r
1209     * (X,Y,Z) value with the chromaticity plane.\r
1210     *\r
1211     * To fully invert the chromaticity calculation we would need the three\r
1212     * end-point scale factors, (red-scale, green-scale, blue-scale), but these\r
1213     * were not recorded.  Instead we calculated the reference white (X,Y,Z) and\r
1214     * recorded the chromaticity of this.  The reference white (X,Y,Z) would have\r
1215     * given all three of the scale factors since:\r
1216     *\r
1217     *    color-C = color-c * color-scale\r
1218     *    white-C = red-C + green-C + blue-C\r
1219     *            = red-c*red-scale + green-c*green-scale + blue-c*blue-scale\r
1220     *\r
1221     * But cHRM records only white-x and white-y, so we have lost the white scale\r
1222     * factor:\r
1223     *\r
1224     *    white-C = white-c*white-scale\r
1225     *\r
1226     * To handle this the inverse transformation makes an arbitrary assumption\r
1227     * about white-scale:\r
1228     *\r
1229     *    Assume: white-Y = 1.0\r
1230     *    Hence:  white-scale = 1/white-y\r
1231     *    Or:     red-Y + green-Y + blue-Y = 1.0\r
1232     *\r
1233     * Notice the last statement of the assumption gives an equation in three of\r
1234     * the nine values we want to calculate.  8 more equations come from the\r
1235     * above routine as summarised at the top above (the chromaticity\r
1236     * calculation):\r
1237     *\r
1238     *    Given: color-x = color-X / (color-X + color-Y + color-Z)\r
1239     *    Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0\r
1240     *\r
1241     * This is 9 simultaneous equations in the 9 variables "color-C" and can be\r
1242     * solved by Cramer's rule.  Cramer's rule requires calculating 10 9x9 matrix\r
1243     * determinants, however this is not as bad as it seems because only 28 of\r
1244     * the total of 90 terms in the various matrices are non-zero.  Nevertheless\r
1245     * Cramer's rule is notoriously numerically unstable because the determinant\r
1246     * calculation involves the difference of large, but similar, numbers.  It is\r
1247     * difficult to be sure that the calculation is stable for real world values\r
1248     * and it is certain that it becomes unstable where the end points are close\r
1249     * together.\r
1250     *\r
1251     * So this code uses the perhaps slightly less optimal but more\r
1252     * understandable and totally obvious approach of calculating color-scale.\r
1253     *\r
1254     * This algorithm depends on the precision in white-scale and that is\r
1255     * (1/white-y), so we can immediately see that as white-y approaches 0 the\r
1256     * accuracy inherent in the cHRM chunk drops off substantially.\r
1257     *\r
1258     * libpng arithmetic: a simple invertion of the above equations\r
1259     * ------------------------------------------------------------\r
1260     *\r
1261     *    white_scale = 1/white-y\r
1262     *    white-X = white-x * white-scale\r
1263     *    white-Y = 1.0\r
1264     *    white-Z = (1 - white-x - white-y) * white_scale\r
1265     *\r
1266     *    white-C = red-C + green-C + blue-C\r
1267     *            = red-c*red-scale + green-c*green-scale + blue-c*blue-scale\r
1268     *\r
1269     * This gives us three equations in (red-scale,green-scale,blue-scale) where\r
1270     * all the coefficients are now known:\r
1271     *\r
1272     *    red-x*red-scale + green-x*green-scale + blue-x*blue-scale\r
1273     *       = white-x/white-y\r
1274     *    red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1\r
1275     *    red-z*red-scale + green-z*green-scale + blue-z*blue-scale\r
1276     *       = (1 - white-x - white-y)/white-y\r
1277     *\r
1278     * In the last equation color-z is (1 - color-x - color-y) so we can add all\r
1279     * three equations together to get an alternative third:\r
1280     *\r
1281     *    red-scale + green-scale + blue-scale = 1/white-y = white-scale\r
1282     *\r
1283     * So now we have a Cramer's rule solution where the determinants are just\r
1284     * 3x3 - far more tractible.  Unfortunately 3x3 determinants still involve\r
1285     * multiplication of three coefficients so we can't guarantee to avoid\r
1286     * overflow in the libpng fixed point representation.  Using Cramer's rule in\r
1287     * floating point is probably a good choice here, but it's not an option for\r
1288     * fixed point.  Instead proceed to simplify the first two equations by\r
1289     * eliminating what is likely to be the largest value, blue-scale:\r
1290     *\r
1291     *    blue-scale = white-scale - red-scale - green-scale\r
1292     *\r
1293     * Hence:\r
1294     *\r
1295     *    (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale =\r
1296     *                (white-x - blue-x)*white-scale\r
1297     *\r
1298     *    (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale =\r
1299     *                1 - blue-y*white-scale\r
1300     *\r
1301     * And now we can trivially solve for (red-scale,green-scale):\r
1302     *\r
1303     *    green-scale =\r
1304     *                (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale\r
1305     *                -----------------------------------------------------------\r
1306     *                                  green-x - blue-x\r
1307     *\r
1308     *    red-scale =\r
1309     *                1 - blue-y*white-scale - (green-y - blue-y) * green-scale\r
1310     *                ---------------------------------------------------------\r
1311     *                                  red-y - blue-y\r
1312     *\r
1313     * Hence:\r
1314     *\r
1315     *    red-scale =\r
1316     *          ( (green-x - blue-x) * (white-y - blue-y) -\r
1317     *            (green-y - blue-y) * (white-x - blue-x) ) / white-y\r
1318     * -------------------------------------------------------------------------\r
1319     *  (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)\r
1320     *\r
1321     *    green-scale =\r
1322     *          ( (red-y - blue-y) * (white-x - blue-x) -\r
1323     *            (red-x - blue-x) * (white-y - blue-y) ) / white-y\r
1324     * -------------------------------------------------------------------------\r
1325     *  (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)\r
1326     *\r
1327     * Accuracy:\r
1328     * The input values have 5 decimal digits of accuracy.  The values are all in\r
1329     * the range 0 < value < 1, so simple products are in the same range but may\r
1330     * need up to 10 decimal digits to preserve the original precision and avoid\r
1331     * underflow.  Because we are using a 32-bit signed representation we cannot\r
1332     * match this; the best is a little over 9 decimal digits, less than 10.\r
1333     *\r
1334     * The approach used here is to preserve the maximum precision within the\r
1335     * signed representation.  Because the red-scale calculation above uses the\r
1336     * difference between two products of values that must be in the range -1..+1\r
1337     * it is sufficient to divide the product by 7; ceil(100,000/32767*2).  The\r
1338     * factor is irrelevant in the calculation because it is applied to both\r
1339     * numerator and denominator.\r
1340     *\r
1341     * Note that the values of the differences of the products of the\r
1342     * chromaticities in the above equations tend to be small, for example for\r
1343     * the sRGB chromaticities they are:\r
1344     *\r
1345     * red numerator:    -0.04751\r
1346     * green numerator:  -0.08788\r
1347     * denominator:      -0.2241 (without white-y multiplication)\r
1348     *\r
1349     *  The resultant Y coefficients from the chromaticities of some widely used\r
1350     *  color space definitions are (to 15 decimal places):\r
1351     *\r
1352     *  sRGB\r
1353     *    0.212639005871510 0.715168678767756 0.072192315360734\r
1354     *  Kodak ProPhoto\r
1355     *    0.288071128229293 0.711843217810102 0.000085653960605\r
1356     *  Adobe RGB\r
1357     *    0.297344975250536 0.627363566255466 0.075291458493998\r
1358     *  Adobe Wide Gamut RGB\r
1359     *    0.258728243040113 0.724682314948566 0.016589442011321\r
1360     */\r
1361    /* By the argument, above overflow should be impossible here. The return\r
1362     * value of 2 indicates an internal error to the caller.\r
1363     */\r
1364    if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7))\r
1365       return 2;\r
1366    if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7))\r
1367       return 2;\r
1368    denominator = left - right;\r
1369 \r
1370    /* Now find the red numerator. */\r
1371    if (!png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7))\r
1372       return 2;\r
1373    if (!png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7))\r
1374       return 2;\r
1375 \r
1376    /* Overflow is possible here and it indicates an extreme set of PNG cHRM\r
1377     * chunk values.  This calculation actually returns the reciprocal of the\r
1378     * scale value because this allows us to delay the multiplication of white-y\r
1379     * into the denominator, which tends to produce a small number.\r
1380     */\r
1381    if (!png_muldiv(&red_inverse, xy->whitey, denominator, left-right) ||\r
1382        red_inverse <= xy->whitey /* r+g+b scales = white scale */)\r
1383       return 1;\r
1384 \r
1385    /* Similarly for green_inverse: */\r
1386    if (!png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7))\r
1387       return 2;\r
1388    if (!png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7))\r
1389       return 2;\r
1390    if (!png_muldiv(&green_inverse, xy->whitey, denominator, left-right) ||\r
1391        green_inverse <= xy->whitey)\r
1392       return 1;\r
1393 \r
1394    /* And the blue scale, the checks above guarantee this can't overflow but it\r
1395     * can still produce 0 for extreme cHRM values.\r
1396     */\r
1397    blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -\r
1398       png_reciprocal(green_inverse);\r
1399    if (blue_scale <= 0) return 1;\r
1400 \r
1401 \r
1402    /* And fill in the png_XYZ: */\r
1403    if (!png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse)) return 1;\r
1404    if (!png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse)) return 1;\r
1405    if (!png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1,\r
1406       red_inverse))\r
1407       return 1;\r
1408 \r
1409    if (!png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse))\r
1410       return 1;\r
1411    if (!png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse))\r
1412       return 1;\r
1413    if (!png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1,\r
1414       green_inverse))\r
1415       return 1;\r
1416 \r
1417    if (!png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1)) return 1;\r
1418    if (!png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1)) return 1;\r
1419    if (!png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale,\r
1420       PNG_FP_1))\r
1421       return 1;\r
1422 \r
1423    return 0; /*success*/\r
1424 }\r
1425 \r
1426 static int\r
1427 png_XYZ_normalize(png_XYZ *XYZ)\r
1428 {\r
1429    png_int_32 Y;\r
1430 \r
1431    if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||\r
1432       XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||\r
1433       XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)\r
1434       return 1;\r
1435 \r
1436    /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.\r
1437     * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore\r
1438     * relying on addition of two positive values producing a negative one is not\r
1439     * safe.\r
1440     */\r
1441    Y = XYZ->red_Y;\r
1442    if (0x7fffffff - Y < XYZ->green_X) return 1;\r
1443    Y += XYZ->green_Y;\r
1444    if (0x7fffffff - Y < XYZ->blue_X) return 1;\r
1445    Y += XYZ->blue_Y;\r
1446 \r
1447    if (Y != PNG_FP_1)\r
1448    {\r
1449       if (!png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y)) return 1;\r
1450       if (!png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y)) return 1;\r
1451       if (!png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y)) return 1;\r
1452 \r
1453       if (!png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y)) return 1;\r
1454       if (!png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y)) return 1;\r
1455       if (!png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y)) return 1;\r
1456 \r
1457       if (!png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y)) return 1;\r
1458       if (!png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y)) return 1;\r
1459       if (!png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y)) return 1;\r
1460    }\r
1461 \r
1462    return 0;\r
1463 }\r
1464 \r
1465 static int\r
1466 png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta)\r
1467 {\r
1468    /* Allow an error of +/-0.01 (absolute value) on each chromaticity */\r
1469    return !(PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||\r
1470       PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||\r
1471       PNG_OUT_OF_RANGE(xy1->redx,   xy2->redx,  delta) ||\r
1472       PNG_OUT_OF_RANGE(xy1->redy,   xy2->redy,  delta) ||\r
1473       PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||\r
1474       PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||\r
1475       PNG_OUT_OF_RANGE(xy1->bluex,  xy2->bluex, delta) ||\r
1476       PNG_OUT_OF_RANGE(xy1->bluey,  xy2->bluey, delta));\r
1477 }\r
1478 \r
1479 /* Added in libpng-1.6.0, a different check for the validity of a set of cHRM\r
1480  * chunk chromaticities.  Earlier checks used to simply look for the overflow\r
1481  * condition (where the determinant of the matrix to solve for XYZ ends up zero\r
1482  * because the chromaticity values are not all distinct.)  Despite this it is\r
1483  * theoretically possible to produce chromaticities that are apparently valid\r
1484  * but that rapidly degrade to invalid, potentially crashing, sets because of\r
1485  * arithmetic inaccuracies when calculations are performed on them.  The new\r
1486  * check is to round-trip xy -> XYZ -> xy and then check that the result is\r
1487  * within a small percentage of the original.\r
1488  */\r
1489 static int\r
1490 png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy)\r
1491 {\r
1492    int result;\r
1493    png_xy xy_test;\r
1494 \r
1495    /* As a side-effect this routine also returns the XYZ endpoints. */\r
1496    result = png_XYZ_from_xy(XYZ, xy);\r
1497    if (result) return result;\r
1498 \r
1499    result = png_xy_from_XYZ(&xy_test, XYZ);\r
1500    if (result) return result;\r
1501 \r
1502    if (png_colorspace_endpoints_match(xy, &xy_test,\r
1503       5/*actually, the math is pretty accurate*/))\r
1504       return 0;\r
1505 \r
1506    /* Too much slip */\r
1507    return 1;\r
1508 }\r
1509 \r
1510 /* This is the check going the other way.  The XYZ is modified to normalize it\r
1511  * (another side-effect) and the xy chromaticities are returned.\r
1512  */\r
1513 static int\r
1514 png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ)\r
1515 {\r
1516    int result;\r
1517    png_XYZ XYZtemp;\r
1518 \r
1519    result = png_XYZ_normalize(XYZ);\r
1520    if (result) return result;\r
1521 \r
1522    result = png_xy_from_XYZ(xy, XYZ);\r
1523    if (result) return result;\r
1524 \r
1525    XYZtemp = *XYZ;\r
1526    return png_colorspace_check_xy(&XYZtemp, xy);\r
1527 }\r
1528 \r
1529 /* Used to check for an endpoint match against sRGB */\r
1530 static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */\r
1531 {\r
1532    /* color      x       y */\r
1533    /* red   */ 64000, 33000,\r
1534    /* green */ 30000, 60000,\r
1535    /* blue  */ 15000,  6000,\r
1536    /* white */ 31270, 32900\r
1537 };\r
1538 \r
1539 static int\r
1540 png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr,\r
1541    png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,\r
1542    int preferred)\r
1543 {\r
1544    if (colorspace->flags & PNG_COLORSPACE_INVALID)\r
1545       return 0;\r
1546 \r
1547    /* The consistency check is performed on the chromaticities; this factors out\r
1548     * variations because of the normalization (or not) of the end point Y\r
1549     * values.\r
1550     */\r
1551    if (preferred < 2 && (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS))\r
1552    {\r
1553       /* The end points must be reasonably close to any we already have.  The\r
1554        * following allows an error of up to +/-.001\r
1555        */\r
1556       if (!png_colorspace_endpoints_match(xy, &colorspace->end_points_xy, 100))\r
1557       {\r
1558          colorspace->flags |= PNG_COLORSPACE_INVALID;\r
1559          png_benign_error(png_ptr, "inconsistent chromaticities");\r
1560          return 0; /* failed */\r
1561       }\r
1562 \r
1563       /* Only overwrite with preferred values */\r
1564       if (!preferred)\r
1565          return 1; /* ok, but no change */\r
1566    }\r
1567 \r
1568    colorspace->end_points_xy = *xy;\r
1569    colorspace->end_points_XYZ = *XYZ;\r
1570    colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;\r
1571 \r
1572    /* The end points are normally quoted to two decimal digits, so allow +/-0.01\r
1573     * on this test.\r
1574     */\r
1575    if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000))\r
1576       colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;\r
1577 \r
1578    else\r
1579       colorspace->flags &= PNG_COLORSPACE_CANCEL(\r
1580          PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);\r
1581 \r
1582    return 2; /* ok and changed */\r
1583 }\r
1584 \r
1585 int /* PRIVATE */\r
1586 png_colorspace_set_chromaticities(png_const_structrp png_ptr,\r
1587    png_colorspacerp colorspace, const png_xy *xy, int preferred)\r
1588 {\r
1589    /* We must check the end points to ensure they are reasonable - in the past\r
1590     * color management systems have crashed as a result of getting bogus\r
1591     * colorant values, while this isn't the fault of libpng it is the\r
1592     * responsibility of libpng because PNG carries the bomb and libpng is in a\r
1593     * position to protect against it.\r
1594     */\r
1595    png_XYZ XYZ;\r
1596 \r
1597    switch (png_colorspace_check_xy(&XYZ, xy))\r
1598    {\r
1599       case 0: /* success */\r
1600          return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,\r
1601             preferred);\r
1602 \r
1603       case 1:\r
1604          /* We can't invert the chromaticities so we can't produce value XYZ\r
1605           * values.  Likely as not a color management system will fail too.\r
1606           */\r
1607          colorspace->flags |= PNG_COLORSPACE_INVALID;\r
1608          png_benign_error(png_ptr, "invalid chromaticities");\r
1609          break;\r
1610 \r
1611       default:\r
1612          /* libpng is broken; this should be a warning but if it happens we\r
1613           * want error reports so for the moment it is an error.\r
1614           */\r
1615          colorspace->flags |= PNG_COLORSPACE_INVALID;\r
1616          png_error(png_ptr, "internal error checking chromaticities");\r
1617          break;\r
1618    }\r
1619 \r
1620    return 0; /* failed */\r
1621 }\r
1622 \r
1623 int /* PRIVATE */\r
1624 png_colorspace_set_endpoints(png_const_structrp png_ptr,\r
1625    png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)\r
1626 {\r
1627    png_XYZ XYZ = *XYZ_in;\r
1628    png_xy xy;\r
1629 \r
1630    switch (png_colorspace_check_XYZ(&xy, &XYZ))\r
1631    {\r
1632       case 0:\r
1633          return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,\r
1634             preferred);\r
1635 \r
1636       case 1:\r
1637          /* End points are invalid. */\r
1638          colorspace->flags |= PNG_COLORSPACE_INVALID;\r
1639          png_benign_error(png_ptr, "invalid end points");\r
1640          break;\r
1641 \r
1642       default:\r
1643          colorspace->flags |= PNG_COLORSPACE_INVALID;\r
1644          png_error(png_ptr, "internal error checking chromaticities");\r
1645          break;\r
1646    }\r
1647 \r
1648    return 0; /* failed */\r
1649 }\r
1650 \r
1651 #if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED)\r
1652 /* Error message generation */\r
1653 static char\r
1654 png_icc_tag_char(png_uint_32 byte)\r
1655 {\r
1656    byte &= 0xff;\r
1657    if (byte >= 32 && byte <= 126)\r
1658       return (char)byte;\r
1659    else\r
1660       return '?';\r
1661 }\r
1662 \r
1663 static void\r
1664 png_icc_tag_name(char *name, png_uint_32 tag)\r
1665 {\r
1666    name[0] = '\'';\r
1667    name[1] = png_icc_tag_char(tag >> 24);\r
1668    name[2] = png_icc_tag_char(tag >> 16);\r
1669    name[3] = png_icc_tag_char(tag >>  8);\r
1670    name[4] = png_icc_tag_char(tag      );\r
1671    name[5] = '\'';\r
1672 }\r
1673 \r
1674 static int\r
1675 is_ICC_signature_char(png_alloc_size_t it)\r
1676 {\r
1677    return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) ||\r
1678       (it >= 97 && it <= 122);\r
1679 }\r
1680 \r
1681 static int is_ICC_signature(png_alloc_size_t it)\r
1682 {\r
1683    return is_ICC_signature_char(it >> 24) /* checks all the top bits */ &&\r
1684       is_ICC_signature_char((it >> 16) & 0xff) &&\r
1685       is_ICC_signature_char((it >> 8) & 0xff) &&\r
1686       is_ICC_signature_char(it & 0xff);\r
1687 }\r
1688 \r
1689 static int\r
1690 png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,\r
1691    png_const_charp name, png_alloc_size_t value, png_const_charp reason)\r
1692 {\r
1693    size_t pos;\r
1694    char message[196]; /* see below for calculation */\r
1695 \r
1696    if (colorspace != NULL)\r
1697       colorspace->flags |= PNG_COLORSPACE_INVALID;\r
1698 \r
1699    pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */\r
1700    pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */\r
1701    pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */\r
1702    if (is_ICC_signature(value))\r
1703    {\r
1704       /* So 'value' is at most 4 bytes and the following cast is safe */\r
1705       png_icc_tag_name(message+pos, (png_uint_32)value);\r
1706       pos += 6; /* total +8; less than the else clause */\r
1707       message[pos++] = ':';\r
1708       message[pos++] = ' ';\r
1709    }\r
1710 #  ifdef PNG_WARNINGS_SUPPORTED\r
1711    else\r
1712       {\r
1713          char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/\r
1714 \r
1715          pos = png_safecat(message, (sizeof message), pos,\r
1716             png_format_number(number, number+(sizeof number),\r
1717                PNG_NUMBER_FORMAT_x, value));\r
1718          pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/\r
1719       }\r
1720 #  endif\r
1721    /* The 'reason' is an arbitrary message, allow +79 maximum 195 */\r
1722    pos = png_safecat(message, (sizeof message), pos, reason);\r
1723 \r
1724    /* This is recoverable, but make it unconditionally an app_error on write to\r
1725     * avoid writing invalid ICC profiles into PNG files.  (I.e.  we handle them\r
1726     * on read, with a warning, but on write unless the app turns off\r
1727     * application errors the PNG won't be written.)\r
1728     */\r
1729    png_chunk_report(png_ptr, message,\r
1730       (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);\r
1731 \r
1732    return 0;\r
1733 }\r
1734 #endif /* sRGB || iCCP */\r
1735 \r
1736 #ifdef PNG_sRGB_SUPPORTED\r
1737 int /* PRIVATE */\r
1738 png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,\r
1739    int intent)\r
1740 {\r
1741    /* sRGB sets known gamma, end points and (from the chunk) intent. */\r
1742    /* IMPORTANT: these are not necessarily the values found in an ICC profile\r
1743     * because ICC profiles store values adapted to a D50 environment; it is\r
1744     * expected that the ICC profile mediaWhitePointTag will be D50, see the\r
1745     * checks and code elsewhere to understand this better.\r
1746     *\r
1747     * These XYZ values, which are accurate to 5dp, produce rgb to gray\r
1748     * coefficients of (6968,23435,2366), which are reduced (because they add up\r
1749     * to 32769 not 32768) to (6968,23434,2366).  These are the values that\r
1750     * libpng has traditionally used (and are the best values given the 15bit\r
1751     * algorithm used by the rgb to gray code.)\r
1752     */\r
1753    static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */\r
1754    {\r
1755       /* color      X      Y      Z */\r
1756       /* red   */ 41239, 21264,  1933,\r
1757       /* green */ 35758, 71517, 11919,\r
1758       /* blue  */ 18048,  7219, 95053\r
1759    };\r
1760 \r
1761    /* Do nothing if the colorspace is already invalidated. */\r
1762    if (colorspace->flags & PNG_COLORSPACE_INVALID)\r
1763       return 0;\r
1764 \r
1765    /* Check the intent, then check for existing settings.  It is valid for the\r
1766     * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must\r
1767     * be consistent with the correct values.  If, however, this function is\r
1768     * called below because an iCCP chunk matches sRGB then it is quite\r
1769     * conceivable that an older app recorded incorrect gAMA and cHRM because of\r
1770     * an incorrect calculation based on the values in the profile - this does\r
1771     * *not* invalidate the profile (though it still produces an error, which can\r
1772     * be ignored.)\r
1773     */\r
1774    if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)\r
1775       return png_icc_profile_error(png_ptr, colorspace, "sRGB",\r
1776          (unsigned)intent, "invalid sRGB rendering intent");\r
1777 \r
1778    if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&\r
1779       colorspace->rendering_intent != intent)\r
1780       return png_icc_profile_error(png_ptr, colorspace, "sRGB",\r
1781          (unsigned)intent, "inconsistent rendering intents");\r
1782 \r
1783    if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)\r
1784    {\r
1785       png_benign_error(png_ptr, "duplicate sRGB information ignored");\r
1786       return 0;\r
1787    }\r
1788 \r
1789    /* If the standard sRGB cHRM chunk does not match the one from the PNG file\r
1790     * warn but overwrite the value with the correct one.\r
1791     */\r
1792    if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 &&\r
1793       !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,\r
1794          100))\r
1795       png_chunk_report(png_ptr, "cHRM chunk does not match sRGB",\r
1796          PNG_CHUNK_ERROR);\r
1797 \r
1798    /* This check is just done for the error reporting - the routine always\r
1799     * returns true when the 'from' argument corresponds to sRGB (2).\r
1800     */\r
1801    (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE,\r
1802       2/*from sRGB*/);\r
1803 \r
1804    /* intent: bugs in GCC force 'int' to be used as the parameter type. */\r
1805    colorspace->rendering_intent = (png_uint_16)intent;\r
1806    colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT;\r
1807 \r
1808    /* endpoints */\r
1809    colorspace->end_points_xy = sRGB_xy;\r
1810    colorspace->end_points_XYZ = sRGB_XYZ;\r
1811    colorspace->flags |=\r
1812       (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);\r
1813 \r
1814    /* gamma */\r
1815    colorspace->gamma = PNG_GAMMA_sRGB_INVERSE;\r
1816    colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA;\r
1817 \r
1818    /* Finally record that we have an sRGB profile */\r
1819    colorspace->flags |=\r
1820       (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB);\r
1821 \r
1822    return 1; /* set */\r
1823 }\r
1824 #endif /* sRGB */\r
1825 \r
1826 #ifdef PNG_iCCP_SUPPORTED\r
1827 /* Encoded value of D50 as an ICC XYZNumber.  From the ICC 2010 spec the value\r
1828  * is XYZ(0.9642,1.0,0.8249), which scales to:\r
1829  *\r
1830  *    (63189.8112, 65536, 54060.6464)\r
1831  */\r
1832 static const png_byte D50_nCIEXYZ[12] =\r
1833    { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d };\r
1834 \r
1835 int /* PRIVATE */\r
1836 png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,\r
1837    png_const_charp name, png_uint_32 profile_length)\r
1838 {\r
1839    if (profile_length < 132)\r
1840       return png_icc_profile_error(png_ptr, colorspace, name, profile_length,\r
1841          "too short");\r
1842 \r
1843    if (profile_length & 3)\r
1844       return png_icc_profile_error(png_ptr, colorspace, name, profile_length,\r
1845          "invalid length");\r
1846 \r
1847    return 1;\r
1848 }\r
1849 \r
1850 int /* PRIVATE */\r
1851 png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,\r
1852    png_const_charp name, png_uint_32 profile_length,\r
1853    png_const_bytep profile/* first 132 bytes only */, int color_type)\r
1854 {\r
1855    png_uint_32 temp;\r
1856 \r
1857    /* Length check; this cannot be ignored in this code because profile_length\r
1858     * is used later to check the tag table, so even if the profile seems over\r
1859     * long profile_length from the caller must be correct.  The caller can fix\r
1860     * this up on read or write by just passing in the profile header length.\r
1861     */\r
1862    temp = png_get_uint_32(profile);\r
1863    if (temp != profile_length)\r
1864       return png_icc_profile_error(png_ptr, colorspace, name, temp,\r
1865          "length does not match profile");\r
1866 \r
1867    temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */\r
1868    if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */\r
1869       profile_length < 132+12*temp) /* truncated tag table */\r
1870       return png_icc_profile_error(png_ptr, colorspace, name, temp,\r
1871          "tag count too large");\r
1872 \r
1873    /* The 'intent' must be valid or we can't store it, ICC limits the intent to\r
1874     * 16 bits.\r
1875     */\r
1876    temp = png_get_uint_32(profile+64);\r
1877    if (temp >= 0xffff) /* The ICC limit */\r
1878       return png_icc_profile_error(png_ptr, colorspace, name, temp,\r
1879          "invalid rendering intent");\r
1880 \r
1881    /* This is just a warning because the profile may be valid in future\r
1882     * versions.\r
1883     */\r
1884    if (temp >= PNG_sRGB_INTENT_LAST)\r
1885       (void)png_icc_profile_error(png_ptr, NULL, name, temp,\r
1886          "intent outside defined range");\r
1887 \r
1888    /* At this point the tag table can't be checked because it hasn't necessarily\r
1889     * been loaded; however, various header fields can be checked.  These checks\r
1890     * are for values permitted by the PNG spec in an ICC profile; the PNG spec\r
1891     * restricts the profiles that can be passed in an iCCP chunk (they must be\r
1892     * appropriate to processing PNG data!)\r
1893     */\r
1894 \r
1895    /* Data checks (could be skipped).  These checks must be independent of the\r
1896     * version number; however, the version number doesn't accomodate changes in\r
1897     * the header fields (just the known tags and the interpretation of the\r
1898     * data.)\r
1899     */\r
1900    temp = png_get_uint_32(profile+36); /* signature 'ascp' */\r
1901    if (temp != 0x61637370)\r
1902       return png_icc_profile_error(png_ptr, colorspace, name, temp,\r
1903          "invalid signature");\r
1904 \r
1905    /* Currently the PCS illuminant/adopted white point (the computational\r
1906     * white point) are required to be D50,\r
1907     * however the profile contains a record of the illuminant so perhaps ICC\r
1908     * expects to be able to change this in the future (despite the rationale in\r
1909     * the introduction for using a fixed PCS adopted white.)  Consequently the\r
1910     * following is just a warning.\r
1911     */\r
1912    if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)\r
1913       (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,\r
1914          "PCS illuminant is not D50");\r
1915 \r
1916    /* The PNG spec requires this:\r
1917     * "If the iCCP chunk is present, the image samples conform to the colour\r
1918     * space represented by the embedded ICC profile as defined by the\r
1919     * International Color Consortium [ICC]. The colour space of the ICC profile\r
1920     * shall be an RGB colour space for colour images (PNG colour types 2, 3, and\r
1921     * 6), or a greyscale colour space for greyscale images (PNG colour types 0\r
1922     * and 4)."\r
1923     *\r
1924     * This checking code ensures the embedded profile (on either read or write)\r
1925     * conforms to the specification requirements.  Notice that an ICC 'gray'\r
1926     * color-space profile contains the information to transform the monochrome\r
1927     * data to XYZ or L*a*b (according to which PCS the profile uses) and this\r
1928     * should be used in preference to the standard libpng K channel replication\r
1929     * into R, G and B channels.\r
1930     *\r
1931     * Previously it was suggested that an RGB profile on grayscale data could be\r
1932     * handled.  However it it is clear that using an RGB profile in this context\r
1933     * must be an error - there is no specification of what it means.  Thus it is\r
1934     * almost certainly more correct to ignore the profile.\r
1935     */\r
1936    temp = png_get_uint_32(profile+16); /* data colour space field */\r
1937    switch (temp)\r
1938    {\r
1939       case 0x52474220: /* 'RGB ' */\r
1940          if (!(color_type & PNG_COLOR_MASK_COLOR))\r
1941             return png_icc_profile_error(png_ptr, colorspace, name, temp,\r
1942                "RGB color space not permitted on grayscale PNG");\r
1943          break;\r
1944 \r
1945       case 0x47524159: /* 'GRAY' */\r
1946          if (color_type & PNG_COLOR_MASK_COLOR)\r
1947             return png_icc_profile_error(png_ptr, colorspace, name, temp,\r
1948                "Gray color space not permitted on RGB PNG");\r
1949          break;\r
1950 \r
1951       default:\r
1952          return png_icc_profile_error(png_ptr, colorspace, name, temp,\r
1953             "invalid ICC profile color space");\r
1954    }\r
1955 \r
1956    /* It is up to the application to check that the profile class matches the\r
1957     * application requirements; the spec provides no guidance, but it's pretty\r
1958     * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer\r
1959     * ('prtr') or 'spac' (for generic color spaces).  Issue a warning in these\r
1960     * cases.  Issue an error for device link or abstract profiles - these don't\r
1961     * contain the records necessary to transform the color-space to anything\r
1962     * other than the target device (and not even that for an abstract profile).\r
1963     * Profiles of these classes may not be embedded in images.\r
1964     */\r
1965    temp = png_get_uint_32(profile+12); /* profile/device class */\r
1966    switch (temp)\r
1967    {\r
1968       case 0x73636E72: /* 'scnr' */\r
1969       case 0x6D6E7472: /* 'mntr' */\r
1970       case 0x70727472: /* 'prtr' */\r
1971       case 0x73706163: /* 'spac' */\r
1972          /* All supported */\r
1973          break;\r
1974 \r
1975       case 0x61627374: /* 'abst' */\r
1976          /* May not be embedded in an image */\r
1977          return png_icc_profile_error(png_ptr, colorspace, name, temp,\r
1978             "invalid embedded Abstract ICC profile");\r
1979 \r
1980       case 0x6C696E6B: /* 'link' */\r
1981          /* DeviceLink profiles cannnot be interpreted in a non-device specific\r
1982           * fashion, if an app uses the AToB0Tag in the profile the results are\r
1983           * undefined unless the result is sent to the intended device,\r
1984           * therefore a DeviceLink profile should not be found embedded in a\r
1985           * PNG.\r
1986           */\r
1987          return png_icc_profile_error(png_ptr, colorspace, name, temp,\r
1988             "unexpected DeviceLink ICC profile class");\r
1989 \r
1990       case 0x6E6D636C: /* 'nmcl' */\r
1991          /* A NamedColor profile is also device specific, however it doesn't\r
1992           * contain an AToB0 tag that is open to misintrepretation.  Almost\r
1993           * certainly it will fail the tests below.\r
1994           */\r
1995          (void)png_icc_profile_error(png_ptr, NULL, name, temp,\r
1996             "unexpected NamedColor ICC profile class");\r
1997          break;\r
1998 \r
1999       default:\r
2000          /* To allow for future enhancements to the profile accept unrecognized\r
2001           * profile classes with a warning, these then hit the test below on the\r
2002           * tag content to ensure they are backward compatible with one of the\r
2003           * understood profiles.\r
2004           */\r
2005          (void)png_icc_profile_error(png_ptr, NULL, name, temp,\r
2006             "unrecognized ICC profile class");\r
2007          break;\r
2008    }\r
2009 \r
2010    /* For any profile other than a device link one the PCS must be encoded\r
2011     * either in XYZ or Lab.\r
2012     */\r
2013    temp = png_get_uint_32(profile+20);\r
2014    switch (temp)\r
2015    {\r
2016       case 0x58595A20: /* 'XYZ ' */\r
2017       case 0x4C616220: /* 'Lab ' */\r
2018          break;\r
2019 \r
2020       default:\r
2021          return png_icc_profile_error(png_ptr, colorspace, name, temp,\r
2022             "unexpected ICC PCS encoding");\r
2023    }\r
2024 \r
2025    return 1;\r
2026 }\r
2027 \r
2028 int /* PRIVATE */\r
2029 png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,\r
2030    png_const_charp name, png_uint_32 profile_length,\r
2031    png_const_bytep profile /* header plus whole tag table */)\r
2032 {\r
2033    png_uint_32 tag_count = png_get_uint_32(profile+128);\r
2034    png_uint_32 itag;\r
2035    png_const_bytep tag = profile+132; /* The first tag */\r
2036 \r
2037    /* First scan all the tags in the table and add bits to the icc_info value\r
2038     * (temporarily in 'tags').\r
2039     */\r
2040    for (itag=0; itag < tag_count; ++itag, tag += 12)\r
2041    {\r
2042       png_uint_32 tag_id = png_get_uint_32(tag+0);\r
2043       png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */\r
2044       png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */\r
2045 \r
2046       /* The ICC specification does not exclude zero length tags, therefore the\r
2047        * start might actually be anywhere if there is no data, but this would be\r
2048        * a clear abuse of the intent of the standard so the start is checked for\r
2049        * being in range.  All defined tag types have an 8 byte header - a 4 byte\r
2050        * type signature then 0.\r
2051        */\r
2052       if ((tag_start & 3) != 0)\r
2053       {\r
2054          /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is\r
2055           * only a warning here because libpng does not care about the\r
2056           * alignment.\r
2057           */\r
2058          (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,\r
2059             "ICC profile tag start not a multiple of 4");\r
2060       }\r
2061 \r
2062       /* This is a hard error; potentially it can cause read outside the\r
2063        * profile.\r
2064        */\r
2065       if (tag_start > profile_length || tag_length > profile_length - tag_start)\r
2066          return png_icc_profile_error(png_ptr, colorspace, name, tag_id,\r
2067             "ICC profile tag outside profile");\r
2068    }\r
2069 \r
2070    return 1; /* success, maybe with warnings */\r
2071 }\r
2072 \r
2073 #ifdef PNG_sRGB_SUPPORTED\r
2074 /* Information about the known ICC sRGB profiles */\r
2075 static const struct\r
2076 {\r
2077    png_uint_32 adler, crc, length;\r
2078    png_uint_32 md5[4];\r
2079    png_byte    have_md5;\r
2080    png_byte    is_broken;\r
2081    png_uint_16 intent;\r
2082 \r
2083 #  define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)\r
2084 #  define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\\r
2085       { adler, crc, length, md5, broke, intent },\r
2086 \r
2087 } png_sRGB_checks[] =\r
2088 {\r
2089    /* This data comes from contrib/tools/checksum-icc run on downloads of\r
2090     * all four ICC sRGB profiles from www.color.org.\r
2091     */\r
2092    /* adler32, crc32, MD5[4], intent, date, length, file-name */\r
2093    PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,\r
2094       PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,\r
2095       "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")\r
2096 \r
2097    /* ICC sRGB v2 perceptual no black-compensation: */\r
2098    PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,\r
2099       PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,\r
2100       "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")\r
2101 \r
2102    PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,\r
2103       PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,\r
2104       "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")\r
2105 \r
2106    /* ICC sRGB v4 perceptual */\r
2107    PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,\r
2108       PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,\r
2109       "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")\r
2110 \r
2111    /* The following profiles have no known MD5 checksum. If there is a match\r
2112     * on the (empty) MD5 the other fields are used to attempt a match and\r
2113     * a warning is produced.  The first two of these profiles have a 'cprt' tag\r
2114     * which suggests that they were also made by Hewlett Packard.\r
2115     */\r
2116    PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,\r
2117       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,\r
2118       "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")\r
2119 \r
2120    /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not\r
2121     * match the D50 PCS illuminant in the header (it is in fact the D65 values,\r
2122     * so the white point is recorded as the un-adapted value.)  The profiles\r
2123     * below only differ in one byte - the intent - and are basically the same as\r
2124     * the previous profile except for the mediaWhitePointTag error and a missing\r
2125     * chromaticAdaptationTag.\r
2126     */\r
2127    PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,\r
2128       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,\r
2129       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")\r
2130 \r
2131    PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,\r
2132       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,\r
2133       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")\r
2134 };\r
2135 \r
2136 static int\r
2137 png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,\r
2138    png_const_bytep profile, uLong adler)\r
2139 {\r
2140    /* The quick check is to verify just the MD5 signature and trust the\r
2141     * rest of the data.  Because the profile has already been verified for\r
2142     * correctness this is safe.  png_colorspace_set_sRGB will check the 'intent'\r
2143     * field too, so if the profile has been edited with an intent not defined\r
2144     * by sRGB (but maybe defined by a later ICC specification) the read of\r
2145     * the profile will fail at that point.\r
2146     */\r
2147    png_uint_32 length = 0;\r
2148    png_uint_32 intent = 0x10000; /* invalid */\r
2149 #if PNG_sRGB_PROFILE_CHECKS > 1\r
2150    uLong crc = 0; /* the value for 0 length data */\r
2151 #endif\r
2152    unsigned int i;\r
2153 \r
2154    for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)\r
2155    {\r
2156       if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&\r
2157          png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&\r
2158          png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&\r
2159          png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])\r
2160       {\r
2161          /* This may be one of the old HP profiles without an MD5, in that\r
2162           * case we can only use the length and Adler32 (note that these\r
2163           * are not used by default if there is an MD5!)\r
2164           */\r
2165 #        if PNG_sRGB_PROFILE_CHECKS == 0\r
2166             if (png_sRGB_checks[i].have_md5)\r
2167                return 1+png_sRGB_checks[i].is_broken;\r
2168 #        endif\r
2169 \r
2170          /* Profile is unsigned or more checks have been configured in. */\r
2171          if (length == 0)\r
2172          {\r
2173             length = png_get_uint_32(profile);\r
2174             intent = png_get_uint_32(profile+64);\r
2175          }\r
2176 \r
2177          /* Length *and* intent must match */\r
2178          if (length == png_sRGB_checks[i].length &&\r
2179             intent == png_sRGB_checks[i].intent)\r
2180          {\r
2181             /* Now calculate the adler32 if not done already. */\r
2182             if (adler == 0)\r
2183             {\r
2184                adler = adler32(0, NULL, 0);\r
2185                adler = adler32(adler, profile, length);\r
2186             }\r
2187 \r
2188             if (adler == png_sRGB_checks[i].adler)\r
2189             {\r
2190                /* These basic checks suggest that the data has not been\r
2191                 * modified, but if the check level is more than 1 perform\r
2192                 * our own crc32 checksum on the data.\r
2193                 */\r
2194 #              if PNG_sRGB_PROFILE_CHECKS > 1\r
2195                   if (crc == 0)\r
2196                   {\r
2197                      crc = crc32(0, NULL, 0);\r
2198                      crc = crc32(crc, profile, length);\r
2199                   }\r
2200 \r
2201                   /* So this check must pass for the 'return' below to happen.\r
2202                    */\r
2203                   if (crc == png_sRGB_checks[i].crc)\r
2204 #              endif\r
2205                {\r
2206                   if (png_sRGB_checks[i].is_broken)\r
2207                   {\r
2208                      /* These profiles are known to have bad data that may cause\r
2209                       * problems if they are used, therefore attempt to\r
2210                       * discourage their use, skip the 'have_md5' warning below,\r
2211                       * which is made irrelevant by this error.\r
2212                       */\r
2213                      png_chunk_report(png_ptr, "known incorrect sRGB profile",\r
2214                         PNG_CHUNK_ERROR);\r
2215                   }\r
2216 \r
2217                   /* Warn that this being done; this isn't even an error since\r
2218                    * the profile is perfectly valid, but it would be nice if\r
2219                    * people used the up-to-date ones.\r
2220                    */\r
2221                   else if (!png_sRGB_checks[i].have_md5)\r
2222                   {\r
2223                      png_chunk_report(png_ptr,\r
2224                         "out-of-date sRGB profile with no signature",\r
2225                         PNG_CHUNK_WARNING);\r
2226                   }\r
2227 \r
2228                   return 1+png_sRGB_checks[i].is_broken;\r
2229                }\r
2230             }\r
2231          }\r
2232 \r
2233 #        if PNG_sRGB_PROFILE_CHECKS > 0\r
2234             /* The signature matched, but the profile had been changed in some\r
2235              * way.  This is an apparent violation of the ICC terms of use and,\r
2236              * anyway, probably indicates a data error or uninformed hacking.\r
2237              */\r
2238             if (png_sRGB_checks[i].have_md5)\r
2239                png_benign_error(png_ptr,\r
2240                   "copyright violation: edited ICC profile ignored");\r
2241 #        endif\r
2242       }\r
2243    }\r
2244 \r
2245    return 0; /* no match */\r
2246 }\r
2247 #endif\r
2248 \r
2249 #ifdef PNG_sRGB_SUPPORTED\r
2250 void /* PRIVATE */\r
2251 png_icc_set_sRGB(png_const_structrp png_ptr,\r
2252    png_colorspacerp colorspace, png_const_bytep profile, uLong adler)\r
2253 {\r
2254    /* Is this profile one of the known ICC sRGB profiles?  If it is, just set\r
2255     * the sRGB information.\r
2256     */\r
2257    if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler))\r
2258       (void)png_colorspace_set_sRGB(png_ptr, colorspace,\r
2259          (int)/*already checked*/png_get_uint_32(profile+64));\r
2260 }\r
2261 #endif /* PNG_READ_sRGB_SUPPORTED */\r
2262 \r
2263 int /* PRIVATE */\r
2264 png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,\r
2265    png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,\r
2266    int color_type)\r
2267 {\r
2268    if (colorspace->flags & PNG_COLORSPACE_INVALID)\r
2269       return 0;\r
2270 \r
2271    if (png_icc_check_length(png_ptr, colorspace, name, profile_length) &&\r
2272       png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,\r
2273          color_type) &&\r
2274       png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,\r
2275          profile))\r
2276    {\r
2277 #     ifdef PNG_sRGB_SUPPORTED\r
2278          /* If no sRGB support, don't try storing sRGB information */\r
2279          png_icc_set_sRGB(png_ptr, colorspace, profile, 0);\r
2280 #     endif\r
2281       return 1;\r
2282    }\r
2283 \r
2284    /* Failure case */\r
2285    return 0;\r
2286 }\r
2287 #endif /* iCCP */\r
2288 \r
2289 #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED\r
2290 void /* PRIVATE */\r
2291 png_colorspace_set_rgb_coefficients(png_structrp png_ptr)\r
2292 {\r
2293    /* Set the rgb_to_gray coefficients from the colorspace. */\r
2294    if (!png_ptr->rgb_to_gray_coefficients_set &&\r
2295       (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)\r
2296    {\r
2297       /* png_set_background has not been called, get the coefficients from the Y\r
2298        * values of the colorspace colorants.\r
2299        */\r
2300       png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;\r
2301       png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;\r
2302       png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;\r
2303       png_fixed_point total = r+g+b;\r
2304 \r
2305       if (total > 0 &&\r
2306          r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&\r
2307          g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&\r
2308          b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&\r
2309          r+g+b <= 32769)\r
2310       {\r
2311          /* We allow 0 coefficients here.  r+g+b may be 32769 if two or\r
2312           * all of the coefficients were rounded up.  Handle this by\r
2313           * reducing the *largest* coefficient by 1; this matches the\r
2314           * approach used for the default coefficients in pngrtran.c\r
2315           */\r
2316          int add = 0;\r
2317 \r
2318          if (r+g+b > 32768)\r
2319             add = -1;\r
2320          else if (r+g+b < 32768)\r
2321             add = 1;\r
2322 \r
2323          if (add != 0)\r
2324          {\r
2325             if (g >= r && g >= b)\r
2326                g += add;\r
2327             else if (r >= g && r >= b)\r
2328                r += add;\r
2329             else\r
2330                b += add;\r
2331          }\r
2332 \r
2333          /* Check for an internal error. */\r
2334          if (r+g+b != 32768)\r
2335             png_error(png_ptr,\r
2336                "internal error handling cHRM coefficients");\r
2337 \r
2338          else\r
2339          {\r
2340             png_ptr->rgb_to_gray_red_coeff   = (png_uint_16)r;\r
2341             png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;\r
2342          }\r
2343       }\r
2344 \r
2345       /* This is a png_error at present even though it could be ignored -\r
2346        * it should never happen, but it is important that if it does, the\r
2347        * bug is fixed.\r
2348        */\r
2349       else\r
2350          png_error(png_ptr, "internal error handling cHRM->XYZ");\r
2351    }\r
2352 }\r
2353 #endif\r
2354 \r
2355 #endif /* COLORSPACE */\r
2356 \r
2357 void /* PRIVATE */\r
2358 png_check_IHDR(png_const_structrp png_ptr,\r
2359    png_uint_32 width, png_uint_32 height, int bit_depth,\r
2360    int color_type, int interlace_type, int compression_type,\r
2361    int filter_type)\r
2362 {\r
2363    int error = 0;\r
2364 \r
2365    /* Check for width and height valid values */\r
2366    if (width == 0)\r
2367    {\r
2368       png_warning(png_ptr, "Image width is zero in IHDR");\r
2369       error = 1;\r
2370    }\r
2371 \r
2372    if (height == 0)\r
2373    {\r
2374       png_warning(png_ptr, "Image height is zero in IHDR");\r
2375       error = 1;\r
2376    }\r
2377 \r
2378 #  ifdef PNG_SET_USER_LIMITS_SUPPORTED\r
2379    if (width > png_ptr->user_width_max)\r
2380 \r
2381 #  else\r
2382    if (width > PNG_USER_WIDTH_MAX)\r
2383 #  endif\r
2384    {\r
2385       png_warning(png_ptr, "Image width exceeds user limit in IHDR");\r
2386       error = 1;\r
2387    }\r
2388 \r
2389 #  ifdef PNG_SET_USER_LIMITS_SUPPORTED\r
2390    if (height > png_ptr->user_height_max)\r
2391 #  else\r
2392    if (height > PNG_USER_HEIGHT_MAX)\r
2393 #  endif\r
2394    {\r
2395       png_warning(png_ptr, "Image height exceeds user limit in IHDR");\r
2396       error = 1;\r
2397    }\r
2398 \r
2399    if (width > PNG_UINT_31_MAX)\r
2400    {\r
2401       png_warning(png_ptr, "Invalid image width in IHDR");\r
2402       error = 1;\r
2403    }\r
2404 \r
2405    if (height > PNG_UINT_31_MAX)\r
2406    {\r
2407       png_warning(png_ptr, "Invalid image height in IHDR");\r
2408       error = 1;\r
2409    }\r
2410 \r
2411    if (width > (PNG_UINT_32_MAX\r
2412                  >> 3)      /* 8-byte RGBA pixels */\r
2413                  - 48       /* bigrowbuf hack */\r
2414                  - 1        /* filter byte */\r
2415                  - 7*8      /* rounding of width to multiple of 8 pixels */\r
2416                  - 8)       /* extra max_pixel_depth pad */\r
2417       png_warning(png_ptr, "Width is too large for libpng to process pixels");\r
2418 \r
2419    /* Check other values */\r
2420    if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&\r
2421        bit_depth != 8 && bit_depth != 16)\r
2422    {\r
2423       png_warning(png_ptr, "Invalid bit depth in IHDR");\r
2424       error = 1;\r
2425    }\r
2426 \r
2427    if (color_type < 0 || color_type == 1 ||\r
2428        color_type == 5 || color_type > 6)\r
2429    {\r
2430       png_warning(png_ptr, "Invalid color type in IHDR");\r
2431       error = 1;\r
2432    }\r
2433 \r
2434    if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||\r
2435        ((color_type == PNG_COLOR_TYPE_RGB ||\r
2436          color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||\r
2437          color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))\r
2438    {\r
2439       png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR");\r
2440       error = 1;\r
2441    }\r
2442 \r
2443    if (interlace_type >= PNG_INTERLACE_LAST)\r
2444    {\r
2445       png_warning(png_ptr, "Unknown interlace method in IHDR");\r
2446       error = 1;\r
2447    }\r
2448 \r
2449    if (compression_type != PNG_COMPRESSION_TYPE_BASE)\r
2450    {\r
2451       png_warning(png_ptr, "Unknown compression method in IHDR");\r
2452       error = 1;\r
2453    }\r
2454 \r
2455 #  ifdef PNG_MNG_FEATURES_SUPPORTED\r
2456    /* Accept filter_method 64 (intrapixel differencing) only if\r
2457     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and\r
2458     * 2. Libpng did not read a PNG signature (this filter_method is only\r
2459     *    used in PNG datastreams that are embedded in MNG datastreams) and\r
2460     * 3. The application called png_permit_mng_features with a mask that\r
2461     *    included PNG_FLAG_MNG_FILTER_64 and\r
2462     * 4. The filter_method is 64 and\r
2463     * 5. The color_type is RGB or RGBA\r
2464     */\r
2465    if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) &&\r
2466        png_ptr->mng_features_permitted)\r
2467       png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");\r
2468 \r
2469    if (filter_type != PNG_FILTER_TYPE_BASE)\r
2470    {\r
2471       if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&\r
2472           (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&\r
2473           ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&\r
2474           (color_type == PNG_COLOR_TYPE_RGB ||\r
2475           color_type == PNG_COLOR_TYPE_RGB_ALPHA)))\r
2476       {\r
2477          png_warning(png_ptr, "Unknown filter method in IHDR");\r
2478          error = 1;\r
2479       }\r
2480 \r
2481       if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE)\r
2482       {\r
2483          png_warning(png_ptr, "Invalid filter method in IHDR");\r
2484          error = 1;\r
2485       }\r
2486    }\r
2487 \r
2488 #  else\r
2489    if (filter_type != PNG_FILTER_TYPE_BASE)\r
2490    {\r
2491       png_warning(png_ptr, "Unknown filter method in IHDR");\r
2492       error = 1;\r
2493    }\r
2494 #  endif\r
2495 \r
2496    if (error == 1)\r
2497       png_error(png_ptr, "Invalid IHDR data");\r
2498 }\r
2499 \r
2500 #if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)\r
2501 /* ASCII to fp functions */\r
2502 /* Check an ASCII formated floating point value, see the more detailed\r
2503  * comments in pngpriv.h\r
2504  */\r
2505 /* The following is used internally to preserve the sticky flags */\r
2506 #define png_fp_add(state, flags) ((state) |= (flags))\r
2507 #define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))\r
2508 \r
2509 int /* PRIVATE */\r
2510 png_check_fp_number(png_const_charp string, png_size_t size, int *statep,\r
2511    png_size_tp whereami)\r
2512 {\r
2513    int state = *statep;\r
2514    png_size_t i = *whereami;\r
2515 \r
2516    while (i < size)\r
2517    {\r
2518       int type;\r
2519       /* First find the type of the next character */\r
2520       switch (string[i])\r
2521       {\r
2522       case 43:  type = PNG_FP_SAW_SIGN;                   break;\r
2523       case 45:  type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break;\r
2524       case 46:  type = PNG_FP_SAW_DOT;                    break;\r
2525       case 48:  type = PNG_FP_SAW_DIGIT;                  break;\r
2526       case 49: case 50: case 51: case 52:\r
2527       case 53: case 54: case 55: case 56:\r
2528       case 57:  type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break;\r
2529       case 69:\r
2530       case 101: type = PNG_FP_SAW_E;                      break;\r
2531       default:  goto PNG_FP_End;\r
2532       }\r
2533 \r
2534       /* Now deal with this type according to the current\r
2535        * state, the type is arranged to not overlap the\r
2536        * bits of the PNG_FP_STATE.\r
2537        */\r
2538       switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))\r
2539       {\r
2540       case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:\r
2541          if (state & PNG_FP_SAW_ANY)\r
2542             goto PNG_FP_End; /* not a part of the number */\r
2543 \r
2544          png_fp_add(state, type);\r
2545          break;\r
2546 \r
2547       case PNG_FP_INTEGER + PNG_FP_SAW_DOT:\r
2548          /* Ok as trailer, ok as lead of fraction. */\r
2549          if (state & PNG_FP_SAW_DOT) /* two dots */\r
2550             goto PNG_FP_End;\r
2551 \r
2552          else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */\r
2553             png_fp_add(state, type);\r
2554 \r
2555          else\r
2556             png_fp_set(state, PNG_FP_FRACTION | type);\r
2557 \r
2558          break;\r
2559 \r
2560       case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:\r
2561          if (state & PNG_FP_SAW_DOT) /* delayed fraction */\r
2562             png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);\r
2563 \r
2564          png_fp_add(state, type | PNG_FP_WAS_VALID);\r
2565 \r
2566          break;\r
2567 \r
2568       case PNG_FP_INTEGER + PNG_FP_SAW_E:\r
2569          if ((state & PNG_FP_SAW_DIGIT) == 0)\r
2570             goto PNG_FP_End;\r
2571 \r
2572          png_fp_set(state, PNG_FP_EXPONENT);\r
2573 \r
2574          break;\r
2575 \r
2576    /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN:\r
2577          goto PNG_FP_End; ** no sign in fraction */\r
2578 \r
2579    /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT:\r
2580          goto PNG_FP_End; ** Because SAW_DOT is always set */\r
2581 \r
2582       case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT:\r
2583          png_fp_add(state, type | PNG_FP_WAS_VALID);\r
2584          break;\r
2585 \r
2586       case PNG_FP_FRACTION + PNG_FP_SAW_E:\r
2587          /* This is correct because the trailing '.' on an\r
2588           * integer is handled above - so we can only get here\r
2589           * with the sequence ".E" (with no preceding digits).\r
2590           */\r
2591          if ((state & PNG_FP_SAW_DIGIT) == 0)\r
2592             goto PNG_FP_End;\r
2593 \r
2594          png_fp_set(state, PNG_FP_EXPONENT);\r
2595 \r
2596          break;\r
2597 \r
2598       case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:\r
2599          if (state & PNG_FP_SAW_ANY)\r
2600             goto PNG_FP_End; /* not a part of the number */\r
2601 \r
2602          png_fp_add(state, PNG_FP_SAW_SIGN);\r
2603 \r
2604          break;\r
2605 \r
2606    /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT:\r
2607          goto PNG_FP_End; */\r
2608 \r
2609       case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT:\r
2610          png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID);\r
2611 \r
2612          break;\r
2613 \r
2614    /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E:\r
2615          goto PNG_FP_End; */\r
2616 \r
2617       default: goto PNG_FP_End; /* I.e. break 2 */\r
2618       }\r
2619 \r
2620       /* The character seems ok, continue. */\r
2621       ++i;\r
2622    }\r
2623 \r
2624 PNG_FP_End:\r
2625    /* Here at the end, update the state and return the correct\r
2626     * return code.\r
2627     */\r
2628    *statep = state;\r
2629    *whereami = i;\r
2630 \r
2631    return (state & PNG_FP_SAW_DIGIT) != 0;\r
2632 }\r
2633 \r
2634 \r
2635 /* The same but for a complete string. */\r
2636 int\r
2637 png_check_fp_string(png_const_charp string, png_size_t size)\r
2638 {\r
2639    int        state=0;\r
2640    png_size_t char_index=0;\r
2641 \r
2642    if (png_check_fp_number(string, size, &state, &char_index) &&\r
2643       (char_index == size || string[char_index] == 0))\r
2644       return state /* must be non-zero - see above */;\r
2645 \r
2646    return 0; /* i.e. fail */\r
2647 }\r
2648 #endif /* pCAL or sCAL */\r
2649 \r
2650 #ifdef PNG_sCAL_SUPPORTED\r
2651 #  ifdef PNG_FLOATING_POINT_SUPPORTED\r
2652 /* Utility used below - a simple accurate power of ten from an integral\r
2653  * exponent.\r
2654  */\r
2655 static double\r
2656 png_pow10(int power)\r
2657 {\r
2658    int recip = 0;\r
2659    double d = 1;\r
2660 \r
2661    /* Handle negative exponent with a reciprocal at the end because\r
2662     * 10 is exact whereas .1 is inexact in base 2\r
2663     */\r
2664    if (power < 0)\r
2665    {\r
2666       if (power < DBL_MIN_10_EXP) return 0;\r
2667       recip = 1, power = -power;\r
2668    }\r
2669 \r
2670    if (power > 0)\r
2671    {\r
2672       /* Decompose power bitwise. */\r
2673       double mult = 10;\r
2674       do\r
2675       {\r
2676          if (power & 1) d *= mult;\r
2677          mult *= mult;\r
2678          power >>= 1;\r
2679       }\r
2680       while (power > 0);\r
2681 \r
2682       if (recip) d = 1/d;\r
2683    }\r
2684    /* else power is 0 and d is 1 */\r
2685 \r
2686    return d;\r
2687 }\r
2688 \r
2689 /* Function to format a floating point value in ASCII with a given\r
2690  * precision.\r
2691  */\r
2692 void /* PRIVATE */\r
2693 png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,\r
2694     double fp, unsigned int precision)\r
2695 {\r
2696    /* We use standard functions from math.h, but not printf because\r
2697     * that would require stdio.  The caller must supply a buffer of\r
2698     * sufficient size or we will png_error.  The tests on size and\r
2699     * the space in ascii[] consumed are indicated below.\r
2700     */\r
2701    if (precision < 1)\r
2702       precision = DBL_DIG;\r
2703 \r
2704    /* Enforce the limit of the implementation precision too. */\r
2705    if (precision > DBL_DIG+1)\r
2706       precision = DBL_DIG+1;\r
2707 \r
2708    /* Basic sanity checks */\r
2709    if (size >= precision+5) /* See the requirements below. */\r
2710    {\r
2711       if (fp < 0)\r
2712       {\r
2713          fp = -fp;\r
2714          *ascii++ = 45; /* '-'  PLUS 1 TOTAL 1 */\r
2715          --size;\r
2716       }\r
2717 \r
2718       if (fp >= DBL_MIN && fp <= DBL_MAX)\r
2719       {\r
2720          int exp_b10;       /* A base 10 exponent */\r
2721          double base;   /* 10^exp_b10 */\r
2722 \r
2723          /* First extract a base 10 exponent of the number,\r
2724           * the calculation below rounds down when converting\r
2725           * from base 2 to base 10 (multiply by log10(2) -\r
2726           * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to\r
2727           * be increased.  Note that the arithmetic shift\r
2728           * performs a floor() unlike C arithmetic - using a\r
2729           * C multiply would break the following for negative\r
2730           * exponents.\r
2731           */\r
2732          (void)frexp(fp, &exp_b10); /* exponent to base 2 */\r
2733 \r
2734          exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */\r
2735 \r
2736          /* Avoid underflow here. */\r
2737          base = png_pow10(exp_b10); /* May underflow */\r
2738 \r
2739          while (base < DBL_MIN || base < fp)\r
2740          {\r
2741             /* And this may overflow. */\r
2742             double test = png_pow10(exp_b10+1);\r
2743 \r
2744             if (test <= DBL_MAX)\r
2745                ++exp_b10, base = test;\r
2746 \r
2747             else\r
2748                break;\r
2749          }\r
2750 \r
2751          /* Normalize fp and correct exp_b10, after this fp is in the\r
2752           * range [.1,1) and exp_b10 is both the exponent and the digit\r
2753           * *before* which the decimal point should be inserted\r
2754           * (starting with 0 for the first digit).  Note that this\r
2755           * works even if 10^exp_b10 is out of range because of the\r
2756           * test on DBL_MAX above.\r
2757           */\r
2758          fp /= base;\r
2759          while (fp >= 1) fp /= 10, ++exp_b10;\r
2760 \r
2761          /* Because of the code above fp may, at this point, be\r
2762           * less than .1, this is ok because the code below can\r
2763           * handle the leading zeros this generates, so no attempt\r
2764           * is made to correct that here.\r
2765           */\r
2766 \r
2767          {\r
2768             int czero, clead, cdigits;\r
2769             char exponent[10];\r
2770 \r
2771             /* Allow up to two leading zeros - this will not lengthen\r
2772              * the number compared to using E-n.\r
2773              */\r
2774             if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */\r
2775             {\r
2776                czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */\r
2777                exp_b10 = 0;      /* Dot added below before first output. */\r
2778             }\r
2779             else\r
2780                czero = 0;    /* No zeros to add */\r
2781 \r
2782             /* Generate the digit list, stripping trailing zeros and\r
2783              * inserting a '.' before a digit if the exponent is 0.\r
2784              */\r
2785             clead = czero; /* Count of leading zeros */\r
2786             cdigits = 0;   /* Count of digits in list. */\r
2787 \r
2788             do\r
2789             {\r
2790                double d;\r
2791 \r
2792                fp *= 10;\r
2793                /* Use modf here, not floor and subtract, so that\r
2794                 * the separation is done in one step.  At the end\r
2795                 * of the loop don't break the number into parts so\r
2796                 * that the final digit is rounded.\r
2797                 */\r
2798                if (cdigits+czero-clead+1 < (int)precision)\r
2799                   fp = modf(fp, &d);\r
2800 \r
2801                else\r
2802                {\r
2803                   d = floor(fp + .5);\r
2804 \r
2805                   if (d > 9)\r
2806                   {\r
2807                      /* Rounding up to 10, handle that here. */\r
2808                      if (czero > 0)\r
2809                      {\r
2810                         --czero, d = 1;\r
2811                         if (cdigits == 0) --clead;\r
2812                      }\r
2813                      else\r
2814                      {\r
2815                         while (cdigits > 0 && d > 9)\r
2816                         {\r
2817                            int ch = *--ascii;\r
2818 \r
2819                            if (exp_b10 != (-1))\r
2820                               ++exp_b10;\r
2821 \r
2822                            else if (ch == 46)\r
2823                            {\r
2824                               ch = *--ascii, ++size;\r
2825                               /* Advance exp_b10 to '1', so that the\r
2826                                * decimal point happens after the\r
2827                                * previous digit.\r
2828                                */\r
2829                               exp_b10 = 1;\r
2830                            }\r
2831 \r
2832                            --cdigits;\r
2833                            d = ch - 47;  /* I.e. 1+(ch-48) */\r
2834                         }\r
2835 \r
2836                         /* Did we reach the beginning? If so adjust the\r
2837                          * exponent but take into account the leading\r
2838                          * decimal point.\r
2839                          */\r
2840                         if (d > 9)  /* cdigits == 0 */\r
2841                         {\r
2842                            if (exp_b10 == (-1))\r
2843                            {\r
2844                               /* Leading decimal point (plus zeros?), if\r
2845                                * we lose the decimal point here it must\r
2846                                * be reentered below.\r
2847                                */\r
2848                               int ch = *--ascii;\r
2849 \r
2850                               if (ch == 46)\r
2851                                  ++size, exp_b10 = 1;\r
2852 \r
2853                               /* Else lost a leading zero, so 'exp_b10' is\r
2854                                * still ok at (-1)\r
2855                                */\r
2856                            }\r
2857                            else\r
2858                               ++exp_b10;\r
2859 \r
2860                            /* In all cases we output a '1' */\r
2861                            d = 1;\r
2862                         }\r
2863                      }\r
2864                   }\r
2865                   fp = 0; /* Guarantees termination below. */\r
2866                }\r
2867 \r
2868                if (d == 0)\r
2869                {\r
2870                   ++czero;\r
2871                   if (cdigits == 0) ++clead;\r
2872                }\r
2873                else\r
2874                {\r
2875                   /* Included embedded zeros in the digit count. */\r
2876                   cdigits += czero - clead;\r
2877                   clead = 0;\r
2878 \r
2879                   while (czero > 0)\r
2880                   {\r
2881                      /* exp_b10 == (-1) means we just output the decimal\r
2882                       * place - after the DP don't adjust 'exp_b10' any\r
2883                       * more!\r
2884                       */\r
2885                      if (exp_b10 != (-1))\r
2886                      {\r
2887                         if (exp_b10 == 0) *ascii++ = 46, --size;\r
2888                         /* PLUS 1: TOTAL 4 */\r
2889                         --exp_b10;\r
2890                      }\r
2891                      *ascii++ = 48, --czero;\r
2892                   }\r
2893 \r
2894                   if (exp_b10 != (-1))\r
2895                   {\r
2896                      if (exp_b10 == 0) *ascii++ = 46, --size; /* counted\r
2897                                                                  above */\r
2898                      --exp_b10;\r
2899                   }\r
2900                   *ascii++ = (char)(48 + (int)d), ++cdigits;\r
2901                }\r
2902             }\r
2903             while (cdigits+czero-clead < (int)precision && fp > DBL_MIN);\r
2904 \r
2905             /* The total output count (max) is now 4+precision */\r
2906 \r
2907             /* Check for an exponent, if we don't need one we are\r
2908              * done and just need to terminate the string.  At\r
2909              * this point exp_b10==(-1) is effectively if flag - it got\r
2910              * to '-1' because of the decrement after outputing\r
2911              * the decimal point above (the exponent required is\r
2912              * *not* -1!)\r
2913              */\r
2914             if (exp_b10 >= (-1) && exp_b10 <= 2)\r
2915             {\r
2916                /* The following only happens if we didn't output the\r
2917                 * leading zeros above for negative exponent, so this\r
2918                 * doest add to the digit requirement.  Note that the\r
2919                 * two zeros here can only be output if the two leading\r
2920                 * zeros were *not* output, so this doesn't increase\r
2921                 * the output count.\r
2922                 */\r
2923                while (--exp_b10 >= 0) *ascii++ = 48;\r
2924 \r
2925                *ascii = 0;\r
2926 \r
2927                /* Total buffer requirement (including the '\0') is\r
2928                 * 5+precision - see check at the start.\r
2929                 */\r
2930                return;\r
2931             }\r
2932 \r
2933             /* Here if an exponent is required, adjust size for\r
2934              * the digits we output but did not count.  The total\r
2935              * digit output here so far is at most 1+precision - no\r
2936              * decimal point and no leading or trailing zeros have\r
2937              * been output.\r
2938              */\r
2939             size -= cdigits;\r
2940 \r
2941             *ascii++ = 69, --size;    /* 'E': PLUS 1 TOTAL 2+precision */\r
2942 \r
2943             /* The following use of an unsigned temporary avoids ambiguities in\r
2944              * the signed arithmetic on exp_b10 and permits GCC at least to do\r
2945              * better optimization.\r
2946              */\r
2947             {\r
2948                unsigned int uexp_b10;\r
2949 \r
2950                if (exp_b10 < 0)\r
2951                {\r
2952                   *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */\r
2953                   uexp_b10 = -exp_b10;\r
2954                }\r
2955 \r
2956                else\r
2957                   uexp_b10 = exp_b10;\r
2958 \r
2959                cdigits = 0;\r
2960 \r
2961                while (uexp_b10 > 0)\r
2962                {\r
2963                   exponent[cdigits++] = (char)(48 + uexp_b10 % 10);\r
2964                   uexp_b10 /= 10;\r
2965                }\r
2966             }\r
2967 \r
2968             /* Need another size check here for the exponent digits, so\r
2969              * this need not be considered above.\r
2970              */\r
2971             if ((int)size > cdigits)\r
2972             {\r
2973                while (cdigits > 0) *ascii++ = exponent[--cdigits];\r
2974 \r
2975                *ascii = 0;\r
2976 \r
2977                return;\r
2978             }\r
2979          }\r
2980       }\r
2981       else if (!(fp >= DBL_MIN))\r
2982       {\r
2983          *ascii++ = 48; /* '0' */\r
2984          *ascii = 0;\r
2985          return;\r
2986       }\r
2987       else\r
2988       {\r
2989          *ascii++ = 105; /* 'i' */\r
2990          *ascii++ = 110; /* 'n' */\r
2991          *ascii++ = 102; /* 'f' */\r
2992          *ascii = 0;\r
2993          return;\r
2994       }\r
2995    }\r
2996 \r
2997    /* Here on buffer too small. */\r
2998    png_error(png_ptr, "ASCII conversion buffer too small");\r
2999 }\r
3000 \r
3001 #  endif /* FLOATING_POINT */\r
3002 \r
3003 #  ifdef PNG_FIXED_POINT_SUPPORTED\r
3004 /* Function to format a fixed point value in ASCII.\r
3005  */\r
3006 void /* PRIVATE */\r
3007 png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,\r
3008     png_size_t size, png_fixed_point fp)\r
3009 {\r
3010    /* Require space for 10 decimal digits, a decimal point, a minus sign and a\r
3011     * trailing \0, 13 characters:\r
3012     */\r
3013    if (size > 12)\r
3014    {\r
3015       png_uint_32 num;\r
3016 \r
3017       /* Avoid overflow here on the minimum integer. */\r
3018       if (fp < 0)\r
3019          *ascii++ = 45, --size, num = -fp;\r
3020       else\r
3021          num = fp;\r
3022 \r
3023       if (num <= 0x80000000) /* else overflowed */\r
3024       {\r
3025          unsigned int ndigits = 0, first = 16 /* flag value */;\r
3026          char digits[10];\r
3027 \r
3028          while (num)\r
3029          {\r
3030             /* Split the low digit off num: */\r
3031             unsigned int tmp = num/10;\r
3032             num -= tmp*10;\r
3033             digits[ndigits++] = (char)(48 + num);\r
3034             /* Record the first non-zero digit, note that this is a number\r
3035              * starting at 1, it's not actually the array index.\r
3036              */\r
3037             if (first == 16 && num > 0)\r
3038                first = ndigits;\r
3039             num = tmp;\r
3040          }\r
3041 \r
3042          if (ndigits > 0)\r
3043          {\r
3044             while (ndigits > 5) *ascii++ = digits[--ndigits];\r
3045             /* The remaining digits are fractional digits, ndigits is '5' or\r
3046              * smaller at this point.  It is certainly not zero.  Check for a\r
3047              * non-zero fractional digit:\r
3048              */\r
3049             if (first <= 5)\r
3050             {\r
3051                unsigned int i;\r
3052                *ascii++ = 46; /* decimal point */\r
3053                /* ndigits may be <5 for small numbers, output leading zeros\r
3054                 * then ndigits digits to first:\r
3055                 */\r
3056                i = 5;\r
3057                while (ndigits < i) *ascii++ = 48, --i;\r
3058                while (ndigits >= first) *ascii++ = digits[--ndigits];\r
3059                /* Don't output the trailing zeros! */\r
3060             }\r
3061          }\r
3062          else\r
3063             *ascii++ = 48;\r
3064 \r
3065          /* And null terminate the string: */\r
3066          *ascii = 0;\r
3067          return;\r
3068       }\r
3069    }\r
3070 \r
3071    /* Here on buffer too small. */\r
3072    png_error(png_ptr, "ASCII conversion buffer too small");\r
3073 }\r
3074 #   endif /* FIXED_POINT */\r
3075 #endif /* READ_SCAL */\r
3076 \r
3077 #if defined(PNG_FLOATING_POINT_SUPPORTED) && \\r
3078    !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \\r
3079    (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \\r
3080    defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \\r
3081    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \\r
3082    (defined(PNG_sCAL_SUPPORTED) && \\r
3083    defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))\r
3084 png_fixed_point\r
3085 png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)\r
3086 {\r
3087    double r = floor(100000 * fp + .5);\r
3088 \r
3089    if (r > 2147483647. || r < -2147483648.)\r
3090       png_fixed_error(png_ptr, text);\r
3091 \r
3092    return (png_fixed_point)r;\r
3093 }\r
3094 #endif\r
3095 \r
3096 #if defined(PNG_READ_GAMMA_SUPPORTED) || \\r
3097     defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)\r
3098 /* muldiv functions */\r
3099 /* This API takes signed arguments and rounds the result to the nearest\r
3100  * integer (or, for a fixed point number - the standard argument - to\r
3101  * the nearest .00001).  Overflow and divide by zero are signalled in\r
3102  * the result, a boolean - true on success, false on overflow.\r
3103  */\r
3104 int\r
3105 png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,\r
3106     png_int_32 divisor)\r
3107 {\r
3108    /* Return a * times / divisor, rounded. */\r
3109    if (divisor != 0)\r
3110    {\r
3111       if (a == 0 || times == 0)\r
3112       {\r
3113          *res = 0;\r
3114          return 1;\r
3115       }\r
3116       else\r
3117       {\r
3118 #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED\r
3119          double r = a;\r
3120          r *= times;\r
3121          r /= divisor;\r
3122          r = floor(r+.5);\r
3123 \r
3124          /* A png_fixed_point is a 32-bit integer. */\r
3125          if (r <= 2147483647. && r >= -2147483648.)\r
3126          {\r
3127             *res = (png_fixed_point)r;\r
3128             return 1;\r
3129          }\r
3130 #else\r
3131          int negative = 0;\r
3132          png_uint_32 A, T, D;\r
3133          png_uint_32 s16, s32, s00;\r
3134 \r
3135          if (a < 0)\r
3136             negative = 1, A = -a;\r
3137          else\r
3138             A = a;\r
3139 \r
3140          if (times < 0)\r
3141             negative = !negative, T = -times;\r
3142          else\r
3143             T = times;\r
3144 \r
3145          if (divisor < 0)\r
3146             negative = !negative, D = -divisor;\r
3147          else\r
3148             D = divisor;\r