[Feature][ZXW-88]merge P50 version

Only Configure: No
Affected branch: master
Affected module: unknown
Is it affected on both ZXIC and MTK: only ZXIC
Self-test: Yes
Doc Update: No

Change-Id: I34667719d9e0e7e29e8e4368848601cde0a48408
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/README.txt b/ap/lib/libpng/libpng-1.6.37/contrib/tools/README.txt
new file mode 100755
index 0000000..f53be6d
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/README.txt
@@ -0,0 +1,27 @@
+This directory (contrib/tools) contains tools used by the authors of libpng.
+
+Code and data placed in this directory is not required to build libpng,
+however the code in this directory has been used to generate data or code in
+the body of the libpng source.  The source code identifies where this has
+been done.  Code in this directory may not compile on all operating systems
+that libpng supports.
+
+NO COPYRIGHT RIGHTS ARE CLAIMED TO ANY OF THE FILES IN THIS DIRECTORY.
+
+To the extent possible under law, the authors have waived all copyright and
+related or neighboring rights to this work.  This work is published from:
+United States.
+
+The files may be used freely in any way.
+
+The source code and comments in this directory are the original work of the
+people named below.  No other person or organization has made contributions to
+the work in this directory.
+
+ORIGINAL AUTHORS
+    The following people have contributed to the code in this directory.  None
+    of the people below claim any rights with regard to the contents of this
+    directory.
+
+    John Bowler <jbowler at acm.org>
+    Glenn Randers-Pehrson <glennrp at users.sourceforge.net>
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/checksum-icc.c b/ap/lib/libpng/libpng-1.6.37/contrib/tools/checksum-icc.c
new file mode 100755
index 0000000..581e708
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/checksum-icc.c
@@ -0,0 +1,102 @@
+/* checksum-icc.c
+ *
+ * Copyright (c) 2013 John Cunningham Bowler
+ *
+ * Last changed in libpng 1.6.0 [February 14, 2013]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * Generate crc32 and adler32 checksums of the given input files, used to
+ * generate check-codes for use when matching ICC profiles within libpng.
+ */
+#include <stdio.h>
+
+#include <zlib.h>
+
+static int
+read_one_file(FILE *ip, const char *name)
+{
+   uLong length = 0;
+   uLong a32 = adler32(0, NULL, 0);
+   uLong c32 = crc32(0, NULL, 0);
+   Byte header[132];
+
+   for (;;)
+   {
+      int ch = getc(ip);
+      Byte b;
+
+      if (ch == EOF) break;
+
+      b = (Byte)ch;
+
+      if (length < sizeof header)
+         header[length] = b;
+
+      ++length;
+      a32 = adler32(a32, &b, 1);
+      c32 = crc32(c32, &b, 1);
+   }
+
+   if (ferror(ip))
+      return 0;
+
+   /* Success */
+   printf("PNG_ICC_CHECKSUM(0x%8.8lx, 0x%8.8lx,\n   PNG_MD5("
+      "0x%2.2x%2.2x%2.2x%2.2x, 0x%2.2x%2.2x%2.2x%2.2x, 0x%2.2x%2.2x%2.2x%2.2x,"
+      " 0x%2.2x%2.2x%2.2x%2.2x), %d,\n"
+      "   \"%4.4d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d\", %lu, \"%s\")\n",
+      (unsigned long)a32, (unsigned long)c32,
+      header[84], header[85], header[86], header[87],
+      header[88], header[89], header[90], header[91],
+      header[92], header[93], header[94], header[95],
+      header[96], header[97], header[98], header[99],
+#     define u16(x) (header[x] * 256 + header[x+1])
+#     define u32(x) (u16(x) * 65536 + u16(x+2))
+      u32(64), u16(24), u16(26), u16(28), u16(30), u16(32), u16(34),
+      (unsigned long)length, name);
+
+   return 1;
+}
+
+int main(int argc, char **argv)
+{
+   int err = 0;
+
+   printf("/* adler32, crc32, MD5[16], intent, date, length, file-name */\n");
+
+   if (argc > 1)
+   {
+      int i;
+
+      for (i=1; i<argc; ++i)
+      {
+         FILE *ip = fopen(argv[i], "rb");
+
+         if (ip == NULL || !read_one_file(ip, argv[i]))
+         {
+            err = 1;
+            perror(argv[i]);
+            fprintf(stderr, "%s: read error\n", argv[i]);
+            printf("/* ERROR: %s */\n", argv[i]);
+         }
+
+         (void)fclose(ip);
+      }
+   }
+
+   else
+   {
+      if (!read_one_file(stdin, "-"))
+      {
+         err = 1;
+         perror("stdin");
+         fprintf(stderr, "stdin: read error\n");
+         printf("/* ERROR: stdin */\n");
+      }
+   }
+
+   return err;
+}
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/chkfmt b/ap/lib/libpng/libpng-1.6.37/contrib/tools/chkfmt
new file mode 100755
index 0000000..95181fd
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/chkfmt
@@ -0,0 +1,144 @@
+#!/bin/sh
+
+# chkfmt
+#
+# COPYRIGHT: Written by John Cunningham Bowler, 2010.
+# To the extent possible under law, the author has waived all copyright and
+# related or neighboring rights to this work.  This work is published from:
+# United States.
+#
+# Check the format of the source files in the current directory - checks for a
+# line length of 80 characters max and no tab characters.
+#
+# Optionally arguments are files or directories to check.
+#
+# -v: output the long lines (makes fixing them easier)
+# -e: spawn an editor for each file that needs a change ($EDITOR must be
+#     defined).  When using -e the script MUST be run from an interactive
+#     command line.
+verbose=
+edit=
+vers=
+test "$1" = "-v" && {
+   shift
+   verbose=yes
+}
+test "$1" = "-e" && {
+   shift
+   if test -n "$EDITOR"
+   then
+      edit=yes
+
+      # Copy the standard streams for the editor
+      exec 3>&0 4>&1 5>&2
+   else
+      echo "chkfmt -e: EDITOR must be defined" >&2
+      exit 1
+   fi
+}
+
+# Function to edit a single file - if the file isn't changed ask the user
+# whether or not to continue.  This stuff only works if the script is run from
+# the command line (otherwise, don't specify -e or you will be sorry).
+doed(){
+   cp "$file" "$file".orig
+   "$EDITOR" "$file" 0>&3 1>&4 2>&5 3>&- 4>&- 5>&- || exit 1
+   if cmp -s "$file".orig "$file"
+   then
+      rm "$file".orig
+      echo -n "$file: file not changed, type anything to continue: " >&5
+      read ans 0>&3
+      test -n "$ans" || return 1
+   fi
+   return 0
+}
+
+# In beta versions the version string which appears in files can be a little
+# long and cause spuriously overlong lines.  To avoid this substitute the version
+# string with a 'standard' version a.b.cc before checking for long lines.
+if test -r png.h
+then
+   vers="`sed -n -e \
+   's/^#define PNG_LIBPNG_VER_STRING .\([0-9]\.[0-9]\.[0-9][0-9a-z]*\).$/\1/p' \
+   png.h`"
+   echo "chkfmt: checking version $vers"
+fi
+if test -z "$vers"
+then
+   echo "chkfmt: png.h not found, ignoring version number" >&2
+fi
+
+test -n "$1" || set -- .
+find "$@" \( -type d \( -name '.git' -o -name '.libs' -o -name 'projects' \) \
+   -prune \) -o \( -type f \
+   ! -name '*.[oa]' ! -name '*.l[oa]' !  -name '*.png' ! -name '*.out' \
+   ! -name '*.jpg' ! -name '*.patch' ! -name '*.obj' ! -name '*.exe' \
+   ! -name '*.com' ! -name '*.tar.*' ! -name '*.zip' ! -name '*.ico' \
+   ! -name '*.res' ! -name '*.rc' ! -name '*.mms' ! -name '*.rej' \
+   ! -name '*.dsp' ! -name '*.orig' ! -name '*.dfn' ! -name '*.swp' \
+   ! -name '~*' ! -name '*.3' \
+   ! -name 'missing' ! -name 'mkinstalldirs' ! -name 'depcomp' \
+   ! -name 'aclocal.m4' ! -name 'install-sh' ! -name 'Makefile.in' \
+   ! -name 'ltmain.sh' ! -name 'config*' -print \) | {
+   st=0
+   while read file
+   do
+      case "$file" in
+      *.mak|*[Mm]akefile.*|*[Mm]akefile)
+         # Makefiles require tabs, dependency lines can be this long.
+         check_tabs=
+         line_length=100;;
+      *.awk)
+         # Includes literal tabs
+         check_tabs=
+         # The following is arbitrary
+         line_length=132;;
+      *contrib/*/*.[ch])
+         check_tabs=yes
+         line_length=96;;
+      *)
+         check_tabs=yes
+         line_length=80;;
+      esac
+
+      # Note that vers can only contain 0-9, . and a-z
+      if test -n "$vers"
+      then
+         sed -e "s/$vers/a.b.cc/g" "$file" >"$file".$$
+      else
+         cp "$file" "$file".$$
+      fi
+      splt="`fold -$line_length "$file".$$ | diff -c "$file".$$ -`"
+      rm "$file".$$
+
+      if test -n "$splt"
+      then
+         echo "$file: lines too long"
+         st=1
+         if test -n "$EDITOR" -a -n "$edit"
+         then
+            doed "$file" || exit 1
+         elif test -n "$verbose"
+         then
+            echo "$splt"
+         fi
+      fi
+      if test -n "$check_tabs"
+      then
+         tab="`tr -c -d '\t' <"$file"`"
+         if test -n "$tab"
+         then
+            echo "$file: file contains tab characters"
+            st=1
+            if test -n "$EDITOR" -a -n "$edit"
+            then
+               doed "$file" || exit 1
+            elif test -n "$verbose"
+            then
+               echo "$splt"
+            fi
+         fi
+      fi
+   done
+   exit $st
+}
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/cvtcolor.c b/ap/lib/libpng/libpng-1.6.37/contrib/tools/cvtcolor.c
new file mode 100755
index 0000000..e6793c7
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/cvtcolor.c
@@ -0,0 +1,188 @@
+/*-
+ * convert.c
+ *
+ * Last changed in libpng 1.6.0 [February 14, 2013]
+ *
+ * COPYRIGHT: Written by John Cunningham Bowler, 2013.
+ * To the extent possible under law, the author has waived all copyright and
+ * related or neighboring rights to this work.  This work is published from:
+ * United States.
+ *
+ * Convert 8-bit sRGB or 16-bit linear values to another format.
+ */
+#define _ISOC99_SOURCE 1
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <stdio.h>
+
+#include <fenv.h>
+
+#include "sRGB.h"
+
+static void
+usage(const char *prog)
+{
+   fprintf(stderr,
+      "%s: usage: %s [-linear|-sRGB] [-gray|-color] component{1,4}\n",
+      prog, prog);
+   exit(1);
+}
+
+unsigned long
+component(const char *prog, const char *arg, int issRGB)
+{
+   char *ep;
+   unsigned long c = strtoul(arg, &ep, 0);
+
+   if (ep <= arg || *ep || c > 65535 || (issRGB && c > 255))
+   {
+      fprintf(stderr, "%s: %s: invalid component value (%lu)\n", prog, arg, c);
+      usage(prog);
+   }
+
+   return c;
+}
+
+int
+main(int argc, const char **argv)
+{
+   const char *prog = *argv++;
+   int to_linear = 0, to_gray = 0, to_color = 0;
+   int channels = 0;
+   double c[4];
+
+   /* FE_TONEAREST is the IEEE754 round to nearest, preferring even, mode; i.e.
+    * everything rounds to the nearest value except that '.5' rounds to the
+    * nearest even value.
+    */
+   fesetround(FE_TONEAREST);
+
+   c[3] = c[2] = c[1] = c[0] = 0;
+
+   while (--argc > 0 && **argv == '-')
+   {
+      const char *arg = 1+*argv++;
+
+      if (strcmp(arg, "sRGB") == 0)
+         to_linear = 0;
+
+      else if (strcmp(arg, "linear") == 0)
+         to_linear = 1;
+
+      else if (strcmp(arg, "gray") == 0)
+         to_gray = 1, to_color = 0;
+
+      else if (strcmp(arg, "color") == 0)
+         to_gray = 0, to_color = 1;
+
+      else
+         usage(prog);
+   }
+
+   switch (argc)
+   {
+      default:
+         usage(prog);
+         break;
+
+      case 4:
+         c[3] = component(prog, argv[3], to_linear);
+         ++channels;
+      case 3:
+         c[2] = component(prog, argv[2], to_linear);
+         ++channels;
+      case 2:
+         c[1] = component(prog, argv[1], to_linear);
+         ++channels;
+      case 1:
+         c[0] = component(prog, argv[0], to_linear);
+         ++channels;
+         break;
+      }
+
+   if (to_linear)
+   {
+      int i;
+      int components = channels;
+
+      if ((components & 1) == 0)
+         --components;
+
+      for (i=0; i<components; ++i) c[i] = linear_from_sRGB(c[i] / 255);
+      if (components < channels)
+         c[components] = c[components] / 255;
+   }
+
+   else
+   {
+      int i;
+      for (i=0; i<4; ++i) c[i] /= 65535;
+
+      if ((channels & 1) == 0)
+      {
+         double alpha = c[channels-1];
+
+         if (alpha > 0)
+            for (i=0; i<channels-1; ++i) c[i] /= alpha;
+         else
+            for (i=0; i<channels-1; ++i) c[i] = 1;
+      }
+   }
+
+   if (to_gray)
+   {
+      if (channels < 3)
+      {
+         fprintf(stderr, "%s: too few channels (%d) for -gray\n",
+            prog, channels);
+         usage(prog);
+      }
+
+      c[0] = YfromRGB(c[0], c[1], c[2]);
+      channels -= 2;
+   }
+
+   if (to_color)
+   {
+      if (channels > 2)
+      {
+         fprintf(stderr, "%s: too many channels (%d) for -color\n",
+            prog, channels);
+         usage(prog);
+      }
+
+      c[3] = c[1]; /* alpha, if present */
+      c[2] = c[1] = c[0];
+   }
+
+   if (to_linear)
+   {
+      int i;
+      if ((channels & 1) == 0)
+      {
+         double alpha = c[channels-1];
+         for (i=0; i<channels-1; ++i) c[i] *= alpha;
+      }
+
+      for (i=0; i<channels; ++i) c[i] = nearbyint(c[i] * 65535);
+   }
+
+   else /* to sRGB */
+   {
+      int i = (channels+1)&~1;
+      while (--i >= 0)
+         c[i] = sRGB_from_linear(c[i]);
+
+      for (i=0; i<channels; ++i) c[i] = nearbyint(c[i] * 255);
+   }
+
+   {
+      int i;
+      for (i=0; i<channels; ++i) printf(" %g", c[i]);
+   }
+   printf("\n");
+
+   return 0;
+}
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/genpng.c b/ap/lib/libpng/libpng-1.6.37/contrib/tools/genpng.c
new file mode 100755
index 0000000..0b3f981
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/genpng.c
@@ -0,0 +1,881 @@
+/*- genpng
+ *
+ * COPYRIGHT: Written by John Cunningham Bowler, 2015.
+ * Revised by Glenn Randers-Pehrson, 2017, to add buffer-size check.
+ * To the extent possible under law, the authors have waived all copyright and
+ * related or neighboring rights to this work.  This work is published from:
+ * United States.
+ *
+ * Generate a PNG with an alpha channel, correctly.
+ *
+ * This is a test case generator; the resultant PNG files are only of interest
+ * to those of us who care about whether the edges of circles are green, red,
+ * or yellow.
+ *
+ * The program generates an RGB+Alpha PNG of a given size containing the given
+ * shapes on a transparent background:
+ *
+ *  genpng width height { shape }
+ *    shape ::= color width shape x1 y1 x2 y2
+ *
+ * 'color' is:
+ *
+ *  black white red green yellow blue brown purple pink orange gray cyan
+ *
+ * The point is to have colors that are linguistically meaningful plus that old
+ * bugbear of the department store dress murders, Cyan, the only color we argue
+ * about.
+ *
+ * 'shape' is:
+ *
+ *  circle: an ellipse
+ *  square: a rectangle
+ *  line: a straight line
+ *
+ * Each shape is followed by four numbers, these are two points in the output
+ * coordinate space (as real numbers) which describe the circle, square, or
+ * line.  The shape is filled if it is preceded by 'filled' (not valid for
+ * 'line') or is drawn with a line, in which case the width of the line must
+ * precede the shape.
+ *
+ * The whole set of information can be repeated as many times as desired:
+ *
+ *    shape ::= color width shape x1 y1 x2 y2
+ *
+ *    color ::= black|white|red|green|yellow|blue
+ *    color ::= brown|purple|pink|orange|gray|cyan
+ *    width ::= filled
+ *    width ::= <number>
+ *    shape ::= circle|square|line
+ *    x1    ::= <number>
+ *    x2    ::= <number>
+ *    y1    ::= <number>
+ *    y2    ::= <number>
+ *
+ * The output PNG is generated by down-sampling a 4x supersampled image using
+ * a bi-cubic filter.  The bi-cubic has a 2 (output) pixel width, so an 8x8
+ * array of super-sampled points contribute to each output pixel.  The value of
+ * a super-sampled point is found using an unfiltered, aliased, infinite
+ * precision image: Each shape from the last to the first is checked to see if
+ * the point is in the drawn area and, if it is, the color of the point is the
+ * color of the shape and the alpha is 1, if not the previous shape is checked.
+ *
+ * This is an aliased algorithm because no filtering is done; a point is either
+ * inside or outside each shape and 'close' points do not contribute to the
+ * sample.  The down-sampling is relied on to correct the error of not using
+ * a filter.
+ *
+ * The line end-caps are 'flat'; they go through the points.  The square line
+ * joins are mitres; the outside of the lines are continued to the point of
+ * intersection.
+ */
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+/* Normally use <png.h> here to get the installed libpng, but this is done to
+ * ensure the code picks up the local libpng implementation:
+ */
+#include "../../png.h"
+
+#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+
+static const struct color
+{
+   const char *name;
+   double      red;
+   double      green;
+   double      blue;
+} colors[] =
+/* color ::= black|white|red|green|yellow|blue
+ * color ::= brown|purple|pink|orange|gray|cyan
+ */
+{
+   { "black",   0,    0,  0 },
+   { "white",   1,    1,  1 },
+   { "red",     1,    0,  0 },
+   { "green",   0,    1,  0 },
+   { "yellow",  1,    1,  0 },
+   { "blue",    0,    0,  1 },
+   { "brown",  .5, .125,  0 },
+   { "purple",  1,    0,  1 },
+   { "pink",    1,   .5, .5 },
+   { "orange",  1,   .5,  0 },
+   { "gray",    0,   .5, .5 },
+   { "cyan",    0,    1,  1 }
+};
+#define color_count ((sizeof colors)/(sizeof colors[0]))
+
+static const struct color *
+color_of(const char *arg)
+{
+   int icolor = color_count;
+
+   while (--icolor >= 0)
+   {
+      if (strcmp(colors[icolor].name, arg) == 0)
+         return colors+icolor;
+   }
+
+   fprintf(stderr, "genpng: invalid color %s\n", arg);
+   exit(1);
+}
+
+static double
+width_of(const char *arg)
+{
+   if (strcmp(arg, "filled") == 0)
+      return 0;
+
+   else
+   {
+      char *ep = NULL;
+      double w = strtod(arg, &ep);
+
+      if (ep != NULL && *ep == 0 && w > 0)
+         return w;
+   }
+
+   fprintf(stderr, "genpng: invalid line width %s\n", arg);
+   exit(1);
+}
+
+static double
+coordinate_of(const char *arg)
+{
+   char *ep = NULL;
+   double w = strtod(arg, &ep);
+
+   if (ep != NULL && *ep == 0)
+      return w;
+
+   fprintf(stderr, "genpng: invalid coordinate value %s\n", arg);
+   exit(1);
+}
+
+struct arg; /* forward declaration */
+
+typedef int (*shape_fn_ptr)(const struct arg *arg, double x, double y);
+   /* A function to determine if (x,y) is inside the shape.
+    *
+    * There are two implementations:
+    *
+    *    inside_fn: returns true if the point is inside
+    *    check_fn:  returns;
+    *       -1: the point is outside the shape by more than the filter width (2)
+    *        0: the point may be inside the shape
+    *       +1: the point is inside the shape by more than the filter width
+    */
+#define OUTSIDE (-1)
+#define INSIDE  (1)
+
+struct arg
+{
+   const struct color *color;
+   shape_fn_ptr        inside_fn;
+   shape_fn_ptr        check_fn;
+   double              width; /* line width, 0 for 'filled' */
+   double              x1, y1, x2, y2;
+};
+
+/* IMPLEMENTATION NOTE:
+ *
+ * We want the contribution of each shape to the sample corresponding to each
+ * pixel.  This could be obtained by super sampling the image to infinite
+ * dimensions, finding each point within the shape and assigning that a value
+ * '1' while leaving every point outside the shape with value '0' then
+ * downsampling to the image size with sinc; computationally very expensive.
+ *
+ * Approximations are as follows:
+ *
+ * 1) If the pixel coordinate is within the shape assume the sample has the
+ *    shape color and is opaque, else assume there is no contribution from
+ *    the shape.
+ *
+ *    This is the equivalent of aliased rendering or resampling an image with
+ *    a block filter.  The maximum error in the calculated alpha (which will
+ *    always be 0 or 1) is 0.5.
+ *
+ * 2) If the shape is within a square of size 1x1 centered on the pixel assume
+ *    that the shape obscures an amount of the pixel equal to its area within
+ *    that square.
+ *
+ *    This is the equivalent of 'pixel coverage' alpha calculation or resampling
+ *    an image with a bi-linear filter.  The maximum error is over 0.2, but the
+ *    results are often acceptable.
+ *
+ *    This can be approximated by applying (1) to a super-sampled image then
+ *    downsampling with a bi-linear filter.  The error in the super-sampled
+ *    image is 0.5 per sample, but the resampling reduces this.
+ *
+ * 3) Use a better filter with a super-sampled image; in the limit this is the
+ *    sinc() approach.
+ *
+ * 4) Do the geometric calculation; a bivariate definite integral across the
+ *    shape, unfortunately this means evaluating Si(x), the integral of sinc(x),
+ *    which is still a lot of math.
+ *
+ * This code uses approach (3) with a bi-cubic filter and 8x super-sampling
+ * and method (1) for the super-samples.  This means that the sample is either
+ * 0 or 1, depending on whether the sub-pixel is within or outside the shape.
+ * The bi-cubic weights are also fixed and the 16 required weights are
+ * pre-computed here (note that the 'scale' setting will need to be changed if
+ * 'super' is increased).
+ *
+ * The code also calculates a sum to the edge of the filter. This is not
+ * currently used by could be used to optimize the calculation.
+ */
+#if 0 /* bc code */
+scale=10
+super=8
+define bicubic(x) {
+   if (x <= 1) return (1.5*x - 2.5)*x*x + 1;
+   if (x <  2) return (((2.5 - 0.5*x)*x - 4)*x + 2);
+   return 0;
+}
+define sum(x) {
+   auto s;
+   s = 0;
+   while (x < 2*super) {
+      s = s + bicubic(x/super);
+      x = x + 1;
+   }
+   return s;
+}
+define results(x) {
+   auto b, s;
+   b = bicubic(x/super);
+   s = sum(x);
+
+   print "   /*", x, "*/ { ", b, ", ", s, " }";
+   return 1;
+}
+x=0
+while (x<2*super) {
+   x = x + results(x)
+   if (x < 2*super) print ","
+   print "\n"
+}
+quit
+#endif
+
+#define BICUBIC1(x) /*     |x| <= 1 */ ((1.5*(x)* - 2.5)*(x)*(x) + 1)
+#define BICUBIC2(x) /* 1 < |x| <  2 */ (((2.5 - 0.5*(x))*(x) - 4)*(x) + 2)
+#define FILTER_WEIGHT 9 /* Twice the first sum below */
+#define FILTER_WIDTH  2 /* Actually half the width; -2..+2 */
+#define FILTER_STEPS  8 /* steps per filter unit */
+static const double
+bicubic[16][2] =
+{
+   /* These numbers are exact; the weight for the filter is 1/9, but this
+    * would make the numbers inexact, so it is not included here.
+    */
+   /*          bicubic      sum        */
+   /* 0*/ { 1.0000000000, 4.5000000000 },
+   /* 1*/ {  .9638671875, 3.5000000000 },
+   /* 2*/ {  .8671875000, 2.5361328125 },
+   /* 3*/ {  .7275390625, 1.6689453125 },
+   /* 4*/ {  .5625000000,  .9414062500 },
+   /* 5*/ {  .3896484375,  .3789062500 },
+   /* 6*/ {  .2265625000, -.0107421875 },
+   /* 7*/ {  .0908203125, -.2373046875 },
+   /* 8*/ {            0, -.3281250000 },
+   /* 9*/ { -.0478515625, -.3281250000 },
+   /*10*/ { -.0703125000, -.2802734375 },
+   /*11*/ { -.0732421875, -.2099609375 },
+   /*12*/ { -.0625000000, -.1367187500 },
+   /*13*/ { -.0439453125, -.0742187500 },
+   /*14*/ { -.0234375000, -.0302734375 },
+   /*15*/ { -.0068359375, -.0068359375 }
+};
+
+static double
+alpha_calc(const struct arg *arg, double x, double y)
+{
+   /* For [x-2..x+2],[y-2,y+2] calculate the weighted bicubic given a function
+    * which tells us whether a point is inside or outside the shape.  First
+    * check if we need to do this at all:
+    */
+   switch (arg->check_fn(arg, x, y))
+   {
+      case OUTSIDE:
+         return 0; /* all samples outside the shape */
+
+      case INSIDE:
+         return 1; /* all samples inside the shape */
+
+      default:
+      {
+         int dy;
+         double alpha = 0;
+
+#        define FILTER_D (FILTER_WIDTH*FILTER_STEPS-1)
+         for (dy=-FILTER_D; dy<=FILTER_D; ++dy)
+         {
+            double wy = bicubic[abs(dy)][0];
+
+            if (wy != 0)
+            {
+               double alphay = 0;
+               int dx;
+
+               for (dx=-FILTER_D; dx<=FILTER_D; ++dx)
+               {
+                  double wx = bicubic[abs(dx)][0];
+
+                  if (wx != 0 && arg->inside_fn(arg, x+dx/16, y+dy/16))
+                     alphay += wx;
+               }
+
+               alpha += wy * alphay;
+            }
+         }
+
+         /* This needs to be weighted for each dimension: */
+         return alpha / (FILTER_WEIGHT*FILTER_WEIGHT);
+      }
+   }
+}
+
+/* These are the shape functions. */
+/* "square",
+ * { inside_square_filled, check_square_filled },
+ * { inside_square, check_square }
+ */
+static int
+square_check(double x, double y, double x1, double y1, double x2, double y2)
+   /* Is x,y inside the square (x1,y1)..(x2,y2)? */
+{
+   /* Do a modified Cohen-Sutherland on one point, bit patterns that indicate
+    * 'outside' are:
+    *
+    *   x<x1 | x<y1 | x<x2 | x<y2
+    *    0      x      0      x     To the right
+    *    1      x      1      x     To the left
+    *    x      0      x      0     Below
+    *    x      1      x      1     Above
+    *
+    * So 'inside' is (x<x1) != (x<x2) && (y<y1) != (y<y2);
+    */
+   return ((x<x1) ^ (x<x2)) & ((y<y1) ^ (y<y2));
+}
+
+static int
+inside_square_filled(const struct arg *arg, double x, double y)
+{
+   return square_check(x, y, arg->x1, arg->y1, arg->x2, arg->y2);
+}
+
+static int
+square_check_line(const struct arg *arg, double x, double y, double w)
+   /* Check for a point being inside the boundaries implied by the given arg
+    * and assuming a width 2*w each side of the boundaries.  This returns the
+    * 'check' INSIDE/OUTSIDE/0 result but note the semantics:
+    *
+    *          +--------------+
+    *          |              |   OUTSIDE
+    *          |   INSIDE     |
+    *          |              |
+    *          +--------------+
+    *
+    * And '0' means within the line boundaries.
+    */
+{
+   double cx = (arg->x1+arg->x2)/2;
+   double wx = fabs(arg->x1-arg->x2)/2;
+   double cy = (arg->y1+arg->y2)/2;
+   double wy = fabs(arg->y1-arg->y2)/2;
+
+   if (square_check(x, y, cx-wx-w, cy-wy-w, cx+wx+w, cy+wy+w))
+   {
+      /* Inside, but maybe too far; check for the redundant case where
+       * the lines overlap:
+       */
+      wx -= w;
+      wy -= w;
+      if (wx > 0 && wy > 0 && square_check(x, y, cx-wx, cy-wy, cx+wx, cy+wy))
+         return INSIDE; /* between (inside) the boundary lines. */
+
+      return 0; /* inside the lines themselves. */
+   }
+
+   return OUTSIDE; /* outside the boundary lines. */
+}
+
+static int
+check_square_filled(const struct arg *arg, double x, double y)
+{
+   /* The filter extends +/-FILTER_WIDTH each side of each output point, so
+    * the check has to expand and contract the square by that amount; '0'
+    * means close enough to the edge of the square that the bicubic filter has
+    * to be run, OUTSIDE means alpha==0, INSIDE means alpha==1.
+    */
+   return square_check_line(arg, x, y, FILTER_WIDTH);
+}
+
+static int
+inside_square(const struct arg *arg, double x, double y)
+{
+   /* Return true if within the drawn lines, else false, no need to distinguish
+    * INSIDE vs OUTSIDE here:
+    */
+   return square_check_line(arg, x, y, arg->width/2) == 0;
+}
+
+static int
+check_square(const struct arg *arg, double x, double y)
+{
+   /* So for this function a result of 'INSIDE' means inside the actual lines.
+    */
+   double w = arg->width/2;
+
+   if (square_check_line(arg, x, y, w+FILTER_WIDTH) == 0)
+   {
+      /* Somewhere close to the boundary lines. If far enough inside one of
+       * them then we can return INSIDE:
+       */
+      w -= FILTER_WIDTH;
+
+      if (w > 0 && square_check_line(arg, x, y, w) == 0)
+         return INSIDE;
+
+      /* Point is somewhere in the filter region: */
+      return 0;
+   }
+
+   else /* Inside or outside the square by more than w+FILTER_WIDTH. */
+      return OUTSIDE;
+}
+
+/* "circle",
+ * { inside_circle_filled, check_circle_filled },
+ * { inside_circle, check_circle }
+ *
+ * The functions here are analoguous to the square ones; however, they check
+ * the corresponding ellipse as opposed to the rectangle.
+ */
+static int
+circle_check(double x, double y, double x1, double y1, double x2, double y2)
+{
+   if (square_check(x, y, x1, y1, x2, y2))
+   {
+      /* Inside the square, so maybe inside the circle too: */
+      const double cx = (x1 + x2)/2;
+      const double cy = (y1 + y2)/2;
+      const double dx = x1 - x2;
+      const double dy = y1 - y2;
+
+      x = (x - cx)/dx;
+      y = (y - cy)/dy;
+
+      /* It is outside if the distance from the center is more than half the
+       * diameter:
+       */
+      return x*x+y*y < .25;
+   }
+
+   return 0; /* outside */
+}
+
+static int
+inside_circle_filled(const struct arg *arg, double x, double y)
+{
+   return circle_check(x, y, arg->x1, arg->y1, arg->x2, arg->y2);
+}
+
+static int
+circle_check_line(const struct arg *arg, double x, double y, double w)
+   /* Check for a point being inside the boundaries implied by the given arg
+    * and assuming a width 2*w each side of the boundaries.  This function has
+    * the same semantic as square_check_line but tests the circle.
+    */
+{
+   double cx = (arg->x1+arg->x2)/2;
+   double wx = fabs(arg->x1-arg->x2)/2;
+   double cy = (arg->y1+arg->y2)/2;
+   double wy = fabs(arg->y1-arg->y2)/2;
+
+   if (circle_check(x, y, cx-wx-w, cy-wy-w, cx+wx+w, cy+wy+w))
+   {
+      /* Inside, but maybe too far; check for the redundant case where
+       * the lines overlap:
+       */
+      wx -= w;
+      wy -= w;
+      if (wx > 0 && wy > 0 && circle_check(x, y, cx-wx, cy-wy, cx+wx, cy+wy))
+         return INSIDE; /* between (inside) the boundary lines. */
+
+      return 0; /* inside the lines themselves. */
+   }
+
+   return OUTSIDE; /* outside the boundary lines. */
+}
+
+static int
+check_circle_filled(const struct arg *arg, double x, double y)
+{
+   return circle_check_line(arg, x, y, FILTER_WIDTH);
+}
+
+static int
+inside_circle(const struct arg *arg, double x, double y)
+{
+   return circle_check_line(arg, x, y, arg->width/2) == 0;
+}
+
+static int
+check_circle(const struct arg *arg, double x, double y)
+{
+   /* Exactly as the 'square' code.  */
+   double w = arg->width/2;
+
+   if (circle_check_line(arg, x, y, w+FILTER_WIDTH) == 0)
+   {
+      w -= FILTER_WIDTH;
+
+      if (w > 0 && circle_check_line(arg, x, y, w) == 0)
+         return INSIDE;
+
+      /* Point is somewhere in the filter region: */
+      return 0;
+   }
+
+   else /* Inside or outside the square by more than w+FILTER_WIDTH. */
+      return OUTSIDE;
+}
+
+/* "line",
+ * { NULL, NULL },  There is no 'filled' line.
+ * { inside_line, check_line }
+ */
+static int
+line_check(double x, double y, double x1, double y1, double x2, double y2,
+   double w, double expand)
+{
+   /* Shift all the points to (arg->x1, arg->y1) */
+   double lx = x2 - x1;
+   double ly = y2 - y1;
+   double len2 = lx*lx + ly*ly;
+   double cross, dot;
+
+   x -= x1;
+   y -= y1;
+
+   /* The dot product is the distance down the line, the cross product is
+    * the distance away from the line:
+    *
+    *    distance = |cross| / sqrt(len2)
+    */
+   cross = x * ly - y * lx;
+
+   /* If 'distance' is more than w the point is definitely outside the line:
+    *
+    *     distance >= w
+    *     |cross|  >= w * sqrt(len2)
+    *     cross^2  >= w^2 * len2:
+    */
+   if (cross*cross >= (w+expand)*(w+expand)*len2)
+      return 0; /* outside */
+
+   /* Now find the distance *along* the line; this comes from the dot product
+    * lx.x+ly.y. The actual distance (in pixels) is:
+    *
+    *   distance = dot / sqrt(len2)
+    */
+   dot = lx * x + ly * y;
+
+   /* The test for 'outside' is:
+    *
+    *    distance < 0 || distance > sqrt(len2)
+    *                 -> dot / sqrt(len2) > sqrt(len2)
+    *                 -> dot > len2
+    *
+    * But 'expand' is used for the filter width and needs to be handled too:
+    */
+   return dot > -expand && dot < len2+expand;
+}
+
+static int
+inside_line(const struct arg *arg, double x, double y)
+{
+   return line_check(x, y, arg->x1, arg->y1, arg->x2, arg->y2, arg->width/2, 0);
+}
+
+static int
+check_line(const struct arg *arg, double x, double y)
+{
+   /* The end caps of the line must be checked too; it's not enough just to
+    * widen the line by FILTER_WIDTH; 'expand' exists for this purpose:
+    */
+   if (line_check(x, y, arg->x1, arg->y1, arg->x2, arg->y2, arg->width/2,
+       FILTER_WIDTH))
+   {
+      /* Inside the line+filter; far enough inside that the filter isn't
+       * required?
+       */
+      if (arg->width > 2*FILTER_WIDTH &&
+          line_check(x, y, arg->x1, arg->y1, arg->x2, arg->y2, arg->width/2,
+             -FILTER_WIDTH))
+         return INSIDE;
+
+      return 0;
+   }
+
+   return OUTSIDE;
+}
+
+static const struct
+{
+   const char    *name;
+   shape_fn_ptr   function[2/*fill,line*/][2];
+#  define         FN_INSIDE 0
+#  define         FN_CHECK 1
+} shape_defs[] =
+{
+   {  "square",
+      {  { inside_square_filled, check_square_filled },
+         { inside_square, check_square } }
+   },
+   {  "circle",
+      {  { inside_circle_filled, check_circle_filled },
+         { inside_circle, check_circle } }
+   },
+   {  "line",
+      {  { NULL, NULL },
+         { inside_line, check_line } }
+   }
+};
+
+#define shape_count ((sizeof shape_defs)/(sizeof shape_defs[0]))
+
+static shape_fn_ptr
+shape_of(const char *arg, double width, int f)
+{
+   unsigned int i;
+
+   for (i=0; i<shape_count; ++i) if (strcmp(shape_defs[i].name, arg) == 0)
+   {
+      shape_fn_ptr fn = shape_defs[i].function[width != 0][f];
+
+      if (fn != NULL)
+         return fn;
+
+      fprintf(stderr, "genpng: %s %s not supported\n",
+         width == 0 ? "filled" : "unfilled", arg);
+      exit(1);
+   }
+
+   fprintf(stderr, "genpng: %s: not a valid shape name\n", arg);
+   exit(1);
+}
+
+static void
+parse_arg(struct arg *arg, const char **argv/*7 arguments*/)
+{
+   /* shape ::= color width shape x1 y1 x2 y2 */
+   arg->color = color_of(argv[0]);
+   arg->width = width_of(argv[1]);
+   arg->inside_fn = shape_of(argv[2], arg->width, FN_INSIDE);
+   arg->check_fn = shape_of(argv[2], arg->width, FN_CHECK);
+   arg->x1 = coordinate_of(argv[3]);
+   arg->y1 = coordinate_of(argv[4]);
+   arg->x2 = coordinate_of(argv[5]);
+   arg->y2 = coordinate_of(argv[6]);
+}
+
+static png_uint_32
+read_wh(const char *name, const char *str)
+   /* read a PNG width or height */
+{
+   char *ep = NULL;
+   unsigned long ul = strtoul(str, &ep, 10);
+
+   if (ep != NULL && *ep == 0 && ul > 0 && ul <= 0x7fffffff)
+      return (png_uint_32)/*SAFE*/ul;
+
+   fprintf(stderr, "genpng: %s: invalid number %s\n", name, str);
+   exit(1);
+}
+
+static void
+pixel(png_uint_16p p, struct arg *args, int nargs, double x, double y)
+{
+   /* Fill in the pixel by checking each shape (args[nargs]) for effects on
+    * the corresponding sample:
+    */
+   double r=0, g=0, b=0, a=0;
+
+   while (--nargs >= 0 && a != 1)
+   {
+      /* NOTE: alpha_calc can return a value outside the range 0..1 with the
+       * bicubic filter.
+       */
+      const double alpha = alpha_calc(args+nargs, x, y) * (1-a);
+
+      r += alpha * args[nargs].color->red;
+      g += alpha * args[nargs].color->green;
+      b += alpha * args[nargs].color->blue;
+      a += alpha;
+   }
+
+   /* 'a' may be negative or greater than 1; if it is, negative clamp the
+    * pixel to 0 if >1 clamp r/g/b:
+    */
+   if (a > 0)
+   {
+      if (a > 1)
+      {
+         if (r > 1) r = 1;
+         if (g > 1) g = 1;
+         if (b > 1) b = 1;
+         a = 1;
+      }
+
+      /* And fill in the pixel: */
+      p[0] = (png_uint_16)/*SAFE*/round(r * 65535);
+      p[1] = (png_uint_16)/*SAFE*/round(g * 65535);
+      p[2] = (png_uint_16)/*SAFE*/round(b * 65535);
+      p[3] = (png_uint_16)/*SAFE*/round(a * 65535);
+   }
+
+   else
+      p[3] = p[2] = p[1] = p[0] = 0;
+}
+
+int
+main(int argc, const char **argv)
+{
+   int convert_to_8bit = 0;
+
+   /* There is one option: --8bit: */
+   if (argc > 1 && strcmp(argv[1], "--8bit") == 0)
+      --argc, ++argv, convert_to_8bit = 1;
+
+   if (argc >= 3)
+   {
+      png_uint_16p buffer;
+      int nshapes;
+      png_image image;
+#     define max_shapes 256
+      struct arg arg_list[max_shapes];
+
+      /* The libpng Simplified API write code requires a fully initialized
+       * structure.
+       */
+      memset(&image, 0, sizeof image);
+      image.version = PNG_IMAGE_VERSION;
+      image.opaque = NULL;
+      image.width = read_wh("width", argv[1]);
+      image.height = read_wh("height", argv[2]);
+      image.format = PNG_FORMAT_LINEAR_RGB_ALPHA;
+      image.flags = 0;
+      image.colormap_entries = 0;
+
+      /* Check the remainder of the arguments */
+      for (nshapes=0; 3+7*(nshapes+1) <= argc && nshapes < max_shapes;
+           ++nshapes)
+         parse_arg(arg_list+nshapes, argv+3+7*nshapes);
+
+      if (3+7*nshapes != argc)
+      {
+         fprintf(stderr, "genpng: %s: too many arguments\n", argv[3+7*nshapes]);
+         return 1;
+      }
+
+#if 1
+     /* TO do: determine whether this guard against overflow is necessary.
+      * This comment in png.h indicates that it should be safe: "libpng will
+      * refuse to process an image where such an overflow would occur", but
+      * I don't see where the image gets rejected when the buffer is too
+      * large before the malloc is attempted.
+      */
+      if (image.height > ((size_t)(-1))/(8*image.width)) {
+         fprintf(stderr, "genpng: image buffer would be too big");
+         return 1;
+      }
+#endif
+
+      /* Create the buffer: */
+      buffer = malloc(PNG_IMAGE_SIZE(image));
+
+      if (buffer != NULL)
+      {
+         png_uint_32 y;
+
+         /* Write each row... */
+         for (y=0; y<image.height; ++y)
+         {
+            png_uint_32 x;
+
+            /* Each pixel in each row: */
+            for (x=0; x<image.width; ++x)
+               pixel(buffer + 4*(x + y*image.width), arg_list, nshapes, x, y);
+         }
+
+         /* Write the result (to stdout) */
+         if (png_image_write_to_stdio(&image, stdout, convert_to_8bit,
+             buffer, 0/*row_stride*/, NULL/*colormap*/))
+         {
+            free(buffer);
+            return 0; /* success */
+         }
+
+         else
+            fprintf(stderr, "genpng: write stdout: %s\n", image.message);
+
+         free(buffer);
+      }
+
+      else
+         fprintf(stderr, "genpng: out of memory: %lu bytes\n",
+               (unsigned long)PNG_IMAGE_SIZE(image));
+   }
+
+   else
+   {
+      /* Wrong number of arguments */
+      fprintf(stderr, "genpng: usage: genpng [--8bit] width height {shape}\n"
+         " Generate a transparent PNG in RGBA (truecolor+alpha) format\n"
+         " containing the given shape or shapes.  Shapes are defined:\n"
+         "\n"
+         "  shape ::= color width shape x1 y1 x2 y2\n"
+         "  color ::= black|white|red|green|yellow|blue\n"
+         "  color ::= brown|purple|pink|orange|gray|cyan\n"
+         "  width ::= filled|<number>\n"
+         "  shape ::= circle|square|line\n"
+         "  x1,x2 ::= <number>\n"
+         "  y1,y2 ::= <number>\n"
+         "\n"
+         " Numbers are floating point numbers describing points relative to\n"
+         " the top left of the output PNG as pixel coordinates.  The 'width'\n"
+         " parameter is either the width of the line (in output pixels) used\n"
+         " to draw the shape or 'filled' to indicate that the shape should\n"
+         " be filled with the color.\n"
+         "\n"
+         " Colors are interpreted loosely to give access to the eight full\n"
+         " intensity RGB values:\n"
+         "\n"
+         "  black, red, green, blue, yellow, cyan, purple, white,\n"
+         "\n"
+         " Cyan is full intensity blue+green; RGB(0,1,1), plus the following\n"
+         " lower intensity values:\n"
+         "\n"
+         "  brown:  red+orange:  RGB(0.5, 0.125, 0) (dark red+orange)\n"
+         "  pink:   red+white:   RGB(1.0, 0.5,   0.5)\n"
+         "  orange: red+yellow:  RGB(1.0, 0.5,   0)\n"
+         "  gray:   black+white: RGB(0.5, 0.5,   0.5)\n"
+         "\n"
+         " The RGB values are selected to make detection of aliasing errors\n"
+         " easy. The names are selected to make the description of errors\n"
+         " easy.\n"
+         "\n"
+         " The PNG is written to stdout, if --8bit is given a 32bpp RGBA sRGB\n"
+         " file is produced, otherwise a 64bpp RGBA linear encoded file is\n"
+         " written.\n");
+   }
+
+   return 1;
+}
+#endif /* SIMPLIFIED_WRITE && STDIO */
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/intgamma.sh b/ap/lib/libpng/libpng-1.6.37/contrib/tools/intgamma.sh
new file mode 100755
index 0000000..41c5d6d
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/intgamma.sh
@@ -0,0 +1,110 @@
+#!/bin/sh
+#
+# intgamma.sh
+#
+# Last changed in libpng 1.6.0 [February 14, 2013]
+#
+# COPYRIGHT: Written by John Cunningham Bowler, 2013.
+# To the extent possible under law, the author has waived all copyright and
+# related or neighboring rights to this work.  This work is published from:
+# United States.
+#
+# Shell script to generate png.c 8-bit and 16-bit log tables (see the code in
+# png.c for details).
+#
+# This script uses the "bc" arbitrary precision calculator to calculate 32-bit
+# fixed point values of logarithms appropriate to finding the log of an 8-bit
+# (0..255) value and a similar table for the exponent calculation.
+#
+# "bc" must be on the path when the script is executed, and the math library
+# (-lm) must be available
+#
+# function to print out a list of numbers as integers; the function truncates
+# the integers which must be one-per-line
+function print(){
+   awk 'BEGIN{
+      str = ""
+   }
+   {
+      sub("\\.[0-9]*$", "")
+      if ($0 == "")
+         $0 = "0"
+
+      if (str == "")
+         t = "   " $0 "U"
+      else
+         t = str ", " $0 "U"
+
+      if (length(t) >= 80) {
+         print str ","
+         str = "   " $0 "U"
+      } else
+         str = t
+   }
+   END{
+      print str
+   }'
+}
+#
+# The logarithm table.
+cat <<END
+/* 8-bit log table: png_8bit_l2[128]
+ * 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.
+ */
+static const png_uint_32
+png_8bit_l2[128] =
+{
+END
+#
+bc -lqws <<END | print
+f=65536*65536/l(2)
+for (i=128;i<256;++i) { .5 - l(i/255)*f; }
+END
+echo '};'
+echo
+#
+# The exponent table.
+cat <<END
+/* 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 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
+ * top four fractional bits then multiplying in the remaining bits.
+ */
+static const png_uint_32
+png_32bit_exp[16] =
+{
+END
+#
+bc -lqws <<END | print
+f=l(2)/16
+for (i=0;i<16;++i) {
+   x = .5 + e(-i*f)*2^32;
+   if (x >= 2^32) x = 2^32-1;
+   x;
+}
+END
+echo '};'
+echo
+#
+# And the table of adjustment values.
+cat <<END
+/* Adjustment table; provided to explain the numbers in the code below. */
+#if 0
+END
+bc -lqws <<END | awk '{ printf "%5d %s\n", 12-NR, $0 }'
+for (i=11;i>=0;--i){
+   (1 - e(-(2^i)/65536*l(2))) * 2^(32-i)
+}
+END
+echo '#endif'
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/makesRGB.c b/ap/lib/libpng/libpng-1.6.37/contrib/tools/makesRGB.c
new file mode 100755
index 0000000..d0c0ca9
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/makesRGB.c
@@ -0,0 +1,430 @@
+/* makesRGB.c -- build sRGB-to-linear and linear-to-sRGB conversion tables
+ *
+ * Last changed in libpng 1.6.0 [February 14, 2013]
+ *
+ * COPYRIGHT: Written by John Cunningham Bowler, 2013.
+ * To the extent possible under law, the author has waived all copyright and
+ * related or neighboring rights to this work.  This work is published from:
+ * United States.
+ *
+ * Make a table to convert 8-bit sRGB encoding values into the closest 16-bit
+ * linear value.
+ *
+ * Make two tables to take a linear value scaled to 255*65535 and return an
+ * approximation to the 8-bit sRGB encoded value.  Calculate the error in these
+ * tables and display it.
+ */
+#define _C99_SOURCE 1
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+
+/* pngpriv.h includes the definition of 'PNG_sRGB_FROM_LINEAR' which is required
+ * to verify the actual code.
+ */
+#include "../../pngpriv.h"
+
+#include "sRGB.h"
+
+/* The tables are declared 'const' in pngpriv.h, so this redefines the tables to
+ * be used.
+ */
+#define png_sRGB_table sRGB_table
+#define png_sRGB_base sRGB_base
+#define png_sRGB_delta sRGB_delta
+
+static png_uint_16 png_sRGB_table[256];
+static png_uint_16 png_sRGB_base[512];
+static png_byte png_sRGB_delta[512];
+
+static const unsigned int max_input = 255*65535;
+
+double
+fsRGB(double l)
+{
+   return sRGB_from_linear(l/max_input);
+}
+
+double
+sRGB(unsigned int i)
+{
+   return fsRGB(i);
+}
+
+double
+finvsRGB(unsigned int i)
+{
+   return 65535 * linear_from_sRGB(i/255.);
+}
+
+png_uint_16
+invsRGB(unsigned int i)
+{
+   unsigned int x = nearbyint(finvsRGB(i));
+
+   if (x > 65535)
+   {
+      fprintf(stderr, "invsRGB(%u) overflows to %u\n", i, x);
+      exit(1);
+   }
+
+   return (png_uint_16)x;
+}
+
+int
+main(int argc, char **argv)
+{
+   unsigned int i, i16, ibase;
+   double min_error = 0;
+   double max_error = 0;
+   double min_error16 = 0;
+   double max_error16 = 0;
+   double adjust;
+   double adjust_lo = 0.4, adjust_hi = 0.6, adjust_mid = 0.5;
+   unsigned int ec_lo = 0, ec_hi = 0, ec_mid = 0;
+   unsigned int error_count = 0;
+   unsigned int error_count16 = 0;
+   int test_only = 0;
+
+   if (argc > 1)
+      test_only = strcmp("--test", argv[1]) == 0;
+
+   /* Initialize the encoding table first. */
+   for (i=0; i<256; ++i)
+   {
+      png_sRGB_table[i] = invsRGB(i);
+   }
+
+   /* Now work out the decoding tables (this is where the error comes in because
+    * there are 512 set points and 512 straight lines between them.)
+    */
+   for (;;)
+   {
+      if (ec_lo == 0)
+         adjust = adjust_lo;
+
+      else if (ec_hi == 0)
+         adjust = adjust_hi;
+
+      else if (ec_mid == 0)
+         adjust = adjust_mid;
+
+      else if (ec_mid < ec_hi)
+         adjust = (adjust_mid + adjust_hi)/2;
+
+      else if (ec_mid < ec_lo)
+         adjust = (adjust_mid + adjust_lo)/2;
+
+      else
+      {
+         fprintf(stderr, "not reached: %u .. %u .. %u\n", ec_lo, ec_mid, ec_hi);
+         exit(1);
+      }
+
+      /* Calculate the table using the current 'adjust' */
+      for (i=0; i<=511; ++i)
+      {
+         double lo = 255 * sRGB(i << 15);
+         double hi = 255 * sRGB((i+1) << 15);
+         unsigned int calc;
+
+         calc = nearbyint((lo+adjust) * 256);
+         if (calc > 65535)
+         {
+            fprintf(stderr, "table[%d][0]: overflow %08x (%d)\n", i, calc,
+               calc);
+            exit(1);
+         }
+         png_sRGB_base[i] = calc;
+
+         calc = nearbyint((hi-lo) * 32);
+         if (calc > 255)
+         {
+            fprintf(stderr, "table[%d][1]: overflow %08x (%d)\n", i, calc,
+               calc);
+            exit(1);
+         }
+         png_sRGB_delta[i] = calc;
+      }
+
+      /* Check the 16-bit linear values alone: */
+      error_count16 = 0;
+      for (i16=0; i16 <= 65535; ++i16)
+      {
+         unsigned int i = 255*i16;
+         unsigned int iexact = nearbyint(255*sRGB(i));
+         unsigned int icalc = PNG_sRGB_FROM_LINEAR(i);
+
+         if (icalc != iexact)
+            ++error_count16;
+      }
+
+      /* Now try changing the adjustment. */
+      if (ec_lo == 0)
+         ec_lo = error_count16;
+
+      else if (ec_hi == 0)
+         ec_hi = error_count16;
+
+      else if (ec_mid == 0)
+      {
+         ec_mid = error_count16;
+         printf("/* initial error counts: %u .. %u .. %u */\n", ec_lo, ec_mid,
+            ec_hi);
+      }
+
+      else if (error_count16 < ec_mid)
+      {
+         printf("/* adjust (mid ): %f: %u -> %u */\n", adjust, ec_mid,
+            error_count16);
+         ec_mid = error_count16;
+         adjust_mid = adjust;
+      }
+
+      else if (adjust < adjust_mid && error_count16 < ec_lo)
+      {
+         printf("/* adjust (low ): %f: %u -> %u */\n", adjust, ec_lo,
+            error_count16);
+         ec_lo = error_count16;
+         adjust_lo = adjust;
+      }
+
+      else if (adjust > adjust_mid && error_count16 < ec_hi)
+      {
+         printf("/* adjust (high): %f: %u -> %u */\n", adjust, ec_hi,
+            error_count16);
+         ec_hi = error_count16;
+         adjust_hi = adjust;
+      }
+
+      else
+      {
+         adjust = adjust_mid;
+         printf("/* adjust: %f: %u */\n", adjust, ec_mid);
+         break;
+      }
+   }
+
+   /* For each entry in the table try to adjust it to minimize the error count
+    * in that entry.  Each entry corresponds to 128 input values.
+    */
+   for (ibase=0; ibase<65536; ibase+=128)
+   {
+      png_uint_16 base = png_sRGB_base[ibase >> 7], trybase = base, ob=base;
+      png_byte delta = png_sRGB_delta[ibase >> 7], trydelta = delta, od=delta;
+      unsigned int ecbase = 0, eco;
+
+      for (;;)
+      {
+         png_sRGB_base[ibase >> 7] = trybase;
+         png_sRGB_delta[ibase >> 7] = trydelta;
+
+         /* Check the 16-bit linear values alone: */
+         error_count16 = 0;
+         for (i16=ibase; i16 < ibase+128; ++i16)
+         {
+            unsigned int i = 255*i16;
+            unsigned int iexact = nearbyint(255*sRGB(i));
+            unsigned int icalc = PNG_sRGB_FROM_LINEAR(i);
+
+            if (icalc != iexact)
+               ++error_count16;
+         }
+
+         if (error_count16 == 0)
+            break;
+
+         if (ecbase == 0)
+         {
+            eco = ecbase = error_count16;
+            ++trybase; /* First test */
+         }
+
+         else if (error_count16 < ecbase)
+         {
+            if (trybase > base)
+            {
+               base = trybase;
+               ++trybase;
+            }
+            else if (trybase < base)
+            {
+               base = trybase;
+               --trybase;
+            }
+            else if (trydelta > delta)
+            {
+               delta = trydelta;
+               ++trydelta;
+            }
+            else if (trydelta < delta)
+            {
+               delta = trydelta;
+               --trydelta;
+            }
+            else
+            {
+               fprintf(stderr, "makesRGB: impossible\n");
+               exit(1);
+            }
+            ecbase = error_count16;
+         }
+
+         else
+         {
+            if (trybase > base)
+               trybase = base-1;
+            else if (trybase < base)
+            {
+               trybase = base;
+               ++trydelta;
+            }
+            else if (trydelta > delta)
+               trydelta = delta-1;
+            else if (trydelta < delta)
+               break; /* end of tests */
+         }
+      }
+
+      png_sRGB_base[ibase >> 7] = base;
+      png_sRGB_delta[ibase >> 7] = delta;
+      if (base != ob || delta != od)
+      {
+         printf("/* table[%u]={%u,%u} -> {%u,%u} %u -> %u errors */\n",
+            ibase>>7, ob, od, base, delta, eco, ecbase);
+      }
+      else if (0)
+         printf("/* table[%u]={%u,%u} %u errors */\n", ibase>>7, ob, od,
+            ecbase);
+   }
+
+   /* Only do the full (slow) test at the end: */
+   min_error = -.4999;
+   max_error = .4999;
+   error_count = 0;
+
+   for (i=0; i <= max_input; ++i)
+   {
+      unsigned int iexact = nearbyint(255*sRGB(i));
+      unsigned int icalc = PNG_sRGB_FROM_LINEAR(i);
+
+      if (icalc != iexact)
+      {
+         double err = 255*sRGB(i) - icalc;
+
+         if (err > (max_error+.001) || err < (min_error-.001))
+         {
+            printf(
+               "/* 0x%08x: exact: %3d, got: %3d [tables: %08x, %08x] (%f) */\n",
+               i, iexact, icalc, png_sRGB_base[i>>15],
+               png_sRGB_delta[i>>15], err);
+         }
+
+         ++error_count;
+         if (err > max_error)
+            max_error = err;
+         else if (err < min_error)
+            min_error = err;
+      }
+   }
+
+   /* Re-check the 16-bit cases too, including the warning if there is an error
+    * bigger than 1.
+    */
+   error_count16 = 0;
+   max_error16 = 0;
+   min_error16 = 0;
+   for (i16=0; i16 <= 65535; ++i16)
+   {
+      unsigned int i = 255*i16;
+      unsigned int iexact = nearbyint(255*sRGB(i));
+      unsigned int icalc = PNG_sRGB_FROM_LINEAR(i);
+
+      if (icalc != iexact)
+      {
+         double err = 255*sRGB(i) - icalc;
+
+         ++error_count16;
+         if (err > max_error16)
+            max_error16 = err;
+         else if (err < min_error16)
+            min_error16 = err;
+
+         if (abs(icalc - iexact) > 1)
+            printf(
+               "/* 0x%04x: exact: %3d, got: %3d [tables: %08x, %08x] (%f) */\n",
+               i16, iexact, icalc, png_sRGB_base[i>>15],
+               png_sRGB_delta[i>>15], err);
+      }
+   }
+
+   /* Check the round trip for each 8-bit sRGB value. */
+   for (i16=0; i16 <= 255; ++i16)
+   {
+      unsigned int i = 255 * png_sRGB_table[i16];
+      unsigned int iexact = nearbyint(255*sRGB(i));
+      unsigned int icalc = PNG_sRGB_FROM_LINEAR(i);
+
+      if (i16 != iexact)
+      {
+         fprintf(stderr, "8-bit rounding error: %d -> %d\n", i16, iexact);
+         exit(1);
+      }
+
+      if (icalc != i16)
+      {
+         double finv = finvsRGB(i16);
+
+         printf("/* 8-bit roundtrip error: %d -> %f -> %d(%f) */\n",
+            i16, finv, icalc, fsRGB(255*finv));
+      }
+   }
+
+
+   printf("/* error: %g - %g, %u (%g%%) of readings inexact */\n",
+      min_error, max_error, error_count, (100.*error_count)/max_input);
+   printf("/* 16-bit error: %g - %g, %u (%g%%) of readings inexact */\n",
+      min_error16, max_error16, error_count16, (100.*error_count16)/65535);
+
+   if (!test_only)
+   {
+      printf("const png_uint_16 png_sRGB_table[256] =\n{\n   ");
+      for (i=0; i<255; )
+      {
+         do
+         {
+            printf("%d,", png_sRGB_table[i++]);
+         }
+         while ((i & 0x7) != 0 && i<255);
+         if (i<255) printf("\n   ");
+      }
+      printf("%d\n};\n\n", png_sRGB_table[i]);
+
+
+      printf("const png_uint_16 png_sRGB_base[512] =\n{\n   ");
+      for (i=0; i<511; )
+      {
+         do
+         {
+            printf("%d,", png_sRGB_base[i++]);
+         }
+         while ((i & 0x7) != 0 && i<511);
+         if (i<511) printf("\n   ");
+      }
+      printf("%d\n};\n\n", png_sRGB_base[i]);
+
+      printf("const png_byte png_sRGB_delta[512] =\n{\n   ");
+      for (i=0; i<511; )
+      {
+         do
+         {
+            printf("%d,", png_sRGB_delta[i++]);
+         }
+         while ((i & 0xf) != 0 && i<511);
+         if (i<511) printf("\n   ");
+      }
+      printf("%d\n};\n\n", png_sRGB_delta[i]);
+   }
+
+   return 0;
+}
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/png-fix-itxt.c b/ap/lib/libpng/libpng-1.6.37/contrib/tools/png-fix-itxt.c
new file mode 100755
index 0000000..c7654c1
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/png-fix-itxt.c
@@ -0,0 +1,164 @@
+
+/* png-fix-itxt version 1.0.0
+ *
+ * Copyright 2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.18 [July 23, 2015]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * Usage:
+ *
+ *     png-fix-itxt.exe < bad.png > good.png
+ *
+ * Fixes a PNG file written with libpng-1.6.0 or 1.6.1 that has one or more
+ * uncompressed iTXt chunks.  Assumes that the actual length is greater
+ * than or equal to the value in the length byte, and that the CRC is
+ * correct for the actual length.  This program hunts for the CRC and
+ * adjusts the length byte accordingly.  It is not an error to process a
+ * PNG file that has no iTXt chunks or one that has valid iTXt chunks;
+ * such files will simply be copied.
+ *
+ * Requires zlib (for crc32 and Z_NULL); build with
+ *
+ *     gcc -O -o png-fix-itxt png-fix-itxt.c -lz
+ *
+ * If you need to handle iTXt chunks larger than 500000 kbytes you must
+ * rebuild png-fix-itxt with a larger values of MAX_LENGTH (or a smaller value
+ * if you know you will never encounter such huge iTXt chunks).
+ */
+
+#include <stdio.h>
+#include <zlib.h>
+
+#define MAX_LENGTH 500000
+
+/* Read one character (inchar), also return octet (c), break if EOF */
+#define GETBREAK inchar=getchar(); \
+                 c=(inchar & 0xffU);\
+                 if (inchar != c) break
+int
+main(void)
+{
+   unsigned int i;
+   unsigned char buf[MAX_LENGTH];
+   unsigned long crc;
+   unsigned char c;
+   int inchar;
+
+/* Skip 8-byte signature */
+   for (i=8; i; i--)
+   {
+      GETBREAK;
+      putchar(c);
+   }
+
+if (inchar == c) /* !EOF */
+for (;;)
+ {
+   /* Read the length */
+   unsigned long length; /* must be 32 bits! */
+   GETBREAK; buf[0] = c; length  = c; length <<= 8;
+   GETBREAK; buf[1] = c; length += c; length <<= 8;
+   GETBREAK; buf[2] = c; length += c; length <<= 8;
+   GETBREAK; buf[3] = c; length += c;
+
+   /* Read the chunkname */
+   GETBREAK; buf[4] = c;
+   GETBREAK; buf[5] = c;
+   GETBREAK; buf[6] = c;
+   GETBREAK; buf[7] = c;
+
+
+   /* The iTXt chunk type expressed as integers is (105, 84, 88, 116) */
+   if (buf[4] == 105 && buf[5] == 84 && buf[6] == 88 && buf[7] == 116)
+   {
+      if (length >= MAX_LENGTH-12)
+         break;  /* To do: handle this more gracefully */
+
+      /* Initialize the CRC */
+      crc = crc32(0, Z_NULL, 0);
+
+      /* Copy the data bytes */
+      for (i=8; i < length + 12; i++)
+      {
+         GETBREAK; buf[i] = c;
+      }
+
+      if (inchar != c) /* EOF */
+         break;
+
+      /* Calculate the CRC */
+      crc = crc32(crc, buf+4, (uInt)length+4);
+
+      for (;;)
+      {
+        /* Check the CRC */
+        if (((crc >> 24) & 0xffU) == buf[length+8] &&
+            ((crc >> 16) & 0xffU) == buf[length+9] &&
+            ((crc >>  8) & 0xffU) == buf[length+10] &&
+            ((crc      ) & 0xffU) == buf[length+11])
+           break;
+
+        length++;
+
+        if (length >= MAX_LENGTH-12)
+           break;
+
+        GETBREAK;
+        buf[length+11] = c;
+
+        /* Update the CRC */
+        crc = crc32(crc, buf+7+length, 1);
+      }
+
+      if (inchar != c) /* EOF */
+         break;
+
+      /* Update length bytes */
+      buf[0] = (unsigned char)((length >> 24) & 0xffU);
+      buf[1] = (unsigned char)((length >> 16) & 0xffU);
+      buf[2] = (unsigned char)((length >>  8) & 0xffU);
+      buf[3] = (unsigned char)((length      ) & 0xffU);
+
+      /* Write the fixed iTXt chunk (length, name, data, crc) */
+      for (i=0; i<length+12; i++)
+         putchar(buf[i]);
+   }
+
+   else
+   {
+      if (inchar != c) /* EOF */
+         break;
+
+      /* Copy bytes that were already read (length and chunk name) */
+      for (i=0; i<8; i++)
+         putchar(buf[i]);
+
+      /* Copy data bytes and CRC */
+      for (i=8; i< length+12; i++)
+      {
+         GETBREAK;
+         putchar(c);
+      }
+
+      if (inchar != c) /* EOF */
+      {
+         break;
+      }
+
+   /* The IEND chunk type expressed as integers is (73, 69, 78, 68) */
+      if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68)
+         break;
+   }
+
+   if (inchar != c) /* EOF */
+      break;
+
+   if (buf[4] == 73 && buf[5] == 69 && buf[6] == 78 && buf[7] == 68)
+     break;
+ }
+
+ return 0;
+}
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/pngcp.c b/ap/lib/libpng/libpng-1.6.37/contrib/tools/pngcp.c
new file mode 100755
index 0000000..16d4e7f
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/pngcp.c
@@ -0,0 +1,2453 @@
+/* pngcp.c
+ *
+ * Copyright (c) 2016 John Cunningham Bowler
+ *
+ * Last changed in libpng 1.6.24 [August 4, 2016]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * This is an example of copying a PNG without changes using the png_read_png
+ * and png_write_png interfaces.  A considerable number of options are provided
+ * to manipulate the compression of the PNG data and other compressed chunks.
+ *
+ * For a more extensive example that uses the transforms see
+ * contrib/libtests/pngimage.c in the libpng distribution.
+ */
+#include "pnglibconf.h" /* To find how libpng was configured. */
+
+#ifdef PNG_PNGCP_TIMING_SUPPORTED
+   /* WARNING:
+    *
+    * This test is here to allow POSIX.1b extensions to be used if enabled in
+    * the compile; specifically the code requires_POSIX_C_SOURCE support of
+    * 199309L or later to enable clock_gettime use.
+    *
+    * IF this causes problems THEN compile with a strict ANSI C compiler and let
+    * this code turn on the POSIX features that it minimally requires.
+    *
+    * IF this does not work there is probably a bug in your ANSI C compiler or
+    * your POSIX implementation.
+    */
+#  define _POSIX_C_SOURCE 199309L
+#else /* No timing support required */
+#  define _POSIX_SOURCE 1
+#endif
+
+#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
+#  include <config.h>
+#endif
+
+#include <stdio.h>
+
+/* Define the following to use this test against your installed libpng, rather
+ * than the one being built here:
+ */
+#ifdef PNG_FREESTANDING_TESTS
+#  include <png.h>
+#else
+#  include "../../png.h"
+#endif
+
+#if PNG_LIBPNG_VER < 10700
+   /* READ_PNG and WRITE_PNG were not defined, so: */
+#  ifdef PNG_INFO_IMAGE_SUPPORTED
+#     ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+#        define PNG_READ_PNG_SUPPORTED
+#     endif /* SEQUENTIAL_READ */
+#     ifdef PNG_WRITE_SUPPORTED
+#        define PNG_WRITE_PNG_SUPPORTED
+#     endif /* WRITE */
+#  endif /* INFO_IMAGE */
+#endif /* pre 1.7.0 */
+
+#if (defined(PNG_READ_PNG_SUPPORTED)) && (defined(PNG_WRITE_PNG_SUPPORTED))
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <assert.h>
+
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include <zlib.h>
+
+#ifndef PNG_SETJMP_SUPPORTED
+#  include <setjmp.h> /* because png.h did *not* include this */
+#endif
+
+#ifdef __cplusplus
+#  define voidcast(type, value) static_cast<type>(value)
+#else
+#  define voidcast(type, value) (value)
+#endif /* __cplusplus */
+
+#ifdef __GNUC__
+   /* Many versions of GCC erroneously report that local variables unmodified
+    * within the scope of a setjmp may be clobbered.  This hacks round the
+    * problem (sometimes) without harming other compilers.
+    */
+#  define gv volatile
+#else
+#  define gv
+#endif
+
+/* 'CLOCK_PROCESS_CPUTIME_ID' is one of the clock timers for clock_gettime.  It
+ * need not be supported even when clock_gettime is available.  It returns the
+ * 'CPU' time the process has consumed.  'CPU' time is assumed to include time
+ * when the CPU is actually blocked by a pending cache fill but not time
+ * waiting for page faults.  The attempt is to get a measure of the actual time
+ * the implementation takes to read a PNG ignoring the potentially very large IO
+ * overhead.
+ */
+#ifdef PNG_PNGCP_TIMING_SUPPORTED
+#  include <time.h>   /* clock_gettime and associated definitions */
+#  ifndef CLOCK_PROCESS_CPUTIME_ID
+      /* Prevent inclusion of the spurious code: */
+#     undef PNG_PNGCP_TIMING_SUPPORTED
+#  endif
+#endif /* PNGCP_TIMING */
+
+/* So if the timing feature has been activated: */
+
+/* This structure is used to control the test of a single file. */
+typedef enum
+{
+   VERBOSE,        /* switches on all messages */
+   INFORMATION,
+   WARNINGS,       /* switches on warnings */
+   LIBPNG_WARNING,
+   APP_WARNING,
+   ERRORS,         /* just errors */
+   APP_FAIL,       /* continuable error - no need to longjmp */
+   LIBPNG_ERROR,   /* this and higher cause a longjmp */
+   LIBPNG_BUG,     /* erroneous behavior in libpng */
+   APP_ERROR,      /* such as out-of-memory in a callback */
+   QUIET,          /* no normal messages */
+   USER_ERROR,     /* such as file-not-found */
+   INTERNAL_ERROR
+} error_level;
+#define LEVEL_MASK      0xf   /* where the level is in 'options' */
+
+#define STRICT          0x010 /* Fail on warnings as well as errors */
+#define LOG             0x020 /* Log pass/fail to stdout */
+#define CONTINUE        0x040 /* Continue on APP_FAIL errors */
+#define SIZES           0x080 /* Report input and output sizes */
+#define SEARCH          0x100 /* Search IDAT compression options */
+#define NOWRITE         0x200 /* Do not write an output file */
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+#  define IGNORE_INDEX  0x400 /* Ignore out of range palette indices (BAD!) */
+#  ifdef PNG_GET_PALETTE_MAX_SUPPORTED
+#     define FIX_INDEX  0x800 /* 'Fix' out of range palette indices (OK) */
+#  endif /* GET_PALETTE_MAX */
+#endif /* CHECK_FOR_INVALID_INDEX */
+#define OPTION     0x80000000 /* Used for handling options */
+#define LIST       0x80000001 /* Used for handling options */
+
+/* Result masks apply to the result bits in the 'results' field below; these
+ * bits are simple 1U<<error_level.  A pass requires either nothing worse than
+ * warnings (--relaxes) or nothing worse than information (--strict)
+ */
+#define RESULT_STRICT(r)   (((r) & ~((1U<<WARNINGS)-1)) == 0)
+#define RESULT_RELAXED(r)  (((r) & ~((1U<<ERRORS)-1)) == 0)
+
+/* OPTION DEFINITIONS */
+static const char range_lo[] = "low";
+static const char range_hi[] = "high";
+static const char all[] = "all";
+#define RANGE(lo,hi) { range_lo, lo }, { range_hi, hi }
+typedef struct value_list
+{
+   const char *name;  /* the command line name of the value */
+   int         value; /* the actual value to use */
+}  value_list;
+
+static const value_list
+#ifdef PNG_SW_COMPRESS_png_level
+vl_compression[] =
+{
+   /* Overall compression control.  The order controls the search order for
+    * 'all'.  Since the search is for the smallest the order used is low memory
+    * then high speed.
+    */
+   { "low-memory",      PNG_COMPRESSION_LOW_MEMORY },
+   { "high-speed",      PNG_COMPRESSION_HIGH_SPEED },
+   { "high-read-speed", PNG_COMPRESSION_HIGH_READ_SPEED },
+   { "low",             PNG_COMPRESSION_LOW },
+   { "medium",          PNG_COMPRESSION_MEDIUM },
+   { "old",             PNG_COMPRESSION_COMPAT },
+   { "high",            PNG_COMPRESSION_HIGH },
+   { all, 0 }
+},
+#endif /* SW_COMPRESS_png_level */
+
+#if defined(PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED) ||\
+    defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED)
+vl_strategy[] =
+{
+   /* This controls the order of search. */
+   { "huffman", Z_HUFFMAN_ONLY },
+   { "RLE", Z_RLE },
+   { "fixed", Z_FIXED }, /* the remainder do window searches */
+   { "filtered", Z_FILTERED },
+   { "default", Z_DEFAULT_STRATEGY },
+   { all, 0 }
+},
+#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
+vl_windowBits_text[] =
+{
+   { "default", MAX_WBITS/*from zlib*/ },
+   { "minimum", 8 },
+   RANGE(8, MAX_WBITS/*from zlib*/),
+   { all, 0 }
+},
+#endif /* text compression */
+vl_level[] =
+{
+   { "default", Z_DEFAULT_COMPRESSION /* this is -1 */ },
+   { "none", Z_NO_COMPRESSION },
+   { "speed", Z_BEST_SPEED },
+   { "best", Z_BEST_COMPRESSION },
+   { "0", Z_NO_COMPRESSION },
+   RANGE(1, 9), /* this deliberately excludes '0' */
+   { all, 0 }
+},
+vl_memLevel[] =
+{
+   { "max", MAX_MEM_LEVEL }, /* zlib maximum */
+   { "1", 1 }, /* zlib minimum */
+   { "default", 8 }, /* zlib default */
+   { "2", 2 },
+   { "3", 3 },
+   { "4", 4 },
+   { "5", 5 }, /* for explicit testing */
+   RANGE(6, MAX_MEM_LEVEL/*zlib*/), /* exclude 5 and below: zlib bugs */
+   { all, 0 }
+},
+#endif /* WRITE_CUSTOMIZE_*COMPRESSION */
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+vl_filter[] =
+{
+   { all,      PNG_ALL_FILTERS   },
+   { "off",    PNG_NO_FILTERS    },
+   { "none",   PNG_FILTER_NONE   },
+   { "sub",    PNG_FILTER_SUB    },
+   { "up",     PNG_FILTER_UP     },
+   { "avg",    PNG_FILTER_AVG    },
+   { "paeth",  PNG_FILTER_PAETH  }
+},
+#endif /* WRITE_FILTER */
+#ifdef PNG_PNGCP_TIMING_SUPPORTED
+#  define PNGCP_TIME_READ  1
+#  define PNGCP_TIME_WRITE 2
+vl_time[] =
+{
+   { "both",  PNGCP_TIME_READ+PNGCP_TIME_WRITE },
+   { "off",   0 },
+   { "read",  PNGCP_TIME_READ },
+   { "write", PNGCP_TIME_WRITE }
+},
+#endif /* PNGCP_TIMING */
+vl_IDAT_size[] = /* for png_set_IDAT_size */
+{
+   { "default", 0x7FFFFFFF },
+   { "minimal", 1 },
+   RANGE(1, 0x7FFFFFFF)
+},
+#ifndef PNG_SW_IDAT_size
+   /* Pre 1.7 API: */
+#  define png_set_IDAT_size(p,v) png_set_compression_buffer_size(p, v)
+#endif /* !SW_IDAT_size */
+#define SL 8 /* stack limit in display, below */
+vl_log_depth[] = { { "on", 1 }, { "off", 0 }, RANGE(0, SL) },
+vl_on_off[] = { { "on", 1 }, { "off", 0 } };
+
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
+static value_list
+vl_windowBits_IDAT[] =
+{
+   { "default", MAX_WBITS },
+   { "small", 9 },
+   RANGE(8, MAX_WBITS), /* modified by set_windowBits_hi */
+   { all, 0 }
+};
+#endif /* IDAT compression */
+
+typedef struct option
+{
+   const char       *name;         /* name of the option */
+   png_uint_32       opt;          /* an option, or OPTION or LIST */
+   png_byte          search;       /* Search on --search */
+   png_byte          value_count;  /* length of the list of values: */
+   const value_list *values;       /* values for OPTION or LIST */
+}  option;
+
+static const option options[] =
+{
+   /* struct display options, these are set when the command line is read */
+#  define S(n,v) { #n, v, 0, 2, vl_on_off },
+   S(verbose,  VERBOSE)
+   S(warnings, WARNINGS)
+   S(errors,   ERRORS)
+   S(quiet,    QUIET)
+   S(strict,   STRICT)
+   S(log,      LOG)
+   S(continue, CONTINUE)
+   S(sizes,    SIZES)
+   S(search,   SEARCH)
+   S(nowrite,  NOWRITE)
+#  ifdef IGNORE_INDEX
+      S(ignore-palette-index, IGNORE_INDEX)
+#  endif /* IGNORE_INDEX */
+#  ifdef FIX_INDEX
+      S(fix-palette-index, FIX_INDEX)
+#  endif /* FIX_INDEX */
+#  undef S
+
+   /* OPTION settings, these and LIST settings are read on demand */
+#  define VLNAME(name) vl_ ## name
+#  define VLSIZE(name) voidcast(png_byte,\
+                           (sizeof VLNAME(name))/(sizeof VLNAME(name)[0]))
+#  define VL(oname, name, type, search)\
+   { oname, type, search, VLSIZE(name), VLNAME(name) },
+#  define VLO(oname, name, search) VL(oname, name, OPTION, search)
+
+#  ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
+#     define VLCIDAT(name) VLO(#name, name, 1/*search*/)
+#     ifdef PNG_SW_COMPRESS_level
+#        define VLCiCCP(name) VLO("ICC-profile-" #name, name, 0/*search*/)
+#     else
+#        define VLCiCCP(name)
+#     endif
+#  else
+#     define VLCIDAT(name)
+#     define VLCiCCP(name)
+#  endif /* WRITE_CUSTOMIZE_COMPRESSION */
+
+#  ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
+#     define VLCzTXt(name) VLO("text-" #name, name, 0/*search*/)
+#  else
+#     define VLCzTXt(name)
+#  endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
+
+#  define VLC(name) VLCIDAT(name) VLCiCCP(name) VLCzTXt(name)
+
+#  ifdef PNG_SW_COMPRESS_png_level
+      /* The libpng compression level isn't searched because it justs sets the
+       * other things that are searched!
+       */
+      VLO("compression", compression, 0)
+      VLO("text-compression", compression, 0)
+      VLO("ICC-profile-compression", compression, 0)
+#  endif /* SW_COMPRESS_png_level */
+   VLC(strategy)
+   VLO("windowBits", windowBits_IDAT, 1)
+#  ifdef PNG_SW_COMPRESS_windowBits
+      VLO("ICC-profile-windowBits", windowBits_text/*sic*/, 0)
+#  endif
+   VLO("text-windowBits", windowBits_text, 0)
+   VLC(level)
+   VLC(memLevel)
+   VLO("IDAT-size", IDAT_size, 0)
+   VLO("log-depth", log_depth, 0)
+
+#  undef VLO
+
+   /* LIST settings */
+#  define VLL(name, search) VL(#name, name, LIST, search)
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+   VLL(filter, 0)
+#endif /* WRITE_FILTER */
+#ifdef PNG_PNGCP_TIMING_SUPPORTED
+   VLL(time, 0)
+#endif /* PNGCP_TIMING */
+#  undef VLL
+#  undef VL
+};
+
+#ifdef __cplusplus
+   static const size_t option_count((sizeof options)/(sizeof options[0]));
+#else /* !__cplusplus */
+#  define option_count ((sizeof options)/(sizeof options[0]))
+#endif /* !__cplusplus */
+
+static const char *
+cts(int ct)
+{
+   switch (ct)
+   {
+      case PNG_COLOR_TYPE_PALETTE:     return "P";
+      case PNG_COLOR_TYPE_GRAY:        return "G";
+      case PNG_COLOR_TYPE_GRAY_ALPHA:  return "GA";
+      case PNG_COLOR_TYPE_RGB:         return "RGB";
+      case PNG_COLOR_TYPE_RGB_ALPHA:   return "RGBA";
+      default:                         return "INVALID";
+   }
+}
+
+struct display
+{
+   jmp_buf          error_return;      /* Where to go to on error */
+   unsigned int     errset;            /* error_return is set */
+
+   const char      *operation;         /* What is happening */
+   const char      *filename;          /* The name of the original file */
+   const char      *output_file;       /* The name of the output file */
+
+   /* Used on both read and write: */
+   FILE            *fp;
+
+   /* Used on a read, both the original read and when validating a written
+    * image.
+    */
+   png_alloc_size_t read_size;
+   png_structp      read_pp;
+   png_infop        ip;
+#  if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
+      png_textp     text_ptr; /* stash of text chunks */
+      int           num_text;
+      int           text_stashed;
+#  endif /* pre 1.7 */
+
+#  ifdef PNG_PNGCP_TIMING_SUPPORTED
+      struct timespec   read_time;
+      struct timespec   read_time_total;
+      struct timespec   write_time;
+      struct timespec   write_time_total;
+#  endif /* PNGCP_TIMING */
+
+   /* Used to write a new image (the original info_ptr is used) */
+#  define MAX_SIZE ((png_alloc_size_t)(-1))
+   png_alloc_size_t write_size;
+   png_alloc_size_t best_size;
+   png_structp      write_pp;
+
+   /* Base file information */
+   png_alloc_size_t size;
+   png_uint_32      w;
+   png_uint_32      h;
+   int              bpp;
+   png_byte         ct;
+   int              no_warnings;       /* Do not output libpng warnings */
+   int              min_windowBits;    /* The windowBits range is 8..8 */
+
+   /* Options handling */
+   png_uint_32      results;             /* A mask of errors seen */
+   png_uint_32      options;             /* See display_log below */
+   png_byte         entry[option_count]; /* The selected entry+1 of an option
+                                          * that appears on the command line, or
+                                          * 0 if it was not given. */
+   int              value[option_count]; /* Corresponding value */
+
+   /* Compression exhaustive testing */
+   /* Temporary variables used only while testing a single collection of
+    * settings:
+    */
+   unsigned int     csp;               /* next stack entry to use */
+   unsigned int     nsp;               /* highest active entry+1 found so far */
+
+   /* Values used while iterating through all the combinations of settings for a
+    * single file:
+    */
+   unsigned int     tsp;               /* nsp from the last run; this is the
+                                        * index+1 of the highest active entry on
+                                        * this run; this entry will be advanced.
+                                        */
+   int              opt_string_start;  /* Position in buffer for the first
+                                        * searched option; non-zero if earlier
+                                        * options were set on the command line.
+                                        */
+   struct stack
+   {
+      png_alloc_size_t best_size;      /* Best so far for this option */
+      png_alloc_size_t lo_size;
+      png_alloc_size_t hi_size;
+      int              lo, hi;         /* For binary chop of a range */
+      int              best_val;       /* Best value found so far */
+      int              opt_string_end; /* End of the option string in 'curr' */
+      png_byte         opt;            /* The option being tested */
+      png_byte         entry;          /* The next value entry to be tested */
+      png_byte         end;            /* This is the last entry */
+   }                stack[SL];         /* Stack of entries being tested */
+   char             curr[32*SL];       /* current options being tested */
+   char             best[32*SL];       /* best options */
+
+   char             namebuf[FILENAME_MAX]; /* output file name */
+};
+
+static void
+display_init(struct display *dp)
+   /* Call this only once right at the start to initialize the control
+    * structure, the (struct buffer) lists are maintained across calls - the
+    * memory is not freed.
+    */
+{
+   memset(dp, 0, sizeof *dp);
+   dp->operation = "internal error";
+   dp->filename = "command line";
+   dp->output_file = "no output file";
+   dp->options = WARNINGS; /* default to !verbose, !quiet */
+   dp->fp = NULL;
+   dp->read_pp = NULL;
+   dp->ip = NULL;
+   dp->write_pp = NULL;
+   dp->min_windowBits = -1; /* this is an OPTIND, so -1 won't match anything */
+#  if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
+      dp->text_ptr = NULL;
+      dp->num_text = 0;
+      dp->text_stashed = 0;
+#  endif /* pre 1.7 */
+}
+
+static void
+display_clean_read(struct display *dp)
+{
+   if (dp->read_pp != NULL)
+      png_destroy_read_struct(&dp->read_pp, NULL, NULL);
+
+   if (dp->fp != NULL)
+   {
+      FILE *fp = dp->fp;
+      dp->fp = NULL;
+      (void)fclose(fp);
+   }
+}
+
+static void
+display_clean_write(struct display *dp)
+{
+   if (dp->fp != NULL)
+   {
+      FILE *fp = dp->fp;
+      dp->fp = NULL;
+      (void)fclose(fp);
+   }
+
+   if (dp->write_pp != NULL)
+      png_destroy_write_struct(&dp->write_pp, dp->tsp > 0 ? NULL : &dp->ip);
+}
+
+static void
+display_clean(struct display *dp)
+{
+   display_clean_read(dp);
+   display_clean_write(dp);
+   dp->output_file = NULL;
+
+#  if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
+      /* This is actually created and used by the write code, but only
+       * once; it has to be retained for subsequent writes of the same file.
+       */
+      if (dp->text_stashed)
+      {
+         dp->text_stashed = 0;
+         dp->num_text = 0;
+         free(dp->text_ptr);
+         dp->text_ptr = NULL;
+      }
+#  endif /* pre 1.7 */
+
+   /* leave the filename for error detection */
+   dp->results = 0; /* reset for next time */
+}
+
+static void
+display_destroy(struct display *dp)
+{
+   /* Release any memory held in the display. */
+   display_clean(dp);
+}
+
+static struct display *
+get_dp(png_structp pp)
+   /* The display pointer is always stored in the png_struct error pointer */
+{
+   struct display *dp = (struct display*)png_get_error_ptr(pp);
+
+   if (dp == NULL)
+   {
+      fprintf(stderr, "pngcp: internal error (no display)\n");
+      exit(99); /* prevents a crash */
+   }
+
+   return dp;
+}
+
+/* error handling */
+#ifdef __GNUC__
+#  define VGATTR __attribute__((__format__ (__printf__,3,4)))
+   /* Required to quiet GNUC warnings when the compiler sees a stdarg function
+    * that calls one of the stdio v APIs.
+    */
+#else
+#  define VGATTR
+#endif
+static void VGATTR
+display_log(struct display *dp, error_level level, const char *fmt, ...)
+   /* 'level' is as above, fmt is a stdio style format string.  This routine
+    * does not return if level is above LIBPNG_WARNING
+    */
+{
+   dp->results |= 1U << level;
+
+   if (level > (error_level)(dp->options & LEVEL_MASK))
+   {
+      const char *lp;
+      va_list ap;
+
+      switch (level)
+      {
+         case INFORMATION:    lp = "information"; break;
+         case LIBPNG_WARNING: lp = "warning(libpng)"; break;
+         case APP_WARNING:    lp = "warning(pngcp)"; break;
+         case APP_FAIL:       lp = "error(continuable)"; break;
+         case LIBPNG_ERROR:   lp = "error(libpng)"; break;
+         case LIBPNG_BUG:     lp = "bug(libpng)"; break;
+         case APP_ERROR:      lp = "error(pngcp)"; break;
+         case USER_ERROR:     lp = "error(user)"; break;
+
+         case INTERNAL_ERROR: /* anything unexpected is an internal error: */
+         case VERBOSE: case WARNINGS: case ERRORS: case QUIET:
+         default:             lp = "bug(pngcp)"; break;
+      }
+
+      fprintf(stderr, "%s: %s: %s",
+         dp->filename != NULL ? dp->filename : "<stdin>", lp, dp->operation);
+
+      fprintf(stderr, ": ");
+
+      va_start(ap, fmt);
+      vfprintf(stderr, fmt, ap);
+      va_end(ap);
+
+      fputc('\n', stderr);
+   }
+   /* else do not output any message */
+
+   /* Errors cause this routine to exit to the fail code */
+   if (level > APP_FAIL || (level > ERRORS && !(dp->options & CONTINUE)))
+   {
+      if (dp->errset)
+         longjmp(dp->error_return, level);
+
+      else
+         exit(99);
+   }
+}
+
+#if PNG_LIBPNG_VER < 10700 && defined PNG_TEXT_SUPPORTED
+static void
+text_stash(struct display *dp)
+{
+   /* libpng 1.6 and earlier fixed a bug whereby text chunks were written
+    * multiple times by png_write_png; the issue was that png_write_png passed
+    * the same png_info to both png_write_info and png_write_end.  Rather than
+    * fixing it by recording the information in the png_struct, or by recording
+    * where to write the chunks, the fix made was to change the 'compression'
+    * field of the chunk to invalid values, rendering the png_info somewhat
+    * useless.
+    *
+    * The only fix for this given that we use the png_info more than once is to
+    * make a copy of the text chunks and png_set_text it each time.  This adds a
+    * text chunks, so they get replicated, but only the new set gets written
+    * each time.  This uses memory like crazy but there is no way to delete the
+    * useless chunks from the png_info.
+    *
+    * To make this slightly more efficient only the top level structure is
+    * copied; since the old strings are actually preserved (in 1.6 and earlier)
+    * this happens to work.
+    */
+   png_textp chunks = NULL;
+
+   dp->num_text = png_get_text(dp->write_pp, dp->ip, &chunks, NULL);
+
+   if (dp->num_text > 0)
+   {
+      dp->text_ptr = voidcast(png_textp, malloc(dp->num_text * sizeof *chunks));
+
+      if (dp->text_ptr == NULL)
+         display_log(dp, APP_ERROR, "text chunks: stash malloc failed");
+
+      else
+         memcpy(dp->text_ptr, chunks, dp->num_text * sizeof *chunks);
+   }
+
+   dp->text_stashed = 1; /* regardless of whether there are chunks or not */
+}
+
+#define text_stash(dp) if (!dp->text_stashed) text_stash(dp)
+
+static void
+text_restore(struct display *dp)
+{
+   /* libpng makes a copy, so this is fine: */
+   if (dp->text_ptr != NULL)
+      png_set_text(dp->write_pp, dp->ip, dp->text_ptr, dp->num_text);
+}
+
+#define text_restore(dp) if (dp->text_stashed) text_restore(dp)
+
+#else
+#define text_stash(dp) ((void)0)
+#define text_restore(dp) ((void)0)
+#endif /* pre 1.7 */
+
+/* OPTIONS:
+ *
+ * The command handles options of the forms:
+ *
+ *    --option
+ *       Turn an option on (Option)
+ *    --no-option
+ *       Turn an option off (Option)
+ *    --option=value
+ *       Set an option to a value (Value)
+ *    --option=val1,val2,val3
+ *       Set an option to a bitmask constructed from the values (List)
+ */
+static png_byte
+option_index(struct display *dp, const char *opt, size_t len)
+   /* Return the index (in options[]) of the given option, outputs an error if
+    * it does not exist.  Takes the name of the option and a length (number of
+    * characters in the name).
+    */
+{
+   png_byte j;
+
+   for (j=0; j<option_count; ++j)
+      if (strncmp(options[j].name, opt, len) == 0 && options[j].name[len] == 0)
+         return j;
+
+   /* If the setjmp buffer is set the code is asking for an option index; this
+    * is bad.  Otherwise this is the command line option parsing.
+    */
+   display_log(dp, dp->errset ? INTERNAL_ERROR : USER_ERROR,
+         "%.*s: unknown option", (int)/*SAFE*/len, opt);
+   abort(); /* NOT REACHED */
+}
+
+/* This works for an option name (no quotes): */
+#define OPTIND(dp, name) option_index(dp, #name, (sizeof #name)-1)
+
+static int
+get_option(struct display *dp, const char *opt, int *value)
+{
+   png_byte i = option_index(dp, opt, strlen(opt));
+
+   if (dp->entry[i]) /* option was set on command line */
+   {
+      *value = dp->value[i];
+      return 1;
+   }
+
+   else
+      return 0;
+}
+
+static int
+set_opt_string_(struct display *dp, unsigned int sp, png_byte opt,
+      const char *entry_name)
+   /* Add the appropriate option string to dp->curr. */
+{
+   int offset, add;
+
+   if (sp > 0)
+      offset = dp->stack[sp-1].opt_string_end;
+
+   else
+      offset = dp->opt_string_start;
+
+   if (entry_name == range_lo)
+      add = sprintf(dp->curr+offset, " --%s=%d", options[opt].name,
+            dp->value[opt]);
+
+   else
+      add = sprintf(dp->curr+offset, " --%s=%s", options[opt].name, entry_name);
+
+   if (add < 0)
+      display_log(dp, INTERNAL_ERROR, "sprintf failed");
+
+   assert(offset+add < (int)/*SAFE*/sizeof dp->curr);
+   return offset+add;
+}
+
+static void
+set_opt_string(struct display *dp, unsigned int sp)
+   /* Add the appropriate option string to dp->curr. */
+{
+   dp->stack[sp].opt_string_end = set_opt_string_(dp, sp, dp->stack[sp].opt, 
+      options[dp->stack[sp].opt].values[dp->stack[sp].entry].name);
+}
+
+static void
+record_opt(struct display *dp, png_byte opt, const char *entry_name)
+   /* Record this option in dp->curr; called for an option not being searched,
+    * the caller passes in the name of the value, or range_lo to use the
+    * numerical value.
+    */
+{
+   unsigned int sp = dp->csp; /* stack entry of next searched option */
+
+   if (sp >= dp->tsp)
+   {
+      /* At top of stack; add the opt string for this entry to the previous
+       * searched entry or the start of the dp->curr buffer if there is nothing
+       * on the stack yet (sp == 0).
+       */
+      int offset = set_opt_string_(dp, sp, opt, entry_name);
+
+      if (sp > 0)
+         dp->stack[sp-1].opt_string_end = offset;
+
+      else
+         dp->opt_string_start = offset;
+   }
+
+   /* else do nothing: option already recorded */
+}
+
+static int
+opt_list_end(struct display *dp, png_byte opt, png_byte entry)
+{
+   if (options[opt].values[entry].name == range_lo)
+      return entry+1U >= options[opt].value_count /* missing range_hi */ ||
+         options[opt].values[entry+1U].name != range_hi /* likewise */ ||
+         options[opt].values[entry+1U].value <= dp->value[opt] /* range end */;
+
+   else
+      return entry+1U >= options[opt].value_count /* missing 'all' */ ||
+         options[opt].values[entry+1U].name == all /* last entry */;
+}
+
+static void
+push_opt(struct display *dp, unsigned int sp, png_byte opt, int search)
+   /* Push a new option onto the stack, initializing the new stack entry
+    * appropriately; this does all the work of next_opt (setting end/nsp) for
+    * the first entry in the list.
+    */
+{
+   png_byte entry;
+   const char *entry_name;
+
+   assert(sp == dp->tsp && sp < SL);
+
+   /* The starting entry is entry 0 unless there is a range in which case it is
+    * the entry corresponding to range_lo:
+    */
+   entry = options[opt].value_count;
+   assert(entry > 0U);
+
+   do
+   {
+      entry_name = options[opt].values[--entry].name;
+      if (entry_name == range_lo)
+         break;
+   }
+   while (entry > 0U);
+
+   dp->tsp = sp+1U;
+   dp->stack[sp].best_size =
+      dp->stack[sp].lo_size =
+      dp->stack[sp].hi_size = MAX_SIZE;
+
+   if (search && entry_name == range_lo) /* search this range */
+   {
+      dp->stack[sp].lo = options[opt].values[entry].value;
+      /* check for a mal-formed RANGE above: */
+      assert(entry+1 < options[opt].value_count &&
+             options[opt].values[entry+1].name == range_hi);
+      dp->stack[sp].hi = options[opt].values[entry+1].value;
+   }
+
+   else
+   {
+      /* next_opt will just iterate over the range. */
+      dp->stack[sp].lo = INT_MAX;
+      dp->stack[sp].hi = INT_MIN; /* Prevent range chop */
+   }
+
+   dp->stack[sp].opt = opt;
+   dp->stack[sp].entry = entry;
+   dp->stack[sp].best_val = dp->value[opt] = options[opt].values[entry].value;
+
+   set_opt_string(dp, sp);
+
+   /* This works for the search case too; if the range has only one entry 'end'
+    * will be marked here.
+    */
+   if (opt_list_end(dp, opt, entry))
+   {
+      dp->stack[sp].end = 1;
+      /* Skip the warning if pngcp did this itself.  See the code in
+       * set_windowBits_hi.
+       */
+      if (opt != dp->min_windowBits)
+         display_log(dp, APP_WARNING, "%s: only testing one value",
+               options[opt].name);
+   }
+
+   else
+   {
+      dp->stack[sp].end = 0;
+      dp->nsp = dp->tsp;
+   }
+
+   /* Do a lazy cache of the text chunks for libpng 1.6 and earlier; this is
+    * because they can only be written once(!) so if we are going to re-use the
+    * png_info we need a copy.
+    */
+   text_stash(dp);
+}
+
+static void
+next_opt(struct display *dp, unsigned int sp)
+   /* Return the next value for this option.  When called 'sp' is expected to be
+    * the topmost stack entry - only the topmost entry changes each time round -
+    * and there must be a valid entry to return.  next_opt will set dp->nsp to
+    * sp+1 if more entries are available, otherwise it will not change it and
+    * set dp->stack[s].end to true.
+    */
+{
+   int search = 0;
+   png_byte entry, opt;
+   const char *entry_name;
+
+   /* dp->stack[sp] must be the top stack entry and it must be active: */
+   assert(sp+1U == dp->tsp && !dp->stack[sp].end);
+
+   opt = dp->stack[sp].opt;
+   entry = dp->stack[sp].entry;
+   assert(entry+1U < options[opt].value_count);
+   entry_name = options[opt].values[entry].name;
+   assert(entry_name != NULL);
+
+   /* For ranges increment the value but don't change the entry, for all other
+    * cases move to the next entry and load its value:
+    */
+   if (entry_name == range_lo) /* a range */
+   {
+      /* A range can be iterated over or searched.  The default iteration option
+       * is indicated by hi < lo on the stack, otherwise the range being search
+       * is [lo..hi] (inclusive).
+       */
+      if (dp->stack[sp].lo > dp->stack[sp].hi)
+         dp->value[opt]++;
+
+      else
+      {
+         /* This is the best size found for this option value: */
+         png_alloc_size_t best_size = dp->stack[sp].best_size;
+         int lo = dp->stack[sp].lo;
+         int hi = dp->stack[sp].hi;
+         int val = dp->value[opt];
+
+         search = 1; /* end is determined here */
+         assert(best_size < MAX_SIZE);
+
+         if (val == lo)
+         {
+            /* Finding the best for the low end of the range: */
+            dp->stack[sp].lo_size = best_size;
+            assert(hi > val);
+
+            if (hi == val+1) /* only 2 entries */
+               dp->stack[sp].end = 1;
+
+            val = hi;
+         }
+
+         else if (val == hi)
+         {
+            dp->stack[sp].hi_size = best_size;
+            assert(val > lo+1); /* else 'end' set above */
+
+            if (val == lo+2) /* only three entries to test */
+               dp->stack[sp].end = 1;
+
+            val = (lo + val)/2;
+         }
+
+         else
+         {
+            png_alloc_size_t lo_size = dp->stack[sp].lo_size;
+            png_alloc_size_t hi_size = dp->stack[sp].hi_size;
+
+            /* lo and hi should have been tested. */
+            assert(lo_size < MAX_SIZE && hi_size < MAX_SIZE);
+
+            /* These cases arise with the 'probe' handling below when there is a
+             * dip or peak in the size curve.
+             */
+            if (val < lo) /* probing a new lo */
+            {
+               /* Swap lo and val: */
+               dp->stack[sp].lo = val;
+               dp->stack[sp].lo_size = best_size;
+               val = lo;
+               best_size = lo_size;
+               lo = dp->stack[sp].lo;
+               lo_size = dp->stack[sp].lo_size;
+            }
+
+            else if (val > hi) /* probing a new hi */
+            {
+               /* Swap hi and val: */
+               dp->stack[sp].hi = val;
+               dp->stack[sp].hi_size = best_size;
+               val = hi;
+               best_size = hi_size;
+               hi = dp->stack[sp].hi;
+               hi_size = dp->stack[sp].hi_size;
+            }
+
+            /* The following should be true or something got messed up above. */
+            assert(lo < val && val < hi);
+
+            /* If there are only four entries (lo, val, hi plus one more) just
+             * test the remaining entry.
+             */
+            if (hi == lo+3)
+            {
+               /* Because of the 'probe' code val can either be lo+1 or hi-1; we
+                * need to test the other.
+                */
+               val = lo + ((val == lo+1) ? 2 : 1);
+               assert(lo < val && val < hi);
+               dp->stack[sp].end = 1;
+            }
+
+            else
+            {
+               /* There are at least 2 entries still untested between lo and hi,
+                * i.e. hi >= lo+4.  'val' is the midpoint +/- 0.5
+                *
+                * Separate out the four easy cases when lo..val..hi are
+                * monotonically decreased or (more weird) increasing:
+                */
+               assert(hi > lo+3);
+
+               if (lo_size <= best_size && best_size <= hi_size)
+               {
+                  /* Select the low range; testing this first favours the low
+                   * range over the high range when everything comes out equal.
+                   * Because of the probing 'val' may be lo+1.  In that case end
+                   * the search and set 'val' to lo+2.
+                   */
+                  if (val == lo+1)
+                  {
+                     ++val;
+                     dp->stack[sp].end = 1;
+                  }
+
+                  else
+                  {
+                     dp->stack[sp].hi = hi = val;
+                     dp->stack[sp].hi_size = best_size;
+                     val = (lo + val) / 2;
+                  }
+               }
+
+               else if (lo_size >= best_size && best_size >= hi_size)
+               {
+                  /* Monotonically decreasing size; this is the expected case.
+                   * Select the high end of the range.  As above, val may be
+                   * hi-1.
+                   */
+                  if (val == hi-1)
+                  {
+                     --val;
+                     dp->stack[sp].end = 1;
+                  }
+
+                  else
+                  {
+                     dp->stack[sp].lo = lo = val;
+                     dp->stack[sp].lo_size = best_size;
+                     val = (val + hi) / 2;
+                  }
+               }
+
+               /* If both those tests failed 'best_size' is either greater than
+                * or less than both lo_size and hi_size.  There is a peak or dip
+                * in the curve of sizes from lo to hi and val is on the peak or
+                * dip.
+                *
+                * Because the ranges being searched as so small (level is 1..9,
+                * windowBits 8..15, memLevel 1..9) there will only be at most
+                * three untested values between lo..val and val..hi, so solve
+                * the problem by probing down from hi or up from lo, whichever
+                * is the higher.
+                *
+                * This is the place where 'val' is set to outside the range
+                * lo..hi, described as 'probing', though maybe 'narrowing' would
+                * be more accurate.
+                */
+               else if (lo_size <= hi_size) /* down from hi */
+               {
+                  dp->stack[sp].hi = val;
+                  dp->stack[sp].hi_size = best_size;
+                  val = --hi;
+               }
+
+               else /* up from low */
+               {
+                  dp->stack[sp].lo = val;
+                  dp->stack[sp].lo_size = best_size;
+                  val = ++lo;
+               }
+
+               /* lo and hi are still the true range limits, check for the end
+                * condition.
+                */
+               assert(hi > lo+1);
+               if (hi <= lo+2)
+                  dp->stack[sp].end = 1;
+            }
+         }
+
+         assert(val != dp->stack[sp].best_val); /* should be a new value */
+         dp->value[opt] = val;
+         dp->stack[sp].best_size = MAX_SIZE;
+      }
+   }
+
+   else
+   {
+      /* Increment 'entry' */
+      dp->value[opt] = options[opt].values[++entry].value;
+      dp->stack[sp].entry = entry;
+   }
+
+   set_opt_string(dp, sp);
+
+   if (!search && opt_list_end(dp, opt, entry)) /* end of list */
+      dp->stack[sp].end = 1;
+
+   else if (!dp->stack[sp].end) /* still active after all these tests */
+      dp->nsp = dp->tsp;
+}
+
+static int
+compare_option(const struct display *dp, unsigned int sp)
+{
+   int opt = dp->stack[sp].opt;
+
+   /* If the best so far is numerically less than the current value the
+    * current set of options is invariably worse.
+    */
+   if (dp->stack[sp].best_val < dp->value[opt])
+      return -1;
+
+   /* Lists of options are searched out of numerical order (currently only
+    * strategy), so only return +1 here when a range is being searched.
+    */
+   else if (dp->stack[sp].best_val > dp->value[opt])
+   {
+      if (dp->stack[sp].lo <= dp->stack[sp].hi /*searching*/)
+         return 1;
+
+      else
+         return -1;
+   }
+
+   else
+      return 0; /* match; current value is the best one */
+}
+
+static int
+advance_opt(struct display *dp, png_byte opt, int search)
+{
+   unsigned int sp = dp->csp++; /* my stack entry */
+
+   assert(sp >= dp->nsp); /* nsp starts off zero */
+
+   /* If the entry was active in the previous run dp->stack[sp] is already
+    * set up and dp->tsp will be greater than sp, otherwise a new entry
+    * needs to be created.
+    *
+    * dp->nsp is handled this way:
+    *
+    * 1) When an option is pushed onto the stack dp->nsp and dp->tsp are
+    *    both set (by push_opt) to the next stack entry *unless* there is
+    *    only one entry in the new list, in which case dp->stack[sp].end
+    *    is set.
+    *
+    * 2) For the top stack entry next_opt is called.  The entry must be
+    *    active (dp->stack[sp].end is not set) and either 'nsp' or 'end'
+    *    will be updated as appropriate.
+    *
+    * 3) For lower stack entries nsp is set unless the stack entry is
+    *    already at the end.  This means that when all the higher entries
+    *    are popped this entry will be too.
+    */
+   if (sp >= dp->tsp)
+   {
+      push_opt(dp, sp, opt, search); /* This sets tsp to sp+1 */
+      return 1; /* initialized */
+   }
+
+   else
+   {
+      int ret = 0; /* unchanged */
+
+      /* An option that is already on the stack; update best_size and best_val
+       * if appropriate.  On the first run there are no previous values and
+       * dp->write_size will be MAX_SIZE, however on the first run dp->tsp
+       * starts off as 0.
+       */
+      assert(dp->write_size > 0U && dp->write_size < MAX_SIZE);
+
+      if (dp->stack[sp].best_size > dp->write_size ||
+          (dp->stack[sp].best_size == dp->write_size &&
+           compare_option(dp, sp) > 0))
+      {
+         dp->stack[sp].best_size = dp->write_size;
+         dp->stack[sp].best_val = dp->value[opt];
+      }
+
+      if (sp+1U >= dp->tsp)
+      {
+         next_opt(dp, sp);
+         ret = 1; /* advanced */
+      }
+
+      else if (!dp->stack[sp].end) /* Active, not at top of stack */
+         dp->nsp = sp+1U;
+
+      return ret; /* advanced || unchanged */
+   }
+}
+
+static int
+getallopts_(struct display *dp, png_byte opt, int *value, int record)
+   /* Like getop but iterate over all the values if the option was set to "all".
+    */
+{
+   if (dp->entry[opt]) /* option was set on command line */
+   {
+      /* Simple, single value, entries don't have a stack frame and have a fixed
+       * value (it doesn't change once set on the command line).  Otherwise the
+       * value (entry) selected from the command line is 'all':
+       */
+      const char *entry_name = options[opt].values[dp->entry[opt]-1].name;
+
+      if (entry_name == all)
+         (void)advance_opt(dp, opt, 0/*do not search; iterate*/);
+
+      else if (record)
+         record_opt(dp, opt, entry_name);
+
+      *value = dp->value[opt];
+      return 1; /* set */
+   }
+
+   else
+      return 0; /* not set */
+}
+
+static int
+getallopts(struct display *dp, const char *opt_str, int *value)
+{
+   return getallopts_(dp, option_index(dp, opt_str, strlen(opt_str)), value, 0);
+}
+
+static int
+getsearchopts(struct display *dp, const char *opt_str, int *value)
+   /* As above except that if the option was not set try a search */
+{
+   png_byte istrat;
+   png_byte opt = option_index(dp, opt_str, strlen(opt_str));
+   int record = options[opt].search;
+   const char *entry_name;
+
+   /* If it was set on the command line honour the setting, including 'all'
+    * which will override the built in search:
+    */
+   if (getallopts_(dp, opt, value, record))
+      return 1;
+
+   else if (!record) /* not a search option */
+      return 0; /* unset and not searched */
+
+   /* Otherwise decide what to do here. */
+   istrat = OPTIND(dp, strategy);
+   entry_name = range_lo; /* record the value, not the name */
+
+   if (opt == istrat) /* search all strategies */
+      (void)advance_opt(dp, opt, 0/*iterate*/), record=0;
+
+   else if (opt == OPTIND(dp, level))
+   {
+      /* Both RLE and HUFFMAN don't benefit from level increases */
+      if (dp->value[istrat] == Z_RLE || dp->value[istrat] == Z_HUFFMAN_ONLY)
+         dp->value[opt] = 1;
+
+      else /* fixed, filtered or default */
+         (void)advance_opt(dp, opt, 1/*search*/), record=0;
+   }
+
+   else if (opt == OPTIND(dp, windowBits))
+   {
+      /* Changing windowBits for strategies that do not search the window is
+       * pointless.  Huffman-only does not search, RLE only searches backwards
+       * one byte, so given that the maximum string length is 258, a windowBits
+       * of 9 is always sufficient.
+       */
+      if (dp->value[istrat] == Z_HUFFMAN_ONLY)
+         dp->value[opt] = 8;
+
+      else if (dp->value[istrat] == Z_RLE)
+         dp->value[opt] = 9;
+
+      else /* fixed, filtered or default */
+         (void)advance_opt(dp, opt, 1/*search*/), record=0;
+   }
+
+   else if (opt == OPTIND(dp, memLevel))
+   {
+#     if 0
+         (void)advance_opt(dp, opt, 0/*all*/), record=0;
+#     else
+         dp->value[opt] = MAX_MEM_LEVEL;
+#     endif
+   }
+
+   else /* something else */
+      assert(0=="reached");
+
+   if (record)
+      record_opt(dp, opt, entry_name);
+
+   /* One of the above searched options: */
+   *value = dp->value[opt];
+   return 1;
+}
+
+static int
+find_val(struct display *dp, png_byte opt, const char *str, size_t len)
+   /* Like option_index but sets (index+i) of the entry in options[opt] that
+    * matches str[0..len-1] into dp->entry[opt] as well as returning the actual
+    * value.
+    */
+{
+   int rlo = INT_MAX, rhi = INT_MIN;
+   png_byte j, irange = 0;
+
+   for (j=1U; j<=options[opt].value_count; ++j)
+   {
+      if (strncmp(options[opt].values[j-1U].name, str, len) == 0 &&
+          options[opt].values[j-1U].name[len] == 0)
+      {
+         dp->entry[opt] = j;
+         return options[opt].values[j-1U].value;
+      }
+      else if (options[opt].values[j-1U].name == range_lo)
+         rlo = options[opt].values[j-1U].value, irange = j;
+      else if (options[opt].values[j-1U].name == range_hi)
+         rhi = options[opt].values[j-1U].value;
+   }
+
+   /* No match on the name, but there may be a range. */
+   if (irange > 0)
+   {
+      char *ep = NULL;
+      long l = strtol(str, &ep, 0);
+
+      if (ep == str+len && l >= rlo && l <= rhi)
+      {
+         dp->entry[opt] = irange; /* range_lo */
+         return (int)/*SAFE*/l;
+      }
+   }
+
+   display_log(dp, dp->errset ? INTERNAL_ERROR : USER_ERROR,
+         "%s: unknown value setting '%.*s'", options[opt].name,
+         (int)/*SAFE*/len, str);
+   abort(); /* NOT REACHED */
+}
+
+static int
+opt_check(struct display *dp, const char *arg)
+{
+   assert(dp->errset == 0);
+
+   if (arg != NULL && arg[0] == '-' && arg[1] == '-')
+   {
+      int i = 0, negate = (strncmp(arg+2, "no-", 3) == 0), val;
+      png_byte j;
+
+      if (negate)
+         arg += 5; /* --no- */
+
+      else
+         arg += 2; /* -- */
+
+      /* Find the length (expect arg\0 or arg=) */
+      while (arg[i] != 0 && arg[i] != '=') ++i;
+
+      /* So arg[0..i-1] is the argument name, this does not return if this isn't
+       * a valid option name.
+       */
+      j = option_index(dp, arg, i);
+
+      /* It matcheth an option; check the remainder. */
+      if (arg[i] == 0) /* no specified value, use the default */
+      {
+         val = options[j].values[negate].value;
+         dp->entry[j] = (png_byte)/*SAFE*/(negate + 1U);
+      }
+
+      else
+      {
+         const char *list = arg + (i+1);
+
+         /* Expect a single value here unless this is a list, in which case
+          * multiple values are combined.
+          */
+         if (options[j].opt != LIST)
+         {
+            /* find_val sets 'dp->entry[j]' to a non-zero value: */
+            val = find_val(dp, j, list, strlen(list));
+
+            if (negate)
+            {
+               if (options[j].opt < OPTION)
+                  val = !val;
+
+               else
+               {
+                  display_log(dp, USER_ERROR,
+                        "%.*s: option=arg cannot be negated", i, arg);
+                  abort(); /* NOT REACHED */
+               }
+            }
+         }
+
+         else /* multiple options separated by ',' characters */
+         {
+            /* --no-option negates list values from the default, which should
+             * therefore be 'all'.  Notice that if the option list is empty in
+             * this case nothing will be removed and therefore --no-option= is
+             * the same as --option.
+             */
+            if (negate)
+               val = options[j].values[0].value;
+
+            else
+               val = 0;
+
+            while (*list != 0) /* allows option= which sets 0 */
+            {
+               /* A value is terminated by the end of the list or a ','
+                * character.
+                */
+               int v, iv;
+
+               iv = 0; /* an index into 'list' */
+               while (list[++iv] != 0 && list[iv] != ',') {}
+
+               v = find_val(dp, j, list, iv);
+
+               if (negate)
+                  val &= ~v;
+
+               else
+                  val |= v;
+
+               list += iv;
+               if (*list != 0)
+                  ++list; /* skip the ',' */
+            }
+         }
+      }
+
+      /* 'val' is the new value, store it for use later and debugging: */
+      dp->value[j] = val;
+
+      if (options[j].opt < LEVEL_MASK)
+      {
+         /* The handling for error levels is to set the level. */
+         if (val) /* Set this level */
+            dp->options = (dp->options & ~LEVEL_MASK) | options[j].opt;
+
+         else
+            display_log(dp, USER_ERROR,
+      "%.*s: messages cannot be turned off individually; set a message level",
+                  i, arg);
+      }
+
+      else if (options[j].opt < OPTION)
+      {
+         if (val)
+            dp->options |= options[j].opt;
+
+         else
+            dp->options &= ~options[j].opt;
+      }
+
+      return 1; /* this is an option */
+   }
+
+   else
+      return 0; /* not an option */
+}
+
+#ifdef PNG_PNGCP_TIMING_SUPPORTED
+static void
+set_timer(struct display *dp, struct timespec *timer)
+{
+   /* Do the timing using clock_gettime and the per-process timer. */
+   if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, timer))
+   {
+      display_log(dp, APP_ERROR,
+            "CLOCK_PROCESS_CPUTIME_ID: %s: timing disabled\n", strerror(errno));
+      dp->value[OPTIND(dp,time)] = 0; /* i.e. off */
+   }
+}
+
+static void
+start_timer(struct display *dp, int what)
+{
+   if ((dp->value[OPTIND(dp,time)] & what) != 0)
+      set_timer(dp, what == PNGCP_TIME_READ ? &dp->read_time : &dp->write_time);
+}
+
+static void
+end_timer(struct display *dp, int what)
+{
+   if ((dp->value[OPTIND(dp,time)] & what) != 0)
+   {
+      struct timespec t, tmp;
+
+      set_timer(dp, &t);
+
+      if (what == PNGCP_TIME_READ)
+         tmp = dp->read_time;
+
+      else
+         tmp = dp->write_time;
+
+      t.tv_sec -= tmp.tv_sec;
+      t.tv_nsec -= tmp.tv_nsec;
+
+      if (t.tv_nsec < 0)
+      {
+         --(t.tv_sec);
+         t.tv_nsec += 1000000000L;
+      }
+
+      if (what == PNGCP_TIME_READ)
+         dp->read_time = t, tmp = dp->read_time_total;
+
+      else
+         dp->write_time = t, tmp = dp->write_time_total;
+
+      tmp.tv_sec += t.tv_sec;
+      tmp.tv_nsec += t.tv_nsec;
+
+      if (tmp.tv_nsec >= 1000000000L)
+      {
+         ++(tmp.tv_sec);
+         tmp.tv_nsec -= 1000000000L;
+      }
+
+      if (what == PNGCP_TIME_READ)
+         dp->read_time_total = tmp;
+
+      else
+         dp->write_time_total = tmp;
+   }
+}
+
+static void
+print_time(const char *what, struct timespec t)
+{
+   printf("%s %.2lu.%.9ld", what, (unsigned long)t.tv_sec, t.tv_nsec);
+}
+#else /* !PNGCP_TIMING */
+#define start_timer(dp, what) ((void)0)
+#define end_timer(dp, what) ((void)0)
+#endif /* !PNGCP_TIMING */
+
+/* The following is used in main to verify that the final argument is a
+ * directory:
+ */
+static int
+checkdir(const char *pathname)
+{
+   struct stat buf;
+   return stat(pathname, &buf) == 0 && S_ISDIR(buf.st_mode);
+}
+
+/* Work out whether a path is valid (if not a display_log occurs), a directory
+ * (1 is returned) or a file *or* non-existent (0 is returned).
+ *
+ * Used for a write path.
+ */
+static int
+isdir(struct display *dp, const char *pathname)
+{
+   if (pathname == NULL)
+      return 0; /* stdout */
+
+   else if (pathname[0] == 0)
+      return 1; /* empty string */
+
+   else
+   {
+      struct stat buf;
+      int ret = stat(pathname, &buf);
+
+      if (ret == 0) /* the entry exists */
+      {
+         if (S_ISDIR(buf.st_mode))
+            return 1;
+
+         /* Else expect an object that exists and can be written: */
+         if (access(pathname, W_OK) != 0)
+            display_log(dp, USER_ERROR, "%s: cannot be written (%s)", pathname,
+                  strerror(errno));
+
+         return 0; /* file (exists, can be written) */
+      }
+
+      else /* an error */
+      {
+         /* Non-existence is fine, other errors are not: */
+         if (errno != ENOENT)
+            display_log(dp, USER_ERROR, "%s: invalid output name (%s)",
+                  pathname, strerror(errno));
+
+         return 0; /* file (does not exist) */
+      }
+   }
+}
+
+static void
+makename(struct display *dp, const char *dir, const char *infile)
+{
+   /* Make a name for an output file (and check it). */
+   dp->namebuf[0] = 0;
+
+   if (dir == NULL || infile == NULL)
+      display_log(dp, INTERNAL_ERROR, "NULL name to makename");
+
+   else
+   {
+      size_t dsize = strlen(dir);
+
+      if (dsize <= (sizeof dp->namebuf)-2) /* Allow for name + '/' + '\0' */
+      {
+         size_t isize = strlen(infile);
+         size_t istart = isize-1;
+
+         /* This should fail before here: */
+         if (infile[istart] == '/')
+            display_log(dp, INTERNAL_ERROR, "infile with trailing /");
+
+         memcpy(dp->namebuf, dir, dsize);
+         if (dsize > 0 && dp->namebuf[dsize-1] != '/')
+            dp->namebuf[dsize++] = '/';
+
+         /* Find the rightmost non-/ character: */
+         while (istart > 0 && infile[istart-1] != '/')
+            --istart;
+
+         isize -= istart;
+         infile += istart;
+
+         if (dsize+isize < (sizeof dp->namebuf)) /* dsize + infile + '\0' */
+         {
+            memcpy(dp->namebuf+dsize, infile, isize+1);
+
+            if (isdir(dp, dp->namebuf))
+               display_log(dp, USER_ERROR, "%s: output file is a directory",
+                     dp->namebuf);
+         }
+
+         else
+         {
+            dp->namebuf[dsize] = 0; /* allowed for: -2 at start */
+            display_log(dp, USER_ERROR, "%s%s: output file name too long",
+                  dp->namebuf, infile);
+         }
+      }
+
+      else
+         display_log(dp, USER_ERROR, "%s: output directory name too long", dir);
+   }
+}
+
+/* error handler callbacks for libpng */
+static void PNGCBAPI
+display_warning(png_structp pp, png_const_charp warning)
+{
+   struct display *dp = get_dp(pp);
+
+   /* This is used to prevent repeated warnings while searching */
+   if (!dp->no_warnings)
+      display_log(get_dp(pp), LIBPNG_WARNING, "%s", warning);
+}
+
+static void PNGCBAPI
+display_error(png_structp pp, png_const_charp error)
+{
+   struct display *dp = get_dp(pp);
+
+   display_log(dp, LIBPNG_ERROR, "%s", error);
+}
+
+static void
+display_start_read(struct display *dp, const char *filename)
+{
+   if (filename != NULL)
+   {
+      dp->filename = filename;
+      dp->fp = fopen(filename, "rb");
+   }
+
+   else
+   {
+      dp->filename = "<stdin>";
+      dp->fp = stdin;
+   }
+
+   dp->w = dp->h = 0U;
+   dp->bpp = 0U;
+   dp->size = 0U;
+   dp->read_size = 0U;
+
+   if (dp->fp == NULL)
+      display_log(dp, USER_ERROR, "file open failed (%s)", strerror(errno));
+}
+
+static void PNGCBAPI
+read_function(png_structp pp, png_bytep data, size_t size)
+{
+   struct display *dp = get_dp(pp);
+
+   if (size == 0U || fread(data, size, 1U, dp->fp) == 1U)
+      dp->read_size += size;
+
+   else
+   {
+      if (feof(dp->fp))
+         display_log(dp, LIBPNG_ERROR, "PNG file truncated");
+      else
+         display_log(dp, LIBPNG_ERROR, "PNG file read failed (%s)",
+               strerror(errno));
+   }
+}
+
+static void
+read_png(struct display *dp, const char *filename)
+{
+   display_clean_read(dp); /* safety */
+   display_start_read(dp, filename);
+
+   dp->read_pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, dp,
+      display_error, display_warning);
+   if (dp->read_pp == NULL)
+      display_log(dp, LIBPNG_ERROR, "failed to create read struct");
+
+#  ifdef PNG_BENIGN_ERRORS_SUPPORTED
+      png_set_benign_errors(dp->read_pp, 1/*allowed*/);
+#  endif /* BENIGN_ERRORS */
+
+#  ifdef FIX_INDEX
+      if ((dp->options & FIX_INDEX) != 0)
+         png_set_check_for_invalid_index(dp->read_pp, 1/*on, no warning*/);
+#     ifdef IGNORE_INDEX
+         else
+#     endif /* IGNORE_INDEX */
+#  endif /* FIX_INDEX */
+#  ifdef IGNORE_INDEX
+      if ((dp->options & IGNORE_INDEX) != 0) /* DANGEROUS */
+         png_set_check_for_invalid_index(dp->read_pp, -1/*off completely*/);
+#  endif /* IGNORE_INDEX */
+
+   /* The png_read_png API requires us to make the info struct, but it does the
+    * call to png_read_info.
+    */
+   dp->ip = png_create_info_struct(dp->read_pp);
+   if (dp->ip == NULL)
+      png_error(dp->read_pp, "failed to create info struct");
+
+   /* Set the IO handling */
+   png_set_read_fn(dp->read_pp, dp, read_function);
+
+#  ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+      png_set_keep_unknown_chunks(dp->read_pp, PNG_HANDLE_CHUNK_ALWAYS, NULL,
+            0);
+#  endif /* HANDLE_AS_UNKNOWN */
+
+#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
+      /* Remove the user limits, if any */
+      png_set_user_limits(dp->read_pp, 0x7fffffff, 0x7fffffff);
+#  endif /* SET_USER_LIMITS */
+
+   /* Now read the PNG. */
+   start_timer(dp, PNGCP_TIME_READ);
+   png_read_png(dp->read_pp, dp->ip, 0U/*transforms*/, NULL/*params*/);
+   end_timer(dp, PNGCP_TIME_READ);
+   dp->w = png_get_image_width(dp->read_pp, dp->ip);
+   dp->h = png_get_image_height(dp->read_pp, dp->ip);
+   dp->ct = png_get_color_type(dp->read_pp, dp->ip);
+   dp->bpp = png_get_bit_depth(dp->read_pp, dp->ip) *
+             png_get_channels(dp->read_pp, dp->ip);
+   {
+      /* png_get_rowbytes should never return 0 because the value is set by the
+       * first call to png_set_IHDR, which should have happened by now, but just
+       * in case:
+       */
+      png_alloc_size_t rb = png_get_rowbytes(dp->read_pp, dp->ip);
+
+      if (rb == 0)
+         png_error(dp->read_pp, "invalid row byte count from libpng");
+
+      /* The size calc can overflow. */
+      if ((MAX_SIZE-dp->h)/rb < dp->h)
+         png_error(dp->read_pp, "image too large");
+
+      dp->size = rb * dp->h + dp->h/*filter byte*/;
+   }
+
+#ifdef FIX_INDEX
+   if (dp->ct == PNG_COLOR_TYPE_PALETTE && (dp->options & FIX_INDEX) != 0)
+   {
+      int max = png_get_palette_max(dp->read_pp, dp->ip);
+      png_colorp palette = NULL;
+      int num = -1;
+
+      if (png_get_PLTE(dp->read_pp, dp->ip, &palette, &num) != PNG_INFO_PLTE
+          || max < 0 || num <= 0 || palette == NULL)
+         display_log(dp, LIBPNG_ERROR, "invalid png_get_PLTE result");
+
+      if (max >= num)
+      {
+         /* 'Fix' the palette. */
+         int i;
+         png_color newpal[256];
+
+         for (i=0; i<num; ++i)
+            newpal[i] = palette[i];
+
+         /* Fill in any remainder with a warning color: */
+         for (; i<=max; ++i)
+         {
+            newpal[i].red = 0xbe;
+            newpal[i].green = 0xad;
+            newpal[i].blue = 0xed;
+         }
+
+         png_set_PLTE(dp->read_pp, dp->ip, newpal, i);
+      }
+   }
+#endif /* FIX_INDEX */
+
+   display_clean_read(dp);
+   dp->operation = "none";
+}
+
+static void
+display_start_write(struct display *dp, const char *filename)
+{
+   assert(dp->fp == NULL);
+
+   if ((dp->options & NOWRITE) != 0)
+      dp->output_file = "<no write>";
+
+   else
+   {
+      if (filename != NULL)
+      {
+         dp->output_file = filename;
+         dp->fp = fopen(filename, "wb");
+      }
+
+      else
+      {
+         dp->output_file = "<stdout>";
+         dp->fp = stdout;
+      }
+
+      if (dp->fp == NULL)
+         display_log(dp, USER_ERROR, "%s: file open failed (%s)",
+               dp->output_file, strerror(errno));
+   }
+}
+
+static void PNGCBAPI
+write_function(png_structp pp, png_bytep data, size_t size)
+{
+   struct display *dp = get_dp(pp);
+
+   /* The write fail is classed as a USER_ERROR, so --quiet does not turn it
+    * off, this seems more likely to be correct.
+    */
+   if (dp->fp == NULL || fwrite(data, size, 1U, dp->fp) == 1U)
+   {
+      dp->write_size += size;
+      if (dp->write_size < size || dp->write_size == MAX_SIZE)
+         png_error(pp, "IDAT size overflow");
+   }
+
+   else
+      display_log(dp, USER_ERROR, "%s: PNG file write failed (%s)",
+            dp->output_file, strerror(errno));
+}
+
+/* Compression option, 'method' is never set: there is no choice.
+ *
+ * IMPORTANT: the order of the entries in this macro determines the preference
+ * order when two different combos of two of these options produce an IDAT of
+ * the same size.  The logic here is to put the things that affect the decoding
+ * of the PNG image ahead of those that are relevant only to the encoding.
+ */
+#define SET_COMPRESSION\
+   SET(strategy, strategy);\
+   SET(windowBits, window_bits);\
+   SET(level, level);\
+   SET(memLevel, mem_level);
+
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
+static void
+search_compression(struct display *dp)
+{
+   /* Like set_compression below but use a more restricted search than 'all' */
+   int val;
+
+#  define SET(name, func) if (getsearchopts(dp, #name, &val))\
+      png_set_compression_ ## func(dp->write_pp, val);
+   SET_COMPRESSION
+#  undef SET
+}
+
+static void
+set_compression(struct display *dp)
+{
+   int val;
+
+#  define SET(name, func) if (getallopts(dp, #name, &val))\
+      png_set_compression_ ## func(dp->write_pp, val);
+   SET_COMPRESSION
+#  undef SET
+}
+
+#ifdef PNG_SW_COMPRESS_level /* 1.7.0+ */
+static void
+set_ICC_profile_compression(struct display *dp)
+{
+   int val;
+
+#  define SET(name, func) if (getallopts(dp, "ICC-profile-" #name, &val))\
+      png_set_ICC_profile_compression_ ## func(dp->write_pp, val);
+   SET_COMPRESSION
+#  undef SET
+}
+#else
+#  define set_ICC_profile_compression(dp) ((void)0)
+#endif
+#else
+#  define search_compression(dp) ((void)0)
+#  define set_compression(dp) ((void)0)
+#  define set_ICC_profile_compression(dp) ((void)0)
+#endif /* WRITE_CUSTOMIZE_COMPRESSION */
+
+#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
+static void
+set_text_compression(struct display *dp)
+{
+   int val;
+
+#  define SET(name, func) if (getallopts(dp, "text-" #name, &val))\
+      png_set_text_compression_ ## func(dp->write_pp, val);
+   SET_COMPRESSION
+#  undef SET
+}
+#else
+#  define set_text_compression(dp) ((void)0)
+#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
+
+static void
+write_png(struct display *dp, const char *destname)
+{
+   display_clean_write(dp); /* safety */
+   display_start_write(dp, destname);
+
+   dp->write_pp = png_create_write_struct(PNG_LIBPNG_VER_STRING, dp,
+      display_error, display_warning);
+
+   if (dp->write_pp == NULL)
+      display_log(dp, LIBPNG_ERROR, "failed to create write png_struct");
+
+#  ifdef PNG_BENIGN_ERRORS_SUPPORTED
+      png_set_benign_errors(dp->write_pp, 1/*allowed*/);
+#  endif /* BENIGN_ERRORS */
+
+   png_set_write_fn(dp->write_pp, dp, write_function, NULL/*flush*/);
+
+#ifdef IGNORE_INDEX
+   if ((dp->options & IGNORE_INDEX) != 0) /* DANGEROUS */
+      png_set_check_for_invalid_index(dp->write_pp, -1/*off completely*/);
+#endif /* IGNORE_INDEX */
+
+   /* Restore the text chunks when using libpng 1.6 or less; this is a macro
+    * which expands to nothing in 1.7+  In earlier versions it tests
+    * dp->text_stashed, which is only set (below) *after* the first write.
+    */
+   text_restore(dp);
+
+#  ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+      png_set_keep_unknown_chunks(dp->write_pp, PNG_HANDLE_CHUNK_ALWAYS, NULL,
+            0);
+#  endif /* HANDLE_AS_UNKNOWN */
+
+#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
+      /* Remove the user limits, if any */
+      png_set_user_limits(dp->write_pp, 0x7fffffff, 0x7fffffff);
+#  endif
+
+   /* OPTION HANDLING */
+   /* compression outputs, IDAT and zTXt/iTXt: */
+   dp->tsp = dp->nsp;
+   dp->nsp = dp->csp = 0;
+#  ifdef PNG_SW_COMPRESS_png_level
+      {
+         int val;
+
+         /* This sets everything, but then the following options just override
+          * the specific settings for ICC profiles and text.
+          */
+         if (getallopts(dp, "compression", &val))
+            png_set_compression(dp->write_pp, val);
+
+         if (getallopts(dp, "ICC-profile-compression", &val))
+            png_set_ICC_profile_compression(dp->write_pp, val);
+
+         if (getallopts(dp, "text-compression", &val))
+            png_set_text_compression(dp->write_pp, val);
+      }
+#  endif /* png_level support */
+   if (dp->options & SEARCH)
+      search_compression(dp);
+   else
+      set_compression(dp);
+   set_ICC_profile_compression(dp);
+   set_text_compression(dp);
+
+   {
+      int val;
+
+      /* The permitted range is 1..0x7FFFFFFF, so the cast is safe */
+      if (get_option(dp, "IDAT-size", &val))
+         png_set_IDAT_size(dp->write_pp, val);
+   }
+
+   /* filter handling */
+#  ifdef PNG_WRITE_FILTER_SUPPORTED
+      {
+         int val;
+
+         if (get_option(dp, "filter", &val))
+            png_set_filter(dp->write_pp, PNG_FILTER_TYPE_BASE, val);
+      }
+#  endif /* WRITE_FILTER */
+
+   /* This just uses the 'read' info_struct directly, it contains the image. */
+   dp->write_size = 0U;
+   start_timer(dp, PNGCP_TIME_WRITE);
+   png_write_png(dp->write_pp, dp->ip, 0U/*transforms*/, NULL/*params*/);
+   end_timer(dp, PNGCP_TIME_WRITE);
+
+   /* Make sure the file was written ok: */
+   if (dp->fp != NULL)
+   {
+      FILE *fp = dp->fp;
+      dp->fp = NULL;
+      if (fclose(fp))
+         display_log(dp, APP_ERROR, "%s: write failed (%s)",
+               destname == NULL ? "stdout" : destname, strerror(errno));
+   }
+
+   /* Clean it on the way out - if control returns to the caller then the
+    * written_file contains the required data.
+    */
+   display_clean_write(dp);
+   dp->operation = "none";
+}
+
+static void
+set_windowBits_hi(struct display *dp)
+{
+   /* windowBits is in the range 8..15 but zlib maps '8' to '9' so it is only
+    * worth using if the data size is 256 byte or less.
+    */
+   int wb = MAX_WBITS; /* for large images */
+   int i = VLSIZE(windowBits_IDAT);
+
+   while (wb > 8 && dp->size <= 1U<<(wb-1)) --wb;
+
+   while (--i >= 0) if (VLNAME(windowBits_IDAT)[i].name == range_hi) break;
+
+   assert(i > 1); /* vl_windowBits_IDAT always has a RANGE() */
+   VLNAME(windowBits_IDAT)[i].value = wb;
+
+   assert(VLNAME(windowBits_IDAT)[--i].name == range_lo);
+   VLNAME(windowBits_IDAT)[i].value = wb > 8 ? 9 : 8;
+
+   /* If wb == 8 then any search has been restricted to just one windowBits
+    * entry.  Record that here to avoid producing a spurious app-level warning
+    * above.
+    */
+   if (wb == 8)
+      dp->min_windowBits = OPTIND(dp, windowBits);
+}
+
+static int
+better_options(const struct display *dp)
+{
+   /* Are these options better than the best found so far?  Normally the
+    * options are tested in preference order, best first, however when doing a
+    * search operation on a range the range values are tested out of order.  In
+    * that case preferable options will get tested later.
+    *
+    * This function looks through the stack from the bottom up looking for an
+    * option that does not match the current best value.  When it finds one it
+    * checks to see if it is more or less desirable and returns true or false
+    * as appropriate.
+    *
+    * Notice that this means that the order options are pushed onto the stack
+    * conveys a priority; lower/earlier options are more important than later
+    * ones.
+    */
+   unsigned int sp;
+
+   for (sp=0; sp<dp->csp; ++sp)
+   {
+      int c = compare_option(dp, sp);
+
+      if (c < 0)
+         return 0; /* worse */
+
+      else if (c > 0)
+         return 1; /* better */
+   }
+
+   assert(0 && "unreached");
+}
+
+static void
+print_search_results(struct display *dp)
+{
+   assert(dp->filename != NULL);
+   printf("%s [%ld x %ld %d bpp %s, %lu bytes] %lu -> %lu with '%s'\n",
+      dp->filename, (unsigned long)dp->w, (unsigned long)dp->h, dp->bpp,
+      cts(dp->ct), (unsigned long)dp->size, (unsigned long)dp->read_size,
+      (unsigned long)dp->best_size, dp->best);
+   fflush(stdout);
+}
+
+static void
+log_search(struct display *dp, unsigned int log_depth)
+{
+   /* Log, and reset, the search so far: */
+   if (dp->nsp/*next entry to change*/ <= log_depth)
+   {
+      print_search_results(dp);
+      /* Start again with this entry: */
+      dp->best_size = MAX_SIZE;
+   }
+}
+
+static void
+cp_one_file(struct display *dp, const char *filename, const char *destname)
+{
+   unsigned int log_depth;
+
+   dp->filename = filename;
+   dp->operation = "read";
+   dp->no_warnings = 0;
+
+   /* Read it then write it: */
+   if (filename != NULL && access(filename, R_OK) != 0)
+      display_log(dp, USER_ERROR, "%s: invalid file name (%s)",
+            filename, strerror(errno));
+
+   read_png(dp, filename);
+
+   /* But 'destname' may be a directory. */
+   dp->operation = "write";
+
+   /* Limit the upper end of the windowBits range for this file */
+   set_windowBits_hi(dp);
+
+   /* For logging, depth to log: */
+   {
+      int val;
+
+      if (get_option(dp, "log-depth", &val) && val >= 0)
+         log_depth = (unsigned int)/*SAFE*/val;
+
+      else
+         log_depth = 0U;
+   }
+
+   if (destname != NULL) /* else stdout */
+   {
+      if (isdir(dp, destname))
+      {
+         makename(dp, destname, filename);
+         destname = dp->namebuf;
+      }
+
+      else if (access(destname, W_OK) != 0 && errno != ENOENT)
+         display_log(dp, USER_ERROR, "%s: invalid output name (%s)", destname,
+               strerror(errno));
+   }
+
+   dp->nsp = 0;
+   dp->curr[0] = 0; /* acts as a flag for the caller */
+   dp->opt_string_start = 0;
+   dp->best[0] = 0; /* safety */
+   dp->best_size = MAX_SIZE;
+   write_png(dp, destname);
+
+   /* Initialize the 'best' fields: */
+   strcpy(dp->best, dp->curr);
+   dp->best_size = dp->write_size;
+
+   if (dp->nsp > 0) /* iterating over lists */
+   {
+      char *tmpname, tmpbuf[(sizeof dp->namebuf) + 4];
+      assert(dp->curr[0] == ' ' && dp->tsp > 0);
+
+      /* Cancel warnings on subsequent writes */
+      log_search(dp, log_depth);
+      dp->no_warnings = 1;
+
+      /* Make a temporary name for the subsequent tests: */
+      if (destname != NULL)
+      {
+         strcpy(tmpbuf, destname);
+         strcat(tmpbuf, ".tmp"); /* space for .tmp allocated above */
+         tmpname = tmpbuf;
+      }
+
+      else
+         tmpname = NULL; /* stdout */
+
+      /* Loop to find the best option. */
+      do
+      {
+         write_png(dp, tmpname);
+
+         /* And compare the sizes (the write function makes sure write_size
+          * doesn't overflow.)
+          */
+         assert(dp->csp > 0);
+
+         if (dp->write_size < dp->best_size ||
+             (dp->write_size == dp->best_size && better_options(dp)))
+         {
+            if (destname != NULL && rename(tmpname, destname) != 0)
+               display_log(dp, APP_ERROR, "rename %s %s failed (%s)", tmpname,
+                     destname, strerror(errno));
+
+            strcpy(dp->best, dp->curr);
+            dp->best_size = dp->write_size;
+         }
+
+         else if (tmpname != NULL && unlink(tmpname) != 0)
+            display_log(dp, APP_WARNING, "unlink %s failed (%s)", tmpname,
+                  strerror(errno));
+
+         log_search(dp, log_depth);
+      }
+      while (dp->nsp > 0);
+
+      /* Do this for the 'sizes' option so that it reports the correct size. */
+      dp->write_size = dp->best_size;
+   }
+}
+
+static int
+cppng(struct display *dp, const char *file, const char *gv dest)
+   /* Exists solely to isolate the setjmp clobbers which some versions of GCC
+    * erroneously generate.
+    */
+{
+   int ret = setjmp(dp->error_return);
+
+   if (ret == 0)
+   {
+      dp->errset = 1;
+      cp_one_file(dp, file, dest);
+      dp->errset = 0;
+      return 0;
+   }
+
+   else
+   {
+      dp->errset = 0;
+
+      if (ret < ERRORS) /* shouldn't longjmp on warnings */
+         display_log(dp, INTERNAL_ERROR, "unexpected return code %d", ret);
+
+      return ret;
+   }
+}
+
+int
+main(int argc, char **argv)
+{
+   /* For each file on the command line test it with a range of transforms */
+   int option_end;
+   struct display d;
+
+   display_init(&d);
+
+   d.operation = "options";
+   for (option_end = 1;
+        option_end < argc && opt_check(&d, argv[option_end]);
+        ++option_end)
+   {
+   }
+
+   /* Do a quick check on the directory target case; when there are more than
+    * two arguments the last one must be a directory.
+    */
+   if (!(d.options & NOWRITE) && option_end+2 < argc && !checkdir(argv[argc-1]))
+   {
+      fprintf(stderr,
+            "pngcp: %s: directory required with more than two arguments\n",
+            argv[argc-1]);
+      return 99;
+   }
+
+   {
+      int errors = 0;
+      int i = option_end;
+
+      /* Do this at least once; if there are no arguments stdin/stdout are used.
+       */
+      d.operation = "files";
+      do
+      {
+         const char *infile = NULL;
+         const char *outfile = NULL;
+         int ret;
+
+         if (i < argc)
+         {
+            infile = argv[i++];
+            if (!(d.options & NOWRITE) && i < argc)
+               outfile = argv[argc-1];
+         }
+
+         ret = cppng(&d, infile, outfile);
+
+         if (ret)
+         {
+            if (ret > QUIET) /* abort on user or internal error */
+               return 99;
+
+            /* An error: the output is meaningless */
+         }
+
+         else if (d.best[0] != 0)
+         {
+            /* This result may already have been output, in which case best_size
+             * has been reset.
+             */
+            if (d.best_size < MAX_SIZE)
+               print_search_results(&d);
+         }
+
+         else if (d.options & SIZES)
+         {
+            printf("%s [%ld x %ld %d bpp %s, %lu bytes] %lu -> %lu [0x%lx]\n",
+                  infile, (unsigned long)d.w, (unsigned long)d.h, d.bpp,
+                  cts(d.ct), (unsigned long)d.size, (unsigned long)d.read_size,
+                  (unsigned long)d.write_size, (unsigned long)d.results);
+            fflush(stdout);
+         }
+
+         /* Here on any return, including failures, except user/internal issues
+          */
+         {
+            int pass = (d.options & STRICT) ?
+               RESULT_STRICT(d.results) : RESULT_RELAXED(d.results);
+
+            if (!pass)
+               ++errors;
+
+            if (d.options & LOG)
+            {
+               int j;
+
+               printf("%s: pngcp", pass ? "PASS" : "FAIL");
+
+               for (j=1; j<option_end; ++j)
+                  printf(" %s", argv[j]);
+
+               if (infile != NULL)
+                  printf(" %s", infile);
+
+#              ifdef PNG_PNGCP_TIMING_SUPPORTED
+                  /* When logging output the files for each file, if enabled. */
+                  if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_READ) != 0)
+                     print_time(" read", d.read_time);
+
+                  if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_WRITE) != 0)
+                     print_time(" write", d.write_time);
+#              endif /* PNGCP_TIMING */
+
+               printf("\n");
+               fflush(stdout);
+            }
+         }
+
+         display_clean(&d);
+      }
+      while (i+!(d.options & NOWRITE) < argc);
+         /* I.e. for write cases after the first time through the loop require
+          * there to be at least two arguments left and for the last one to be a
+          * directory (this was checked above).
+          */
+
+      /* Release allocated memory */
+      display_destroy(&d);
+
+#     ifdef PNG_PNGCP_TIMING_SUPPORTED
+         {
+            int output = 0;
+
+            if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_READ) != 0)
+               print_time("read", d.read_time_total), output = 1;
+
+            if ((d.value[OPTIND(&d,time)] & PNGCP_TIME_WRITE) != 0)
+            {
+               if (output) putchar(' ');
+               print_time("write", d.write_time_total);
+               output = 1;
+            }
+
+            if (output) putchar('\n');
+         }
+#     endif /* PNGCP_TIMING */
+
+      return errors != 0;
+   }
+}
+#else /* !READ_PNG || !WRITE_PNG */
+int
+main(void)
+{
+   fprintf(stderr, "pngcp: no support for png_read/write_image\n");
+   return 77;
+}
+#endif /* !READ_PNG || !WRITE_PNG */
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/pngfix.c b/ap/lib/libpng/libpng-1.6.37/contrib/tools/pngfix.c
new file mode 100755
index 0000000..2fa5d13
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/pngfix.c
@@ -0,0 +1,4049 @@
+/* pngfix.c
+ *
+ * Last changed in libpng 1.6.31 [July 27, 2017]
+ * Copyright (c) 2014-2017 John Cunningham Bowler
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * Tool to check and fix the zlib inflate 'too far back' problem.
+ * See the usage message for more information.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <errno.h>
+#include <assert.h>
+
+#define implies(x,y) assert(!(x) || (y))
+
+#ifdef __GNUC__
+   /* This is used to fix the error:
+    *
+    * pngfix.c:
+    * In function 'zlib_advance':
+    * pngfix.c:181:13: error: assuming signed overflow does not
+    *   occur when simplifying conditional to constant [-Werror=strict-overflow]
+    */
+#  define FIX_GCC volatile
+#else
+#  define FIX_GCC
+#endif
+
+#define PROGRAM_NAME "pngfix"
+
+/* Define the following to use this program against your installed libpng,
+ * rather than the one being built here:
+ */
+#ifdef PNG_FREESTANDING_TESTS
+#  include <png.h>
+#else
+#  include "../../png.h"
+#endif
+
+#if PNG_LIBPNG_VER < 10603 /* 1.6.3 */
+#  error "pngfix will not work with libpng prior to 1.6.3"
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+#include <setjmp.h>
+
+#if defined(PNG_READ_SUPPORTED) && defined(PNG_EASY_ACCESS_SUPPORTED) &&\
+   (defined(PNG_READ_DEINTERLACE_SUPPORTED) ||\
+    defined(PNG_READ_INTERLACING_SUPPORTED))
+
+/* zlib.h defines the structure z_stream, an instance of which is included
+ * in this structure and is required for decompressing the LZ compressed
+ * data in PNG files.
+ */
+#ifndef ZLIB_CONST
+   /* We must ensure that zlib uses 'const' in declarations. */
+#  define ZLIB_CONST
+#endif
+#include <zlib.h>
+#ifdef const
+   /* zlib.h sometimes #defines const to nothing, undo this. */
+#  undef const
+#endif
+
+/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility
+ * with older builds.
+ */
+#if ZLIB_VERNUM < 0x1260
+#  define PNGZ_MSG_CAST(s) constcast(char*,s)
+#  define PNGZ_INPUT_CAST(b) constcast(png_bytep,b)
+#else
+#  define PNGZ_MSG_CAST(s) (s)
+#  define PNGZ_INPUT_CAST(b) (b)
+#endif
+
+#ifndef PNG_MAXIMUM_INFLATE_WINDOW
+#  error "pngfix not supported in this libpng version"
+#endif
+
+#if ZLIB_VERNUM >= 0x1240
+
+/* Copied from pngpriv.h */
+#ifdef __cplusplus
+#  define voidcast(type, value) static_cast<type>(value)
+#  define constcast(type, value) const_cast<type>(value)
+#  define aligncast(type, value) \
+   static_cast<type>(static_cast<void*>(value))
+#  define aligncastconst(type, value) \
+   static_cast<type>(static_cast<const void*>(value))
+#else
+#  define voidcast(type, value) (value)
+#  define constcast(type, value) ((type)(value))
+#  define aligncast(type, value) ((void*)(value))
+#  define aligncastconst(type, value) ((const void*)(value))
+#endif /* __cplusplus */
+
+#if PNG_LIBPNG_VER < 10700
+/* Chunk tags (copied from pngpriv.h) */
+#define PNG_32b(b,s) ((png_uint_32)(b) << (s))
+#define PNG_U32(b1,b2,b3,b4) \
+   (PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0))
+
+/* Constants for known chunk types. */
+#define png_IDAT PNG_U32( 73,  68,  65,  84)
+#define png_IEND PNG_U32( 73,  69,  78,  68)
+#define png_IHDR PNG_U32( 73,  72,  68,  82)
+#define png_PLTE PNG_U32( 80,  76,  84,  69)
+#define png_bKGD PNG_U32( 98,  75,  71,  68)
+#define png_cHRM PNG_U32( 99,  72,  82,  77)
+#define png_fRAc PNG_U32(102,  82,  65,  99) /* registered, not defined */
+#define png_gAMA PNG_U32(103,  65,  77,  65)
+#define png_gIFg PNG_U32(103,  73,  70, 103)
+#define png_gIFt PNG_U32(103,  73,  70, 116) /* deprecated */
+#define png_gIFx PNG_U32(103,  73,  70, 120)
+#define png_hIST PNG_U32(104,  73,  83,  84)
+#define png_iCCP PNG_U32(105,  67,  67,  80)
+#define png_iTXt PNG_U32(105,  84,  88, 116)
+#define png_oFFs PNG_U32(111,  70,  70, 115)
+#define png_pCAL PNG_U32(112,  67,  65,  76)
+#define png_pHYs PNG_U32(112,  72,  89, 115)
+#define png_sBIT PNG_U32(115,  66,  73,  84)
+#define png_sCAL PNG_U32(115,  67,  65,  76)
+#define png_sPLT PNG_U32(115,  80,  76,  84)
+#define png_sRGB PNG_U32(115,  82,  71,  66)
+#define png_sTER PNG_U32(115,  84,  69,  82)
+#define png_tEXt PNG_U32(116,  69,  88, 116)
+#define png_tIME PNG_U32(116,  73,  77,  69)
+#define png_tRNS PNG_U32(116,  82,  78,  83)
+#define png_zTXt PNG_U32(122,  84,  88, 116)
+#endif
+
+/* The 8-byte signature as a pair of 32-bit quantities */
+#define sig1 PNG_U32(137,  80,  78,  71)
+#define sig2 PNG_U32( 13,  10,  26,  10)
+
+/* Is the chunk critical? */
+#define CRITICAL(chunk) (((chunk) & PNG_U32(32,0,0,0)) == 0)
+
+/* Is it safe to copy? */
+#define SAFE_TO_COPY(chunk) (((chunk) & PNG_U32(0,0,0,32)) != 0)
+
+/* Fix ups for builds with limited read support */
+#ifndef PNG_ERROR_TEXT_SUPPORTED
+#  define png_error(a,b) png_err(a)
+#endif
+
+/********************************* UTILITIES **********************************/
+/* UNREACHED is a value to cause an assert to fail. Because of the way the
+ * assert macro is written the string "UNREACHED" is produced in the error
+ * message.
+ */
+#define UNREACHED 0
+
+/* 80-bit number handling - a PNG image can be up to (2^31-1)x(2^31-1) 8-byte
+ * (16-bit RGBA) pixels in size; that's less than 2^65 bytes or 2^68 bits, so
+ * arithmetic of 80-bit numbers is sufficient.  This representation uses an
+ * arbitrary length array of png_uint_16 digits (0..65535).  The representation
+ * is little endian.
+ *
+ * The arithmetic functions take zero to two uarb values together with the
+ * number of digits in those values and write the result to the given uarb
+ * (always the first argument) returning the number of digits in the result.
+ * If the result is negative the return value is also negative (this would
+ * normally be an error).
+ */
+typedef png_uint_16  udigit; /* A 'unum' is an array of these */
+typedef png_uint_16p uarb;
+typedef png_const_uint_16p uarbc;
+
+#define UDIGITS(unum) ((sizeof unum)/(sizeof (udigit))
+   /* IMPORTANT: only apply this to an array, applied to a pointer the result
+    * will typically be '2', which is not useful.
+    */
+
+static int
+uarb_set(uarb result, png_alloc_size_t val)
+   /* Set (initialize) 'result' to 'val'.  The size required for 'result' must
+    * be determined by the caller from a knowledge of the maximum for 'val'.
+    */
+{
+   int ndigits = 0;
+
+   while (val > 0)
+   {
+      result[ndigits++] = (png_uint_16)(val & 0xffff);
+      val >>= 16;
+   }
+
+   return ndigits;
+}
+
+static int
+uarb_copy(uarb to, uarb from, int idigits)
+   /* Copy a uarb, may reduce the digit count */
+{
+   int d, odigits;
+
+   for (d=odigits=0; d<idigits; ++d)
+      if ((to[d] = from[d]) != 0)
+         odigits = d+1;
+
+   return odigits;
+}
+
+static int
+uarb_inc(uarb num, int in_digits, png_int_32 add)
+   /* This is a signed 32-bit add, except that to avoid overflow the value added
+    * or subtracted must be no more than 2^31-65536.  A negative result
+    * indicates a negative number (which is an error below).  The size of
+    * 'num' should be max(in_digits+1,2) for arbitrary 'add' but can be just
+    * in_digits+1 if add is known to be in the range -65535..65535.
+    */
+{
+   FIX_GCC int out_digits = 0;
+
+   while (out_digits < in_digits)
+   {
+      add += num[out_digits];
+      num[out_digits++] = (png_uint_16)(add & 0xffff);
+      add >>= 16;
+   }
+
+   while (add != 0 && add != (-1))
+   {
+      num[out_digits++] = (png_uint_16)(add & 0xffff);
+      add >>= 16;
+   }
+
+   if (add == 0)
+   {
+      while (out_digits > 0 && num[out_digits-1] == 0)
+         --out_digits;
+      return out_digits; /* may be 0 */
+   }
+
+   else /* negative result */
+   {
+      while (out_digits > 1 && num[out_digits-1] == 0xffff)
+         --out_digits;
+
+      return -out_digits;
+   }
+}
+
+static int
+uarb_add32(uarb num, int in_digits, png_uint_32 add)
+   /* As above but this works with any 32-bit value and only does 'add' */
+{
+   if (in_digits > 0)
+   {
+      in_digits = uarb_inc(num, in_digits, add & 0xffff);
+      return uarb_inc(num+1, in_digits-1, add >> 16)+1;
+   }
+
+   return uarb_set(num, add);
+}
+
+static int
+uarb_mult_digit(uarb acc, int a_digits, uarb num, FIX_GCC int n_digits,
+   png_uint_16 val)
+   /* Primitive one-digit multiply - 'val' must be 0..65535. Note that this
+    * primitive is a multiply and accumulate - the result of *num * val is added
+    * to *acc.
+    *
+    * This is a one-digit multiply, so the product may be up to one digit longer
+    * than 'num', however the add to 'acc' means that the caller must ensure
+    * that 'acc' is at least one digit longer than this *and* at least one digit
+    * longer than the current length of 'acc'.  (Or the caller must otherwise
+    * ensure 'adigits' is adequate from knowledge of the values.)
+    */
+{
+   /* The digits in *acc, *num and val are in the range 0..65535, so the
+    * result below is at most (65535*65535)+2*65635 = 65535*(65535+2), which is
+    * exactly 0xffffffff.
+    */
+   if (val > 0 && n_digits > 0) /* Else the product is 0 */
+   {
+      png_uint_32 carry = 0;
+      int out_digits = 0;
+
+      while (out_digits < n_digits || carry > 0)
+      {
+         if (out_digits < a_digits)
+            carry += acc[out_digits];
+
+         if (out_digits < n_digits)
+            carry += (png_uint_32)num[out_digits] * val;
+
+         acc[out_digits++] = (png_uint_16)(carry & 0xffff);
+         carry >>= 16;
+      }
+
+      /* So carry is 0 and all the input digits have been consumed. This means
+       * that it is possible to skip any remaining digits in acc.
+       */
+      if (out_digits > a_digits)
+         return out_digits;
+   }
+
+   return a_digits;
+}
+
+static int
+uarb_mult32(uarb acc, int a_digits, uarb num, int n_digits, png_uint_32 val)
+   /* calculate acc += num * val, 'val' may be any 32-bit value, 'acc' and 'num'
+    * may be any value, returns the number of digits in 'acc'.
+    */
+{
+   if (n_digits > 0 && val > 0)
+   {
+      a_digits = uarb_mult_digit(acc, a_digits, num, n_digits,
+         (png_uint_16)(val & 0xffff));
+
+      val >>= 16;
+      if (val > 0)
+         a_digits = uarb_mult_digit(acc+1, a_digits-1, num, n_digits,
+            (png_uint_16)val) + 1;
+
+      /* Because n_digits and val are >0 the following must be true: */
+      assert(a_digits > 0);
+   }
+
+   return a_digits;
+}
+
+static int
+uarb_shift(uarb inout, int ndigits, unsigned int right_shift)
+   /* Shift inout right by right_shift bits, right_shift must be in the range
+    * 1..15
+    */
+{
+   FIX_GCC int i = ndigits;
+   png_uint_16 carry = 0;
+
+   assert(right_shift >= 1 && right_shift <= 15);
+
+   while (--i >= 0)
+   {
+      png_uint_16 temp = (png_uint_16)(carry | (inout[i] >> right_shift));
+
+      /* Bottom bits to top bits of carry */
+      carry = (png_uint_16)((inout[i] << (16-right_shift)) & 0xffff);
+
+      inout[i] = temp;
+
+      /* The shift may reduce ndigits */
+      if (i == ndigits-1 && temp == 0)
+         ndigits = i;
+   }
+
+   return ndigits;
+}
+
+static int
+uarb_cmp(uarb a, int adigits, uarb b, int bdigits)
+   /* Return -1/0/+1 according as a<b/a==b/a>b */
+{
+   if (adigits < bdigits)
+      return -1;
+
+   if (adigits > bdigits)
+      return 1;
+
+   while (adigits-- > 0)
+      if (a[adigits] < b[adigits])
+         return -1;
+
+      else if (a[adigits] > b[adigits])
+         return 1;
+
+   return 0;
+}
+
+#if 0 /*UNUSED*/
+static int
+uarb_eq32(uarb num, int digits, png_uint_32 val)
+   /* Return true if the uarb is equal to 'val' */
+{
+   switch (digits)
+   {
+      case 0:  return val == 0;
+      case 1:  return val == num[0];
+      case 2:  return (val & 0xffff) == num[0] && (val >> 16) == num[1];
+      default: return 0;
+   }
+}
+#endif
+
+static void
+uarb_printx(uarb num, int digits, FILE *out)
+   /* Print 'num' as a hexadecimal number (easier than decimal!) */
+{
+   while (digits > 0)
+      if (num[--digits] > 0)
+      {
+         fprintf(out, "0x%x", num[digits]);
+
+         while (digits > 0)
+            fprintf(out, "%.4x", num[--digits]);
+      }
+
+      else if (digits == 0) /* the number is 0 */
+         fputs("0x0", out);
+}
+
+static void
+uarb_print(uarb num, int digits, FILE *out)
+   /* Prints 'num' as a decimal if it will fit in an unsigned long, else as a
+    * hexadecimal number.  Notice that the results vary for images over 4GByte
+    * in a system dependent way, and the hexadecimal form doesn't work very well
+    * in awk script input.
+    *
+    *
+    * TODO: write uarb_div10
+    */
+{
+   if (digits * sizeof (udigit) > sizeof (unsigned long))
+      uarb_printx(num, digits, out);
+
+   else
+   {
+      unsigned long n = 0;
+
+      while (digits > 0)
+         n = (n << 16) + num[--digits];
+
+      fprintf(out, "%lu", n);
+   }
+}
+
+/* Generate random bytes.  This uses a boring repeatable algorithm and it
+ * is implemented here so that it gives the same set of numbers on every
+ * architecture.  It's a linear congruential generator (Knuth or Sedgewick
+ * "Algorithms") but it comes from the 'feedback taps' table in Horowitz and
+ * Hill, "The Art of Electronics" (Pseudo-Random Bit Sequences and Noise
+ * Generation.)
+ *
+ * (Copied from contrib/libtests/pngvalid.c)
+ */
+static void
+make_random_bytes(png_uint_32* seed, void* pv, size_t size)
+{
+   png_uint_32 u0 = seed[0], u1 = seed[1];
+   png_bytep bytes = voidcast(png_bytep, pv);
+
+   /* There are thirty-three bits; the next bit in the sequence is bit-33 XOR
+    * bit-20.  The top 1 bit is in u1, the bottom 32 are in u0.
+    */
+   size_t i;
+   for (i=0; i<size; ++i)
+   {
+      /* First generate 8 new bits then shift them in at the end. */
+      png_uint_32 u = ((u0 >> (20-8)) ^ ((u1 << 7) | (u0 >> (32-7)))) & 0xff;
+      u1 <<= 8;
+      u1 |= u0 >> 24;
+      u0 <<= 8;
+      u0 |= u;
+      *bytes++ = (png_byte)u;
+   }
+
+   seed[0] = u0;
+   seed[1] = u1;
+}
+
+/* Clear an object to a random value. */
+static void
+clear(void *pv, size_t size)
+{
+   static png_uint_32 clear_seed[2] = { 0x12345678, 0x9abcdef0 };
+   make_random_bytes(clear_seed, pv, size);
+}
+
+#define CLEAR(object) clear(&(object), sizeof (object))
+
+/* Copied from unreleased 1.7 code.
+ *
+ * CRC checking uses a local pre-built implementation of the Ethernet CRC32.
+ * This is to avoid a function call to the zlib DLL and to optimize the
+ * byte-by-byte case.
+ */
+static png_uint_32 crc_table[256] =
+{
+   0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+   0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+   0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+   0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+   0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+   0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+   0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+   0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+   0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+   0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+   0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+   0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+   0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+   0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+   0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+   0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+   0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+   0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+   0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+   0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+   0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+   0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+   0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+   0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+   0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+   0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+   0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+   0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+   0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+   0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+   0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+   0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+   0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+   0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+   0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+   0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+   0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+   0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+   0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+   0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+   0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+   0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+   0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+   0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+   0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+   0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+   0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+   0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+   0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+   0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+   0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+   0x2d02ef8d
+};
+
+/* The CRC calculated here *IS* conditioned, the corresponding value used by
+ * zlib and the result value is obtained by XORing with CRC_INIT, which is also
+ * the first value that must be passed in (for the first byte) to crc_one_byte.
+ */
+#define CRC_INIT 0xffffffff
+
+static png_uint_32
+crc_one_byte(png_uint_32 crc, int b)
+{
+   return crc_table[(crc ^ b) & 0xff] ^ (crc >> 8);
+}
+
+static png_uint_32
+crc_init_4(png_uint_32 value)
+{
+   /* This is an alternative to the algorithm used in zlib, which requires four
+    * separate tables to parallelize the four byte operations, it only works for
+    * a CRC of the first four bytes of the stream, but this is what happens in
+    * the parser below where length+chunk-name is read and chunk-name used to
+    * initialize the CRC.  Notice that the calculation here avoids repeated
+    * conditioning (xor with 0xffffffff) by storing the conditioned value.
+    */
+   png_uint_32 crc = crc_table[(~value >> 24)] ^ 0xffffff;
+
+   crc = crc_table[(crc ^ (value >> 16)) & 0xff] ^ (crc >> 8);
+   crc = crc_table[(crc ^ (value >> 8)) & 0xff] ^ (crc >> 8);
+   return crc_table[(crc ^ value) & 0xff] ^ (crc >> 8);
+}
+
+static int
+chunk_type_valid(png_uint_32 c)
+   /* Bit whacking approach to chunk name validation that is intended to avoid
+    * branches.  The cost is that it uses a lot of 32-bit constants, which might
+    * be bad on some architectures.
+    */
+{
+   png_uint_32 t;
+
+   /* Remove bit 5 from all but the reserved byte; this means every
+    * 8-bit unit must be in the range 65-90 to be valid.  So bit 5
+    * must be zero, bit 6 must be set and bit 7 zero.
+    */
+   c &= ~PNG_U32(32,32,0,32);
+   t = (c & ~0x1f1f1f1f) ^ 0x40404040;
+
+   /* Subtract 65 for each 8-bit quantity, this must not overflow
+    * and each byte must then be in the range 0-25.
+    */
+   c -= PNG_U32(65,65,65,65);
+   t |=c ;
+
+   /* Subtract 26, handling the overflow which should set the top
+    * three bits of each byte.
+    */
+   c -= PNG_U32(25,25,25,26);
+   t |= ~c;
+
+   return (t & 0xe0e0e0e0) == 0;
+}
+
+/**************************** CONTROL INFORMATION *****************************/
+
+/* Information about a sequence of IDAT chunks, the chunks have been re-synced
+ * using sync_stream below and the new lengths are recorded here.  Because the
+ * number of chunks is unlimited this is handled using a linked list of these
+ * structures.
+ */
+struct IDAT_list
+{
+   struct IDAT_list *next;     /* Linked list */
+   unsigned int      length;   /* Actual length of the array below */
+   unsigned int      count;    /* Number of entries that are valid */
+#     define IDAT_INIT_LENGTH 16
+   png_uint_32       lengths[IDAT_INIT_LENGTH];
+};
+
+static void
+IDAT_list_init(struct IDAT_list *list)
+{
+   CLEAR(*list);
+
+   list->next = NULL;
+   list->length = IDAT_INIT_LENGTH;
+}
+
+static size_t
+IDAT_list_size(struct IDAT_list *list, unsigned int length)
+   /* Return the size in bytes of an IDAT_list of the given length. */
+{
+   if (list != NULL)
+      length = list->length;
+
+   return sizeof *list - sizeof list->lengths +
+      length * sizeof list->lengths[0];
+}
+
+static void
+IDAT_list_end(struct IDAT_list *IDAT_list)
+{
+   struct IDAT_list *list = IDAT_list->next;
+
+   CLEAR(*IDAT_list);
+
+   while (list != NULL)
+   {
+      struct IDAT_list *next = list->next;
+
+      clear(list, IDAT_list_size(list, 0));
+      free(list);
+      list = next;
+   }
+}
+
+static struct IDAT_list *
+IDAT_list_extend(struct IDAT_list *tail)
+{
+   /* Use the previous cached value if available. */
+   struct IDAT_list *next = tail->next;
+
+   if (next == NULL)
+   {
+      /* Insert a new, malloc'ed, block of IDAT information buffers, this
+       * one twice as large as the previous one:
+       */
+      unsigned int length = 2 * tail->length;
+
+      if (length < tail->length) /* arithmetic overflow */
+         length = tail->length;
+
+      next = voidcast(IDAT_list*, malloc(IDAT_list_size(NULL, length)));
+      CLEAR(*next);
+
+      /* The caller must handle this: */
+      if (next == NULL)
+         return NULL;
+
+      next->next = NULL;
+      next->length = length;
+      tail->next = next;
+   }
+
+   return next;
+}
+
+/* GLOBAL CONTROL STRUCTURE */
+struct global
+{
+   /* PUBLIC GLOBAL VARIABLES: OWNER INITIALIZE */
+   unsigned int   errors        :1; /* print file errors to stderr */
+   unsigned int   warnings      :1; /* print libpng warnings to stderr */
+   unsigned int   optimize_zlib :1; /* Run optimization search */
+   unsigned int   quiet         :2; /* don't output summaries */
+   unsigned int   verbose       :3; /* various internal tracking */
+   unsigned int   skip          :3; /* Non-critical chunks to skip */
+#     define SKIP_NONE      0
+#     define SKIP_BAD_CRC   1    /* Chunks with a bad CRC */
+#     define SKIP_UNSAFE    2    /* Chunks not safe to copy */
+#     define SKIP_UNUSED    3    /* Chunks not used by libpng */
+#     define SKIP_TRANSFORM 4    /* Chunks only used in transforms */
+#     define SKIP_COLOR     5    /* Everything but tRNS, sBIT, gAMA and sRGB */
+#     define SKIP_ALL       6    /* Everything but tRNS and sBIT */
+
+   png_uint_32    idat_max;         /* 0 to perform no re-chunking */
+
+   int            status_code;      /* Accumulated status code */
+#     define TOO_FAR_BACK   0x01 /* found a too-far-back error */
+#     define CRC_ERROR      0x02 /* fixed an invalid CRC */
+#     define STREAM_ERROR   0x04 /* damaged PNG stream (may be fixable) */
+#     define TRUNCATED      0x08 /* truncated but still readable */
+#     define FILE_ERROR     0x10 /* could not read the file */
+#     define WRITE_ERROR    0x20 /* write error (this terminates the read) */
+#     define INTERNAL_ERROR 0x40 /* internal limits/errors encountered */
+
+   /* PUBLIC GLOBAL VARIABLES: USED INTERNALLY BY IDAT READ CODE */
+   struct IDAT_list idat_cache;  /* Cache of file IDAT information buffers */
+      /* The structure is shared across all uses of this global control
+       * structure to avoid reallocation between IDAT streams.
+       */
+};
+
+static int
+global_end(struct global *global)
+{
+
+   int rc;
+
+   IDAT_list_end(&global->idat_cache);
+   rc = global->status_code;
+   CLEAR(*global);
+   return rc;
+}
+
+static void
+global_init(struct global *global)
+   /* Call this once (and only once) to initialize the control */
+{
+   CLEAR(*global);
+
+   /* Globals */
+   global->errors        = 0;
+   global->warnings      = 0;
+   global->quiet         = 0;
+   global->verbose       = 0;
+   global->idat_max      = 0;         /* no re-chunking of IDAT */
+   global->optimize_zlib = 0;
+   global->skip          = SKIP_NONE;
+   global->status_code   = 0;
+
+   IDAT_list_init(&global->idat_cache);
+}
+
+static int
+skip_chunk_type(const struct global *global, png_uint_32 type)
+   /* Return true if this chunk is to be skipped according to the --strip
+    * option.  This code needs to recognize all known ancillary chunks in order
+    * to handle the --strip=unsafe option.
+    */
+{
+   /* Never strip critical chunks: */
+   if (CRITICAL(type))
+      return 0;
+
+   switch (type)
+   {
+      /* Chunks that are treated as, effectively, critical because they affect
+       * correct interpretation of the pixel values:
+       */
+      case png_tRNS: case png_sBIT:
+         return 0;
+
+      /* Chunks that specify gamma encoding which should therefore only be
+       * removed if the user insists:
+       */
+      case png_gAMA: case png_sRGB:
+         if (global->skip >= SKIP_ALL)
+            return 1;
+         return 0;
+
+      /* Chunks that affect color interpretation - not used by libpng and rarely
+       * used by applications, but technically still required for correct
+       * interpretation of the image data:
+       */
+      case png_cHRM: case png_iCCP:
+         if (global->skip >= SKIP_COLOR)
+            return 1;
+         return 0;
+
+      /* Other chunks that are used by libpng in image transformations (as
+       * opposed to known chunks that have get/set APIs but are not otherwise
+       * used.)
+       */
+      case png_bKGD:
+         if (global->skip >= SKIP_TRANSFORM)
+            return 1;
+         return 0;
+
+      /* All other chunks that libpng knows about and affect neither image
+       * interpretation nor libpng transforms - chunks that are effectively
+       * unused by libpng even though libpng might recognize and store them.
+       */
+      case png_fRAc: case png_gIFg: case png_gIFt: case png_gIFx: case png_hIST:
+      case png_iTXt: case png_oFFs: case png_pCAL: case png_pHYs: case png_sCAL:
+      case png_sPLT: case png_sTER: case png_tEXt: case png_tIME: case png_zTXt:
+         if (global->skip >= SKIP_UNUSED)
+            return 1;
+         return 0;
+
+      /* Chunks that libpng does not know about (notice that this depends on the
+       * list above including all known chunks!)  The decision here depends on
+       * whether the safe-to-copy bit is set in the chunk type.
+       */
+      default:
+         if (SAFE_TO_COPY(type))
+         {
+            if (global->skip >= SKIP_UNUSED) /* as above */
+               return 1;
+         }
+
+         else if (global->skip >= SKIP_UNSAFE)
+            return 1;
+
+         return 0;
+   }
+}
+
+/* PER-FILE CONTROL STRUCTURE */
+struct chunk;
+struct IDAT;
+struct file
+{
+   /* ANCESTORS */
+   struct global *global;
+
+   /* PUBLIC PER-FILE VARIABLES: CALLER INITIALIZE */
+   const char *   file_name;
+   const char *   out_name;      /* Name of output file (if required) */
+
+   /* PUBLIC PER-FILE VARIABLES: SET BY PNG READ CODE */
+   /* File specific result codes */
+   int            status_code;   /* Set to a bit mask of the following: */
+   int            read_errno;    /* Records a read error errno */
+   int            write_errno;   /* Records a write error errno */
+
+   /* IHDR information */
+   png_uint_32    width;
+   png_uint_32    height;
+   png_byte       bit_depth;
+   png_byte       color_type;
+   png_byte       compression_method;
+   png_byte       filter_method;
+   png_byte       interlace_method;
+
+   udigit         image_bytes[5];
+   int            image_digits;
+
+   /* PROTECTED PER-FILE VARIABLES: USED BY THE READ CODE */
+   FILE *         file;          /* Original PNG file */
+   FILE *         out;           /* If a new one is being written */
+   jmp_buf        jmpbuf;        /* Set while reading a PNG */
+
+   /* PROTECTED CHUNK SPECIFIC VARIABLES: USED BY CHUNK CODE */
+   /* The following variables are used during reading to record the length, type
+    * and data position of the *next* chunk or, right at the start, the
+    * signature (in length,type).
+    *
+    * When a chunk control structure is instantiated these values are copied
+    * into the structure and can then be overritten with the data for the next
+    * chunk.
+    */
+   fpos_t         data_pos;      /* Position of first byte of chunk data */
+   png_uint_32    length;        /* First word (length or signature start) */
+   png_uint_32    type;          /* Second word (type or signature end) */
+   png_uint_32    crc;           /* Running chunk CRC (used by read_chunk) */
+
+   /* These counts are maintained by the read and write routines below and are
+    * reset by the chunk handling code.  They record the total number of bytes
+    * read or written for the chunk, including the header (length,type) bytes.
+    */
+   png_uint_32    read_count;    /* Count of bytes read (in the chunk) */
+   png_uint_32    write_count;   /* Count of bytes written (in the chunk) */
+   int            state;         /* As defined here: */
+#     define STATE_SIGNATURE  0  /* The signature is being written */
+#     define STATE_CHUNKS     1  /* Non-IDAT chunks are being written */
+#     define STATE_IDAT       2  /* An IDAT stream is being written */
+
+   /* Two pointers used to enable clean-up in the event of fatal errors and to
+    * hold state about the parser process (only one of each at present.)
+    */
+   struct chunk * chunk;
+   struct IDAT *  idat;
+
+   /* Interface to allocate a new chunk or IDAT control structure.  The result
+    * is returned by setting one or other of the above variables.  Note that the
+    * relevant initializer is called by the allocator function.  The alloc_ptr
+    * is used only by the implementation of the allocate function.
+    */
+   void *         alloc_ptr;
+   void         (*alloc)(struct file*,int idat);
+                                  /* idat: allocate IDAT not chunk */
+};
+
+/* Valid longjmp (stop) codes are: */
+#define LIBPNG_WARNING_CODE   1 /* generic png_error */
+#define LIBPNG_ERROR_CODE     2 /* generic png_error */
+#define ZLIB_ERROR_CODE       3 /* generic zlib error */
+#define INVALID_ERROR_CODE    4 /* detected an invalid PNG */
+#define READ_ERROR_CODE       5 /* read failed */
+#define WRITE_ERROR_CODE      6 /* error in write */
+#define UNEXPECTED_ERROR_CODE 7 /* unexpected (internal?) error */
+
+static void
+emit_string(const char *str, FILE *out)
+   /* Print a string with spaces replaced by '_' and non-printing characters by
+    * an octal escape.
+    */
+{
+   for (; *str; ++str)
+      if (isgraph(UCHAR_MAX & *str))
+         putc(*str, out);
+
+      else if (isspace(UCHAR_MAX & *str))
+         putc('_', out);
+
+      else
+         fprintf(out, "\\%.3o", *str);
+}
+
+static const char *
+strcode(int code)
+{
+   switch (code)
+   {
+      case LIBPNG_WARNING_CODE:   return "warning";
+      case LIBPNG_ERROR_CODE:     return "libpng";
+      case ZLIB_ERROR_CODE:       return "zlib";
+      case INVALID_ERROR_CODE:    return "invalid";
+      case READ_ERROR_CODE:       return "read";
+      case WRITE_ERROR_CODE:      return "write";
+      case UNEXPECTED_ERROR_CODE: return "unexpected";
+      default:                    return "INVALID";
+   }
+}
+
+static void
+emit_error(struct file *file, int code, const char *what)
+   /* Generic error message routine, takes a 'stop' code but can be used
+    * elsewhere.  Always outputs a message.
+    */
+{
+   const char *reason;
+   int err = 0;
+
+   switch (code)
+   {
+      case LIBPNG_WARNING_CODE:   reason = "libpng warning:"; break;
+      case LIBPNG_ERROR_CODE:     reason = "libpng error:"; break;
+      case ZLIB_ERROR_CODE:       reason = "zlib error:"; break;
+      case INVALID_ERROR_CODE:    reason = "invalid"; break;
+      case READ_ERROR_CODE:       reason = "read failure:";
+                                  err = file->read_errno;
+                                  break;
+      case WRITE_ERROR_CODE:      reason = "write error";
+                                  err = file->write_errno;
+                                  break;
+      case UNEXPECTED_ERROR_CODE: reason = "unexpected error:";
+                                  err = file->read_errno;
+                                  if (err == 0)
+                                     err = file->write_errno;
+                                  break;
+      default:                    reason = "INVALID (internal error):"; break;
+   }
+
+   if (err != 0)
+      fprintf(stderr, "%s: %s %s [%s]\n", file->file_name, reason, what,
+         strerror(err));
+
+   else
+      fprintf(stderr, "%s: %s %s\n", file->file_name, reason, what);
+}
+
+static void chunk_end(struct chunk **);
+static void IDAT_end(struct IDAT **);
+
+static int
+file_end(struct file *file)
+{
+   int rc;
+
+   /* If either of the chunk pointers are set end them here, the IDAT structure
+    * must be deallocated first as it may deallocate the chunk structure.
+    */
+   if (file->idat != NULL)
+      IDAT_end(&file->idat);
+
+   if (file->chunk != NULL)
+      chunk_end(&file->chunk);
+
+   rc = file->status_code;
+
+   if (file->file != NULL)
+      (void)fclose(file->file);
+
+   if (file->out != NULL)
+   {
+      /* NOTE: this is bitwise |, all the following functions must execute and
+       * must succeed.
+       */
+      if (ferror(file->out) | fflush(file->out) | fclose(file->out))
+      {
+         perror(file->out_name);
+         emit_error(file, READ_ERROR_CODE, "output write error");
+         rc |= WRITE_ERROR;
+      }
+   }
+
+   /* Accumulate the result codes */
+   file->global->status_code |= rc;
+
+   CLEAR(*file);
+
+   return rc; /* status code: non-zero on read or write error */
+}
+
+static int
+file_init(struct file *file, struct global *global, const char *file_name,
+   const char *out_name, void *alloc_ptr, void (*alloc)(struct file*,int))
+   /* Initialize a file control structure.  This will open the given files as
+    * well.  The status code returned is 0 on success, non zero (using the flags
+    * above) on a file open error.
+    */
+{
+   CLEAR(*file);
+   file->global = global;
+
+   file->file_name = file_name;
+   file->out_name = out_name;
+   file->status_code = 0;
+   file->read_errno = 0;
+   file->write_errno = 0;
+
+   file->file = NULL;
+   file->out = NULL;
+   /* jmpbuf is garbage: must be set by read_png */
+
+   file->read_count = 0;
+   file->state = STATE_SIGNATURE;
+
+   file->chunk = NULL;
+   file->idat = NULL;
+
+   file->alloc_ptr = alloc_ptr;
+   file->alloc = alloc;
+
+   /* Open the files: */
+   assert(file_name != NULL);
+   file->file = fopen(file_name, "rb");
+
+   if (file->file == NULL)
+   {
+      file->read_errno = errno;
+      file->status_code |= FILE_ERROR;
+      /* Always output: please give a readable file! */
+      perror(file_name);
+      return FILE_ERROR;
+   }
+
+   if (out_name != NULL)
+   {
+      file->out = fopen(out_name, "wb");
+
+      if (file->out == NULL)
+      {
+         file->write_errno = errno;
+         file->status_code |= WRITE_ERROR;
+         perror(out_name);
+         return WRITE_ERROR;
+      }
+   }
+
+   return 0;
+}
+
+static void
+log_error(struct file *file, int code, const char *what)
+   /* Like emit_error but checks the global 'errors' flag */
+{
+   if (file->global->errors)
+      emit_error(file, code, what);
+}
+
+static char
+type_char(png_uint_32 v)
+{
+   /* In fact because chunk::chunk_type is validated prior to any call to this
+    * function it will always return a-zA-Z, but the extra codes are just there
+    * to help in finding internal (programming) errors.  Note that the code only
+    * ever considers the low 7 bits of the value (so it is not necessary for the
+    * type_name function to mask of the byte.)
+    */
+   if (v & 32)
+      return "!abcdefghijklmnopqrstuvwxyz56789"[(v-96)&31];
+
+   else
+      return "@ABCDEFGHIJKLMNOPQRSTUVWXYZ01234"[(v-64)&31];
+}
+
+static void
+type_name(png_uint_32 type, FILE *out)
+{
+   putc(type_char(type >> 24), out);
+   putc(type_char(type >> 16), out);
+   putc(type_char(type >>  8), out);
+   putc(type_char(type      ), out);
+}
+
+static void
+type_sep(FILE *out)
+{
+   putc(':', out);
+   putc(' ', out);
+}
+
+static png_uint_32 current_type(struct file *file, int code);
+
+PNG_NORETURN static void
+stop(struct file *file, int code, const char *what)
+   /* Return control when a PNG file cannot be read. This outputs an 'ERR'
+    * summary line too.
+    */
+{
+   log_error(file, code, what);
+
+   /* The chunk being read is typically identified by file->chunk or, if this is
+    * NULL, by file->type.  This may be wrong if libpng reads ahead, but this
+    * only happens with IDAT where libpng reads the header then jumps around
+    * finding errors in the previous chunks.  We know that is happening because
+    * we are at the start of the IDAT (i.e. no IDAT data has yet been written.)
+    *
+    * SUMMARY FORMAT (stop):
+    *
+    * IDAT ERR status code read-errno write-errno message file
+    *
+    * 'uncompressed' will be 0 if there was a problem in the IHDR.  The errno
+    * values are emit_string(strerror(errno)).
+    */
+   if (file->global->quiet < 2) /* need two quiets to stop this. */
+   {
+      png_uint_32 type;
+
+      if (file->chunk != NULL)
+         type = current_type(file, code); /* Gropes in struct chunk and IDAT */
+
+      else
+         type = file->type;
+
+      if (type)
+         type_name(type, stdout);
+
+      else /* magic: an IDAT header, produces bogons for too many IDATs */
+         fputs("HEAD", stdout); /* not a registered chunk! */
+
+      printf(" ERR %.2x %s ", file->status_code, strcode(code));
+      /* This only works one strerror at a time, because of the way strerror is
+       * implemented.
+       */
+      emit_string(strerror(file->read_errno), stdout);
+      putc(' ', stdout);
+      emit_string(strerror(file->write_errno), stdout);
+      putc(' ', stdout);
+      emit_string(what, stdout);
+      putc(' ', stdout);
+      fputs(file->file_name, stdout);
+      putc('\n', stdout);
+   }
+
+   file->status_code |= FILE_ERROR;
+   longjmp(file->jmpbuf, code);
+}
+
+PNG_NORETURN static void
+stop_invalid(struct file *file, const char *what)
+{
+   stop(file, INVALID_ERROR_CODE, what);
+}
+
+static void
+type_message(struct file *file, png_uint_32 type, const char *what)
+   /* Error message for a chunk; the chunk name comes from 'type' */
+{
+   if (file->global->errors)
+   {
+      fputs(file->file_name, stderr);
+      type_sep(stderr);
+      type_name(type, stderr);
+      type_sep(stderr);
+      fputs(what, stderr);
+      putc('\n', stderr);
+   }
+}
+
+/* Input file positioning - we jump around in the input file while reading
+ * stuff, these wrappers deal with the error handling.
+ */
+static void
+file_getpos(struct file *file, fpos_t *pos)
+{
+   if (fgetpos(file->file, pos))
+   {
+      /* This is unexpected, so perror it */
+      perror(file->file_name);
+      stop(file, READ_ERROR_CODE, "fgetpos");
+   }
+}
+
+static void
+file_setpos(struct file *file, const fpos_t *pos)
+{
+   if (fsetpos(file->file, pos))
+   {
+      perror(file->file_name);
+      stop(file, READ_ERROR_CODE, "fsetpos");
+   }
+}
+
+static void
+getpos(struct file *file)
+   /* Get the current position and store it in 'data_pos'.  The corresponding
+    * setpos() function is chunk specific because it uses the copy of the
+    * position for the specific chunk.
+    */
+{
+   file_getpos(file, &file->data_pos);
+}
+
+
+/* Read utility - read a single byte, returns a value in the range 0..255 or EOF
+ * on a read error.  In the latter case status_code and read_errno are updated
+ * appropriately.
+ */
+static int
+read_byte(struct file *file)
+{
+   int ch = getc(file->file);
+
+   if (ch >= 0 && ch <= 255)
+   {
+      ++(file->read_count);
+      return ch;
+   }
+
+   else if (ch != EOF)
+   {
+      file->status_code |= INTERNAL_ERROR;
+      file->read_errno = ERANGE; /* out of range character */
+
+      /* This is very unexpected; an error message is always output: */
+      emit_error(file, UNEXPECTED_ERROR_CODE, "file read");
+   }
+
+#  ifdef EINTR
+      else if (errno == EINTR) /* Interrupted, try again */
+      {
+         errno = 0;
+         return read_byte(file);
+      }
+#  endif
+
+   else
+   {
+      /* An error, it doesn't really matter what the error is but it gets
+       * recorded anyway.
+       */
+      if (ferror(file->file))
+         file->read_errno = errno;
+
+      else if (feof(file->file))
+         file->read_errno = 0; /* I.e. a regular EOF, no error */
+
+      else /* unexpected */
+         file->read_errno = EDOM;
+   }
+
+   /* 'TRUNCATED' is used for all cases of failure to read a byte, because of
+    * the way libpng works a byte read is never attempted unless the byte is
+    * expected to be there, so EOF should not occur.
+    */
+   file->status_code |= TRUNCATED;
+   return EOF;
+}
+
+static png_byte
+reread_byte(struct file *file)
+   /* Read a byte when an error is not expected to happen because the byte has
+    * been read before without error.
+    */
+{
+   int ch = getc(file->file);
+
+   if (errno != 0)
+      file->read_errno = errno;
+
+   if (ch < 0 || ch > 255)
+      stop(file, UNEXPECTED_ERROR_CODE, "reread");
+
+   return (png_byte)ch;
+}
+
+static png_uint_32
+reread_4(struct file *file)
+   /* The same but for a four byte quantity */
+{
+   png_uint_32 result = 0;
+   int i = 0;
+
+   while (++i <= 4)
+      result = (result << 8) + reread_byte(file);
+
+   return result;
+}
+
+static void
+skip_12(struct file *file)
+   /* Skip exactly 12 bytes in the input stream - used to skip a CRC and chunk
+    * header that has been read before.
+    */
+{
+   /* Since the chunks were read before this shouldn't fail: */
+   if (fseek(file->file, 12, SEEK_CUR) != 0)
+   {
+      if (errno != 0)
+         file->read_errno = errno;
+
+      stop(file, UNEXPECTED_ERROR_CODE, "reskip");
+   }
+}
+
+static void
+write_byte(struct file *file, int b)
+   /* Write one byte to the output - this causes a fatal error if the write
+    * fails and the read of this PNG file immediately terminates.  Just
+    * increments the write count if there is no output file.
+    */
+{
+   if (file->out != NULL)
+   {
+      if (putc(b, file->out) != b)
+      {
+         file->write_errno = errno;
+         file->status_code |= WRITE_ERROR;
+         stop(file, WRITE_ERROR_CODE, "write byte");
+      }
+   }
+
+   ++(file->write_count);
+}
+
+/* Derivatives of the read/write functions. */
+static unsigned int
+read_4(struct file *file, png_uint_32 *pu)
+   /* Read four bytes, returns the number of bytes read successfully and, if all
+    * four bytes are read, assigns the result to *pu.
+    */
+{
+   unsigned int i = 0;
+   png_uint_32 val = 0;
+
+   do
+   {
+      int ch = read_byte(file);
+
+      if (ch == EOF)
+         return i;
+
+      val = (val << 8) + ch;
+   } while (++i < 4);
+
+   *pu = val;
+   return i;
+}
+
+/* CRC handling - read but calculate the CRC while doing so. */
+static int
+crc_read_many(struct file *file, png_uint_32 length)
+   /* Reads 'length' bytes and updates the CRC, returns true on success, false
+    * if the input is truncated.
+    */
+{
+   if (length > 0)
+   {
+      png_uint_32 crc = file->crc;
+
+      do
+      {
+         int ch = read_byte(file);
+
+         if (ch == EOF)
+            return 0; /* Truncated */
+
+         crc = crc_one_byte(crc, ch);
+      }
+      while (--length > 0);
+
+      file->crc = crc;
+   }
+
+   return 1; /* OK */
+}
+
+static int
+calc_image_size(struct file *file)
+   /* Fill in the image_bytes field given the IHDR information, calls stop on
+    * error.
+    */
+{
+   png_uint_16 pd = file->bit_depth;
+
+   switch (file->color_type)
+   {
+      default:
+         stop_invalid(file, "IHDR: colour type");
+
+      invalid_bit_depth:
+         stop_invalid(file, "IHDR: bit depth");
+
+      case 0: /* g */
+         if (pd != 1 && pd != 2 && pd != 4 && pd != 8 && pd != 16)
+            goto invalid_bit_depth;
+         break;
+
+      case 3:
+         if (pd != 1 && pd != 2 && pd != 4 && pd != 8)
+            goto invalid_bit_depth;
+         break;
+
+      case 2: /* rgb */
+         if (pd != 8 && pd != 16)
+            goto invalid_bit_depth;
+
+         pd = (png_uint_16)(pd * 3);
+         break;
+
+      case 4: /* ga */
+         if (pd != 8 && pd != 16)
+            goto invalid_bit_depth;
+
+         pd = (png_uint_16)(pd * 2);
+         break;
+
+      case 6: /* rgba */
+         if (pd != 8 && pd != 16)
+            goto invalid_bit_depth;
+
+         pd = (png_uint_16)(pd * 4);
+         break;
+   }
+
+   if (file->width < 1 || file->width > 0x7fffffff)
+      stop_invalid(file, "IHDR: width");
+
+   else if (file->height < 1 || file->height > 0x7fffffff)
+      stop_invalid(file, "IHDR: height");
+
+   else if (file->compression_method != 0)
+      stop_invalid(file, "IHDR: compression method");
+
+   else if (file->filter_method != 0)
+      stop_invalid(file, "IHDR: filter method");
+
+   else switch (file->interlace_method)
+   {
+      case PNG_INTERLACE_ADAM7:
+         /* Interlacing makes the image larger because of the replication of
+          * both the filter byte and the padding to a byte boundary.
+          */
+         {
+            int pass;
+            int image_digits = 0;
+            udigit row_width[2], row_bytes[3];
+
+            for (pass=0; pass<=6; ++pass)
+            {
+               png_uint_32 pw = PNG_PASS_COLS(file->width, pass);
+
+               if (pw > 0)
+               {
+                  int  digits;
+
+                  /* calculate 1+((pw*pd+7)>>3) in row_bytes */
+                  digits = uarb_mult_digit(row_bytes, uarb_set(row_bytes, 7),
+                     row_width, uarb_set(row_width, pw), pd);
+                  digits = uarb_shift(row_bytes, digits, 3);
+                  digits = uarb_inc(row_bytes, digits, 1);
+
+                  /* Add row_bytes * pass-height to the file image_bytes field
+                   */
+                  image_digits = uarb_mult32(file->image_bytes, image_digits,
+                     row_bytes, digits,
+                     PNG_PASS_ROWS(file->height, pass));
+               }
+            }
+
+            file->image_digits = image_digits;
+         }
+         break;
+
+      case PNG_INTERLACE_NONE:
+         {
+            int  digits;
+            udigit row_width[2], row_bytes[3];
+
+            /* As above, but use image_width in place of the pass width: */
+            digits = uarb_mult_digit(row_bytes, uarb_set(row_bytes, 7),
+               row_width, uarb_set(row_width, file->width), pd);
+            digits = uarb_shift(row_bytes, digits, 3);
+            digits = uarb_inc(row_bytes, digits, 1);
+
+            /* Set row_bytes * image-height to the file image_bytes field */
+            file->image_digits = uarb_mult32(file->image_bytes, 0,
+               row_bytes, digits, file->height);
+         }
+         break;
+
+      default:
+         stop_invalid(file, "IHDR: interlace method");
+   }
+
+   assert(file->image_digits >= 1 && file->image_digits <= 5);
+   return 1;
+}
+
+/* PER-CHUNK CONTROL STRUCTURE
+ * This structure is instantiated for each chunk, except for the IDAT chunks
+ * where one chunk control structure is used for the whole of a single stream of
+ * IDAT chunks (see the IDAT control structure below).
+ */
+struct chunk
+{
+   /* ANCESTORS */
+   struct file *         file;
+   struct global *       global;
+
+   /* PUBLIC IDAT INFORMATION: SET BY THE ZLIB CODE */
+   udigit         uncompressed_bytes[5];
+   int            uncompressed_digits;
+   udigit         compressed_bytes[5];
+   int            compressed_digits;
+
+   /* PUBLIC PER-CHUNK INFORMATION: USED BY CHUNK READ CODE */
+   /* This information is filled in by chunk_init from the data in the file
+    * control structure, but chunk_length may be changed later.
+    */
+   fpos_t         chunk_data_pos;    /* Position of first byte of chunk data */
+   png_uint_32    chunk_length;      /* From header (or modified below) */
+   png_uint_32    chunk_type;        /* From header */
+
+   /* PUBLIC PER-CHUNK INFORMATION: FOR THE CHUNK WRITE CODE */
+   png_uint_32    write_crc;         /* Output CRC (may differ from read_crc) */
+   png_uint_32    rewrite_offset;    /* Count of bytes before rewrite. */
+   int            rewrite_length;    /* Number of bytes left to change */
+   png_byte       rewrite_buffer[2]; /* Buffer of new byte values */
+};
+
+static void
+chunk_message(struct chunk *chunk, const char *message)
+{
+   type_message(chunk->file, chunk->chunk_type, message);
+}
+
+static void
+chunk_end(struct chunk **chunk_var)
+{
+   struct chunk *chunk = *chunk_var;
+
+   *chunk_var = NULL;
+   CLEAR(*chunk);
+}
+
+static void
+chunk_init(struct chunk * const chunk, struct file * const file)
+   /* When a chunk is initialized the file length/type/pos are copied into the
+    * corresponding chunk fields and the new chunk is registered in the file
+    * structure.  There can only be one chunk at a time.
+    *
+    * NOTE: this routine must onely be called from the file alloc routine!
+    */
+{
+   assert(file->chunk == NULL);
+
+   CLEAR(*chunk);
+
+   chunk->file = file;
+   chunk->global = file->global;
+
+   chunk->chunk_data_pos = file->data_pos;
+   chunk->chunk_length = file->length;
+   chunk->chunk_type = file->type;
+
+   /* Compresssed/uncompressed size information (from the zlib control structure
+    * that is used to check the compressed data in a chunk.)
+    */
+   chunk->uncompressed_digits = 0;
+   chunk->compressed_digits = 0;
+
+   file->chunk = chunk;
+}
+
+static png_uint_32
+current_type(struct file *file, int code)
+   /* Guess the actual chunk type that causes a stop() */
+{
+   /* This may return png_IDAT for errors detected (late) in the header; that
+    * includes any inter-chunk consistency check that libpng performs.  Assume
+    * that if the chunk_type is png_IDAT and the file write count is 8 this is
+    * what is happening.
+    */
+   if (file->chunk != NULL)
+   {
+      png_uint_32 type = file->chunk->chunk_type;
+
+      /* This is probably wrong for the excess IDATs case, because then libpng
+       * whines about too many of them (apparently in some cases erroneously)
+       * when the header is read.
+       */
+      if (code <= LIBPNG_ERROR_CODE && type == png_IDAT &&
+         file->write_count == 8)
+         type = 0; /* magic */
+
+      return type;
+   }
+
+   else
+      return file->type;
+}
+
+static void
+setpos(struct chunk *chunk)
+   /* Reset the position to 'chunk_data_pos' - the start of the data for this
+    * chunk.  As a side effect the read_count in the file is reset to 8, just
+    * after the length/type header.
+    */
+{
+   chunk->file->read_count = 8;
+   file_setpos(chunk->file, &chunk->chunk_data_pos);
+}
+
+/* Specific chunk handling - called for each chunk header, all special chunk
+ * processing is initiated in these functions.
+ */
+/* The next functions handle special processing for those chunks with LZ data,
+ * the data is identified and checked for validity.  If there are problems which
+ * cannot be corrected the routines return false, otherwise true (although
+ * modification to the zlib header may be required.)
+ *
+ * The compressed data is in zlib format (RFC1950) and consequently has a
+ * minimum length of 7 bytes.
+ */
+static int zlib_check(struct file *file, png_uint_32 offset);
+
+static int
+process_zTXt_iCCP(struct file *file)
+   /* zTXt and iCCP have exactly the same form - keyword, null, compression
+    * method then compressed data.
+    */
+{
+   struct chunk *chunk = file->chunk;
+   png_uint_32 length;
+   png_uint_32 index = 0;
+
+   assert(chunk != NULL && file->idat == NULL);
+   length = chunk->chunk_length;
+   setpos(chunk);
+
+   while (length >= 9)
+   {
+      --length;
+      ++index;
+      if (reread_byte(file) == 0) /* keyword null terminator */
+      {
+         --length;
+         ++index;
+         (void)reread_byte(file); /* compression method */
+         return zlib_check(file, index);
+      }
+   }
+
+   chunk_message(chunk, "too short");
+   return 0; /* skip */
+}
+
+static int
+process_iTXt(struct file *file)
+{
+   /* Like zTXt but more fields. */
+   struct chunk *chunk = file->chunk;
+   png_uint_32 length;
+   png_uint_32 index = 0;
+
+   assert(chunk != NULL && file->idat == NULL);
+   length = chunk->chunk_length;
+   setpos(chunk);
+
+   while (length >= 5)
+   {
+      --length;
+      ++index;
+      if (reread_byte(file) == 0) /* keyword null terminator */
+      {
+         --length;
+         ++index;
+         if (reread_byte(file) == 0) /* uncompressed text */
+            return 1; /* nothing to check */
+
+         --length;
+         ++index;
+         (void)reread_byte(file); /* compression method */
+
+         /* Skip the language tag (null terminated). */
+         while (length >= 9)
+         {
+            --length;
+            ++index;
+            if (reread_byte(file) == 0) /* terminator */
+            {
+               /* Skip the translated keyword */
+               while (length >= 8)
+               {
+                  --length;
+                  ++index;
+                  if (reread_byte(file) == 0) /* terminator */
+                     return zlib_check(file, index);
+               }
+            }
+         }
+
+         /* Ran out of bytes in the compressed case. */
+         break;
+      }
+   }
+
+   log_error(file, INVALID_ERROR_CODE, "iTXt chunk length");
+
+   return 0; /* skip */
+}
+
+/* IDAT READ/WRITE CONTROL STRUCTURE */
+struct IDAT
+{
+   /* ANCESTORS */
+   struct file *         file;
+   struct global *       global;
+
+   /* PROTECTED IDAT INFORMATION: SET BY THE IDAT READ CODE */
+   struct IDAT_list *idat_list_head; /* START of the list of IDAT information */
+   struct IDAT_list *idat_list_tail; /* *END* of the list of IDAT information */
+
+   /* PROTECTED IDAT INFORMATION: USED BY THE IDAT WRITE CODE */
+   struct IDAT_list *idat_cur;       /* Current list entry */
+   unsigned int      idat_count;     /* And the *current* index into the list */
+   png_uint_32       idat_index;     /* Index of *next* input byte to write */
+   png_uint_32       idat_length;    /* Cache of current chunk length */
+};
+
+/* NOTE: there is currently no IDAT_reset, so a stream cannot contain more than
+ * one IDAT sequence (i.e. MNG is not supported).
+ */
+
+static void
+IDAT_end(struct IDAT **idat_var)
+{
+   struct IDAT *idat = *idat_var;
+   struct file *file = idat->file;
+
+   *idat_var = NULL;
+
+   CLEAR(*idat);
+
+   assert(file->chunk != NULL);
+   chunk_end(&file->chunk);
+
+   /* Regardless of why the IDAT was killed set the state back to CHUNKS (it may
+    * already be CHUNKS because the state isn't changed until process_IDAT
+    * returns; a stop will cause IDAT_end to be entered in state CHUNKS!)
+    */
+   file->state = STATE_CHUNKS;
+}
+
+static void
+IDAT_init(struct IDAT * const idat, struct file * const file)
+   /* When the chunk is png_IDAT instantiate an IDAT control structure in place
+    * of a chunk control structure.  The IDAT will instantiate a chunk control
+    * structure using the file alloc routine.
+    *
+    * NOTE: this routine must only be called from the file alloc routine!
+    */
+{
+   assert(file->chunk == NULL);
+   assert(file->idat == NULL);
+
+   CLEAR(*idat);
+
+   idat->file = file;
+   idat->global = file->global;
+
+   /* Initialize the tail to the pre-allocated buffer and set the count to 0
+    * (empty.)
+    */
+   idat->global->idat_cache.count = 0;
+   idat->idat_list_head = idat->idat_list_tail = &idat->global->idat_cache;
+
+   /* Now the chunk.  The allocator calls the initializer of the new chunk and
+    * stores the result in file->chunk:
+    */
+   file->alloc(file, 0/*chunk*/);
+   assert(file->chunk != NULL);
+
+   /* And store this for cleanup (and to check for double alloc or failure to
+    * free.)
+    */
+   file->idat = idat;
+}
+
+static png_uint_32
+rechunk_length(struct IDAT *idat, int start)
+   /* Return the length for the next IDAT chunk, taking into account
+    * rechunking.
+    */
+{
+   png_uint_32 len = idat->global->idat_max;
+
+   if (len == 0) /* use original chunk lengths */
+   {
+      const struct IDAT_list *cur;
+      unsigned int count;
+
+      if (start)
+         return idat->idat_length; /* use the cache */
+
+      /* Otherwise rechunk_length is called at the end of a chunk for the length
+       * of the next one.
+       */
+      cur = idat->idat_cur;
+      count = idat->idat_count;
+
+      assert(idat->idat_index == idat->idat_length &&
+         idat->idat_length == cur->lengths[count]);
+
+      /* Return length of the *next* chunk */
+      if (++count < cur->count)
+         return cur->lengths[count];
+
+      /* End of this list */
+      assert(cur != idat->idat_list_tail);
+      cur = cur->next;
+      assert(cur != NULL && cur->count > 0);
+      return cur->lengths[0];
+   }
+
+   else /* rechunking */
+   {
+      /* The chunk size is the lesser of file->idat_max and the number
+       * of remaining bytes.
+       */
+      png_uint_32 have = idat->idat_length - idat->idat_index;
+
+      if (len > have)
+      {
+         struct IDAT_list *cur = idat->idat_cur;
+         unsigned int j = idat->idat_count+1; /* the next IDAT in the list */
+
+         do
+         {
+            /* Add up the remaining bytes.  This can't overflow because the
+             * individual lengths are always <= 0x7fffffff, so when we add two
+             * of them overflow is not possible.
+             */
+            assert(cur != NULL);
+
+            for (;;)
+            {
+               /* NOTE: IDAT_list::count here, not IDAT_list::length */
+               for (; j < cur->count; ++j)
+               {
+                  have += cur->lengths[j];
+                  if (len <= have)
+                     return len;
+               }
+
+               /* If this was the end return the count of the available bytes */
+               if (cur == idat->idat_list_tail)
+                  return have;
+
+               cur = cur->next;
+               j = 0;
+            }
+         }
+         while (len > have);
+      }
+
+      return len;
+   }
+}
+
+static int
+process_IDAT(struct file *file)
+   /* Process the IDAT stream, this is the more complex than the preceding
+    * cases because the compressed data is spread across multiple IDAT chunks
+    * (typically).  Rechunking of the data is not handled here; all this
+    * function does is establish whether the zlib header needs to be modified.
+    *
+    * Initially the function returns false, indicating that the chunk should not
+    * be written.  It does this until the last IDAT chunk is passed in, then it
+    * checks the zlib data and returns true.
+    *
+    * It does not return false on a fatal error; it calls stop instead.
+    *
+    * The caller must have an instantiated (IDAT) control structure and it must
+    * have extent over the whole read of the IDAT stream.  For a PNG this means
+    * the whole PNG read, for MNG it could have lesser extent.
+    */
+{
+   struct IDAT_list *list;
+
+   assert(file->idat != NULL && file->chunk != NULL);
+
+   /* We need to first check the entire sequence of IDAT chunks to ensure the
+    * stream is in sync.  Do this by building a list of all the chunks and
+    * recording the length of each because the length may have been fixed up by
+    * sync_stream below.
+    *
+    * At the end of the list of chunks, where the type of the next chunk is not
+    * png_IDAT, process the whole stream using the list data to check validity
+    * then return control to the start and rewrite everything.
+    */
+   list = file->idat->idat_list_tail;
+
+   if (list->count == list->length)
+   {
+      list = IDAT_list_extend(list);
+
+      if (list == NULL)
+         stop(file, READ_ERROR_CODE, "out of memory");
+
+      /* Move to the next block */
+      list->count = 0;
+      file->idat->idat_list_tail = list;
+   }
+
+   /* And fill in the next IDAT information buffer. */
+   list->lengths[(list->count)++] = file->chunk->chunk_length;
+
+   /* The type of the next chunk was recorded in the file control structure by
+    * the caller, if this is png_IDAT return 'skip' to the caller.
+    */
+   if (file->type == png_IDAT)
+      return 0; /* skip this for the moment */
+
+   /* This is the final IDAT chunk, so run the tests to check for the too far
+    * back error and possibly optimize the window bits.  This means going back
+    * to the start of the first chunk data, which is stored in the original
+    * chunk allocation.
+    */
+   setpos(file->chunk);
+
+   if (zlib_check(file, 0))
+   {
+      struct IDAT *idat;
+      int cmp;
+
+      /* The IDAT stream was successfully uncompressed; see whether it
+       * contained the correct number of bytes of image data.
+       */
+      cmp = uarb_cmp(file->image_bytes, file->image_digits,
+         file->chunk->uncompressed_bytes, file->chunk->uncompressed_digits);
+
+      if (cmp < 0)
+         type_message(file, png_IDAT, "extra uncompressed data");
+
+      else if (cmp > 0)
+         stop(file, LIBPNG_ERROR_CODE, "IDAT: uncompressed data too small");
+
+      /* Return the stream to the start of the first IDAT chunk; the length
+       * is set in the write case below but the input chunk variables must be
+       * set (once) here:
+       */
+      setpos(file->chunk);
+
+      idat = file->idat;
+      idat->idat_cur = idat->idat_list_head;
+      idat->idat_length = idat->idat_cur->lengths[0];
+      idat->idat_count = 0; /* Count of chunks read in current list */
+      idat->idat_index = 0; /* Index into chunk data */
+
+      /* Update the chunk length to the correct value for the IDAT chunk: */
+      file->chunk->chunk_length = rechunk_length(idat, 1/*start*/);
+
+      /* Change the state to writing IDAT chunks */
+      file->state = STATE_IDAT;
+
+      return 1;
+   }
+
+   else /* Failure to decompress the IDAT stream; give up. */
+      stop(file, ZLIB_ERROR_CODE, "could not uncompress IDAT");
+}
+
+/* ZLIB CONTROL STRUCTURE */
+struct zlib
+{
+   /* ANCESTORS */
+   struct IDAT *  idat;          /* NOTE: May be NULL */
+   struct chunk * chunk;
+   struct file *  file;
+   struct global *global;
+
+   /* GLOBAL ZLIB INFORMATION: SET BY THE CALLER */
+   png_uint_32    rewrite_offset;
+
+   /* GLOBAL ZLIB INFORMATION: SET BY THE ZLIB READ CODE */
+   udigit         compressed_bytes[5];
+   int            compressed_digits;
+   udigit         uncompressed_bytes[5];
+   int            uncompressed_digits;
+   int            file_bits;             /* window bits from the file */
+   int            ok_bits;               /* Set <16 on a successful read */
+   int            cksum;                 /* Set on a checksum error */
+
+   /* PROTECTED ZLIB INFORMATION: USED BY THE ZLIB ROUTINES */
+   z_stream       z;
+   png_uint_32    extra_bytes;   /* Count of extra compressed bytes */
+   int            state;
+   int            rc;            /* Last return code */
+   int            window_bits;   /* 0 if no change */
+   png_byte       header[2];
+};
+
+static const char *
+zlib_flevel(struct zlib *zlib)
+{
+   switch (zlib->header[1] >> 6)
+   {
+      case 0:  return "supfast";
+      case 1:  return "stdfast";
+      case 2:  return "default";
+      case 3:  return "maximum";
+      default: assert(UNREACHED);
+   }
+
+   return "COMPILER BUG";
+}
+
+static const char *
+zlib_rc(struct zlib *zlib)
+   /* Return a string for the zlib return code */
+{
+   switch (zlib->rc)
+   {
+      case Z_OK:              return "Z_OK";
+      case Z_STREAM_END:      return "Z_STREAM_END";
+      case Z_NEED_DICT:       return "Z_NEED_DICT";
+      case Z_ERRNO:           return "Z_ERRNO";
+      case Z_STREAM_ERROR:    return "Z_STREAM_ERROR";
+      case Z_DATA_ERROR:      return "Z_DATA_ERROR";
+      case Z_MEM_ERROR:       return "Z_MEM_ERROR";
+      case Z_BUF_ERROR:       return "Z_BUF_ERROR";
+      case Z_VERSION_ERROR:   return "Z_VERSION_ERROR";
+      default:                return "Z_*INVALID_RC*";
+   }
+}
+
+static void
+zlib_message(struct zlib *zlib, int unexpected)
+   /* Output a message given a zlib rc */
+{
+   if (zlib->global->errors)
+   {
+      const char *reason = zlib->z.msg;
+
+      if (reason == NULL)
+         reason = "[no message]";
+
+      fputs(zlib->file->file_name, stderr);
+      type_sep(stderr);
+      type_name(zlib->chunk->chunk_type, stderr);
+      fprintf(stderr, ": %szlib error: %d (%s) (%s)\n",
+         unexpected ? "unexpected " : "", zlib->rc, zlib_rc(zlib), reason);
+   }
+}
+
+static void
+zlib_end(struct zlib *zlib)
+{
+   /* Output the summary line now; this ensures a summary line always gets
+    * output regardless of the manner of exit.
+    */
+   if (!zlib->global->quiet)
+   {
+      if (zlib->ok_bits < 16) /* stream was read ok */
+      {
+         const char *reason;
+
+         if (zlib->cksum)
+            reason = "CHK"; /* checksum error */
+
+         else if (zlib->ok_bits > zlib->file_bits)
+            reason = "TFB"; /* fixing a too-far-back error */
+
+         else if (zlib->ok_bits == zlib->file_bits)
+            reason = "OK ";
+
+         else
+            reason = "OPT"; /* optimizing window bits */
+
+         /* SUMMARY FORMAT (for a successful zlib inflate):
+          *
+          * IDAT reason flevel file-bits ok-bits compressed uncompressed file
+          */
+         type_name(zlib->chunk->chunk_type, stdout);
+         printf(" %s %s %d %d ", reason, zlib_flevel(zlib), zlib->file_bits,
+            zlib->ok_bits);
+         uarb_print(zlib->compressed_bytes, zlib->compressed_digits, stdout);
+         putc(' ', stdout);
+         uarb_print(zlib->uncompressed_bytes, zlib->uncompressed_digits,
+            stdout);
+         putc(' ', stdout);
+         fputs(zlib->file->file_name, stdout);
+         putc('\n', stdout);
+      }
+
+      else
+      {
+         /* This is a zlib read error; the chunk will be skipped.  For an IDAT
+          * stream this will also cause a fatal read error (via stop()).
+          *
+          * SUMMARY FORMAT:
+          *
+          * IDAT SKP flevel file-bits z-rc compressed message file
+          *
+          * z-rc is the zlib failure code; message is the error message with
+          * spaces replaced by '-'.  The compressed byte count indicates where
+          * in the zlib stream the error occurred.
+          */
+         type_name(zlib->chunk->chunk_type, stdout);
+         printf(" SKP %s %d %s ", zlib_flevel(zlib), zlib->file_bits,
+            zlib_rc(zlib));
+         uarb_print(zlib->compressed_bytes, zlib->compressed_digits, stdout);
+         putc(' ', stdout);
+         emit_string(zlib->z.msg ? zlib->z.msg : "[no_message]", stdout);
+         putc(' ', stdout);
+         fputs(zlib->file->file_name, stdout);
+         putc('\n', stdout);
+      }
+   }
+
+   if (zlib->state >= 0)
+   {
+      zlib->rc = inflateEnd(&zlib->z);
+
+      if (zlib->rc != Z_OK)
+         zlib_message(zlib, 1/*unexpected*/);
+   }
+
+   CLEAR(*zlib);
+}
+
+static int
+zlib_reset(struct zlib *zlib, int window_bits)
+   /* Reinitializes a zlib with a different window_bits */
+{
+   assert(zlib->state >= 0); /* initialized by zlib_init */
+
+   zlib->z.next_in = Z_NULL;
+   zlib->z.avail_in = 0;
+   zlib->z.next_out = Z_NULL;
+   zlib->z.avail_out = 0;
+
+   zlib->window_bits = window_bits;
+   zlib->compressed_digits = 0;
+   zlib->uncompressed_digits = 0;
+
+   zlib->state = 0; /* initialized, once */
+   zlib->rc = inflateReset2(&zlib->z, 0);
+   if (zlib->rc != Z_OK)
+   {
+      zlib_message(zlib, 1/*unexpected*/);
+      return 0;
+   }
+
+   return 1;
+}
+
+static int
+zlib_init(struct zlib *zlib, struct IDAT *idat, struct chunk *chunk,
+   int window_bits, png_uint_32 offset)
+   /* Initialize a zlib_control; the result is true/false */
+{
+   CLEAR(*zlib);
+
+   zlib->idat = idat;
+   zlib->chunk = chunk;
+   zlib->file = chunk->file;
+   zlib->global = chunk->global;
+   zlib->rewrite_offset = offset; /* never changed for this zlib */
+
+   /* *_out does not need to be set: */
+   zlib->z.next_in = Z_NULL;
+   zlib->z.avail_in = 0;
+   zlib->z.zalloc = Z_NULL;
+   zlib->z.zfree = Z_NULL;
+   zlib->z.opaque = Z_NULL;
+
+   zlib->state = -1;
+   zlib->window_bits = window_bits;
+
+   zlib->compressed_digits = 0;
+   zlib->uncompressed_digits = 0;
+
+   /* These values are sticky across reset (in addition to the stuff in the
+    * first block, which is actually constant.)
+    */
+   zlib->file_bits = 24;
+   zlib->ok_bits = 16; /* unset */
+   zlib->cksum = 0; /* set when a checksum error is detected */
+
+   /* '0' means use the header; inflateInit2 should always succeed because it
+    * does nothing apart from allocating the internal zstate.
+    */
+   zlib->rc = inflateInit2(&zlib->z, 0);
+   if (zlib->rc != Z_OK)
+   {
+      zlib_message(zlib, 1/*unexpected*/);
+      return 0;
+   }
+
+   else
+   {
+      zlib->state = 0; /* initialized */
+      return 1;
+   }
+}
+
+static int
+max_window_bits(uarbc size, int ndigits)
+   /* Return the zlib stream window bits required for data of the given size. */
+{
+   png_uint_16 cb;
+
+   if (ndigits > 1)
+      return 15;
+
+   cb = size[0];
+
+   if (cb > 16384) return 15;
+   if (cb >  8192) return 14;
+   if (cb >  4096) return 13;
+   if (cb >  2048) return 12;
+   if (cb >  1024) return 11;
+   if (cb >   512) return 10;
+   if (cb >   256) return  9;
+   return 8;
+}
+
+static int
+zlib_advance(struct zlib *zlib, png_uint_32 nbytes)
+   /* Read nbytes compressed bytes; the stream will be initialized if required.
+    * Bytes are always being reread and errors are fatal.  The return code is as
+    * follows:
+    *
+    *    -1: saw the "too far back" error
+    *     0: ok, keep going
+    *     1: saw Z_STREAM_END (zlib->extra_bytes indicates too much data)
+    *     2: a zlib error that cannot be corrected (error message already
+    *        output if required.)
+    */
+#  define ZLIB_TOO_FAR_BACK (-1)
+#  define ZLIB_OK           0
+#  define ZLIB_STREAM_END   1
+#  define ZLIB_FATAL        2
+{
+   int state = zlib->state;
+   int endrc = ZLIB_OK;
+   png_uint_32 in_bytes = 0;
+   struct file *file = zlib->file;
+
+   assert(state >= 0);
+
+   while (in_bytes < nbytes && endrc == ZLIB_OK)
+   {
+      png_uint_32 out_bytes;
+      int flush;
+      png_byte bIn = reread_byte(file);
+      png_byte bOut;
+
+      switch (state)
+      {
+         case 0: /* first header byte */
+            {
+               int file_bits = 8+(bIn >> 4);
+               int new_bits = zlib->window_bits;
+
+               zlib->file_bits = file_bits;
+
+               /* Check against the existing value - it may not need to be
+                * changed.  Note that a bogus file_bits is allowed through once,
+                * to see if it works, but the window_bits value is set to 15,
+                * the maximum.
+                */
+               if (new_bits == 0) /* no change */
+                  zlib->window_bits = ((file_bits > 15) ? 15 : file_bits);
+
+               else if (new_bits != file_bits) /* rewrite required */
+                  bIn = (png_byte)((bIn & 0xf) + ((new_bits-8) << 4));
+            }
+
+            zlib->header[0] = bIn;
+            zlib->state = state = 1;
+            break;
+
+         case 1: /* second header byte */
+            {
+               int b2 = bIn & 0xe0; /* top 3 bits */
+
+               /* The checksum calculation, on the first 11 bits: */
+               b2 += 0x1f - ((zlib->header[0] << 8) + b2) % 0x1f;
+
+               /* Update the checksum byte if required: */
+               if (bIn != b2)
+               {
+                  /* If the first byte wasn't changed this indicates an error in
+                   * the checksum calculation; signal this by setting 'cksum'.
+                   */
+                  if (zlib->file_bits == zlib->window_bits)
+                     zlib->cksum = 1;
+
+                  bIn = (png_byte)b2;
+               }
+            }
+
+            zlib->header[1] = bIn;
+            zlib->state = state = 2;
+            break;
+
+         default: /* After the header bytes */
+            break;
+      }
+
+      /* For some streams, perhaps only those compressed with 'superfast
+       * compression' (which results in a lot of copying) Z_BUF_ERROR can happen
+       * immediately after all output has been flushed on the next input byte.
+       * This is handled below when Z_BUF_ERROR is detected by adding an output
+       * byte.
+       */
+      zlib->z.next_in = &bIn;
+      zlib->z.avail_in = 1;
+      zlib->z.next_out = &bOut;
+      zlib->z.avail_out = 0;     /* Initially */
+
+      /* Initially use Z_NO_FLUSH in an attempt to persuade zlib to look at this
+       * byte without confusing what is going on with output.
+       */
+      flush = Z_NO_FLUSH;
+      out_bytes = 0;
+
+      /* NOTE: expression 3 is only evaluated on 'continue', because of the
+       * 'break' at the end of this loop below.
+       */
+      for (;endrc == ZLIB_OK;
+         flush = Z_SYNC_FLUSH,
+         zlib->z.next_out = &bOut,
+         zlib->z.avail_out = 1,
+         ++out_bytes)
+      {
+         zlib->rc = inflate(&zlib->z, flush);
+         out_bytes -= zlib->z.avail_out;
+
+         switch (zlib->rc)
+         {
+            case Z_BUF_ERROR:
+               if (zlib->z.avail_out == 0)
+                  continue; /* Try another output byte. */
+
+               if (zlib->z.avail_in == 0)
+                  break; /* Try another input byte */
+
+               /* Both avail_out and avail_in are 1 yet zlib returned a code
+                * indicating no progress was possible.  This is unexpected.
+                */
+               zlib_message(zlib, 1/*unexpected*/);
+               endrc = ZLIB_FATAL; /* stop processing */
+               break;
+
+            case Z_OK:
+               /* Zlib is supposed to have made progress: */
+               assert(zlib->z.avail_out == 0 || zlib->z.avail_in == 0);
+               continue;
+
+            case Z_STREAM_END:
+               /* This is the successful end. */
+               zlib->state = 3; /* end of stream */
+               endrc = ZLIB_STREAM_END;
+               break;
+
+            case Z_NEED_DICT:
+               zlib_message(zlib, 0/*stream error*/);
+               endrc = ZLIB_FATAL;
+               break;
+
+            case Z_DATA_ERROR:
+               /* The too far back error can be corrected, others cannot: */
+               if (zlib->z.msg != NULL &&
+                  strcmp(zlib->z.msg, "invalid distance too far back") == 0)
+               {
+                  endrc = ZLIB_TOO_FAR_BACK;
+                  break;
+               }
+               /* FALLTHROUGH */
+
+            default:
+               zlib_message(zlib, 0/*stream error*/);
+               endrc = ZLIB_FATAL;
+               break;
+         } /* switch (inflate rc) */
+
+         /* Control gets here when further output is not possible; endrc may
+          * still be ZLIB_OK if more input is required.
+          */
+         break;
+      } /* for (output bytes) */
+
+      /* Keep a running count of output byte produced: */
+      zlib->uncompressed_digits = uarb_add32(zlib->uncompressed_bytes,
+         zlib->uncompressed_digits, out_bytes);
+
+      /* Keep going, the loop will terminate when endrc is no longer set to
+       * ZLIB_OK or all the input bytes have been consumed; meanwhile keep
+       * adding input bytes.
+       */
+      assert(zlib->z.avail_in == 0 || endrc != ZLIB_OK);
+
+      in_bytes += 1 - zlib->z.avail_in;
+   } /* while (input bytes) */
+
+   assert(in_bytes == nbytes || endrc != ZLIB_OK);
+
+   /* Update the running total of input bytes consumed */
+   zlib->compressed_digits = uarb_add32(zlib->compressed_bytes,
+      zlib->compressed_digits, in_bytes - zlib->z.avail_in);
+
+   /* At the end of the stream update the chunk with the accumulated
+    * information if it is an improvement:
+    */
+   if (endrc == ZLIB_STREAM_END && zlib->window_bits < zlib->ok_bits)
+   {
+      struct chunk *chunk = zlib->chunk;
+
+      chunk->uncompressed_digits = uarb_copy(chunk->uncompressed_bytes,
+         zlib->uncompressed_bytes, zlib->uncompressed_digits);
+      chunk->compressed_digits = uarb_copy(chunk->compressed_bytes,
+         zlib->compressed_bytes, zlib->compressed_digits);
+      chunk->rewrite_buffer[0] = zlib->header[0];
+      chunk->rewrite_buffer[1] = zlib->header[1];
+
+      if (zlib->window_bits != zlib->file_bits || zlib->cksum)
+      {
+         /* A rewrite is required */
+         chunk->rewrite_offset = zlib->rewrite_offset;
+         chunk->rewrite_length = 2;
+      }
+
+      else
+      {
+         chunk->rewrite_offset = 0;
+         chunk->rewrite_length = 0;
+      }
+
+      if (in_bytes < nbytes)
+         chunk_message(chunk, "extra compressed data");
+
+      zlib->extra_bytes = nbytes - in_bytes;
+      zlib->ok_bits = zlib->window_bits;
+   }
+
+   return endrc;
+}
+
+static int
+zlib_run(struct zlib *zlib)
+   /* Like zlib_advance but also handles a stream of IDAT chunks. */
+{
+   /* The 'extra_bytes' field is set by zlib_advance if there is extra
+    * compressed data in the chunk it handles (if it sees Z_STREAM_END before
+    * all the input data has been used.)  This function uses the value to update
+    * the correct chunk length, so the problem should only ever be detected once
+    * for each chunk.  zlib_advance outputs the error message, though see the
+    * IDAT specific check below.
+    */
+   zlib->extra_bytes = 0;
+
+   if (zlib->idat != NULL)
+   {
+      struct IDAT_list *list = zlib->idat->idat_list_head;
+      struct IDAT_list *last = zlib->idat->idat_list_tail;
+      int        skip = 0;
+
+      /* 'rewrite_offset' is the offset of the LZ data within the chunk, for
+       * IDAT it should be 0:
+       */
+      assert(zlib->rewrite_offset == 0);
+
+      /* Process each IDAT_list in turn; the caller has left the stream
+       * positioned at the start of the first IDAT chunk data.
+       */
+      for (;;)
+      {
+         unsigned int count = list->count;
+         unsigned int i;
+
+         for (i = 0; i<count; ++i)
+         {
+            int rc;
+
+            if (skip > 0) /* Skip CRC and next IDAT header */
+               skip_12(zlib->file);
+
+            skip = 12; /* for the next time */
+
+            rc = zlib_advance(zlib, list->lengths[i]);
+
+            switch (rc)
+            {
+               case ZLIB_OK: /* keep going */
+                  break;
+
+               case ZLIB_STREAM_END: /* stop */
+                  /* There may be extra chunks; if there are and one of them is
+                   * not zero length output the 'extra data' message.  Only do
+                   * this check if errors are being output.
+                   */
+                  if (zlib->global->errors && zlib->extra_bytes == 0)
+                  {
+                     struct IDAT_list *check = list;
+                     int j = i+1, jcount = count;
+
+                     for (;;)
+                     {
+                        for (; j<jcount; ++j)
+                           if (check->lengths[j] > 0)
+                           {
+                              chunk_message(zlib->chunk,
+                                 "extra compressed data");
+                              goto end_check;
+                           }
+
+                        if (check == last)
+                           break;
+
+                        check = check->next;
+                        jcount = check->count;
+                        j = 0;
+                     }
+                  }
+
+               end_check:
+                  /* Terminate the list at the current position, reducing the
+                   * length of the last IDAT too if required.
+                   */
+                  list->lengths[i] -= zlib->extra_bytes;
+                  list->count = i+1;
+                  zlib->idat->idat_list_tail = list;
+                  /* FALLTHROUGH */
+
+               default:
+                  return rc;
+            }
+         }
+
+         /* At the end of the compressed data and Z_STREAM_END was not seen. */
+         if (list == last)
+            return ZLIB_OK;
+
+         list = list->next;
+      }
+   }
+
+   else
+   {
+      struct chunk *chunk = zlib->chunk;
+      int rc;
+
+      assert(zlib->rewrite_offset < chunk->chunk_length);
+
+      rc = zlib_advance(zlib, chunk->chunk_length - zlib->rewrite_offset);
+
+      /* The extra bytes in the chunk are handled now by adjusting the chunk
+       * length to exclude them; the zlib data is always stored at the end of
+       * the PNG chunk (although clearly this is not necessary.)  zlib_advance
+       * has already output a warning message.
+       */
+      chunk->chunk_length -= zlib->extra_bytes;
+      return rc;
+   }
+}
+
+static int /* global function; not a member function */
+zlib_check(struct file *file, png_uint_32 offset)
+   /* Check the stream of zlib compressed data in either idat (if given) or (if
+    * not) chunk.  In fact it is zlib_run that handles the difference in reading
+    * a single chunk and a list of IDAT chunks.
+    *
+    * In either case the input file must be positioned at the first byte of zlib
+    * compressed data (the first header byte).
+    *
+    * The return value is true on success, including the case where the zlib
+    * header may need to be rewritten, and false on an unrecoverable error.
+    *
+    * In the case of IDAT chunks 'offset' should be 0.
+    */
+{
+   fpos_t start_pos;
+   struct zlib zlib;
+
+   /* Record the start of the LZ data to allow a re-read. */
+   file_getpos(file, &start_pos);
+
+   /* First test the existing (file) window bits: */
+   if (zlib_init(&zlib, file->idat, file->chunk, 0/*window bits*/, offset))
+   {
+      int min_bits, max_bits, rc;
+
+      /* The first run using the existing window bits. */
+      rc = zlib_run(&zlib);
+
+      switch (rc)
+      {
+         case ZLIB_TOO_FAR_BACK:
+            /* too far back error */
+            file->status_code |= TOO_FAR_BACK;
+            min_bits = zlib.window_bits + 1;
+            max_bits = 15;
+            break;
+
+         case ZLIB_STREAM_END:
+            if (!zlib.global->optimize_zlib &&
+               zlib.window_bits == zlib.file_bits && !zlib.cksum)
+            {
+               /* The trivial case where the stream is ok and optimization was
+                * not requested.
+                */
+               zlib_end(&zlib);
+               return 1;
+            }
+
+            max_bits = max_window_bits(zlib.uncompressed_bytes,
+               zlib.uncompressed_digits);
+            if (zlib.ok_bits < max_bits)
+               max_bits = zlib.ok_bits;
+            min_bits = 8;
+
+            /* cksum is set if there is an error in the zlib header checksum
+             * calculation in the original file (and this may be the only reason
+             * a rewrite is required).  We can't rely on the file window bits in
+             * this case, so do the optimization anyway.
+             */
+            if (zlib.cksum)
+               chunk_message(zlib.chunk, "zlib checksum");
+            break;
+
+
+         case ZLIB_OK:
+            /* Truncated stream; unrecoverable, gets converted to ZLIB_FATAL */
+            zlib.z.msg = PNGZ_MSG_CAST("[truncated]");
+            zlib_message(&zlib, 0/*expected*/);
+            /* FALLTHROUGH */
+
+         default:
+            /* Unrecoverable error; skip the chunk; a zlib_message has already
+             * been output.
+             */
+            zlib_end(&zlib);
+            return 0;
+      }
+
+      /* Optimize window bits or fix a too-far-back error.  min_bits and
+       * max_bits have been set appropriately, ok_bits records the bit value
+       * known to work.
+       */
+      while (min_bits < max_bits || max_bits < zlib.ok_bits/*if 16*/)
+      {
+         int test_bits = (min_bits + max_bits) >> 1;
+
+         if (zlib_reset(&zlib, test_bits))
+         {
+            file_setpos(file, &start_pos);
+            rc = zlib_run(&zlib);
+
+            switch (rc)
+            {
+               case ZLIB_TOO_FAR_BACK:
+                  min_bits = test_bits+1;
+                  if (min_bits > max_bits)
+                  {
+                     /* This happens when the stream really is damaged and it
+                      * contains a distance code that addresses bytes before
+                      * the start of the uncompressed data.
+                      */
+                     assert(test_bits == 15);
+
+                     /* Output the error that wasn't output before: */
+                     if (zlib.z.msg == NULL)
+                        zlib.z.msg = PNGZ_MSG_CAST(
+                           "invalid distance too far back");
+                     zlib_message(&zlib, 0/*stream error*/);
+                     zlib_end(&zlib);
+                     return 0;
+                  }
+                  break;
+
+               case ZLIB_STREAM_END: /* success */
+                  max_bits = test_bits;
+                  break;
+
+               default:
+                  /* A fatal error; this happens if a too-far-back error was
+                   * hiding a more serious error, zlib_advance has already
+                   * output a zlib_message.
+                   */
+                  zlib_end(&zlib);
+                  return 0;
+            }
+         }
+
+         else /* inflateReset2 failed */
+         {
+            zlib_end(&zlib);
+            return 0;
+         }
+      }
+
+      /* The loop guarantees this */
+      assert(zlib.ok_bits == max_bits);
+      zlib_end(&zlib);
+      return 1;
+   }
+
+   else /* zlib initialization failed - skip the chunk */
+   {
+      zlib_end(&zlib);
+      return 0;
+   }
+}
+
+/***************************** LIBPNG CALLBACKS *******************************/
+/* The strategy here is to run a regular libpng PNG file read but examine the
+ * input data (from the file) before passing it to libpng so as to be aware of
+ * the state we expect libpng to be in.  Warning and error callbacks are also
+ * intercepted so that they can be quieted and interpreted.  Interpretation
+ * depends on a somewhat risky string match for known error messages; let us
+ * hope that this can be fixed in the next version of libpng.
+ *
+ * The control structure is pointed to by the libpng error pointer.  It contains
+ * that set of structures which must persist across multiple read callbacks,
+ * which is pretty much everything except the 'zlib' control structure.
+ *
+ * The file structure is instantiated in the caller of the per-file routine, but
+ * the per-file routine contains the chunk and IDAT control structures.
+ */
+/* The three routines read_chunk, process_chunk and sync_stream can only be
+ * called via a call to read_chunk and only exit at a return from process_chunk.
+ * These routines could have been written as one confusing large routine,
+ * instead this code relies on the compiler to do tail call elimination.  The
+ * possible calls are as follows:
+ *
+ * read_chunk
+ *    -> sync_stream
+ *       -> process_chunk
+ *    -> process_chunk
+ *       -> read_chunk
+ *       returns
+ */
+static void read_chunk(struct file *file);
+static void
+process_chunk(struct file *file, png_uint_32 file_crc, png_uint_32 next_length,
+   png_uint_32 next_type)
+   /* Called when the chunk data has been read, next_length and next_type
+    * will be set for the next chunk (or 0 if this is IEND).
+    *
+    * When this routine returns, chunk_length and chunk_type will be set for the
+    * next chunk to write because if a chunk is skipped this return calls back
+    * to read_chunk.
+    */
+{
+   png_uint_32 type = file->type;
+
+   if (file->global->verbose > 1)
+   {
+      fputs("  ", stderr);
+      type_name(file->type, stderr);
+      fprintf(stderr, " %lu 0x%.8x 0x%.8x\n", (unsigned long)file->length,
+         file->crc ^ 0xffffffff, file_crc);
+   }
+
+   /* The basic structure seems correct but the CRC may not match, in this
+    * case assume that it is simply a bad CRC, either wrongly calculated or
+    * because of damaged stream data.
+    */
+   if ((file->crc ^ 0xffffffff) != file_crc)
+   {
+      /* The behavior is set by the 'skip' setting; if it is anything other
+       * than SKIP_BAD_CRC ignore the bad CRC and return the chunk, with a
+       * corrected CRC and possibly processed, to libpng.  Otherwise skip the
+       * chunk, which will result in a fatal error if the chunk is critical.
+       */
+      file->status_code |= CRC_ERROR;
+
+      /* Ignore the bad CRC  */
+      if (file->global->skip != SKIP_BAD_CRC)
+         type_message(file, type, "bad CRC");
+
+      /* This will cause an IEND with a bad CRC to stop */
+      else if (CRITICAL(type))
+         stop(file, READ_ERROR_CODE, "bad CRC in critical chunk");
+
+      else
+      {
+         type_message(file, type, "skipped: bad CRC");
+
+         /* NOTE: this cannot be reached for IEND because it is critical. */
+         goto skip_chunk;
+      }
+   }
+
+   /* Check for other 'skip' cases and handle these; these only apply to
+    * ancillary chunks (and not tRNS, which should probably have been a critical
+    * chunk.)
+    */
+   if (skip_chunk_type(file->global, type))
+      goto skip_chunk;
+
+   /* The chunk may still be skipped if problems are detected in the LZ data,
+    * however the LZ data check requires a chunk.  Handle this by instantiating
+    * a chunk unless an IDAT is already instantiated (IDAT control structures
+    * instantiate their own chunk.)
+    */
+   if (type != png_IDAT)
+      file->alloc(file, 0/*chunk*/);
+
+   else if (file->idat == NULL)
+      file->alloc(file, 1/*IDAT*/);
+
+   else
+   {
+      /* The chunk length must be updated for process_IDAT */
+      assert(file->chunk != NULL);
+      assert(file->chunk->chunk_type == png_IDAT);
+      file->chunk->chunk_length = file->length;
+   }
+
+   /* Record the 'next' information too, now that the original values for
+    * this chunk have been copied.  Notice that the IDAT chunks only make a
+    * copy of the position of the first chunk, this is fine - process_IDAT does
+    * not need the position of this chunk.
+    */
+   file->length = next_length;
+   file->type = next_type;
+   getpos(file);
+
+   /* Do per-type processing, note that if this code does not return from the
+    * function the chunk will be skipped.  The rewrite is cancelled here so that
+    * it can be set in the per-chunk processing.
+    */
+   file->chunk->rewrite_length = 0;
+   file->chunk->rewrite_offset = 0;
+   switch (type)
+   {
+      default:
+         return;
+
+      case png_IHDR:
+         /* Read this now and update the control structure with the information
+          * it contains.  The header is validated completely to ensure this is a
+          * PNG.
+          */
+         {
+            struct chunk *chunk = file->chunk;
+
+            if (chunk->chunk_length != 13)
+               stop_invalid(file, "IHDR length");
+
+            /* Read all the IHDR information and validate it. */
+            setpos(chunk);
+            file->width = reread_4(file);
+            file->height = reread_4(file);
+            file->bit_depth = reread_byte(file);
+            file->color_type = reread_byte(file);
+            file->compression_method = reread_byte(file);
+            file->filter_method = reread_byte(file);
+            file->interlace_method = reread_byte(file);
+
+            /* This validates all the fields, and calls stop_invalid if
+             * there is a problem.
+             */
+            calc_image_size(file);
+         }
+         return;
+
+         /* Ancillary chunks that require further processing: */
+      case png_zTXt: case png_iCCP:
+         if (process_zTXt_iCCP(file))
+            return;
+         chunk_end(&file->chunk);
+         file_setpos(file, &file->data_pos);
+         break;
+
+      case png_iTXt:
+         if (process_iTXt(file))
+            return;
+         chunk_end(&file->chunk);
+         file_setpos(file, &file->data_pos);
+         break;
+
+      case png_IDAT:
+         if (process_IDAT(file))
+            return;
+         /* First pass: */
+         assert(next_type == png_IDAT);
+         break;
+   }
+
+   /* Control reaches this point if the chunk must be skipped.  For chunks other
+    * than IDAT this means that the zlib compressed data is fatally damanged and
+    * the chunk will not be passed to libpng.  For IDAT it means that the end of
+    * the IDAT stream has not yet been reached and we must handle the next
+    * (IDAT) chunk.  If the LZ data in an IDAT stream cannot be read 'stop' must
+    * be used to halt parsing of the PNG.
+    */
+   read_chunk(file);
+   return;
+
+   /* This is the generic code to skip the current chunk; simply jump to the
+    * next one.
+    */
+skip_chunk:
+   file->length = next_length;
+   file->type = next_type;
+   getpos(file);
+   read_chunk(file);
+}
+
+static png_uint_32
+get32(png_bytep buffer, int offset)
+   /* Read a 32-bit value from an 8-byte circular buffer (used only below).
+    */
+{
+   return
+      (buffer[ offset    & 7] << 24) +
+      (buffer[(offset+1) & 7] << 16) +
+      (buffer[(offset+2) & 7] <<  8) +
+      (buffer[(offset+3) & 7]      );
+}
+
+static void
+sync_stream(struct file *file)
+   /* The stream seems to be messed up, attempt to resync from the current chunk
+    * header.  Executes stop on a fatal error, otherwise calls process_chunk.
+    */
+{
+   png_uint_32 file_crc;
+
+   file->status_code |= STREAM_ERROR;
+
+   if (file->global->verbose)
+   {
+      fputs(" SYNC ", stderr);
+      type_name(file->type, stderr);
+      putc('\n', stderr);
+   }
+
+   /* Return to the start of the chunk data */
+   file_setpos(file, &file->data_pos);
+   file->read_count = 8;
+
+   if (read_4(file, &file_crc) == 4) /* else completely truncated */
+   {
+      /* Ignore the recorded chunk length, proceed through the data looking for
+       * a leading sequence of bytes that match the CRC in the following four
+       * bytes.  Each time a match is found check the next 8 bytes for a valid
+       * length, chunk-type pair.
+       */
+      png_uint_32 length;
+      png_uint_32 type = file->type;
+      png_uint_32 crc = crc_init_4(type);
+      png_byte buffer[8];
+      unsigned int nread = 0, nused = 0;
+
+      for (length=0; length <= 0x7fffffff; ++length)
+      {
+         int ch;
+
+         if ((crc ^ 0xffffffff) == file_crc)
+         {
+            /* A match on the CRC; for IEND this is sufficient, but for anything
+             * else expect a following chunk header.
+             */
+            if (type == png_IEND)
+            {
+               file->length = length;
+               process_chunk(file, file_crc, 0, 0);
+               return;
+            }
+
+            else
+            {
+               /* Need 8 bytes */
+               while (nread < 8+nused)
+               {
+                  ch = read_byte(file);
+                  if (ch == EOF)
+                     goto truncated;
+                  buffer[(nread++) & 7] = (png_byte)ch;
+               }
+
+               /* Prevent overflow */
+               nread -= nused & ~7;
+               nused -= nused & ~7; /* or, nused &= 7 ;-) */
+
+               /* Examine the 8 bytes for a valid chunk header. */
+               {
+                  png_uint_32 next_length = get32(buffer, nused);
+
+                  if (next_length < 0x7fffffff)
+                  {
+                     png_uint_32 next_type = get32(buffer, nused+4);
+
+                     if (chunk_type_valid(next_type))
+                     {
+                        file->read_count -= 8;
+                        process_chunk(file, file_crc, next_length, next_type);
+                        return;
+                     }
+                  }
+
+                  /* Not valid, keep going. */
+               }
+            }
+         }
+
+         /* This catches up with the circular buffer which gets filled above
+          * while checking a chunk header.  This code is slightly tricky - if
+          * the chunk_type is IEND the buffer will never be used, if it is not
+          * the code will always read ahead exactly 8 bytes and pass this on to
+          * process_chunk.  So the invariant that IEND leaves the file position
+          * after the IEND CRC and other chunk leave it after the *next* chunk
+          * header is not broken.
+          */
+         if (nread <= nused)
+         {
+            ch = read_byte(file);
+
+            if (ch == EOF)
+               goto truncated;
+         }
+
+         else
+            ch = buffer[(++nused) & 7];
+
+         crc = crc_one_byte(crc, file_crc >> 24);
+         file_crc = (file_crc << 8) + ch;
+      }
+
+      /* Control gets to here if when 0x7fffffff bytes (plus 8) have been read,
+       * ok, treat this as a damaged stream too:
+       */
+   }
+
+truncated:
+   stop(file, READ_ERROR_CODE, "damaged PNG stream");
+}
+
+static void
+read_chunk(struct file *file)
+   /* On entry file::data_pos must be set to the position of the first byte
+    * of the chunk data *and* the input file must be at this position.  This
+    * routine (via process_chunk) instantiates a chunk or IDAT control structure
+    * based on file::length and file::type and also resets these fields and
+    * file::data_pos for the chunk after this one.  For an IDAT chunk the whole
+    * stream of IDATs will be read, until something other than an IDAT is
+    * encountered, and the file fields will be set for the chunk after the end
+    * of the stream of IDATs.
+    *
+    * For IEND the file::type field will be set to 0, and nothing beyond the end
+    * of the IEND chunk will have been read.
+    */
+{
+   png_uint_32 length = file->length;
+   png_uint_32 type = file->type;
+
+   /* After IEND file::type is set to 0, if libpng attempts to read
+    * more data at this point this is a bug in libpng.
+    */
+   if (type == 0)
+      stop(file, UNEXPECTED_ERROR_CODE, "read beyond IEND");
+
+   if (file->global->verbose > 2)
+   {
+      fputs("   ", stderr);
+      type_name(type, stderr);
+      fprintf(stderr, " %lu\n", (unsigned long)length);
+   }
+
+   /* Start the read_crc calculation with the chunk type, then read to the end
+    * of the chunk data (without processing it in any way) to check that it is
+    * all there and calculate the CRC.
+    */
+   file->crc = crc_init_4(type);
+   if (crc_read_many(file, length)) /* else it was truncated */
+   {
+      png_uint_32 file_crc; /* CRC read from file */
+      unsigned int nread = read_4(file, &file_crc);
+
+      if (nread == 4)
+      {
+         if (type != png_IEND) /* do not read beyond IEND */
+         {
+            png_uint_32 next_length;
+
+            nread += read_4(file, &next_length);
+            if (nread == 8 && next_length <= 0x7fffffff)
+            {
+               png_uint_32 next_type;
+
+               nread += read_4(file, &next_type);
+
+               if (nread == 12 && chunk_type_valid(next_type))
+               {
+                  /* Adjust the read count back to the correct value for this
+                   * chunk.
+                   */
+                  file->read_count -= 8;
+                  process_chunk(file, file_crc, next_length, next_type);
+                  return;
+               }
+            }
+         }
+
+         else /* IEND */
+         {
+            process_chunk(file, file_crc, 0, 0);
+            return;
+         }
+      }
+   }
+
+   /* Control gets to here if the stream seems invalid or damaged in some
+    * way.  Either there was a problem reading all the expected data (this
+    * chunk's data, its CRC and the length and type of the next chunk) or the
+    * next chunk length/type are invalid.  Notice that the cases that end up
+    * here all correspond to cases that would otherwise terminate the read of
+    * the PNG file.
+    */
+   sync_stream(file);
+}
+
+/* This returns a file* from a png_struct in an implementation specific way. */
+static struct file *get_control(png_const_structrp png_ptr);
+
+static void PNGCBAPI
+error_handler(png_structp png_ptr, png_const_charp message)
+{
+   stop(get_control(png_ptr),  LIBPNG_ERROR_CODE, message);
+}
+
+static void PNGCBAPI
+warning_handler(png_structp png_ptr, png_const_charp message)
+{
+   struct file *file = get_control(png_ptr);
+
+   if (file->global->warnings)
+      emit_error(file, LIBPNG_WARNING_CODE, message);
+}
+
+/* Read callback - this is where the work gets done to check the stream before
+ * passing it to libpng
+ */
+static void PNGCBAPI
+read_callback(png_structp png_ptr, png_bytep buffer, size_t count)
+   /* Return 'count' bytes to libpng in 'buffer' */
+{
+   struct file *file = get_control(png_ptr);
+   png_uint_32 type, length; /* For the chunk be *WRITTEN* */
+   struct chunk *chunk;
+
+   /* libpng should always ask for at least one byte */
+   if (count == 0)
+      stop(file, UNEXPECTED_ERROR_CODE, "read callback for 0 bytes");
+
+   /* The callback always reads ahead by 8 bytes - the signature or chunk header
+    * - these bytes are stored in chunk_length and chunk_type.  This block is
+    * executed once for the signature and once for the first chunk right at the
+    * start.
+    */
+   if (file->read_count < 8)
+   {
+      assert(file->read_count == 0);
+      assert((file->status_code & TRUNCATED) == 0);
+
+      (void)read_4(file, &file->length);
+
+      if (file->read_count == 4)
+         (void)read_4(file, &file->type);
+
+      if (file->read_count < 8)
+      {
+         assert((file->status_code & TRUNCATED) != 0);
+         stop(file, READ_ERROR_CODE, "not a PNG (too short)");
+      }
+
+      if (file->state == STATE_SIGNATURE)
+      {
+         if (file->length != sig1 || file->type != sig2)
+            stop(file, LIBPNG_ERROR_CODE, "not a PNG (signature)");
+
+         /* Else write it (this is the initialization of write_count, prior to
+          * this it contains CLEAR garbage.)
+          */
+         file->write_count = 0;
+      }
+
+      else
+      {
+         assert(file->state == STATE_CHUNKS);
+
+         /* The first chunk must be a well formed IHDR (this could be relaxed to
+          * use the checks in process_chunk, but that seems unnecessary.)
+          */
+         if (file->length != 13 || file->type != png_IHDR)
+            stop(file, LIBPNG_ERROR_CODE, "not a PNG (IHDR)");
+
+         /* The position of the data must be stored too */
+         getpos(file);
+      }
+   }
+
+   /* Retrieve previous state (because the read callbacks are made pretty much
+    * byte-by-byte in the sequential reader prior to 1.7).
+    */
+   chunk = file->chunk;
+
+   if (chunk != NULL)
+   {
+      length = chunk->chunk_length;
+      type = chunk->chunk_type;
+   }
+
+   else
+   {
+      /* This is the signature case; for IDAT and other chunks these values will
+       * be overwritten when read_chunk is called below.
+       */
+      length = file->length;
+      type = file->type;
+   }
+
+   do
+   {
+      png_uint_32 b;
+
+      /* Complete the read of a chunk; as a side effect this also instantiates
+       * a chunk control structure and sets the file length/type/data_pos fields
+       * for the *NEXT* chunk header.
+       *
+       * NOTE: at an IDAT any following IDAT chunks will also be read and the
+       * next_ fields will refer to the chunk after the last IDAT.
+       *
+       * NOTE: read_chunk only returns when it has read a chunk that must now be
+       * written.
+       */
+      if (file->state != STATE_SIGNATURE && chunk == NULL)
+      {
+         assert(file->read_count == 8);
+         assert(file->idat == NULL);
+         read_chunk(file);
+         chunk = file->chunk;
+         assert(chunk != NULL);
+
+         /* Do the initialization that was not done before. */
+         length = chunk->chunk_length;
+         type = chunk->chunk_type;
+
+         /* And start writing the new chunk. */
+         file->write_count = 0;
+      }
+
+      /* The chunk_ fields describe a chunk that must be written, or hold the
+       * signature.  Write the header first.  In the signature case this
+       * rewrites the signature.
+       */
+      switch (file->write_count)
+      {
+         case 0: b = length >> 24; break;
+         case 1: b = length >> 16; break;
+         case 2: b = length >>  8; break;
+         case 3: b = length      ; break;
+
+         case 4: b = type >> 24; break;
+         case 5: b = type >> 16; break;
+         case 6: b = type >>  8; break;
+         case 7: b = type      ; break;
+
+         case 8:
+            /* The header has been written.  If this is really the signature
+             * that's all that is required and we can go to normal chunk
+             * processing.
+             */
+            if (file->state == STATE_SIGNATURE)
+            {
+               /* The signature has been written, the tail call to read_callback
+                * below (it's just a goto to the start with a decent compiler)
+                * will read the IHDR header ahead and validate it.
+                */
+               assert(length == sig1 && type == sig2);
+               file->read_count = 0; /* Forces a header read */
+               file->state = STATE_CHUNKS; /* IHDR: checked above */
+               read_callback(png_ptr, buffer, count);
+               return;
+            }
+
+            else
+            {
+               assert(chunk != NULL);
+
+               /* Set up for write, notice that repositioning the input stream
+                * is only necessary if something is to be read from it.  Also
+                * notice that for the IDAT stream this must only happen once -
+                * on the first IDAT - to get back to the start of the list and
+                * this is done inside process_IDAT:
+                */
+               chunk->write_crc = crc_init_4(type);
+               if (file->state != STATE_IDAT && length > 0)
+                  setpos(chunk);
+            }
+            /* FALLTHROUGH */
+
+         default:
+            assert(chunk != NULL);
+
+            /* NOTE: the arithmetic below overflows and gives a large positive
+             * png_uint_32 value until the whole chunk data has been written.
+             */
+            switch (file->write_count - length)
+            {
+               /* Write the chunk data, normally this just comes from
+                * the file.  The only exception is for that part of a
+                * chunk which is zlib data and which must be rewritten,
+                * and IDAT chunks which can be completely
+                * reconstructed.
+                */
+               default:
+                  if (file->state == STATE_IDAT)
+                  {
+                     struct IDAT *idat = file->idat;
+
+                     assert(idat != NULL);
+
+                     /* Read an IDAT byte from the input stream of IDAT chunks.
+                      * Because the IDAT stream can be re-chunked this stream is
+                      * held in the struct IDAT members.  The chunk members, in
+                      * particular chunk_length (and therefore the length local)
+                      * refer to the output chunk.
+                      */
+                     while (idat->idat_index >= idat->idat_length)
+                     {
+                        /* Advance one chunk */
+                        struct IDAT_list *cur = idat->idat_cur;
+
+                        assert(idat->idat_index == idat->idat_length);
+                        assert(cur != NULL && cur->count > 0);
+
+                        /* NOTE: IDAT_list::count here, not IDAT_list::length */
+                        if (++(idat->idat_count) >= cur->count)
+                        {
+                           assert(idat->idat_count == cur->count);
+
+                           /* Move on to the next IDAT_list: */
+                           cur = cur->next;
+
+                           /* This is an internal error - read beyond the end of
+                            * the pre-calculated stream.
+                            */
+                           if (cur == NULL || cur->count == 0)
+                              stop(file, UNEXPECTED_ERROR_CODE,
+                                 "read beyond end of IDAT");
+
+                           idat->idat_count = 0;
+                           idat->idat_cur = cur;
+                        }
+
+                        idat->idat_index = 0;
+                        /* Zero length IDAT chunks are permitted, so the length
+                         * here may be 0.
+                         */
+                        idat->idat_length = cur->lengths[idat->idat_count];
+
+                        /* And skip 12 bytes to the next chunk data */
+                        skip_12(file);
+                     }
+
+                     /* The index is always that of the next byte, the rest of
+                      * the information is always the current IDAT chunk and the
+                      * current list.
+                      */
+                     ++(idat->idat_index);
+                  }
+
+                  /* Read the byte from the stream. */
+                  b = reread_byte(file);
+
+                  /* If the byte must be rewritten handle that here */
+                  if (chunk->rewrite_length > 0)
+                  {
+                     if (chunk->rewrite_offset > 0)
+                        --(chunk->rewrite_offset);
+
+                     else
+                     {
+                        b = chunk->rewrite_buffer[0];
+                        memmove(chunk->rewrite_buffer, chunk->rewrite_buffer+1,
+                           (sizeof chunk->rewrite_buffer)-
+                              (sizeof chunk->rewrite_buffer[0]));
+
+                        --(chunk->rewrite_length);
+                     }
+                  }
+
+                  chunk->write_crc = crc_one_byte(chunk->write_crc, b);
+                  break;
+
+               /* The CRC is written at:
+                *
+                *    chunk_write == chunk_length+8..chunk_length+11
+                *
+                * so 8 to 11.  The CRC is not (yet) conditioned.
+                */
+               case  8: b = chunk->write_crc >> 24; goto write_crc;
+               case  9: b = chunk->write_crc >> 16; goto write_crc;
+               case 10: b = chunk->write_crc >>  8; goto write_crc;
+               case 11:
+                  /* This must happen before the chunk_end below: */
+                  b = chunk->write_crc;
+
+                  if (file->global->verbose > 2)
+                  {
+                     fputs("   ", stderr);
+                     type_name(type, stderr);
+                     fprintf(stderr, " %lu 0x%.8x\n", (unsigned long)length,
+                        chunk->write_crc ^ 0xffffffff);
+                  }
+
+                  /* The IDAT stream is written without a call to read_chunk
+                   * until the end is reached.  rechunk_length() calculates the
+                   * length of the output chunks.  Control gets to this point at
+                   * the end of an *output* chunk - the length calculated by
+                   * rechunk_length.  If this corresponds to the end of the
+                   * input stream stop writing IDAT chunks, otherwise continue.
+                   */
+                  if (file->state == STATE_IDAT &&
+                     (file->idat->idat_index < file->idat->idat_length ||
+                      1+file->idat->idat_count < file->idat->idat_cur->count ||
+                      file->idat->idat_cur != file->idat->idat_list_tail))
+                  {
+                     /* Write another IDAT chunk.  Call rechunk_length to
+                      * calculate the length required.
+                      */
+                     length = chunk->chunk_length =
+                         rechunk_length(file->idat, 0/*end*/);
+                     assert(type == png_IDAT);
+                     file->write_count = 0; /* for the new chunk */
+                     --(file->write_count); /* fake out the increment below */
+                  }
+
+                  else
+                  {
+                     /* Entered at the end of a non-IDAT chunk and at the end of
+                      * the IDAT stream.  The rewrite should have been cleared.
+                      */
+                     if (chunk->rewrite_length > 0 || chunk->rewrite_offset > 0)
+                        stop(file, UNEXPECTED_ERROR_CODE, "pending rewrite");
+
+                     /* This is the last byte so reset chunk_read for the next
+                      * chunk and move the input file to the position after the
+                      * *next* chunk header if required.
+                      */
+                     file->read_count = 8;
+                     file_setpos(file, &file->data_pos);
+
+                     if (file->idat == NULL)
+                        chunk_end(&file->chunk);
+
+                     else
+                        IDAT_end(&file->idat);
+                  }
+
+               write_crc:
+                  b ^= 0xff; /* conditioning */
+                  break;
+            }
+            break;
+      }
+
+      /* Write one byte */
+      b &= 0xff;
+      *buffer++ = (png_byte)b;
+      --count;
+      write_byte(file, (png_byte)b); /* increments chunk_write */
+   }
+   while (count > 0);
+}
+
+/* Bundle the file and an uninitialized chunk and IDAT control structure
+ * together to allow implementation of the chunk/IDAT allocate routine.
+ */
+struct control
+{
+   struct file  file;
+   struct chunk chunk;
+   struct IDAT  idat;
+};
+
+static int
+control_end(struct control *control)
+{
+   return file_end(&control->file);
+}
+
+static struct file *
+get_control(png_const_structrp png_ptr)
+{
+   /* This just returns the (file*).  The chunk and idat control structures
+    * don't always exist.
+    */
+   struct control *control = voidcast(struct control*,
+      png_get_error_ptr(png_ptr));
+   return &control->file;
+}
+
+static void
+allocate(struct file *file, int allocate_idat)
+{
+   struct control *control = voidcast(struct control*, file->alloc_ptr);
+
+   if (allocate_idat)
+   {
+      assert(file->idat == NULL);
+      IDAT_init(&control->idat, file);
+   }
+
+   else /* chunk */
+   {
+      assert(file->chunk == NULL);
+      chunk_init(&control->chunk, file);
+   }
+}
+
+static int
+control_init(struct control *control, struct global *global,
+   const char *file_name, const char *out_name)
+   /* This wraps file_init(&control::file) and simply returns the result from
+    * file_init.
+    */
+{
+   return file_init(&control->file, global, file_name, out_name, control,
+      allocate);
+}
+
+static int
+read_png(struct control *control)
+   /* Read a PNG, return 0 on success else an error (status) code; a bit mask as
+    * defined for file::status_code as above.
+    */
+{
+   png_structp png_ptr;
+   png_infop info_ptr = NULL;
+   volatile int rc;
+
+   png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, control,
+      error_handler, warning_handler);
+
+   if (png_ptr == NULL)
+   {
+      /* This is not really expected. */
+      log_error(&control->file, LIBPNG_ERROR_CODE, "OOM allocating png_struct");
+      control->file.status_code |= INTERNAL_ERROR;
+      return LIBPNG_ERROR_CODE;
+   }
+
+   rc = setjmp(control->file.jmpbuf);
+   if (rc == 0)
+   {
+#     ifdef PNG_SET_USER_LIMITS_SUPPORTED
+         /* Remove any limits on the size of PNG files that can be read,
+          * without this we may reject files based on built-in safety
+          * limits.
+          */
+         png_set_user_limits(png_ptr, 0x7fffffff, 0x7fffffff);
+         png_set_chunk_cache_max(png_ptr, 0);
+         png_set_chunk_malloc_max(png_ptr, 0);
+#     endif
+
+      png_set_read_fn(png_ptr, control, read_callback);
+
+      info_ptr = png_create_info_struct(png_ptr);
+      if (info_ptr == NULL)
+         png_error(png_ptr, "OOM allocating info structure");
+
+      if (control->file.global->verbose)
+         fprintf(stderr, " INFO\n");
+
+      png_read_info(png_ptr, info_ptr);
+
+      {
+        png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
+        int passes = png_set_interlace_handling(png_ptr);
+        int pass;
+
+        png_start_read_image(png_ptr);
+
+        for (pass = 0; pass < passes; ++pass)
+        {
+           png_uint_32 y = height;
+
+           /* NOTE: this skips asking libpng to return either version of
+            * the image row, but libpng still reads the rows.
+            */
+           while (y-- > 0)
+              png_read_row(png_ptr, NULL, NULL);
+        }
+      }
+
+      if (control->file.global->verbose)
+         fprintf(stderr, " END\n");
+
+      /* Make sure to read to the end of the file: */
+      png_read_end(png_ptr, info_ptr);
+   }
+
+   png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
+   return rc;
+}
+
+static int
+one_file(struct global *global, const char *file_name, const char *out_name)
+{
+   int rc;
+   struct control control;
+
+   if (global->verbose)
+      fprintf(stderr, "FILE %s -> %s\n", file_name,
+         out_name ? out_name : "<none>");
+
+   /* Although control_init can return a failure code the structure is always
+    * initialized, so control_end can be used to accumulate any status codes.
+    */
+   rc = control_init(&control, global, file_name, out_name);
+
+   if (rc == 0)
+      rc = read_png(&control);
+
+   rc |= control_end(&control);
+
+   return rc;
+}
+
+static void
+usage(const char *prog)
+{
+   /* ANSI C-90 limits strings to 509 characters, so use a string array: */
+   size_t i;
+   static const char *usage_string[] = {
+"  Tests, optimizes and optionally fixes the zlib header in PNG files.",
+"  Optionally, when fixing, strips ancillary chunks from the file.",
+0,
+"OPTIONS",
+"  OPERATION",
+"      By default files are just checked for readability with a summary of the",
+"      of zlib issues founds for each compressed chunk and the IDAT stream in",
+"      the file.",
+"    --optimize (-o):",
+"      Find the smallest deflate window size for the compressed data.",
+"    --strip=[none|crc|unsafe|unused|transform|color|all]:",
+"        none (default):   Retain all chunks.",
+"        crc:    Remove chunks with a bad CRC.",
+"        unsafe: Remove chunks that may be unsafe to retain if the image data",
+"                is modified.  This is set automatically if --max is given but",
+"                may be cancelled by a later --strip=none.",
+"        unused: Remove chunks not used by libpng when decoding an image.",
+"                This retains any chunks that might be used by libpng image",
+"                transformations.",
+"        transform: unused+bKGD.",
+"        color:  transform+iCCP and cHRM.",
+"        all:    color+gAMA and sRGB.",
+"      Only ancillary chunks are ever removed.  In addition the tRNS and sBIT",
+"      chunks are never removed as they affect exact interpretation of the",
+"      image pixel values.  The following known chunks are treated specially",
+"      by the above options:",
+"        gAMA, sRGB [all]: These specify the gamma encoding used for the pixel",
+"            values.",
+"        cHRM, iCCP [color]: These specify how colors are encoded.  iCCP also",
+"            specifies the exact encoding of a pixel value; however, in",
+"            practice most programs will ignore it.",
+"        bKGD [transform]: This is used by libpng transforms."
+"    --max=<number>:",
+"      Use IDAT chunks sized <number>.  If no number is given the IDAT",
+"      chunks will be the maximum size permitted; 2^31-1 bytes.  If the option",
+"      is omitted the original chunk sizes will not be changed.  When the",
+"      option is given --strip=unsafe is set automatically. This may be",
+"      cancelled if you know that all unknown unsafe-to-copy chunks really are",
+"      safe to copy across an IDAT size change.  This is true of all chunks",
+"      that have ever been formally proposed as PNG extensions.",
+"  MESSAGES",
+"      By default the program only outputs summaries for each file.",
+"    --quiet (-q):",
+"      Do not output the summaries except for files that cannot be read. With",
+"      two --quiets these are not output either.",
+"    --errors (-e):",
+"      Output errors from libpng and the program (except too-far-back).",
+"    --warnings (-w):",
+"      Output warnings from libpng.",
+"  OUTPUT",
+"      By default nothing is written.",
+"    --out=<file>:",
+"      Write the optimized/corrected version of the next PNG to <file>.  This",
+"      overrides the following two options",
+"    --suffix=<suffix>:",
+"      Set --out=<name><suffix> for all following files unless overridden on",
+"      a per-file basis by explicit --out.",
+"    --prefix=<prefix>:",
+"      Set --out=<prefix><name> for all the following files unless overridden",
+"      on a per-file basis by explicit --out.",
+"      These two options can be used together to produce a suffix and prefix.",
+"  INTERNAL OPTIONS",
+#if 0 /*NYI*/
+#ifdef PNG_MAXIMUM_INFLATE_WINDOW
+"    --test:",
+"      Test the PNG_MAXIMUM_INFLATE_WINDOW option.  Setting this disables",
+"      output as this would produce a broken file.",
+#endif
+#endif
+0,
+"EXIT CODES",
+"  *** SUBJECT TO CHANGE ***",
+"  The program exit code is value in the range 0..127 holding a bit mask of",
+"  the following codes.  Notice that the results for each file are combined",
+"  together - check one file at a time to get a meaningful error code!",
+"    0x01: The zlib too-far-back error existed in at least one chunk.",
+"    0x02: At least one chunk had a CRC error.",
+"    0x04: A chunk length was incorrect.",
+"    0x08: The file was truncated.",
+"  Errors less than 16 are potentially recoverable, for a single file if the",
+"  exit code is less than 16 the file could be read (with corrections if a",
+"  non-zero code is returned).",
+"    0x10: The file could not be read, even with corrections.",
+"    0x20: The output file could not be written.",
+"    0x40: An unexpected, potentially internal, error occurred.",
+"  If the command line arguments are incorrect the program exits with exit",
+"  255.  Some older operating systems only support 7-bit exit codes, on those",
+"  systems it is suggested that this program is first tested by supplying",
+"  invalid arguments.",
+0,
+"DESCRIPTION",
+"  " PROGRAM_NAME ":",
+"  checks each PNG file on the command line for errors.  By default errors are",
+"  not output and the program just returns an exit code and prints a summary.",
+"  With the --quiet (-q) option the summaries are suppressed too and the",
+"  program only outputs unexpected errors (internal errors and file open",
+"  errors).",
+"  Various known problems in PNG files are fixed while the file is being read",
+"  The exit code says what problems were fixed.  In particular the zlib error:",
+0,
+"        \"invalid distance too far back\"",
+0,
+"  caused by an incorrect optimization of a zlib stream is fixed in any",
+"  compressed chunk in which it is encountered.  An integrity problem of the",
+"  PNG stream caused by a bug in libpng which wrote an incorrect chunk length",
+"  is also fixed.  Chunk CRC errors are automatically fixed up.",
+0,
+"  Setting one of the \"OUTPUT\" options causes the possibly modified file to",
+"  be written to a new file.",
+0,
+"  Notice that some PNG files with the zlib optimization problem can still be",
+"  read by libpng under some circumstances.  This program will still detect",
+"  and, if requested, correct the error.",
+0,
+"  The program will reliably process all files on the command line unless",
+"  either an invalid argument causes the usage message (this message) to be",
+"  produced or the program crashes.",
+0,
+"  The summary lines describe issues encountered with the zlib compressed",
+"  stream of a chunk.  They have the following format, which is SUBJECT TO",
+"  CHANGE in the future:",
+0,
+"     chunk reason comp-level p1 p2 p3 p4 file",
+0,
+"  p1 through p4 vary according to the 'reason'.  There are always 8 space",
+"  separated fields.  Reasons specific formats are:",
+0,
+"     chunk ERR status code read-errno write-errno message file",
+"     chunk SKP comp-level file-bits zlib-rc compressed message file",
+"     chunk ??? comp-level file-bits ok-bits compressed uncompress file",
+0,
+"  The various fields are",
+0,
+"$1 chunk:      The chunk type of a chunk in the file or 'HEAD' if a problem",
+"               is reported by libpng at the start of the IDAT stream.",
+"$2 reason:     One of:",
+"          CHK: A zlib header checksum was detected and fixed.",
+"          TFB: The zlib too far back error was detected and fixed.",
+"          OK : No errors were detected in the zlib stream and optimization",
+"               was not requested, or was not possible.",
+"          OPT: The zlib stream window bits value could be improved (and was).",
+"          SKP: The chunk was skipped because of a zlib issue (zlib-rc) with",
+"               explanation 'message'",
+"          ERR: The read of the file was aborted.  The parameters explain why.",
+"$3 status:     For 'ERR' the accumulated status code from 'EXIT CODES' above.",
+"               This is printed as a 2 digit hexadecimal value",
+"   comp-level: The recorded compression level (FLEVEL) of a zlib stream",
+"               expressed as a string {supfast,stdfast,default,maximum}",
+"$4 code:       The file exit code; where stop was called, as a fairly terse",
+"               string {warning,libpng,zlib,invalid,read,write,unexpected}.",
+"   file-bits:  The zlib window bits recorded in the file.",
+"$5 read-errno: A system errno value from a read translated by strerror(3).",
+"   zlib-rc:    A zlib return code as a string (see zlib.h).",
+"   ok-bits:    The smallest zlib window bits value that works.",
+"$6 write-errno:A system errno value from a write translated by strerror(3).",
+"   compressed: The count of compressed bytes in the zlib stream, when the",
+"               reason is 'SKP'; this is a count of the bytes read from the",
+"               stream when the fatal error was encountered.",
+"$7 message:    An error message (spaces replaced by _, as in all parameters),",
+"   uncompress: The count of bytes from uncompressing the zlib stream; this",
+"               may not be the same as the number of bytes in the image.",
+"$8 file:       The name of the file (this may contain spaces).",
+};
+
+   fprintf(stderr, "Usage: %s {[options] png-file}\n", prog);
+
+   for (i=0; i < (sizeof usage_string)/(sizeof usage_string[0]); ++i)
+   {
+      if (usage_string[i] != 0)
+         fputs(usage_string[i], stderr);
+
+      fputc('\n', stderr);
+   }
+
+   exit(255);
+}
+
+int
+main(int argc, const char **argv)
+{
+   char temp_name[FILENAME_MAX+1];
+   const char *  prog = *argv;
+   const char *  outfile = NULL;
+   const char *  suffix = NULL;
+   const char *  prefix = NULL;
+   int           done = 0; /* if at least one file is processed */
+   struct global global;
+
+   global_init(&global);
+
+   while (--argc > 0)
+   {
+      ++argv;
+
+      if (strcmp(*argv, "--debug") == 0)
+      {
+         /* To help debugging problems: */
+         global.errors = global.warnings = 1;
+         global.quiet = 0;
+         global.verbose = 7;
+      }
+
+      else if (strncmp(*argv, "--max=", 6) == 0)
+      {
+         global.idat_max = (png_uint_32)atol(6+*argv);
+
+         if (global.skip < SKIP_UNSAFE)
+            global.skip = SKIP_UNSAFE;
+      }
+
+      else if (strcmp(*argv, "--max") == 0)
+      {
+         global.idat_max = 0x7fffffff;
+
+         if (global.skip < SKIP_UNSAFE)
+            global.skip = SKIP_UNSAFE;
+      }
+
+      else if (strcmp(*argv, "--optimize") == 0 || strcmp(*argv, "-o") == 0)
+         global.optimize_zlib = 1;
+
+      else if (strncmp(*argv, "--out=", 6) == 0)
+         outfile = 6+*argv;
+
+      else if (strncmp(*argv, "--suffix=", 9) == 0)
+         suffix = 9+*argv;
+
+      else if (strncmp(*argv, "--prefix=", 9) == 0)
+         prefix = 9+*argv;
+
+      else if (strcmp(*argv, "--strip=none") == 0)
+         global.skip = SKIP_NONE;
+
+      else if (strcmp(*argv, "--strip=crc") == 0)
+         global.skip = SKIP_BAD_CRC;
+
+      else if (strcmp(*argv, "--strip=unsafe") == 0)
+         global.skip = SKIP_UNSAFE;
+
+      else if (strcmp(*argv, "--strip=unused") == 0)
+         global.skip = SKIP_UNUSED;
+
+      else if (strcmp(*argv, "--strip=transform") == 0)
+         global.skip = SKIP_TRANSFORM;
+
+      else if (strcmp(*argv, "--strip=color") == 0)
+         global.skip = SKIP_COLOR;
+
+      else if (strcmp(*argv, "--strip=all") == 0)
+         global.skip = SKIP_ALL;
+
+      else if (strcmp(*argv, "--errors") == 0 || strcmp(*argv, "-e") == 0)
+         global.errors = 1;
+
+      else if (strcmp(*argv, "--warnings") == 0 || strcmp(*argv, "-w") == 0)
+         global.warnings = 1;
+
+      else if (strcmp(*argv, "--quiet") == 0 || strcmp(*argv, "-q") == 0)
+      {
+         if (global.quiet)
+            global.quiet = 2;
+
+         else
+            global.quiet = 1;
+      }
+
+      else if (strcmp(*argv, "--verbose") == 0 || strcmp(*argv, "-v") == 0)
+         ++global.verbose;
+
+#if 0
+      /* NYI */
+#     ifdef PNG_MAXIMUM_INFLATE_WINDOW
+         else if (strcmp(*argv, "--test") == 0)
+            ++set_option;
+#     endif
+#endif
+
+      else if ((*argv)[0] == '-')
+         usage(prog);
+
+      else
+      {
+         size_t outlen = strlen(*argv);
+
+         if (outfile == NULL) /* else this takes precedence */
+         {
+            /* Consider the prefix/suffix options */
+            if (prefix != NULL)
+            {
+               size_t prefixlen = strlen(prefix);
+
+               if (prefixlen+outlen > FILENAME_MAX)
+               {
+                  fprintf(stderr, "%s: output file name too long: %s%s%s\n",
+                     prog, prefix, *argv, suffix ? suffix : "");
+                  global.status_code |= WRITE_ERROR;
+                  continue;
+               }
+
+               memcpy(temp_name, prefix, prefixlen);
+               memcpy(temp_name+prefixlen, *argv, outlen);
+               outlen += prefixlen;
+               outfile = temp_name;
+            }
+
+            else if (suffix != NULL)
+               memcpy(temp_name, *argv, outlen);
+
+            temp_name[outlen] = 0;
+
+            if (suffix != NULL)
+            {
+               size_t suffixlen = strlen(suffix);
+
+               if (outlen+suffixlen > FILENAME_MAX)
+               {
+                  fprintf(stderr, "%s: output file name too long: %s%s\n",
+                     prog, *argv, suffix);
+                  global.status_code |= WRITE_ERROR;
+                  continue;
+               }
+
+               memcpy(temp_name+outlen, suffix, suffixlen);
+               outlen += suffixlen;
+               temp_name[outlen] = 0;
+               outfile = temp_name;
+            }
+         }
+
+         (void)one_file(&global, *argv, outfile);
+         ++done;
+         outfile = NULL;
+      }
+   }
+
+   if (!done)
+      usage(prog);
+
+   return global_end(&global);
+}
+
+#else /* ZLIB_VERNUM < 0x1240 */
+int
+main(void)
+{
+   fprintf(stderr,
+      "pngfix needs libpng with a zlib >=1.2.4 (not 0x%x)\n",
+      ZLIB_VERNUM);
+   return 77;
+}
+#endif /* ZLIB_VERNUM */
+
+#else /* No read support */
+
+int
+main(void)
+{
+   fprintf(stderr, "pngfix does not work without read deinterlace support\n");
+   return 77;
+}
+#endif /* PNG_READ_SUPPORTED && PNG_EASY_ACCESS_SUPPORTED */
+#else /* No setjmp support */
+int
+main(void)
+{
+   fprintf(stderr, "pngfix does not work without setjmp support\n");
+   return 77;
+}
+#endif /* PNG_SETJMP_SUPPORTED */
+
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/reindent b/ap/lib/libpng/libpng-1.6.37/contrib/tools/reindent
new file mode 100755
index 0000000..f4df309
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/reindent
@@ -0,0 +1,25 @@
+#!/bin/sh
+
+# reindent a libpng C source
+
+# COPYRIGHT: Written by Glenn Randers-Pehrson, 2016.
+# To the extent possible under law, the author has waived all copyright and
+# related or neighboring rights to this work.  This work is published from:
+# United States.
+
+# Usage:
+# reindent inputtabsize outputtabsize inputcontinuestring outputcontinuestring
+#
+# Assumes that continued lines begin with indentation plus one space, and
+# that continued comments begin with indentation plus " *".
+#
+# eg, to change libpng coding style from 3-space indentation with 4-space
+# continuations to 4-space indentation with 2-space continuations:
+#
+#  reindent 3 4 "\t " "  " < example.c > example.c_4_2
+# and to restore the file back to libpng coding style
+#  reindent 4 3 "  " "    " < example.c_4_2 > example.c_3_4
+
+unexpand --first-only --t $1 | \
+   sed -e "/^	*$3[^\*]/{s/$3/$4/}" | \
+   expand -t $2
diff --git a/ap/lib/libpng/libpng-1.6.37/contrib/tools/sRGB.h b/ap/lib/libpng/libpng-1.6.37/contrib/tools/sRGB.h
new file mode 100755
index 0000000..d1ece51
--- /dev/null
+++ b/ap/lib/libpng/libpng-1.6.37/contrib/tools/sRGB.h
@@ -0,0 +1,48 @@
+/*-
+ * sRGB.h
+ *
+ * Last changed in libpng 1.6.0 [February 14, 2013]
+ *
+ * COPYRIGHT: Written by John Cunningham Bowler, 2013.
+ * To the extent possible under law, the author has waived all copyright and
+ * related or neighboring rights to this work.  This work is published from:
+ * United States.
+ *
+ * Utility file; not actually a header, this contains definitions of sRGB
+ * calculation functions for inclusion in those test programs that need them.
+ *
+ * All routines take and return a floating point value in the range
+ * 0 to 1.0, doing a calculation according to the sRGB specification
+ * (in fact the source of the numbers is the wikipedia article at
+ * https://en.wikipedia.org/wiki/SRGB).
+ */
+static double
+sRGB_from_linear(double l)
+{
+   if (l <= 0.0031308)
+      l *= 12.92;
+
+   else
+      l = 1.055 * pow(l, 1/2.4) - 0.055;
+
+   return l;
+}
+
+static double
+linear_from_sRGB(double s)
+{
+   if (s <= 0.04045)
+      return s / 12.92;
+
+   else
+      return pow((s+0.055)/1.055, 2.4);
+}
+
+static double
+YfromRGB(double r, double g, double b)
+{
+   /* Use the sRGB (rounded) coefficients for Rlinear, Glinear, Blinear to get
+    * the CIE Y value (also linear).
+    */
+   return 0.2126 * r + 0.7152 * g + 0.0722 * b;
+}