[DEVENUM]
[reactos.git] / reactos / dll / 3rdparty / libpng / png.c
index 7d09b0d..2fbcf45 100644 (file)
@@ -1,8 +1,8 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * Last changed in libpng 1.5.1 [February 3, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.5.14 [January 24, 2013]
+ * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -14,7 +14,7 @@
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_5_2 Your_png_h_is_not_version_1_5_2;
+typedef png_libpng_version_1_5_14 Your_png_h_is_not_version_1_5_14;
 
 /* Tells libpng that we have already handled the first "num_bytes" bytes
  * of the PNG file signature.  If the PNG data is embedded into another
@@ -43,7 +43,7 @@ png_set_sig_bytes(png_structp png_ptr, int num_bytes)
  * can simply check the remaining bytes for extra assurance.  Returns
  * an integer less than, equal to, or greater than zero if sig is found,
  * respectively, to be less than, to match, or be greater than the correct
- * PNG signature (this is the same behaviour as strcmp, memcmp, etc).
+ * PNG signature (this is the same behavior as strcmp, memcmp, etc).
  */
 int PNGAPI
 png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check)
@@ -73,13 +73,16 @@ PNG_FUNCTION(voidpf /* PRIVATE */,
 png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
 {
    png_voidp ptr;
-   png_structp p=(png_structp)png_ptr;
-   png_uint_32 save_flags=p->flags;
+   png_structp p;
+   png_uint_32 save_flags;
    png_alloc_size_t num_bytes;
 
    if (png_ptr == NULL)
       return (NULL);
 
+   p=(png_structp)png_ptr;
+   save_flags=p->flags;
+
    if (items > PNG_UINT_32_MAX/size)
    {
      png_warning (p, "Potential overflow in png_zalloc()");
@@ -107,7 +110,8 @@ png_zfree(voidpf png_ptr, voidpf ptr)
 void /* PRIVATE */
 png_reset_crc(png_structp png_ptr)
 {
-   png_ptr->crc = crc32(0, Z_NULL, 0);
+   /* The cast is safe because the crc is a 32 bit value. */
+   png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0);
 }
 
 /* Calculate the CRC over a section of data.  We can only pass as
@@ -120,21 +124,103 @@ png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length)
 {
    int need_crc = 1;
 
-   if (png_ptr->chunk_name[0] & 0x20)                     /* ancillary */
+   if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name))
    {
       if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
           (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
          need_crc = 0;
    }
 
-   else                                                    /* critical */
+   else /* critical */
    {
       if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
          need_crc = 0;
    }
 
-   if (need_crc)
-      png_ptr->crc = crc32(png_ptr->crc, ptr, (uInt)length);
+   /* 'uLong' is defined as unsigned long, this means that on some systems it is
+    * a 64 bit value.  crc32, however, returns 32 bits so the following cast is
+    * safe.  'uInt' may be no more than 16 bits, so it is necessary to perform a
+    * loop here.
+    */
+   if (need_crc && length > 0)
+   {
+      uLong crc = png_ptr->crc; /* Should never issue a warning */
+
+      do
+      {
+         uInt safeLength = (uInt)length;
+         if (safeLength == 0)
+            safeLength = (uInt)-1; /* evil, but safe */
+
+         crc = crc32(crc, ptr, safeLength);
+
+         /* The following should never issue compiler warnings, if they do the
+          * target system has characteristics that will probably violate other
+          * assumptions within the libpng code.
+          */
+         ptr += safeLength;
+         length -= safeLength;
+      }
+      while (length > 0);
+
+      /* And the following is always safe because the crc is only 32 bits. */
+      png_ptr->crc = (png_uint_32)crc;
+   }
+}
+
+/* Check a user supplied version number, called from both read and write
+ * functions that create a png_struct
+ */
+int
+png_user_version_check(png_structp png_ptr, png_const_charp user_png_ver)
+{
+   if (user_png_ver)
+   {
+      int i = 0;
+
+      do
+      {
+         if (user_png_ver[i] != png_libpng_ver[i])
+            png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+      } while (png_libpng_ver[i++]);
+   }
+
+   else
+      png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
+
+   if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+   {
+     /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
+      * we must recompile any applications that use any older library version.
+      * For versions after libpng 1.0, we will be compatible, so we need
+      * only check the first digit.
+      */
+      if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
+          (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
+          (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
+      {
+#ifdef PNG_WARNINGS_SUPPORTED
+         size_t pos = 0;
+         char m[128];
+
+         pos = png_safecat(m, sizeof m, pos, "Application built with libpng-");
+         pos = png_safecat(m, sizeof m, pos, user_png_ver);
+         pos = png_safecat(m, sizeof m, pos, " but running with ");
+         pos = png_safecat(m, sizeof m, pos, png_libpng_ver);
+
+         png_warning(png_ptr, m);
+#endif
+
+#ifdef PNG_ERROR_NUMBERS_SUPPORTED
+         png_ptr->flags = 0;
+#endif
+
+         return 0;
+      }
+   }
+
+   /* Success return. */
+   return 1;
 }
 
 /* Allocate the memory for an info_struct for the application.  We don't
@@ -291,12 +377,10 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
    /* Free any sCAL entry */
    if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
    {
-#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
       png_free(png_ptr, info_ptr->scal_s_width);
       png_free(png_ptr, info_ptr->scal_s_height);
       info_ptr->scal_s_width = NULL;
       info_ptr->scal_s_height = NULL;
-#endif
       info_ptr->valid &= ~PNG_INFO_sCAL;
    }
 #endif
@@ -489,8 +573,8 @@ png_get_io_ptr(png_structp png_ptr)
 /* Initialize the default input/output functions for the PNG file.  If you
  * use your own read or write routines, you can call either png_set_read_fn()
  * or png_set_write_fn() instead of png_init_io().  If you have defined
- * PNG_NO_STDIO, you must use a function of your own because "FILE *" isn't
- * necessarily available.
+ * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a
+ * function of your own because "FILE *" isn't necessarily available.
  */
 void PNGAPI
 png_init_io(png_structp png_ptr, png_FILE_p fp)
@@ -518,28 +602,47 @@ png_convert_to_rfc1123(png_structp png_ptr, png_const_timep ptime)
    if (png_ptr == NULL)
       return (NULL);
 
-   if (png_ptr->time_buffer == NULL)
+   if (ptime->year > 9999 /* RFC1123 limitation */ ||
+       ptime->month == 0    ||  ptime->month > 12  ||
+       ptime->day   == 0    ||  ptime->day   > 31  ||
+       ptime->hour  > 23    ||  ptime->minute > 59 ||
+       ptime->second > 60)
    {
-      png_ptr->time_buffer = (png_charp)png_malloc(png_ptr, (png_uint_32)(29*
-         png_sizeof(char)));
+      png_warning(png_ptr, "Ignoring invalid time value");
+      return (NULL);
    }
 
-#    ifdef USE_FAR_KEYWORD
    {
-      char near_time_buf[29];
-      png_snprintf6(near_time_buf, 29, "%d %s %d %02d:%02d:%02d +0000",
-          ptime->day % 32, short_months[(ptime->month - 1) % 12],
-          ptime->year, ptime->hour % 24, ptime->minute % 60,
-          ptime->second % 61);
-      png_memcpy(png_ptr->time_buffer, near_time_buf,
-          29*png_sizeof(char));
+      size_t pos = 0;
+      char number_buf[5]; /* enough for a four-digit year */
+
+#     define APPEND_STRING(string)\
+         pos = png_safecat(png_ptr->time_buffer, sizeof png_ptr->time_buffer,\
+            pos, (string))
+#     define APPEND_NUMBER(format, value)\
+         APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))
+#     define APPEND(ch)\
+         if (pos < (sizeof png_ptr->time_buffer)-1)\
+            png_ptr->time_buffer[pos++] = (ch)
+
+      APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);
+      APPEND(' ');
+      APPEND_STRING(short_months[(ptime->month - 1)]);
+      APPEND(' ');
+      APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year);
+      APPEND(' ');
+      APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour);
+      APPEND(':');
+      APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute);
+      APPEND(':');
+      APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second);
+      APPEND_STRING(" +0000"); /* This reliably terminates the buffer */
+
+#     undef APPEND
+#     undef APPEND_NUMBER
+#     undef APPEND_STRING
    }
