[libpng16] Avoid the double gamma correction warning in the simplified API.

This allows the --strict option to pass in the pngstest checks
diff --git a/ANNOUNCE b/ANNOUNCE
index 62d76fc..f2e652f 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -336,6 +336,8 @@
   Added application error reporting and added chunk names to read
     benign errors; also added --strict to pngstest - not enabled
     yet because a warning is produced.
+  Avoid the double gamma correction warning in the simplified API.
+    This allows the --strict option to pass in the pngstest checks
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/CHANGES b/CHANGES
index e378d3c..6191cda 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4087,6 +4087,8 @@
   Added application error reporting and added chunk names to read
     benign errors; also added --strict to pngstest - not enabled
     yet because a warning is produced.
+  Avoid the double gamma correction warning in the simplified API.
+    This allows the --strict option to pass in the pngstest checks
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/contrib/libtests/pngstest.c b/contrib/libtests/pngstest.c
index d826713..c16de96 100644
--- a/contrib/libtests/pngstest.c
+++ b/contrib/libtests/pngstest.c
@@ -299,7 +299,7 @@
 
 #define READ_FILE 1      /* else memory */
 #define USE_STDIO 2      /* else use file name */
-/* 4: unused */
+#define STRICT 4         /* fail on warnings too */
 #define VERBOSE 8
 #define KEEP_TMPFILES 16 /* else delete temporary files */
 #define KEEP_GOING 32
@@ -313,6 +313,8 @@
       printf(" --file");
    if (opts & USE_STDIO)
       printf(" --stdio");
+   if (opts & STRICT)
+      printf(" --strict");
    if (opts & VERBOSE)
       printf(" --verbose");
    if (opts & KEEP_TMPFILES)
@@ -321,6 +323,8 @@
       printf(" --keep-going");
    if (opts & ACCUMULATE)
       printf(" --accumulate");
+   if (!(opts & FAST_WRITE)) /* --fast is currently the default */
+      printf(" --slow");
 }
 
 #define FORMAT_NO_CHANGE 0x80000000 /* additional flag */
@@ -715,6 +719,9 @@
       return logerror(image, image->file_name, ": opaque not NULL", "");
    }
 
+   else if (image->image.warning_or_error != 0 && (image->opts & STRICT) != 0)
+      return logerror(image, image->file_name, " --strict", "");
+
    else
       return 1;
 }
@@ -3454,6 +3461,8 @@
          redundant = 1;
       else if (strcmp(arg, "--stop") == 0)
          opts &= ~KEEP_GOING;
+      else if (strcmp(arg, "--strict") == 0)
+         opts |= STRICT;
       else if (strcmp(arg, "--touch") == 0)
       {
          if (c+1 < argc)
diff --git a/pngread.c b/pngread.c
index e9cd59c..78285b5 100644
--- a/pngread.c
+++ b/pngread.c
@@ -1839,6 +1839,17 @@
 }
 
 static int
+make_gray_file_colormap(png_image_read_control *display)
+{
+   unsigned int i;
+
+   for (i=0; i<256; ++i)
+      png_create_colormap_entry(display, i, i, i, i, 255, E_FILE);
+
+   return i;
+}
+
+static int
 make_gray_colormap(png_image_read_control *display)
 {
    unsigned int i;
@@ -2368,7 +2379,23 @@
                if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
                   png_error(png_ptr, "rgb[gray] color-map: too few entries");
 
-               cmap_entries = make_gray_colormap(display);
+               /* Ideally this code would use libpng to do the gamma correction,
+                * but if an input alpha channel is to be removed we will hit the
+                * libpng bug in gamma+compose+rgb-to-gray (the double gamma
+                * correction bug).  Fix this by dropping the gamma correction in
+                * this case and doing it in the palette; this will result in
+                * duplicate palette entries, but that's better than the
+                * alternative of double gamma correction.
+                */
+               if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+                  png_ptr->num_trans > 0) && png_gamma_not_sRGB(png_ptr->gamma))
+               {
+                  cmap_entries = make_gray_file_colormap(display);
+                  data_encoding = E_FILE;
+               }
+
+               else
+                  cmap_entries = make_gray_colormap(display);
 
                /* But if the input has alpha or transparency it must be removed
                 */
@@ -2383,18 +2410,38 @@
                    * it.  Achieve this simply by ensuring that the entry
                    * selected for the background really is the background color.
                    */
-                  if (output_encoding == E_LINEAR)
+                  if (data_encoding == E_FILE) /* from the fixup above */
+                  {
+                     /* The app supplied a gray which is in output_encoding, we
+                      * need to convert it to a value of the input (E_FILE)
+                      * encoding then set this palette entry to the required
+                      * output encoding.
+                      */
+                     if (output_encoding == E_sRGB)
+                        gray = png_sRGB_table[gray]; /* now E_LINEAR */
+
+                     gray = PNG_DIV257(png_gamma_16bit_correct(gray,
+                        png_ptr->gamma)); /* now E_FILE */
+
+                     /* And make sure the corresponding palette entry contains
+                      * exactly the required sRGB value.
+                      */
+                     png_create_colormap_entry(display, gray, back_g, back_g,
+                        back_g, 0/*unused*/, output_encoding);
+                  }
+
+                  else if (output_encoding == E_LINEAR)
                   {
                      gray = PNG_sRGB_FROM_LINEAR(gray * 255);
 
                      /* And make sure the corresponding palette entry matches.
                       */
                      png_create_colormap_entry(display, gray, back_g, back_g,
-                        back_g, 65535, E_LINEAR);
+                        back_g, 0/*unused*/, E_LINEAR);
                   }
 
-                  /* The background passed to libpng, however, must be the sRGB
-                   * value.
+                  /* The background passed to libpng, however, must be the
+                   * output (normally sRGB) value.
                    */
                   c.index = 0; /*unused*/
                   c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
@@ -2657,13 +2704,12 @@
          png_error(png_ptr, "bad data option (internal error)");
          break;
 
-      case E_FILE:
-         /* Make no changes */
-         break;
-
       case E_sRGB:
          /* Change to 8-bit sRGB */
          png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
+         /* FALL THROUGH */
+
+      case E_FILE:
          if (png_ptr->bit_depth > 8)
             png_set_scale_16(png_ptr);
          break;
diff --git a/test-pngstest.sh b/test-pngstest.sh
index c9da532..e977a5b 100755
--- a/test-pngstest.sh
+++ b/test-pngstest.sh
@@ -11,7 +11,7 @@
 do
    for opts in ""
    do
-      if ./pngstest --log "$@" $opts $image >>pngtest-log.txt 2>&1
+      if ./pngstest --strict --log "$@" $opts $image >>pngtest-log.txt 2>&1
       then
          echo "  PASS: pngstest $opts $image"
       else