[devel] Added named value and 'flag' gamma support to png_set_gamma.  Made a

minor change from the previous (unreleased) ABI/API to hide the exact value
used for Macs - it's not a good idea to embed this in the ABI!
diff --git a/ANNOUNCE b/ANNOUNCE
index 6663232..23c6d6b 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,5 +1,5 @@
 
-Libpng 1.5.3beta07 - May 9, 2011
+Libpng 1.5.3beta07 - May 11, 2011
 
 This is not intended to be a public release.  It will be replaced
 within a few weeks by a public version or by another test version.
@@ -101,8 +101,11 @@
   Removed the -D_ALL_SOURCE from definitions for AIX in CMakeLists.txt
   Implemented premultiplied alpha support: png_set_alpha_mode API
 
-Version 1.5.3beta07 [May 9, 2011]
+Version 1.5.3beta07 [May 11, 2011]
   Added expand_16 support to the high level interface.
+  Added named value and 'flag' gamma support to png_set_gamma.  Made a minor
+    change from the previous (unreleased) ABI/API to hide the exact value used
+    for Macs - it's not a good idea to embed this in the ABI!
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net:
 (subscription required; visit
diff --git a/CHANGES b/CHANGES
index d40d01a..6ed3dd6 100644
--- a/CHANGES
+++ b/CHANGES
@@ -3360,8 +3360,11 @@
   Removed the -D_ALL_SOURCE from definitions for AIX in CMakeLists.txt
   Implemented premultiplied alpha support: png_set_alpha_mode API
 
-Version 1.5.3beta07 [May 9, 2011]
+Version 1.5.3beta07 [May 11, 2011]
   Added expand_16 support to the high level interface.
+  Added named value and 'flag' gamma support to png_set_gamma.  Made a minor
+    change from the previous (unreleased) ABI/API to hide the exact value used
+    for Macs - it's not a good idea to embed this in the ABI!
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/png.h b/png.h
index fb188d7..19a9296 100644
--- a/png.h
+++ b/png.h
@@ -1,7 +1,7 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.5.3beta07 - May 9, 2011
+ * libpng version 1.5.3beta07 - May 11, 2011
  * Copyright (c) 1998-2011 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.)
@@ -11,7 +11,7 @@
  * Authors and maintainers:
  *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *   libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.5.3beta07 - May 9, 2011: Glenn
+ *   libpng versions 0.97, January 1998, through 1.5.3beta07 - May 11, 2011: Glenn
  *   See also "Contributing Authors", below.
  *
  * Note about libpng version numbers:
@@ -182,7 +182,7 @@
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.2.6, August 15, 2004, through 1.5.3beta07, May 9, 2011, are
+ * libpng versions 1.2.6, August 15, 2004, through 1.5.3beta07, May 11, 2011, are
  * Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
  * distributed according to the same disclaimer and license as libpng-1.2.5
  * with the following individual added to the list of Contributing Authors:
@@ -294,7 +294,7 @@
  * Y2K compliance in libpng:
  * =========================
  *
- *    May 9, 2011
+ *    May 11, 2011
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
@@ -357,7 +357,7 @@
 /* Version information for png.h - this should match the version in png.c */
 #define PNG_LIBPNG_VER_STRING "1.5.3beta07"
 #define PNG_HEADER_VERSION_STRING \
-     " libpng version 1.5.3beta07 - May 9, 2011\n"
+     " libpng version 1.5.3beta07 - May 11, 2011\n"
 
 #define PNG_LIBPNG_VER_SONUM   15
 #define PNG_LIBPNG_VER_DLLNUM  15
@@ -1176,7 +1176,9 @@
     double output_gamma));
 PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr,
     int mode, png_fixed_point output_gamma));
+#endif
 
+#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED)
 /* The output_gamma value is a screen gamma in libpng terminology: it expresses
  * how to decode the output values, not how they are encoded.  The values used
  * correspond to the normal numbers used to describe the overall gamma of a
@@ -1230,14 +1232,22 @@
  * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the
  * default if you don't know what the right answer is!
  *
+ * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS
+ * 10.6) which used a correction table to implement a somewhat lower gamma on an
+ * otherwise sRGB system.
+ *
+ * Both these values are reserved (not simple gamma values) in order to allow
+ * more precise correction internally in the future.
+ *
  * NOTE: the following values can be passed to either the fixed or floating
  * point APIs, but the floating point API will also accept floating point
  * values.
  */