-#    else
-   png_snprintf6(png_ptr->time_buffer, 29, "%d %s %d %02d:%02d:%02d +0000",
-       ptime->day % 32, short_months[(ptime->month - 1) % 12],
-       ptime->year, ptime->hour % 24, ptime->minute % 60,
-       ptime->second % 61);
-#    endif
+
    return png_ptr->time_buffer;
 }
 #  endif /* PNG_TIME_RFC1123_SUPPORTED */
@@ -555,14 +658,14 @@ png_get_copyright(png_const_structp png_ptr)
 #else
 #  ifdef __STDC__
    return PNG_STRING_NEWLINE \
-     "libpng version 1.5.2 - March 31, 2011" PNG_STRING_NEWLINE \
-     "Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+     "libpng version 1.5.14 - January 24, 2013" PNG_STRING_NEWLINE \
+     "Copyright (c) 1998-2013 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
      PNG_STRING_NEWLINE;
 #  else
-      return "libpng version 1.5.2 - March 31, 2011\
-      Copyright (c) 1998-2011 Glenn Randers-Pehrson\
+      return "libpng version 1.5.14 - January 24, 2013\
+      Copyright (c) 1998-2013 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
 #  endif
@@ -608,25 +711,43 @@ png_get_header_version(png_const_structp png_ptr)
 #endif
 }
 
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-#  ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
 int PNGAPI
 png_handle_as_unknown(png_structp png_ptr, png_const_bytep chunk_name)
 {
    /* Check chunk_name and return "keep" value if it's on the list, else 0 */
-   int i;
-   png_bytep p;
-   if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list<=0)
-      return 0;
+   png_const_bytep p, p_end;
+
+   if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list <= 0)
+      return PNG_HANDLE_CHUNK_AS_DEFAULT;
 
-   p = png_ptr->chunk_list + png_ptr->num_chunk_list*5 - 5;
-   for (i = png_ptr->num_chunk_list; i; i--, p -= 5)
+   p_end = png_ptr->chunk_list;
+   p = p_end + png_ptr->num_chunk_list*5; /* beyond end */
+
+   /* The code is the fifth byte after each four byte string.  Historically this
+    * code was always searched from the end of the list, so it should continue
+    * to do so in case there are duplicated entries.
+    */
+   do /* num_chunk_list > 0, so at least one */
+   {
+      p -= 5;
       if (!png_memcmp(chunk_name, p, 4))
-        return ((int)*(p + 4));
-   return 0;
+         return p[4];
+   }
+   while (p > p_end);
+
+   return PNG_HANDLE_CHUNK_AS_DEFAULT;
 }
-#  endif
-#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+
+int /* PRIVATE */
+png_chunk_unknown_handling(png_structp png_ptr, png_uint_32 chunk_name)
+{
+   png_byte chunk_string[5];
+
+   PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
+   return png_handle_as_unknown(png_ptr, chunk_string);
+}
+#endif
 
 #ifdef PNG_READ_SUPPORTED
 /* This function, added to libpng-1.0.6g, is untested. */
@@ -651,18 +772,9 @@ png_access_version_number(void)
 
 
 #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-#  ifdef PNG_SIZE_T
-/* Added at libpng version 1.2.6 */
-   PNG_EXTERN png_size_t PNGAPI png_convert_size PNGARG((size_t size));
-png_size_t PNGAPI
-png_convert_size(size_t size)
-{
-   if (size > (png_size_t)-1)
-      PNG_ABORT();  /* We haven't got access to png_ptr, so no png_error() */
-
-   return ((png_size_t)size);
-}
-#  endif /* PNG_SIZE_T */
+/* png_convert_size: a PNGAPI but no longer in png.h, so deleted
+ * at libpng 1.5.5!
+ */
 
 /* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
 #  ifdef PNG_CHECK_cHRM_SUPPORTED
@@ -681,6 +793,13 @@ png_check_cHRM_fixed(png_structp png_ptr,
    if (png_ptr == NULL)
       return 0;
 
+   /* (x,y,z) values are first limited to 0..100000 (PNG_FP_1), the white
+    * y must also be greater than 0.  To test for the upper limit calculate
+    * (PNG_FP_1-y) - x must be <= to this for z to be >= 0 (and the expression
+    * cannot overflow.)  At this point we know x and y are >= 0 and (x+y) is
+    * <= PNG_FP_1.  The previous test on PNG_MAX_UINT_31 is removed because it
+    * pointless (and it produces compiler warnings!)
+    */
    if (white_x < 0 || white_y <= 0 ||
          red_x < 0 ||   red_y <  0 ||
        green_x < 0 || green_y <  0 ||
@@ -690,38 +809,26 @@ png_check_cHRM_fixed(png_structp png_ptr,
         "Ignoring attempt to set negative chromaticity value");
       ret = 0;
    }
-   if (white_x > (png_fixed_point)PNG_UINT_31_MAX ||
-       white_y > (png_fixed_point)PNG_UINT_31_MAX ||
-         red_x > (png_fixed_point)PNG_UINT_31_MAX ||
-         red_y > (png_fixed_point)PNG_UINT_31_MAX ||
-       green_x > (png_fixed_point)PNG_UINT_31_MAX ||
-       green_y > (png_fixed_point)PNG_UINT_31_MAX ||
-        blue_x > (png_fixed_point)PNG_UINT_31_MAX ||
-        blue_y > (png_fixed_point)PNG_UINT_31_MAX )
-   {
-      png_warning(png_ptr,
-        "Ignoring attempt to set chromaticity value exceeding 21474.83");
-      ret = 0;
-   }
-   if (white_x > 100000L - white_y)
+   /* And (x+y) must be <= PNG_FP_1 (so z is >= 0) */
+   if (white_x > PNG_FP_1 - white_y)
    {
       png_warning(png_ptr, "Invalid cHRM white point");
       ret = 0;
    }
 
-   if (red_x > 100000L - red_y)
+   if (red_x > PNG_FP_1 - red_y)
    {
       png_warning(png_ptr, "Invalid cHRM red point");
       ret = 0;
    }
 
-   if (green_x > 100000L - green_y)
+   if (green_x > PNG_FP_1 - green_y)
    {
       png_warning(png_ptr, "Invalid cHRM green point");
       ret = 0;
    }
 
