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