-#define PNG_DEFAULT_sRGB 0        /* sRGB gamma and color space */
+#define PNG_DEFAULT_sRGB -1       /* sRGB gamma and color space */
+#define PNG_GAMMA_MAC_18 -2       /* Old Mac '1.8' gamma and color space */
 #define PNG_GAMMA_sRGB   220000   /* Television standards--matches sRGB gamma */
-#define PNG_GAMMA_MAC    151724   /* Television with a 1.45 correction table */
 #define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */
+#endif
 
 /* The following are examples of calls to png_set_alpha_mode to achieve the
  * required overall gamma correction and, where necessary, alpha
@@ -1314,7 +1324,6 @@
  *    made in the same read operation, however multiple calls with PNG_ALPHA_PNG
  *    are ignored.
  */
-#endif
 
 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
 PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr));
@@ -1421,7 +1430,13 @@
 /* Handle gamma correction. Screen_gamma=(display_exponent).
  * NOTE: this API simply sets the screen and file gamma values. It will
  * therefore override the value for gamma in a PNG file if it is called after
- * the file header has been read - use with care!
+ * the file header has been read - use with care  - call before reading the PNG
+ * file for best results!
+ *
+ * These routines accept the same gamma values as png_set_alpha_mode (described
+ * above).  The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either
+ * API (floating point or fixed.)  Notice, however, that the 'file_gamma' value
+ * is the inverse of a 'screen gamma' value.
  */
 PNG_FP_EXPORT(50, void, png_set_gamma,
     (png_structp png_ptr, double screen_gamma,
diff --git a/pngpriv.h b/pngpriv.h
index d6849c3..dfe0ca2 100644
--- a/pngpriv.h
+++ b/pngpriv.h
@@ -459,6 +459,11 @@
 #define PNG_tRNS PNG_CONST png_byte png_tRNS[5] = {116,  82,  78,  83, '\0'}
 #define PNG_zTXt PNG_CONST png_byte png_zTXt[5] = {122,  84,  88, 116, '\0'}
 
+/* Gamma values (new at libpng-1.5.3): */
+#define PNG_GAMMA_MAC_OLD 151724  /* Assume '1.8' is really 2.2/1.45! */
+#define PNG_GAMMA_MAC_INVERSE 65909
+#define PNG_GAMMA_sRGB_INVERSE 45455
+
 
 /* Inhibit C++ name-mangling for libpng functions but not for system calls. */
 #ifdef __cplusplus
diff --git a/pngrtran.c b/pngrtran.c
index cdf84ce..dda48c0 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -159,6 +159,68 @@
 }
 #endif
 
+#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
+static png_fixed_point
+translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
+   int is_screen)
+{
+   /* Check for flag values.  The main reason for having the old Mac value as a
+    * flag is that it is pretty near impossible to work out what the correct
+    * value is from Apple documentation - a working Mac system is needed to
+    * discover the value!
+    */
+   if (output_gamma == PNG_DEFAULT_sRGB ||
+      output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
+   {
+      /* If there is no sRGB support this just sets the gamma to the standard
+       * sRGB value.  (This is a side effect of using this function!)
+       */
+#     ifdef PNG_READ_sRGB_SUPPORTED
+         png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
+#     endif
+      if (is_screen)
+         output_gamma = PNG_GAMMA_sRGB;
+      else
+         output_gamma = PNG_GAMMA_sRGB_INVERSE;
+   }
+
+   else if (output_gamma == PNG_GAMMA_MAC_18 ||
+      output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
+   {
+      if (is_screen)
+         output_gamma = PNG_GAMMA_MAC_OLD;
+      else
+         output_gamma = PNG_GAMMA_MAC_INVERSE;
+   }
+
+   return output_gamma;
+}
+
+#  ifdef PNG_FLOATING_POINT_SUPPORTED
+static png_fixed_point
+convert_gamma_value(png_structp png_ptr, double output_gamma)
+{
+   /* The following silently ignores cases where fixed point (times 100,000)
+    * gamma values are passed to the floating point API.  This is safe and it
+    * means the fixed point constants work just fine with the floating point
+    * API.  The alternative would just lead to undetected errors and spurious
+    * bug reports.  Negative values fail inside the _fixed API unless they
+    * correspond to the flag values.
+    */
+   if (output_gamma > 0 && output_gamma < 128)
+      output_gamma *= PNG_FP_1;
+
+   /* This preserves -1 and -2 exactly: */
+   output_gamma = floor(output_gamma + .5);
+
+   if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)
+      png_fixed_error(png_ptr, "gamma value");
+
+   return (png_fixed_point)output_gamma;
+}
+#  endif
+#endif /* READ_ALPHA_MODE || READ_GAMMA */
+
 #ifdef PNG_READ_ALPHA_MODE_SUPPORTED
 void PNGFAPI
 png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
@@ -172,28 +234,15 @@
    if (png_ptr == NULL)
       return;
 
-   /* If the default_gamma value is 0 then switch on the whole sRGB
-    * edifice by this flag (note: this is a flag to the later code,
-    * not a transformation!)
-    */
-   if (output_gamma == PNG_DEFAULT_sRGB)
-   {
-      /* If there is no sRGB support this just sets the gamma to the standard
-       * sRGB value.
-       */
-#     ifdef PNG_READ_sRGB_SUPPORTED
-         png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
-#     endif
-      output_gamma = PNG_GAMMA_sRGB;
-   }
+   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
 
-   /* Else validate the value to ensure it is in a reasonable range. The value
+   /* Validate the value to ensure it is in a reasonable range. The value
     * is expected to be 1 or greater, but this range test allows for some
     * viewing correction values.  The intent is to weed out users of this API
     * who use the inverse of the gamma value accidentally!  Since some of these
     * values are reasonable this may have to be changed.
     */
-   else if (output_gamma < 70000 || output_gamma > 300000)
+   if (output_gamma < 70000 || output_gamma > 300000)
       png_error(png_ptr, "output gamma out of expected range");
 
    /* The default file gamma is the inverse of the output gamma; the output
@@ -286,19 +335,8 @@
 void PNGAPI
 png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
 {
-   /* The following silently ignores cases where fixed point (times 100,000)
-    * gamma values are passed to the floating point API.  This is safe and it
-    * means the fixed point constants work just fine with the floating point
-    * API.  The alternative would just lead to undetected errors and spurious
-    * bug reports.  Negative values fail inside the _fixed API.
-    */
-   if (output_gamma > -128 && output_gamma < 128)
-      output_gamma *= PNG_FP_1;
-
-   if (output_gamma <= PNG_FP_MAX && output_gamma >= PNG_FP_MIN)
-      png_set_alpha_mode_fixed(png_ptr, mode, (png_fixed_point)output_gamma);
-   else
-      png_fixed_error(png_ptr, "png_set_alpha_mode gamma");
+   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
+      output_gamma));
 }
 #  endif
 #endif