-   if (blue_x > 100000L - blue_y)
+   if (blue_x > PNG_FP_1 - blue_y)
    {
       png_warning(png_ptr, "Invalid cHRM blue point");
       ret = 0;
@@ -741,6 +848,326 @@ png_check_cHRM_fixed(png_structp png_ptr,
 }
 #  endif /* PNG_CHECK_cHRM_SUPPORTED */
 
+#ifdef PNG_cHRM_SUPPORTED
+/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
+ * cHRM, as opposed to using chromaticities.  These internal APIs return
+ * non-zero on a parameter error.  The X, Y and Z values are required to be
+ * positive and less than 1.0.
+ */
+int png_xy_from_XYZ(png_xy *xy, png_XYZ XYZ)
+{
+   png_int_32 d, dwhite, whiteX, whiteY;
+
+   d = XYZ.redX + XYZ.redY + XYZ.redZ;
+   if (!png_muldiv(&xy->redx, XYZ.redX, PNG_FP_1, d)) return 1;
+   if (!png_muldiv(&xy->redy, XYZ.redY, PNG_FP_1, d)) return 1;
+   dwhite = d;
+   whiteX = XYZ.redX;
+   whiteY = XYZ.redY;
+
+   d = XYZ.greenX + XYZ.greenY + XYZ.greenZ;
+   if (!png_muldiv(&xy->greenx, XYZ.greenX, PNG_FP_1, d)) return 1;
+   if (!png_muldiv(&xy->greeny, XYZ.greenY, PNG_FP_1, d)) return 1;
+   dwhite += d;
+   whiteX += XYZ.greenX;
+   whiteY += XYZ.greenY;
+
+   d = XYZ.blueX + XYZ.blueY + XYZ.blueZ;
+   if (!png_muldiv(&xy->bluex, XYZ.blueX, PNG_FP_1, d)) return 1;
+   if (!png_muldiv(&xy->bluey, XYZ.blueY, PNG_FP_1, d)) return 1;
+   dwhite += d;
+   whiteX += XYZ.blueX;
+   whiteY += XYZ.blueY;
+
+   /* The reference white is simply the same of the end-point (X,Y,Z) vectors,
+    * thus:
+    */
+   if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1;
+   if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1;
+
+   return 0;
+}
+
+int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
+{
+   png_fixed_point red_inverse, green_inverse, blue_scale;
+   png_fixed_point left, right, denominator;
+
+   /* Check xy and, implicitly, z.  Note that wide gamut color spaces typically
+    * have end points with 0 tristimulus values (these are impossible end
+    * points, but they are used to cover the possible colors.)
+    */
+   if (xy.redx < 0 || xy.redx > PNG_FP_1) return 1;
+   if (xy.redy < 0 || xy.redy > PNG_FP_1-xy.redx) return 1;
+   if (xy.greenx < 0 || xy.greenx > PNG_FP_1) return 1;
+   if (xy.greeny < 0 || xy.greeny > PNG_FP_1-xy.greenx) return 1;
+   if (xy.bluex < 0 || xy.bluex > PNG_FP_1) return 1;
+   if (xy.bluey < 0 || xy.bluey > PNG_FP_1-xy.bluex) return 1;
+   if (xy.whitex < 0 || xy.whitex > PNG_FP_1) return 1;
+   if (xy.whitey < 0 || xy.whitey > PNG_FP_1-xy.whitex) return 1;
+
+   /* The reverse calculation is more difficult because the original tristimulus
+    * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
+    * derived values were recorded in the cHRM chunk;
+    * (red,green,blue,white)x(x,y).  This loses one degree of freedom and
+    * therefore an arbitrary ninth value has to be introduced to undo the
+    * original transformations.
+    *
+    * Think of the original end-points as points in (X,Y,Z) space.  The
+    * chromaticity values (c) have the property:
+    *
+    *           C
+    *   c = ---------
+    *       X + Y + Z
+    *
+    * For each c (x,y,z) from the corresponding original C (X,Y,Z).  Thus the
+    * three chromaticity values (x,y,z) for each end-point obey the
+    * relationship:
+    *
+    *   x + y + z = 1
+    *
+    * This describes the plane in (X,Y,Z) space that intersects each axis at the
+    * value 1.0; call this the chromaticity plane.  Thus the chromaticity
+    * calculation has scaled each end-point so that it is on the x+y+z=1 plane
+    * and chromaticity is the intersection of the vector from the origin to the
+    * (X,Y,Z) value with the chromaticity plane.
+    *
+    * To fully invert the chromaticity calculation we would need the three
+    * end-point scale factors, (red-scale, green-scale, blue-scale), but these
+    * were not recorded.  Instead we calculated the reference white (X,Y,Z) and
+    * recorded the chromaticity of this.  The reference white (X,Y,Z) would have
+    * given all three of the scale factors since:
+    *
+    *    color-C = color-c * color-scale
+    *    white-C = red-C + green-C + blue-C
+    *            = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
+    *
+    * But cHRM records only white-x and white-y, so we have lost the white scale
+    * factor:
+    *
+    *    white-C = white-c*white-scale
+    *
+    * To handle this the inverse transformation makes an arbitrary assumption
+    * about white-scale:
+    *
+    *    Assume: white-Y = 1.0
+    *    Hence:  white-scale = 1/white-y
+    *    Or:     red-Y + green-Y + blue-Y = 1.0
+    *
+    * Notice the last statement of the assumption gives an equation in three of
+    * the nine values we want to calculate.  8 more equations come from the
+    * above routine as summarised at the top above (the chromaticity
+    * calculation):
+    *
+    *    Given: color-x = color-X / (color-X + color-Y + color-Z)
+    *    Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0
+    *
+    * This is 9 simultaneous equations in the 9 variables "color-C" and can be
+    * solved by Cramer's rule.  Cramer's rule requires calculating 10 9x9 matrix
+    * determinants, however this is not as bad as it seems because only 28 of
+    * the total of 90 terms in the various matrices are non-zero.  Nevertheless
+    * Cramer's rule is notoriously numerically unstable because the determinant
+    * calculation involves the difference of large, but similar, numbers.  It is
+    * difficult to be sure that the calculation is stable for real world values
+    * and it is certain that it becomes unstable where the end points are close
+    * together.
+    *
+    * So this code uses the perhaps slightly less optimal but more
+    * understandable and totally obvious approach of calculating color-scale.
+    *
+    * This algorithm depends on the precision in white-scale and that is
+    * (1/white-y), so we can immediately see that as white-y approaches 0 the
+    * accuracy inherent in the cHRM chunk drops off substantially.
+    *
+    * libpng arithmetic: a simple invertion of the above equations
+    * ------------------------------------------------------------
+    *
+    *    white_scale = 1/white-y
+    *    white-X = white-x * white-scale
+    *    white-Y = 1.0
+    *    white-Z = (1 - white-x - white-y) * white_scale
+    *
+    *    white-C = red-C + green-C + blue-C
+    *            = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
+    *
+    * This gives us three equations in (red-scale,green-scale,blue-scale) where
+    * all the coefficients are now known:
+    *
+    *    red-x*red-scale + green-x*green-scale + blue-x*blue-scale
+    *       = white-x/white-y
+    *    red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1
+    *    red-z*red-scale + green-z*green-scale + blue-z*blue-scale
+    *       = (1 - white-x - white-y)/white-y
+    *
+    * In the last equation color-z is (1 - color-x - color-y) so we can add all
+    * three equations together to get an alternative third:
+    *
+    *    red-scale + green-scale + blue-scale = 1/white-y = white-scale
+    *
+    * So now we have a Cramer's rule solution where the determinants are just
+    * 3x3 - far more tractible.  Unfortunately 3x3 determinants still involve
+    * multiplication of three coefficients so we can't guarantee to avoid
+    * overflow in the libpng fixed point representation.  Using Cramer's rule in
+    * floating point is probably a good choice here, but it's not an option for
+    * fixed point.  Instead proceed to simplify the first two equations by
+    * eliminating what is likely to be the largest value, blue-scale:
+    *
+    *    blue-scale = white-scale - red-scale - green-scale
+    *
+    * Hence:
+    *
+    *    (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale =
+    *                (white-x - blue-x)*white-scale
+    *
+    *    (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale =
+    *                1 - blue-y*white-scale
+    *
+    * And now we can trivially solve for (red-scale,green-scale):
+    *
+    *    green-scale =
+    *                (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale
+    *                -----------------------------------------------------------
+    *                                  green-x - blue-x
+    *
+    *    red-scale =
+    *                1 - blue-y*white-scale - (green-y - blue-y) * green-scale
+    *                ---------------------------------------------------------
+    *                                  red-y - blue-y
+    *
+    * Hence:
+    *
+    *    red-scale =
+    *          ( (green-x - blue-x) * (white-y - blue-y) -
+    *            (green-y - blue-y) * (white-x - blue-x) ) / white-y
+    * -------------------------------------------------------------------------
+    *  (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
+    *
+    *    green-scale =
+    *          ( (red-y - blue-y) * (white-x - blue-x) -
+    *            (red-x - blue-x) * (white-y - blue-y) ) / white-y
+    * -------------------------------------------------------------------------
+    *  (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
+    *
+    * Accuracy:
+    * The input values have 5 decimal digits of accuracy.  The values are all in
+    * the range 0 < value < 1, so simple products are in the same range but may
+    * need up to 10 decimal digits to preserve the original precision and avoid
+    * underflow.  Because we are using a 32-bit signed representation we cannot
+    * match this; the best is a little over 9 decimal digits, less than 10.
+    *
+    * The approach used here is to preserve the maximum precision within the
+    * signed representation.  Because the red-scale calculation above uses the
+    * difference between two products of values that must be in the range -1..+1
+    * it is sufficient to divide the product by 7; ceil(100,000/32767*2).  The
+    * factor is irrelevant in the calculation because it is applied to both
+    * numerator and denominator.
+    *
+    * Note that the values of the differences of the products of the
+    * chromaticities in the above equations tend to be small, for example for
+    * the sRGB chromaticities they are:
+    *
+    * red numerator:    -0.04751
+    * green numerator:  -0.08788
+    * denominator:      -0.2241 (without white-y multiplication)
+    *
+    *  The resultant Y coefficients from the chromaticities of some widely used
+    *  color space definitions are (to 15 decimal places):
+    *
+    *  sRGB
+    *    0.212639005871510 0.715168678767756 0.072192315360734
+    *  Kodak ProPhoto
+    *    0.288071128229293 0.711843217810102 0.000085653960605
+    *  Adobe RGB
+    *    0.297344975250536 0.627363566255466 0.075291458493998
+    *  Adobe Wide Gamut RGB
+    *    0.258728243040113 0.724682314948566 0.016589442011321
+    */
+   /* By the argument, above overflow should be impossible here. The return
+    * value of 2 indicates an internal error to the caller.
+    */
+   if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.redy - xy.bluey, 7)) return 2;
+   if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.redx - xy.bluex, 7)) return 2;
+   denominator = left - right;
+
+   /* Now find the red numerator. */
+   if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2;
+   if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.whitex-xy.bluex, 7)) return 2;
+
+   /* Overflow is possible here and it indicates an extreme set of PNG cHRM
+    * chunk values.  This calculation actually returns the reciprocal of the
+    * scale value because this allows us to delay the multiplication of white-y
+    * into the denominator, which tends to produce a small number.
+    */
+   if (!png_muldiv(&red_inverse, xy.whitey, denominator, left-right) ||
+       red_inverse <= xy.whitey /* r+g+b scales = white scale */)
+      return 1;
+
+   /* Similarly for green_inverse: */
+   if (!png_muldiv(&left, xy.redy-xy.bluey, xy.whitex-xy.bluex, 7)) return 2;
+   if (!png_muldiv(&right, xy.redx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2;
+   if (!png_muldiv(&green_inverse, xy.whitey, denominator, left-right) ||
+       green_inverse <= xy.whitey)
+      return 1;
+
+   /* And the blue scale, the checks above guarantee this can't overflow but it
+    * can still produce 0 for extreme cHRM values.
+    */
+   blue_scale = png_reciprocal(xy.whitey) - png_reciprocal(red_inverse) -
+      png_reciprocal(green_inverse);
+   if (blue_scale <= 0) return 1;
+
+
+   /* And fill in the png_XYZ: */
+   if (!png_muldiv(&XYZ->redX, xy.redx, PNG_FP_1, red_inverse)) return 1;
+   if (!png_muldiv(&XYZ->redY, xy.redy, PNG_FP_1, red_inverse)) return 1;
+   if (!png_muldiv(&XYZ->redZ, PNG_FP_1 - xy.redx - xy.redy, PNG_FP_1,
+      red_inverse))
+      return 1;
+
+   if (!png_muldiv(&XYZ->greenX, xy.greenx, PNG_FP_1, green_inverse)) return 1;
+   if (!png_muldiv(&XYZ->greenY, xy.greeny, PNG_FP_1, green_inverse)) return 1;
+   if (!png_muldiv(&XYZ->greenZ, PNG_FP_1 - xy.greenx - xy.greeny, PNG_FP_1,
+      green_inverse))
+      return 1;
+
+   if (!png_muldiv(&XYZ->blueX, xy.bluex, blue_scale, PNG_FP_1)) return 1;
+   if (!png_muldiv(&XYZ->blueY, xy.bluey, blue_scale, PNG_FP_1)) return 1;
+   if (!png_muldiv(&XYZ->blueZ, PNG_FP_1 - xy.bluex - xy.bluey, blue_scale,
+      PNG_FP_1))
+      return 1;
+
+   return 0; /*success*/
+}
+
+int png_XYZ_from_xy_checked(png_structp png_ptr, png_XYZ *XYZ, png_xy xy)
+{
+   switch (png_XYZ_from_xy(XYZ, xy))
+   {
+      case 0: /* success */
+         return 1;
+
+      case 1:
+         /* The chunk may be technically valid, but we got png_fixed_point
+          * overflow while trying to get XYZ values out of it.  This is
+          * entirely benign - the cHRM chunk is pretty extreme.
+          */
+         png_warning(png_ptr,
+            "extreme cHRM chunk cannot be converted to tristimulus values");
+         break;
+
+      default:
+         /* libpng is broken; this should be a warning but if it happens we
+          * want error reports so for the moment it is an error.
+          */
+         png_error(png_ptr, "internal error in png_XYZ_from_xy");
+         break;
+   }
+
+   /* ERROR RETURN */
+   return 0;
+}
+#endif
+
 void /* PRIVATE */
 png_check_IHDR(png_structp png_ptr,
    png_uint_32 width, png_uint_32 height, int bit_depth,
@@ -763,7 +1190,7 @@ png_check_IHDR(png_structp png_ptr,
    }
 
 #  ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (width > png_ptr->user_width_max || width > PNG_USER_WIDTH_MAX)
+   if (width > png_ptr->user_width_max)
 
 #  else
    if (width > PNG_USER_WIDTH_MAX)
@@ -774,7 +1201,7 @@ png_check_IHDR(png_structp png_ptr,
    }
 
 #  ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (height > png_ptr->user_height_max || height > PNG_USER_HEIGHT_MAX)
+   if (height > png_ptr->user_height_max)
 #  else
    if (height > PNG_USER_HEIGHT_MAX)
 #  endif
@@ -889,16 +1316,9 @@ png_check_IHDR(png_structp png_ptr,
 /* Check an ASCII formated floating point value, see the more detailed
  * comments in pngpriv.h
  */
-/* The following is used internally to preserve the 'valid' flag */
+/* The following is used internally to preserve the sticky flags */
 #define png_fp_add(state, flags) ((state) |= (flags))
-#define png_fp_set(state, value)\
-   ((state) = (value) | ((state) & PNG_FP_WAS_VALID))
-
-/* Internal type codes: bits above the base state! */
-#define PNG_FP_SIGN   0  /* [+-] */
-#define PNG_FP_DOT    4  /* . */
-#define PNG_FP_DIGIT  8  /* [0123456789] */
-#define PNG_FP_E     12  /* [Ee] */
+#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))
 
 int /* PRIVATE */
 png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
@@ -911,55 +1331,55 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
    {
       int type;
       /* First find the type of the next character */
+      switch (string[i])
       {
-         char ch = string[i];
-
-         if (ch >= 48 && ch <= 57)
-            type = PNG_FP_DIGIT;
-
-         else switch (ch)
-         {
-         case 43: case 45:  type = PNG_FP_SIGN;  break;
-         case 46:           type = PNG_FP_DOT;   break;
-         case 69: case 101: type = PNG_FP_E;     break;
-         default:           goto PNG_FP_End;
-         }
+      case 43:  type = PNG_FP_SAW_SIGN;                   break;
+      case 45:  type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break;
+      case 46:  type = PNG_FP_SAW_DOT;                    break;
+      case 48:  type = PNG_FP_SAW_DIGIT;                  break;
+      case 49: case 50: case 51: case 52:
+      case 53: case 54: case 55: case 56:
+      case 57:  type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break;
+      case 69:
+      case 101: type = PNG_FP_SAW_E;                      break;
+      default:  goto PNG_FP_End;
       }
 
       /* Now deal with this type according to the current
        * state, the type is arranged to not overlap the
        * bits of the PNG_FP_STATE.
        */
-      switch ((state & PNG_FP_STATE) + type)
+      switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))
       {
-      case PNG_FP_INTEGER + PNG_FP_SIGN:
+      case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:
          if (state & PNG_FP_SAW_ANY)
             goto PNG_FP_End; /* not a part of the number */
 
-         png_fp_add(state, PNG_FP_SAW_SIGN);
+         png_fp_add(state, type);
          break;
 
-      case PNG_FP_INTEGER + PNG_FP_DOT:
+      case PNG_FP_INTEGER + PNG_FP_SAW_DOT:
          /* Ok as trailer, ok as lead of fraction. */
          if (state & PNG_FP_SAW_DOT) /* two dots */
             goto PNG_FP_End;
 
          else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */
-            png_fp_add(state, PNG_FP_SAW_DOT);
+            png_fp_add(state, type);
 
          else
-            png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
+            png_fp_set(state, PNG_FP_FRACTION | type);
 
          break;
 
-      case PNG_FP_INTEGER + PNG_FP_DIGIT:
+      case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:
          if (state & PNG_FP_SAW_DOT) /* delayed fraction */
             png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
 
-         png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID);
+         png_fp_add(state, type | PNG_FP_WAS_VALID);
 
          break;
-      case PNG_FP_INTEGER + PNG_FP_E:
+
+      case PNG_FP_INTEGER + PNG_FP_SAW_E:
          if ((state & PNG_FP_SAW_DIGIT) == 0)
             goto PNG_FP_End;
 
@@ -967,17 +1387,17 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
 
          break;
 
-   /* case PNG_FP_FRACTION + PNG_FP_SIGN:
-         goto PNG_FP_End; ** no sign in exponent */
+   /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN:
+         goto PNG_FP_End; ** no sign in fraction */
 
-   /* case PNG_FP_FRACTION + PNG_FP_DOT:
+   /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT:
          goto PNG_FP_End; ** Because SAW_DOT is always set */
 
-      case PNG_FP_FRACTION + PNG_FP_DIGIT:
-         png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID);
+      case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT:
+         png_fp_add(state, type | PNG_FP_WAS_VALID);
          break;
 
-      case PNG_FP_FRACTION + PNG_FP_E:
+      case PNG_FP_FRACTION + PNG_FP_SAW_E:
          /* This is correct because the trailing '.' on an
           * integer is handled above - so we can only get here
           * with the sequence ".E" (with no preceding digits).
@@ -989,7 +1409,7 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
 
          break;
 
-      case PNG_FP_EXPONENT + PNG_FP_SIGN:
+      case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:
          if (state & PNG_FP_SAW_ANY)
             goto PNG_FP_End; /* not a part of the number */
 
@@ -997,15 +1417,15 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
 
          break;
 
-   /* case PNG_FP_EXPONENT + PNG_FP_DOT:
+   /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT:
          goto PNG_FP_End; */
 
-      case PNG_FP_EXPONENT + PNG_FP_DIGIT:
-         png_fp_add(state, PNG_FP_SAW_DIGIT + PNG_FP_WAS_VALID);
+      case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT:
+         png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID);
 
          break;
 
-   /* case PNG_FP_EXPONEXT + PNG_FP_E:
+   /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E:
          goto PNG_FP_End; */
 
       default: goto PNG_FP_End; /* I.e. break 2 */
@@ -1033,12 +1453,15 @@ png_check_fp_string(png_const_charp string, png_size_t size)
    int        state=0;
    png_size_t char_index=0;
 
-   return png_check_fp_number(string, size, &state, &char_index) &&
-      (char_index == size || string[char_index] == 0);
+   if (png_check_fp_number(string, size, &state, &char_index) &&
+      (char_index == size || string[char_index] == 0))
+      return state /* must be non-zero - see above */;
+
+   return 0; /* i.e. fail */
 }
 #endif /* pCAL or sCAL */
 
-#ifdef PNG_READ_sCAL_SUPPORTED
+#ifdef PNG_sCAL_SUPPORTED
 #  ifdef PNG_FLOATING_POINT_SUPPORTED
 /* Utility used below - a simple accurate power of ten from an integral
  * exponent.
@@ -1047,7 +1470,7 @@ static double
 png_pow10(int power)
 {
    int recip = 0;
-   double d = 1;
+   double d = 1.0;
 
    /* Handle negative exponent with a reciprocal at the end because
     * 10 is exact whereas .1 is inexact in base 2
@@ -1061,7 +1484,7 @@ png_pow10(int power)
    if (power > 0)
    {
       /* Decompose power bitwise. */