@@ -719,6 +757,10 @@
    if (png_ptr == NULL)
       return;
 
+   /* New in libpng-1.5.3 - reserve particular negative values as flags. */
+   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
+   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
+
 #if PNG_LIBPNG_VER >= 10600
    /* Checking the gamma values for being >0 was added in 1.5.3 along with the
     * premultiplied alpha support; this actually hides an undocumented feature
@@ -749,9 +791,8 @@
 void PNGAPI
 png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
 {
-   png_set_gamma_fixed(png_ptr,
-      png_fixed(png_ptr, scrn_gamma, "png_set_gamma screen gamma"),
-      png_fixed(png_ptr, file_gamma, "png_set_gamma file gamma"));
+   png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
+      convert_gamma_value(png_ptr, file_gamma));
 }
 #  endif /* FLOATING_POINT_SUPPORTED */
 #endif /* READ_GAMMA */
diff --git a/pngset.c b/pngset.c
index 1b0fd1d..2c58f7f 100644
--- a/pngset.c
+++ b/pngset.c
@@ -545,7 +545,7 @@
    png_set_sRGB(png_ptr, info_ptr, srgb_intent);
 
 #  ifdef PNG_gAMA_SUPPORTED
-   png_set_gAMA_fixed(png_ptr, info_ptr, 45455L);
+   png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
 #  endif
 
 #  ifdef PNG_cHRM_SUPPORTED