-      double mult = 10;
+      double mult = 10.0;
       do
       {
          if (power & 1) d *= mult;
@@ -1102,7 +1525,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
       if (fp < 0)
       {
          fp = -fp;
-         *ascii++ = 45; /* '-'  PLUS 1 TOTAL 1*/
+         *ascii++ = 45; /* '-'  PLUS 1 TOTAL 1 */
          --size;
       }
 
@@ -1180,7 +1603,8 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
             {
                double d;
 
-               fp *= 10;
+               fp *= 10.0;
+
                /* Use modf here, not floor and subtract, so that
                 * the separation is done in one step.  At the end
                 * of the loop don't break the number into parts so
@@ -1193,7 +1617,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
                {
                   d = floor(fp + .5);
 
-                  if (d > 9)
+                  if (d > 9.0)
                   {
                      /* Rounding up to 10, handle that here. */
                      if (czero > 0)
@@ -1201,9 +1625,10 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
                         --czero, d = 1;
                         if (cdigits == 0) --clead;
                      }
+
                      else
                      {
-                        while (cdigits > 0 && d > 9)
+                        while (cdigits > 0 && d > 9.0)
                         {
                            int ch = *--ascii;
 
@@ -1228,7 +1653,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
                          * exponent but take into account the leading
                          * decimal point.
                          */
-                        if (d > 9)  /* cdigits == 0 */
+                        if (d > 9.0)  /* cdigits == 0 */
                         {
                            if (exp_b10 == (-1))
                            {
@@ -1249,18 +1674,19 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
                               ++exp_b10;
 
                            /* In all cases we output a '1' */
-                           d = 1;
+                           d = 1.0;
                         }
                      }
                   }
                   fp = 0; /* Guarantees termination below. */
                }
 
-               if (d == 0)
+               if (d == 0.0)
                {
                   ++czero;
                   if (cdigits == 0) ++clead;
                }
+
                else
                {
                   /* Included embedded zeros in the digit count. */
@@ -1288,6 +1714,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
                                                                  above */
                      --exp_b10;
                   }
+
                   *ascii++ = (char)(48 + (int)d), ++cdigits;
                }
             }
@@ -1329,19 +1756,31 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
              */
             size -= cdigits;
 
-            *ascii++ = 69, --size;    /* 'E': PLUS 1 TOTAL 2+precision*/
-            if (exp_b10 < 0)
+            *ascii++ = 69, --size;    /* 'E': PLUS 1 TOTAL 2+precision */
+
+            /* The following use of an unsigned temporary avoids ambiguities in
+             * the signed arithmetic on exp_b10 and permits GCC at least to do
+             * better optimization.
+             */
             {
-               *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */
-               exp_b10 = -exp_b10;
-            }
+               unsigned int uexp_b10;
 
-            cdigits = 0;
+               if (exp_b10 < 0)
+               {
+                  *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */
+                  uexp_b10 = -exp_b10;
+               }
 
-            while (exp_b10 > 0)
-            {
-               exponent[cdigits++] = (char)(48 + exp_b10 % 10);
-               exp_b10 /= 10;
+               else
+                  uexp_b10 = exp_b10;
+
+               cdigits = 0;
+
+               while (uexp_b10 > 0)
+               {
+                  exponent[cdigits++] = (char)(48 + uexp_b10 % 10);
+                  uexp_b10 /= 10;
+               }
             }
 
             /* Need another size check here for the exponent digits, so
@@ -1399,9 +1838,9 @@ png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size,
       else
          num = fp;
 
-      if (num <= 0x80000000U) /* else overflowed */
+      if (num <= 0x80000000) /* else overflowed */
       {
-         unsigned int ndigits = 0, first = 16/*flag value*/;
+         unsigned int ndigits = 0, first = 16 /* flag value */;
          char digits[10];
 
          while (num)
@@ -1495,7 +1934,7 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
          r /= divisor;
          r = floor(r+.5);
 
-         /* A png_fixed_point is a 32 bit integer. */
+         /* A png_fixed_point is a 32-bit integer. */
          if (r <= 2147483647. && r >= -2147483648.)
          {
             *res = (png_fixed_point)r;
@@ -1540,7 +1979,7 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
 
          if (s32 < D) /* else overflow */
          {
-            /* s32.s00 is now the 64 bit product, do a standard
+            /* s32.s00 is now the 64-bit product, do a standard
              * division, we know that s32 < D, so the maximum
              * required shift is 31.
              */
@@ -1608,7 +2047,8 @@ png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times,
 }
 #endif
 
-#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */
+#if (defined PNG_READ_GAMMA_SUPPORTED) || (defined PNG_cHRM_SUPPORTED)
+/* more fixed point functions for gamma and cHRM (xy/XYZ) suport. */
 /* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
 png_fixed_point
 png_reciprocal(png_fixed_point a)
@@ -1628,6 +2068,7 @@ png_reciprocal(png_fixed_point a)
    return 0; /* error/overflow */
 }
 
+#ifdef PNG_READ_GAMMA_SUPPORTED
 /* A local convenience routine. */
 static png_fixed_point
 png_product2(png_fixed_point a, png_fixed_point b)
@@ -1649,6 +2090,7 @@ png_product2(png_fixed_point a, png_fixed_point b)
 
    return 0; /* overflow */
 }
+#endif /* READ_GAMMA */
 
 /* The inverse of the above. */
 png_fixed_point
@@ -1676,14 +2118,14 @@ png_reciprocal2(png_fixed_point a, png_fixed_point b)
 
    return 0; /* overflow */
 }
-#endif /* READ_GAMMA */
+#endif /* READ_GAMMA || cHRM */
 
 #ifdef PNG_CHECK_cHRM_SUPPORTED
 /* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2,
  * 2010: moved from pngset.c) */
 /*
  *    Multiply two 32-bit numbers, V1 and V2, using 32-bit
- *    arithmetic, to produce a 64 bit result in the HI/LO words.
+ *    arithmetic, to produce a 64-bit result in the HI/LO words.
  *
  *                  A B
  *                x C D
@@ -1727,24 +2169,24 @@ png_64bit_product (long v1, long v2, unsigned long *hi_product,
 /* Fixed point gamma.
  *
  * To calculate gamma this code implements fast log() and exp() calls using only
- * fixed point arithmetic.  This code has sufficient precision for either 8 or
- * 16 bit sample values.
+ * fixed point arithmetic.  This code has sufficient precision for either 8-bit
+ * or 16-bit sample values.
  *
  * The tables used here were calculated using simple 'bc' programs, but C double
  * precision floating point arithmetic would work fine.  The programs are given
  * at the head of each table.
  *
- * 8 bit log table
+ * 8-bit log table
  *   This is a table of -log(value/255)/log(2) for 'value' in the range 128 to
- *   255, so it's the base 2 logarithm of a normalized 8 bit floating point
- *   mantissa.  The numbers are 32 bit fractions.
+ *   255, so it's the base 2 logarithm of a normalized 8-bit floating point
+ *   mantissa.  The numbers are 32-bit fractions.
  */
 static png_uint_32
 png_8bit_l2[128] =
 {
-#  if PNG_DO_BC
+#  ifdef PNG_DO_BC
       for (i=128;i<256;++i) { .5 - l(i/255)/l(2)*65536*65536; }
-#  endif
+#  else
    4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
    3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
    3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
@@ -1767,11 +2209,13 @@ png_8bit_l2[128] =
    324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
    172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
    24347096U, 0U
+#  endif
+
 #if 0
-   /* The following are the values for 16 bit tables - these work fine for the 8
-    * bit conversions but produce very slightly larger errors in the 16 bit log
-    * (about 1.2 as opposed to 0.7 absolute error in the final value).  To use
-    * these all the shifts below must be adjusted appropriately.
+   /* The following are the values for 16-bit tables - these work fine for the
+    * 8-bit conversions but produce very slightly larger errors in the 16-bit
+    * log (about 1.2 as opposed to 0.7 absolute error in the final value).  To
+    * use these all the shifts below must be adjusted appropriately.
     */
    65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
    57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
@@ -1788,7 +2232,7 @@ png_8bit_l2[128] =
 #endif
 };
 
-static png_int_32
+PNG_STATIC png_int_32
 png_log8bit(unsigned int x)
 {
    unsigned int lg2 = 0;
@@ -1814,11 +2258,11 @@ png_log8bit(unsigned int x)
    return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16));
 }
 
-/* The above gives exact (to 16 binary places) log2 values for 8 bit images,
- * for 16 bit images we use the most significant 8 bits of the 16 bit value to
+/* The above gives exact (to 16 binary places) log2 values for 8-bit images,
+ * for 16-bit images we use the most significant 8 bits of the 16-bit value to
  * get an approximation then multiply the approximation by a correction factor
  * determined by the remaining up to 8 bits.  This requires an additional step
- * in the 16 bit case.
+ * in the 16-bit case.
  *
  * We want log2(value/65535), we have log2(v'/255), where:
  *
@@ -1827,8 +2271,8 @@ png_log8bit(unsigned int x)
  *
  * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
  * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less
- * than 258.  The final factor also needs to correct for the fact that our 8 bit
- * value is scaled by 255, whereas the 16 bit values must be scaled by 65535.
+ * than 258.  The final factor also needs to correct for the fact that our 8-bit
+ * value is scaled by 255, whereas the 16-bit values must be scaled by 65535.
  *
  * This gives a final formula using a calculated value 'x' which is value/v' and
  * scaling by 65536 to match the above table:
@@ -1838,13 +2282,13 @@ png_log8bit(unsigned int x)
  * Since these numbers are so close to '1' we can use simple linear
  * interpolation between the two end values 256/257 (result -368.61) and 258/257
  * (result 367.179).  The values used below are scaled by a further 64 to give
- * 16 bit precision in the interpolation:
+ * 16-bit precision in the interpolation:
  *
  * Start (256): -23591
  * Zero  (257):      0
  * End   (258):  23499
  */
-static png_int_32
+PNG_STATIC png_int_32
 png_log16bit(png_uint_32 x)
 {
    unsigned int lg2 = 0;
@@ -1865,7 +2309,7 @@ png_log16bit(png_uint_32 x)
    if ((x & 0x8000) == 0)
       lg2 += 1, x <<= 1;
 
-   /* Calculate the base logarithm from the top 8 bits as a 28 bit fractional
+   /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional
     * value.
     */
    lg2 <<= 28;
@@ -1895,34 +2339,35 @@ png_log16bit(png_uint_32 x)
    return (png_int_32)((lg2 + 2048) >> 12);
 }
 
-/* The 'exp()' case must invert the above, taking a 20 bit fixed point
- * logarithmic value and returning a 16 or 8 bit number as appropriate.  In
+/* The 'exp()' case must invert the above, taking a 20-bit fixed point
+ * logarithmic value and returning a 16 or 8-bit number as appropriate.  In
  * each case only the low 16 bits are relevant - the fraction - since the
  * integer bits (the top 4) simply determine a shift.
  *
- * The worst case is the 16 bit distinction between 65535 and 65534, this
- * requires perhaps spurious accuracty in the decoding of the logarithm to
+ * The worst case is the 16-bit distinction between 65535 and 65534, this
+ * requires perhaps spurious accuracy in the decoding of the logarithm to
  * distinguish log2(65535/65534.5) - 10^-5 or 17 bits.  There is little chance
  * of getting this accuracy in practice.
  *
  * To deal with this the following exp() function works out the exponent of the
- * frational part of the logarithm by using an accurate 32 bit value from the
+ * frational part of the logarithm by using an accurate 32-bit value from the
  * top four fractional bits then multiplying in the remaining bits.
  */
 static png_uint_32
 png_32bit_exp[16] =
 {
-#  if PNG_DO_BC
+#  ifdef PNG_DO_BC
       for (i=0;i<16;++i) { .5 + e(-i/16*l(2))*2^32; }
-#  endif
-   /* NOTE: the first entry is deliberately set to the maximum 32 bit value. */
+#  else
+   /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */
    4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U,
    3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U,
    2553802834U, 2445529972U, 2341847524U, 2242560872U
+#  endif
 };
 
 /* Adjustment table; provided to explain the numbers in the code below. */
-#if PNG_DO_BC
+#ifdef PNG_DO_BC
 for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
    11 44937.64284865548751208448
    10 45180.98734845585101160448
@@ -1938,12 +2383,12 @@ for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
     0 45425.85339951654943850496
 #endif
 
-static png_uint_32
+PNG_STATIC png_uint_32
 png_exp(png_fixed_point x)
 {
    if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */
    {
-      /* Obtain a 4 bit approximation */
+      /* Obtain a 4-bit approximation */
       png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf];
 
       /* Incorporate the low 12 bits - these decrease the returned value by
@@ -1986,13 +2431,13 @@ png_exp(png_fixed_point x)
    return 0;
 }
 
-static png_byte
+PNG_STATIC png_byte
 png_exp8bit(png_fixed_point lg2)
 {
-   /* Get a 32 bit value: */
+   /* Get a 32-bit value: */
    png_uint_32 x = png_exp(lg2);
 
-   /* Convert the 32 bit value to 0..255 by multiplying by 256-1, note that the
+   /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the
     * second, rounding, step can't overflow because of the first, subtraction,
     * step.
     */
@@ -2000,13 +2445,13 @@ png_exp8bit(png_fixed_point lg2)
    return (png_byte)((x + 0x7fffffU) >> 24);
 }
 
-static png_uint_16
+PNG_STATIC png_uint_16
 png_exp16bit(png_fixed_point lg2)
 {
-   /* Get a 32 bit value: */
+   /* Get a 32-bit value: */
    png_uint_32 x = png_exp(lg2);
 
-   /* Convert the 32 bit value to 0..65535 by multiplying by 65536-1: */
+   /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */
    x -= x >> 16;
    return (png_uint_16)((x + 32767U) >> 16);
 }
@@ -2059,9 +2504,9 @@ png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
 }
 
 /* This does the right thing based on the bit_depth field of the
- * png_struct, interpreting values as 8 or 16 bit.  While the result
- * is nominally a 16 bit value if bit depth is 8 then the result is
- * 8 bit (as are the arguments.)
+ * png_struct, interpreting values as 8-bit or 16-bit.  While the result
+ * is nominally a 16-bit value if bit depth is 8 then the result is
+ * 8-bit (as are the arguments.)
  */
 png_uint_16 /* PRIVATE */
 png_gamma_correct(png_structp png_ptr, unsigned int value,
@@ -2084,8 +2529,8 @@ png_gamma_significant(png_fixed_point gamma_val)
        gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
 }
 
-/* Internal function to build a single 16 bit table - the table consists of
- * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
+/* Internal function to build a single 16-bit table - the table consists of
+ * 'num' 256-entry subtables, where 'num' is determined by 'shift' - the amount
  * to shift the input values right (or 16-number_of_signifiant_bits).
  *
  * The caller is responsible for ensuring that the table gets cleaned up on
@@ -2111,7 +2556,7 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
           (png_uint_16p)png_malloc(png_ptr, 256 * png_sizeof(png_uint_16));
 
       /* The 'threshold' test is repeated here because it can arise for one of
-       * the 16 bit tables even if the others don't hit it.
+       * the 16-bit tables even if the others don't hit it.
        */
       if (png_gamma_significant(gamma_val))
       {
@@ -2172,9 +2617,9 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
    png_uint_16pp table = *ptable =
        (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p));
 
-   /* 'num' is the number of tables and also the number of low bits of low
-    * bits of the input 16 bit value used to select a table.  Each table is
-    * itself index by the high 8 bits of the value.
+   /* 'num' is the number of tables and also the number of low bits of the
+    * input 16-bit value used to select a table.  Each table is itself indexed
+    * by the high 8 bits of the value.
     */
    for (i = 0; i < num; i++)
       table[i] = (png_uint_16p)png_malloc(png_ptr,
@@ -2183,24 +2628,24 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
    /* 'gamma_val' is set to the reciprocal of the value calculated above, so
     * pow(out,g) is an *input* value.  'last' is the last input value set.
     *
-    * In the loop 'i' is used to find output values.  Since the output is 8
-    * bit there are only 256 possible values.  The tables are set up to
+    * In the loop 'i' is used to find output values.  Since the output is
+    * 8-bit there are only 256 possible values.  The tables are set up to
     * select the closest possible output value for each input by finding
     * the input value at the boundary between each pair of output values
     * and filling the table up to that boundary with the lower output
     * value.
     *
-    * The boundary values are 0.5,1.5..253.5,254.5.  Since these are 9 bit
-    * values the code below uses a 16 bit value in i; the values start at
+    * The boundary values are 0.5,1.5..253.5,254.5.  Since these are 9-bit
+    * values the code below uses a 16-bit value in i; the values start at
     * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last
     * entries are filled with 255).  Start i at 128 and fill all 'last'
     * table entries <= 'max'
     */
    last = 0;
-   for (i = 0; i < 255; ++i) /* 8 bit output value */
+   for (i = 0; i < 255; ++i) /* 8-bit output value */
    {
       /* Find the corresponding maximum input value */
-      png_uint_16 out = (png_uint_16)(i * 257U); /* 16 bit output value */
+      png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */
 
       /* Find the boundary value in 16 bits: */
       png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val);
@@ -2223,9 +2668,9 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
    }
 }
 
-/* Build a single 8 bit table: same as the 16 bit case but much simpler (and
+/* Build a single 8-bit table: same as the 16-bit case but much simpler (and
  * typically much faster).  Note that libpng currently does no sBIT processing
- * (apparently contrary to the spec) so a 256 entry table is always generated.
+ * (apparently contrary to the spec) so a 256-entry table is always generated.
  */
 static void
 png_build_8bit_table(png_structp png_ptr, png_bytepp ptable,
@@ -2241,6 +2686,60 @@ png_build_8bit_table(png_structp png_ptr, png_bytepp ptable,
       table[i] = (png_byte)i;
 }
 
+/* Used from png_read_destroy and below to release the memory used by the gamma
+ * tables.
+ */
+void /* PRIVATE */
+png_destroy_gamma_table(png_structp png_ptr)
+{
+   png_free(png_ptr, png_ptr->gamma_table);
+   png_ptr->gamma_table = NULL;
+
+   if (png_ptr->gamma_16_table != NULL)
+   {
+      int i;
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
+      {
+         png_free(png_ptr, png_ptr->gamma_16_table[i]);
+      }
+   png_free(png_ptr, png_ptr->gamma_16_table);
+   png_ptr->gamma_16_table = NULL;
+   }
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
+   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
+   png_free(png_ptr, png_ptr->gamma_from_1);
+   png_ptr->gamma_from_1 = NULL;
+   png_free(png_ptr, png_ptr->gamma_to_1);
+   png_ptr->gamma_to_1 = NULL;
+
+   if (png_ptr->gamma_16_from_1 != NULL)
+   {
+      int i;
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
+      {
+         png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
+      }
+   png_free(png_ptr, png_ptr->gamma_16_from_1);
+   png_ptr->gamma_16_from_1 = NULL;
+   }
+   if (png_ptr->gamma_16_to_1 != NULL)
+   {
+      int i;
+      int istop = (1 << (8 - png_ptr->gamma_shift));
+      for (i = 0; i < istop; i++)
+      {
+         png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
+      }
+   png_free(png_ptr, png_ptr->gamma_16_to_1);
+   png_ptr->gamma_16_to_1 = NULL;
+   }
+#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
+}
+
 /* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
  * tables, we don't make a full table if we are reducing to 8-bit in
  * the future.  Note also how the gamma_16 tables are segmented so that
@@ -2251,6 +2750,18 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
 {
   png_debug(1, "in png_build_gamma_table");
 
+  /* Remove any existing table; this copes with multiple calls to
+   * png_read_update_info.  The warning is because building the gamma tables
+   * multiple times is a performance hit - it's harmless but the ability to call
+   * png_read_update_info() multiple times is new in 1.5.6 so it seems sensible
+   * to warn if the app introduces such a hit.
+   */
+  if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
+  {
+    png_warning(png_ptr, "gamma table being rebuilt");
+    png_destroy_gamma_table(png_ptr);
+  }
+
   if (bit_depth <= 8)
   {
      png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
@@ -2258,8 +2769,9 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
          png_ptr->screen_gamma) : PNG_FP_1);
 
 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-     if (png_ptr->transformations & ((PNG_BACKGROUND) | PNG_RGB_TO_GRAY))
+     if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
      {
         png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
             png_reciprocal(png_ptr->gamma));
@@ -2268,7 +2780,7 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
             png_ptr->screen_gamma > 0 ?  png_reciprocal(png_ptr->screen_gamma) :
             png_ptr->gamma/* Probably doing rgb_to_gray */);
      }
-#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
+#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
   }
   else
   {
@@ -2287,14 +2799,14 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
      else
         sig_bit = png_ptr->sig_bit.gray;
 
-     /* 16 bit gamma code uses this equation:
+     /* 16-bit gamma code uses this equation:
       *
       *   ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
       *
       * Where 'iv' is the input color value and 'ov' is the output value -
       * pow(iv, gamma).
       *
-      * Thus the gamma table consists of up to 256 256 entry tables.  The table
+      * Thus the gamma table consists of up to 256 256-entry tables.  The table
       * is selected by the (8-gamma_shift) most significant of the low 8 bits of
       * the color value then indexed by the upper 8 bits:
       *
@@ -2302,7 +2814,7 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
       *
       * So the table 'n' corresponds to all those 'iv' of:
       *
-      *   <all high 8 bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1>
+      *   <all high 8-bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1>
       *
       */
      if (sig_bit > 0 && sig_bit < 16U)
@@ -2311,7 +2823,7 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
      else
         shift = 0; /* keep all 16 bits */
 
-     if (png_ptr->transformations & PNG_16_TO_8)
+     if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
      {
         /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
          * the significant bits in the *input* when the output will
@@ -2327,7 +2839,12 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
      png_ptr->gamma_shift = shift;
 
 #ifdef PNG_16BIT_SUPPORTED
-     if (png_ptr->transformations & (PNG_16_TO_8 | PNG_BACKGROUND))
+     /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
+      * PNG_COMPOSE).  This effectively smashed the background calculation for
+      * 16-bit output because the 8-bit table assumes the result will be reduced
+      * to 8 bits.
+      */
+     if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
 #endif
          png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
          png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma,
@@ -2341,8 +2858,9 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
 #endif
 
 #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
    defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-     if (png_ptr->transformations & (PNG_BACKGROUND | PNG_RGB_TO_GRAY))
+     if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
      {
         png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
             png_reciprocal(png_ptr->gamma));
@@ -2355,7 +2873,7 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
             png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
             png_ptr->gamma/* Probably doing rgb_to_gray */);
      }
-#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_RGB_TO_GRAY_SUPPORTED */
+#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
   }
 }
 #endif /* READ_GAMMA */