Delete //third_party/libpng16

Deletes now-unused copy of libpng in //third_party/libpng16.

Bug: chromium:1130821
Change-Id: If6c2effe3fbac7f2ac0ac2b461be8cf68f454bab
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/101230
Commit-Queue: K. Moon <kmoon@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/BUILD.gn b/core/fxcrt/BUILD.gn
index 867fc0d..923afe2 100644
--- a/core/fxcrt/BUILD.gn
+++ b/core/fxcrt/BUILD.gn
@@ -123,7 +123,6 @@
     "../../third_party:fx_agg",
     "../../third_party:fx_lcms2",
     "../../third_party:fx_libopenjpeg",
-    "../../third_party:fx_lpng",
     "../../third_party:fx_tiff",
     "../../xfa/*",
   ]
diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn
index b30538a..44a28b5 100644
--- a/third_party/BUILD.gn
+++ b/third_party/BUILD.gn
@@ -447,76 +447,6 @@
   }
 }
 
-source_set("fx_lpng") {
-  configs -= [ "//build/config/compiler:chromium_code" ]
-  configs += [
-    "//build/config/compiler:no_chromium_code",
-    ":pdfium_third_party_config",
-  ]
-  sources = [
-    "libpng16/png.c",
-    "libpng16/png.h",
-    "libpng16/pngconf.h",
-    "libpng16/pngdebug.h",
-    "libpng16/pngerror.c",
-    "libpng16/pngget.c",
-    "libpng16/pnginfo.h",
-    "libpng16/pnglibconf.h",
-    "libpng16/pngmem.c",
-    "libpng16/pngpread.c",
-    "libpng16/pngprefix.h",
-    "libpng16/pngpriv.h",
-    "libpng16/pngread.c",
-    "libpng16/pngrio.c",
-    "libpng16/pngrtran.c",
-    "libpng16/pngrutil.c",
-    "libpng16/pngset.c",
-    "libpng16/pngstruct.h",
-    "libpng16/pngtrans.c",
-    "libpng16/pngwio.c",
-    "libpng16/pngwrite.c",
-    "libpng16/pngwtran.c",
-    "libpng16/pngwutil.c",
-  ]
-
-  defines = []
-  cflags = []
-  deps = [
-    ":zlib",
-    "../core/fxcrt",
-  ]
-
-  if (current_cpu == "x86" || current_cpu == "x64") {
-    sources += [
-      "libpng16/intel/filter_sse2_intrinsics.c",
-      "libpng16/intel/intel_init.c",
-    ]
-    defines += [ "PNG_INTEL_SSE_OPT=1" ]
-  } else if ((current_cpu == "arm" || current_cpu == "arm64") && arm_use_neon) {
-    sources += [
-      "libpng16/arm/arm_init.c",
-      "libpng16/arm/filter_neon_intrinsics.c",
-      "libpng16/arm/palette_neon_intrinsics.c",
-    ]
-    defines += [
-      "PNG_ARM_NEON_OPT=2",
-      "PNG_ARM_NEON_IMPLEMENTATION=1",
-    ]
-    configs -= [ "//build/config/compiler:default_optimization" ]
-    configs += [ "//build/config/compiler:optimize_speed" ]
-  } else if (current_cpu == "mips64el" && mips_use_msa) {
-    sources += [
-      "mips/filter_msa_intrinsics.c",
-      "mips/mips_init.c",
-    ]
-  }
-
-  if (is_win) {
-    # Unary minus applied to unsigned type.
-    cflags += [ "/wd4146" ]
-  }
-}
-
 if (pdf_enable_xfa_tiff) {
   source_set("fx_tiff") {
     configs -= [ "//build/config/compiler:chromium_code" ]
diff --git a/third_party/libpng16/0000-build-config.patch b/third_party/libpng16/0000-build-config.patch
deleted file mode 100644
index 7d4b491..0000000
--- a/third_party/libpng16/0000-build-config.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-diff a/third_party/libpng16/pngmem.c b/third_party/libpng16/pngmem.c
---- a/third_party/libpng16/pngmem.c
-+++ b/third_party/libpng16/pngmem.c
-@@ -19,6 +19,8 @@
- 
- #include "pngpriv.h"
- 
-+#include "core/fxcrt/fx_memory.h"
-+
- #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
- /* Free a png_struct */
- void /* PRIVATE */
-@@ -91,7 +94,7 @@
- 
-       else
- #endif
--         return malloc((size_t)size); /* checked for truncation above */
-+         return FXMEM_DefaultAlloc(size);
-    }
- 
-    else
-@@ -248,7 +251,7 @@
-       return;
- #endif /* USER_MEM */
- 
--   free(ptr);
-+   FXMEM_DefaultFree(ptr);
- }
- 
- #ifdef PNG_USER_MEM_SUPPORTED
diff --git a/third_party/libpng16/0001-unused-variable.patch b/third_party/libpng16/0001-unused-variable.patch
deleted file mode 100644
index ad61072..0000000
--- a/third_party/libpng16/0001-unused-variable.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-diff --git a/third_party/libpng16/pngread.c b/third_party/libpng16/pngread.c
-index 8fa7d9f16..5ab922403 100644
---- a/third_party/libpng16/pngread.c
-+++ b/third_party/libpng16/pngread.c
-@@ -3452,7 +3452,6 @@ png_image_read_background(png_voidp argument)
- 
-             for (pass = 0; pass < passes; ++pass)
-             {
--               png_bytep row = png_voidcast(png_bytep, display->first_row);
-                unsigned int     startx, stepx, stepy;
-                png_uint_32      y;
- 
-@@ -3557,8 +3556,6 @@ png_image_read_background(png_voidp argument)
- 
-                         inrow += 2; /* gray and alpha channel */
-                      }
--
--                     row += display->row_bytes;
-                   }
-                }
-             }
diff --git a/third_party/libpng16/0002-static-png-gt.patch b/third_party/libpng16/0002-static-png-gt.patch
deleted file mode 100644
index b2b1d94..0000000
--- a/third_party/libpng16/0002-static-png-gt.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-diff --git a/third_party/libpng16/png.c b/third_party/libpng16/png.c
-index c183e3f..1cf5271 100644
---- a/third_party/libpng16/png.c
-+++ b/third_party/libpng16/png.c
-@@ -2464,7 +2464,8 @@ png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
- 
- #endif /* COLORSPACE */
- 
--#ifdef __GNUC__
-+/* #ifdef __GNUC__ */
-+#if 1
- /* This exists solely to work round a warning from GNU C. */
- static int /* PRIVATE */
- png_gt(size_t a, size_t b)
diff --git a/third_party/libpng16/LICENSE b/third_party/libpng16/LICENSE
deleted file mode 100644
index e0c5b53..0000000
--- a/third_party/libpng16/LICENSE
+++ /dev/null
@@ -1,134 +0,0 @@
-COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
-=========================================
-
-PNG Reference Library License version 2
----------------------------------------
-
- * Copyright (c) 1995-2019 The PNG Reference Library Authors.
- * Copyright (c) 2018-2019 Cosmin Truta.
- * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
- * Copyright (c) 1996-1997 Andreas Dilger.
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
-
-The software is supplied "as is", without warranty of any kind,
-express or implied, including, without limitation, the warranties
-of merchantability, fitness for a particular purpose, title, and
-non-infringement.  In no event shall the Copyright owners, or
-anyone distributing the software, be liable for any damages or
-other liability, whether in contract, tort or otherwise, arising
-from, out of, or in connection with the software, or the use or
-other dealings in the software, even if advised of the possibility
-of such damage.
-
-Permission is hereby granted to use, copy, modify, and distribute
-this software, or portions hereof, for any purpose, without fee,
-subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you
-    must not claim that you wrote the original software.  If you
-    use this software in a product, an acknowledgment in the product
-    documentation would be appreciated, but is not required.
-
- 2. Altered source versions must be plainly marked as such, and must
-    not be misrepresented as being the original software.
-
- 3. This Copyright notice may not be removed or altered from any
-    source or altered source distribution.
-
-
-PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
------------------------------------------------------------------------
-
-libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
-Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
-derived from libpng-1.0.6, and are distributed according to the same
-disclaimer and license as libpng-1.0.6 with the following individuals
-added to the list of Contributing Authors:
-
-    Simon-Pierre Cadieux
-    Eric S. Raymond
-    Mans Rullgard
-    Cosmin Truta
-    Gilles Vollant
-    James Yu
-    Mandar Sahastrabuddhe
-    Google Inc.
-    Vadim Barkov
-
-and with the following additions to the disclaimer:
-
-    There is no warranty against interference with your enjoyment of
-    the library or against infringement.  There is no warranty that our
-    efforts or the library will fulfill any of your particular purposes
-    or needs.  This library is provided with all faults, and the entire
-    risk of satisfactory quality, performance, accuracy, and effort is
-    with the user.
-
-Some files in the "contrib" directory and some configure-generated
-files that are distributed with libpng have other copyright owners, and
-are released under other open source licenses.
-
-libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
-Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
-libpng-0.96, and are distributed according to the same disclaimer and
-license as libpng-0.96, with the following individuals added to the
-list of Contributing Authors:
-
-    Tom Lane
-    Glenn Randers-Pehrson
-    Willem van Schaik
-
-libpng versions 0.89, June 1996, through 0.96, May 1997, are
-Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
-and are distributed according to the same disclaimer and license as
-libpng-0.88, with the following individuals added to the list of
-Contributing Authors:
-
-    John Bowler
-    Kevin Bracey
-    Sam Bushell
-    Magnus Holmgren
-    Greg Roelofs
-    Tom Tanner
-
-Some files in the "scripts" directory have other copyright owners,
-but are released under this license.
-
-libpng versions 0.5, May 1995, through 0.88, January 1996, are
-Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
-
-For the purposes of this copyright and license, "Contributing Authors"
-is defined as the following set of individuals:
-
-    Andreas Dilger
-    Dave Martindale
-    Guy Eric Schalnat
-    Paul Schmidt
-    Tim Wegner
-
-The PNG Reference Library is supplied "AS IS".  The Contributing
-Authors and Group 42, Inc. disclaim all warranties, expressed or
-implied, including, without limitation, the warranties of
-merchantability and of fitness for any purpose.  The Contributing
-Authors and Group 42, Inc. assume no liability for direct, indirect,
-incidental, special, exemplary, or consequential damages, which may
-result from the use of the PNG Reference Library, even if advised of
-the possibility of such damage.
-
-Permission is hereby granted to use, copy, modify, and distribute this
-source code, or portions hereof, for any purpose, without fee, subject
-to the following restrictions:
-
- 1. The origin of this source code must not be misrepresented.
-
- 2. Altered versions must be plainly marked as such and must not
-    be misrepresented as being the original source.
-
- 3. This Copyright notice may not be removed or altered from any
-    source or altered source distribution.
-
-The Contributing Authors and Group 42, Inc. specifically permit,
-without fee, and encourage the use of this source code as a component
-to supporting the PNG file format in commercial products.  If you use
-this source code in a product, acknowledgment is not required but would
-be appreciated.
diff --git a/third_party/libpng16/README.pdfium b/third_party/libpng16/README.pdfium
deleted file mode 100644
index 8c96461..0000000
--- a/third_party/libpng16/README.pdfium
+++ /dev/null
@@ -1,21 +0,0 @@
-Name: libpng
-URL: http://libpng.org/
-Version: 1.6.37
-CPEPrefix: cpe:/a:libpng:libpng:1.6.37
-Security Critical: yes
-License: libpng license
-License Android Compatible: yes
-
-Description:
-PNG library.
-
-Local Modifications:
-
-Local changes in Chromium's copy of libpng as of
-e87a02987101e2dbe319a4aba6b52470f7624b4a - see README.chromium.
-
-pnglibconf.h: a copy of libpng's scripts/pnglibconf.h.prebuilt.
-pngprefix.h: manually-created redefinitions to avoid conflicts with Chromium.
-0000-build-config.patch: Local build configuration changes.
-0001-unused-variable.patch: Fix -Wunused-but-set-variable.
-0002-static-png-gt.patch: Unconditionally use static png_gt() in png.c to avoid compilation warning.
diff --git a/third_party/libpng16/arm/arm_init.c b/third_party/libpng16/arm/arm_init.c
deleted file mode 100644
index a34ecdb..0000000
--- a/third_party/libpng16/arm/arm_init.c
+++ /dev/null
@@ -1,136 +0,0 @@
-
-/* arm_init.c - NEON optimised filter functions
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 2014,2016 Glenn Randers-Pehrson
- * Written by Mans Rullgard, 2011.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
- * called.
- */
-#define _POSIX_SOURCE 1
-
-#include "../pngpriv.h"
-
-#ifdef PNG_READ_SUPPORTED
-
-#if PNG_ARM_NEON_OPT > 0
-#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */
-/* WARNING: it is strongly recommended that you do not build libpng with
- * run-time checks for CPU features if at all possible.  In the case of the ARM
- * NEON instructions there is no processor-specific way of detecting the
- * presence of the required support, therefore run-time detection is extremely
- * OS specific.
- *
- * You may set the macro PNG_ARM_NEON_FILE to the file name of file containing
- * a fragment of C source code which defines the png_have_neon function.  There
- * are a number of implementations in contrib/arm-neon, but the only one that
- * has partial support is contrib/arm-neon/linux.c - a generic Linux
- * implementation which reads /proc/cpufino.
- */
-#ifndef PNG_ARM_NEON_FILE
-#  ifdef __linux__
-#     define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
-#  endif
-#endif
-
-#ifdef PNG_ARM_NEON_FILE
-
-#include <signal.h> /* for sig_atomic_t */
-static int png_have_neon(png_structp png_ptr);
-#include PNG_ARM_NEON_FILE
-
-#else  /* PNG_ARM_NEON_FILE */
-#  error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks"
-#endif /* PNG_ARM_NEON_FILE */
-#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
-
-#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
-#  error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
-#endif
-
-void
-png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
-{
-   /* The switch statement is compiled in for ARM_NEON_API, the call to
-    * png_have_neon is compiled in for ARM_NEON_CHECK.  If both are defined
-    * the check is only performed if the API has not set the NEON option on
-    * or off explicitly.  In this case the check controls what happens.
-    *
-    * If the CHECK is not compiled in and the option is UNSET the behavior prior
-    * to 1.6.7 was to use the NEON code - this was a bug caused by having the
-    * wrong order of the 'ON' and 'default' cases.  UNSET now defaults to OFF,
-    * as documented in png.h
-    */
-   png_debug(1, "in png_init_filter_functions_neon");
-#ifdef PNG_ARM_NEON_API_SUPPORTED
-   switch ((pp->options >> PNG_ARM_NEON) & 3)
-   {
-      case PNG_OPTION_UNSET:
-         /* Allow the run-time check to execute if it has been enabled -
-          * thus both API and CHECK can be turned on.  If it isn't supported
-          * this case will fall through to the 'default' below, which just
-          * returns.
-          */
-#endif /* PNG_ARM_NEON_API_SUPPORTED */
-#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
-         {
-            static volatile sig_atomic_t no_neon = -1; /* not checked */
-
-            if (no_neon < 0)
-               no_neon = !png_have_neon(pp);
-
-            if (no_neon)
-               return;
-         }
-#ifdef PNG_ARM_NEON_API_SUPPORTED
-         break;
-#endif
-#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
-
-#ifdef PNG_ARM_NEON_API_SUPPORTED
-      default: /* OFF or INVALID */
-         return;
-
-      case PNG_OPTION_ON:
-         /* Option turned on */
-         break;
-   }
-#endif
-
-   /* IMPORTANT: any new external functions used here must be declared using
-    * PNG_INTERNAL_FUNCTION in ../pngpriv.h.  This is required so that the
-    * 'prefix' option to configure works:
-    *
-    *    ./configure --with-libpng-prefix=foobar_
-    *
-    * Verify you have got this right by running the above command, doing a build
-    * and examining pngprefix.h; it must contain a #define for every external
-    * function you add.  (Notice that this happens automatically for the
-    * initialization function.)
-    */
-   pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
-
-   if (bpp == 3)
-   {
-      pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
-      pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
-      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
-         png_read_filter_row_paeth3_neon;
-   }
-
-   else if (bpp == 4)
-   {
-      pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
-      pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
-      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
-          png_read_filter_row_paeth4_neon;
-   }
-}
-#endif /* PNG_ARM_NEON_OPT > 0 */
-#endif /* READ */
diff --git a/third_party/libpng16/arm/filter_neon.S b/third_party/libpng16/arm/filter_neon.S
deleted file mode 100644
index 2308aad..0000000
--- a/third_party/libpng16/arm/filter_neon.S
+++ /dev/null
@@ -1,253 +0,0 @@
-
-/* filter_neon.S - NEON optimised filter functions
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 2014,2017 Glenn Randers-Pehrson
- * Written by Mans Rullgard, 2011.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-/* This is required to get the symbol renames, which are #defines, and the
- * definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
- */
-#define PNG_VERSION_INFO_ONLY
-#include "../pngpriv.h"
-
-#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__)
-.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
-#endif
-
-#ifdef PNG_READ_SUPPORTED
-
-/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for
- * ARM64).  The code in arm/filter_neon_intrinsics.c supports ARM64, however it
- * only works if -mfpu=neon is specified on the GCC command line.  See pngpriv.h
- * for the logic which sets PNG_USE_ARM_NEON_ASM:
- */
-#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */
-
-#if PNG_ARM_NEON_OPT > 0
-
-#ifdef __ELF__
-#   define ELF
-#else
-#   define ELF @
-#endif
-
-        .arch armv7-a
-        .fpu  neon
-
-.macro  func    name, export=0
-    .macro endfunc
-ELF     .size   \name, . - \name
-        .endfunc
-        .purgem endfunc
-    .endm
-        .text
-
-        /* Explicitly specifying alignment here because some versions of
-         * GAS don't align code correctly.  This is harmless in correctly
-         * written versions of GAS.
-         */
-        .align 2
-
-    .if \export
-        .global \name
-    .endif
-ELF     .type   \name, STT_FUNC
-        .func   \name
-\name:
-.endm
-
-func    png_read_filter_row_sub4_neon, export=1
-        ldr             r3,  [r0, #4]           @ rowbytes
-        vmov.i8         d3,  #0
-1:
-        vld4.32         {d4[],d5[],d6[],d7[]},    [r1,:128]
-        vadd.u8         d0,  d3,  d4
-        vadd.u8         d1,  d0,  d5
-        vadd.u8         d2,  d1,  d6
-        vadd.u8         d3,  d2,  d7
-        vst4.32         {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
-        subs            r3,  r3,  #16
-        bgt             1b
-
-        bx              lr
-endfunc
-
-func    png_read_filter_row_sub3_neon, export=1
-        ldr             r3,  [r0, #4]           @ rowbytes
-        vmov.i8         d3,  #0
-        mov             r0,  r1
-        mov             r2,  #3
-        mov             r12, #12
-        vld1.8          {q11},    [r0], r12
-1:
-        vext.8          d5,  d22, d23, #3
-        vadd.u8         d0,  d3,  d22
-        vext.8          d6,  d22, d23, #6
-        vadd.u8         d1,  d0,  d5
-        vext.8          d7,  d23, d23, #1
-        vld1.8          {q11},    [r0], r12
-        vst1.32         {d0[0]},  [r1,:32], r2
-        vadd.u8         d2,  d1,  d6
-        vst1.32         {d1[0]},  [r1], r2
-        vadd.u8         d3,  d2,  d7
-        vst1.32         {d2[0]},  [r1], r2
-        vst1.32         {d3[0]},  [r1], r2
-        subs            r3,  r3,  #12
-        bgt             1b
-
-        bx              lr
-endfunc
-
-func    png_read_filter_row_up_neon, export=1
-        ldr             r3,  [r0, #4]           @ rowbytes
-1:
-        vld1.8          {q0}, [r1,:128]
-        vld1.8          {q1}, [r2,:128]!
-        vadd.u8         q0,  q0,  q1
-        vst1.8          {q0}, [r1,:128]!
-        subs            r3,  r3,  #16
-        bgt             1b
-
-        bx              lr
-endfunc
-
-func    png_read_filter_row_avg4_neon, export=1
-        ldr             r12, [r0, #4]           @ rowbytes
-        vmov.i8         d3,  #0
-1:
-        vld4.32         {d4[],d5[],d6[],d7[]},    [r1,:128]
-        vld4.32         {d16[],d17[],d18[],d19[]},[r2,:128]!
-        vhadd.u8        d0,  d3,  d16
-        vadd.u8         d0,  d0,  d4
-        vhadd.u8        d1,  d0,  d17
-        vadd.u8         d1,  d1,  d5
-        vhadd.u8        d2,  d1,  d18
-        vadd.u8         d2,  d2,  d6
-        vhadd.u8        d3,  d2,  d19
-        vadd.u8         d3,  d3,  d7
-        vst4.32         {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
-        subs            r12, r12, #16
-        bgt             1b
-
-        bx              lr
-endfunc
-
-func    png_read_filter_row_avg3_neon, export=1
-        push            {r4,lr}
-        ldr             r12, [r0, #4]           @ rowbytes
-        vmov.i8         d3,  #0
-        mov             r0,  r1
-        mov             r4,  #3
-        mov             lr,  #12
-        vld1.8          {q11},    [r0], lr
-1:
-        vld1.8          {q10},    [r2], lr
-        vext.8          d5,  d22, d23, #3
-        vhadd.u8        d0,  d3,  d20
-        vext.8          d17, d20, d21, #3
-        vadd.u8         d0,  d0,  d22
-        vext.8          d6,  d22, d23, #6
-        vhadd.u8        d1,  d0,  d17
-        vext.8          d18, d20, d21, #6
-        vadd.u8         d1,  d1,  d5
-        vext.8          d7,  d23, d23, #1
-        vld1.8          {q11},    [r0], lr
-        vst1.32         {d0[0]},  [r1,:32], r4
-        vhadd.u8        d2,  d1,  d18
-        vst1.32         {d1[0]},  [r1], r4
-        vext.8          d19, d21, d21, #1
-        vadd.u8         d2,  d2,  d6
-        vhadd.u8        d3,  d2,  d19
-        vst1.32         {d2[0]},  [r1], r4
-        vadd.u8         d3,  d3,  d7
-        vst1.32         {d3[0]},  [r1], r4
-        subs            r12, r12, #12
-        bgt             1b
-
-        pop             {r4,pc}
-endfunc
-
-.macro  paeth           rx,  ra,  rb,  rc
-        vaddl.u8        q12, \ra, \rb           @ a + b
-        vaddl.u8        q15, \rc, \rc           @ 2*c
-        vabdl.u8        q13, \rb, \rc           @ pa
-        vabdl.u8        q14, \ra, \rc           @ pb
-        vabd.u16        q15, q12, q15           @ pc
-        vcle.u16        q12, q13, q14           @ pa <= pb
-        vcle.u16        q13, q13, q15           @ pa <= pc
-        vcle.u16        q14, q14, q15           @ pb <= pc
-        vand            q12, q12, q13           @ pa <= pb && pa <= pc
-        vmovn.u16       d28, q14
-        vmovn.u16       \rx, q12
-        vbsl            d28, \rb, \rc
-        vbsl            \rx, \ra, d28
-.endm
-
-func    png_read_filter_row_paeth4_neon, export=1
-        ldr             r12, [r0, #4]           @ rowbytes
-        vmov.i8         d3,  #0
-        vmov.i8         d20, #0
-1:
-        vld4.32         {d4[],d5[],d6[],d7[]},    [r1,:128]
-        vld4.32         {d16[],d17[],d18[],d19[]},[r2,:128]!
-        paeth           d0,  d3,  d16, d20
-        vadd.u8         d0,  d0,  d4
-        paeth           d1,  d0,  d17, d16
-        vadd.u8         d1,  d1,  d5
-        paeth           d2,  d1,  d18, d17
-        vadd.u8         d2,  d2,  d6
-        paeth           d3,  d2,  d19, d18
-        vmov            d20, d19
-        vadd.u8         d3,  d3,  d7
-        vst4.32         {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
-        subs            r12, r12, #16
-        bgt             1b
-
-        bx              lr
-endfunc
-
-func    png_read_filter_row_paeth3_neon, export=1
-        push            {r4,lr}
-        ldr             r12, [r0, #4]           @ rowbytes
-        vmov.i8         d3,  #0
-        vmov.i8         d4,  #0
-        mov             r0,  r1
-        mov             r4,  #3
-        mov             lr,  #12
-        vld1.8          {q11},    [r0], lr
-1:
-        vld1.8          {q10},    [r2], lr
-        paeth           d0,  d3,  d20, d4
-        vext.8          d5,  d22, d23, #3
-        vadd.u8         d0,  d0,  d22
-        vext.8          d17, d20, d21, #3
-        paeth           d1,  d0,  d17, d20
-        vst1.32         {d0[0]},  [r1,:32], r4
-        vext.8          d6,  d22, d23, #6
-        vadd.u8         d1,  d1,  d5
-        vext.8          d18, d20, d21, #6
-        paeth           d2,  d1,  d18, d17
-        vext.8          d7,  d23, d23, #1
-        vld1.8          {q11},    [r0], lr
-        vst1.32         {d1[0]},  [r1], r4
-        vadd.u8         d2,  d2,  d6
-        vext.8          d19, d21, d21, #1
-        paeth           d3,  d2,  d19, d18
-        vst1.32         {d2[0]},  [r1], r4
-        vmov            d4,  d19
-        vadd.u8         d3,  d3,  d7
-        vst1.32         {d3[0]},  [r1], r4
-        subs            r12, r12, #12
-        bgt             1b
-
-        pop             {r4,pc}
-endfunc
-#endif /* PNG_ARM_NEON_OPT > 0 */
-#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */
-#endif /* READ */
diff --git a/third_party/libpng16/arm/filter_neon_intrinsics.c b/third_party/libpng16/arm/filter_neon_intrinsics.c
deleted file mode 100644
index 0647bfa..0000000
--- a/third_party/libpng16/arm/filter_neon_intrinsics.c
+++ /dev/null
@@ -1,402 +0,0 @@
-
-/* filter_neon_intrinsics.c - NEON optimised filter functions
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 2014,2016 Glenn Randers-Pehrson
- * Written by James Yu <james.yu at linaro.org>, October 2013.
- * Based on filter_neon.S, written by Mans Rullgard, 2011.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include "../pngpriv.h"
-
-#ifdef PNG_READ_SUPPORTED
-
-/* This code requires -mfpu=neon on the command line: */
-#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
-
-#if defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__)
-#  include <arm64_neon.h>
-#else
-#  include <arm_neon.h>
-#endif
-
-/* libpng row pointers are not necessarily aligned to any particular boundary,
- * however this code will only work with appropriate alignment.  arm/arm_init.c
- * checks for this (and will not compile unless it is done). This code uses
- * variants of png_aligncast to avoid compiler warnings.
- */
-#define png_ptr(type,pointer) png_aligncast(type *,pointer)
-#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
-
-/* The following relies on a variable 'temp_pointer' being declared with type
- * 'type'.  This is written this way just to hide the GCC strict aliasing
- * warning; note that the code is safe because there never is an alias between
- * the input and output pointers.
- *
- * When compiling with MSVC ARM64, the png_ldr macro can't be passed directly
- * to vst4_lane_u32, because of an internal compiler error inside MSVC.
- * To avoid this compiler bug, we use a temporary variable (vdest_val) to store
- * the result of png_ldr.
- */
-#define png_ldr(type,pointer)\
-   (temp_pointer = png_ptr(type,pointer), *temp_pointer)
-
-#if PNG_ARM_NEON_OPT > 0
-
-void
-png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev_row)
-{
-   png_bytep rp = row;
-   png_bytep rp_stop = row + row_info->rowbytes;
-   png_const_bytep pp = prev_row;
-
-   png_debug(1, "in png_read_filter_row_up_neon");
-
-   for (; rp < rp_stop; rp += 16, pp += 16)
-   {
-      uint8x16_t qrp, qpp;
-
-      qrp = vld1q_u8(rp);
-      qpp = vld1q_u8(pp);
-      qrp = vaddq_u8(qrp, qpp);
-      vst1q_u8(rp, qrp);
-   }
-}
-
-void
-png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev_row)
-{
-   png_bytep rp = row;
-   png_bytep rp_stop = row + row_info->rowbytes;
-
-   uint8x16_t vtmp = vld1q_u8(rp);
-   uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp);
-   uint8x8x2_t vrp = *vrpt;
-
-   uint8x8x4_t vdest;
-   vdest.val[3] = vdup_n_u8(0);
-
-   png_debug(1, "in png_read_filter_row_sub3_neon");
-
-   for (; rp < rp_stop;)
-   {
-      uint8x8_t vtmp1, vtmp2;
-      uint32x2_t *temp_pointer;
-
-      vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
-      vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
-      vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6);
-      vdest.val[1] = vadd_u8(vdest.val[0], vtmp1);
-
-      vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
-      vdest.val[2] = vadd_u8(vdest.val[1], vtmp2);
-      vdest.val[3] = vadd_u8(vdest.val[2], vtmp1);
-
-      vtmp = vld1q_u8(rp + 12);
-      vrpt = png_ptr(uint8x8x2_t, &vtmp);
-      vrp = *vrpt;
-
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
-      rp += 3;
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
-      rp += 3;
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
-      rp += 3;
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
-      rp += 3;
-   }
-
-   PNG_UNUSED(prev_row)
-}
-
-void
-png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev_row)
-{
-   png_bytep rp = row;
-   png_bytep rp_stop = row + row_info->rowbytes;
-
-   uint8x8x4_t vdest;
-   vdest.val[3] = vdup_n_u8(0);
-
-   png_debug(1, "in png_read_filter_row_sub4_neon");
-
-   for (; rp < rp_stop; rp += 16)
-   {
-      uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp));
-      uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
-      uint8x8x4_t vrp = *vrpt;
-      uint32x2x4_t *temp_pointer;
-      uint32x2x4_t vdest_val;
-
-      vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
-      vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
-      vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
-      vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
-
-      vdest_val = png_ldr(uint32x2x4_t, &vdest);
-      vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
-   }
-
-   PNG_UNUSED(prev_row)
-}
-
-void
-png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev_row)
-{
-   png_bytep rp = row;
-   png_const_bytep pp = prev_row;
-   png_bytep rp_stop = row + row_info->rowbytes;
-
-   uint8x16_t vtmp;
-   uint8x8x2_t *vrpt;
-   uint8x8x2_t vrp;
-   uint8x8x4_t vdest;
-   vdest.val[3] = vdup_n_u8(0);
-
-   vtmp = vld1q_u8(rp);
-   vrpt = png_ptr(uint8x8x2_t,&vtmp);
-   vrp = *vrpt;
-
-   png_debug(1, "in png_read_filter_row_avg3_neon");
-
-   for (; rp < rp_stop; pp += 12)
-   {
-      uint8x8_t vtmp1, vtmp2, vtmp3;
-
-      uint8x8x2_t *vppt;
-      uint8x8x2_t vpp;
-
-      uint32x2_t *temp_pointer;
-
-      vtmp = vld1q_u8(pp);
-      vppt = png_ptr(uint8x8x2_t,&vtmp);
-      vpp = *vppt;
-
-      vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
-      vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
-      vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
-
-      vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
-      vtmp3 = vext_u8(vrp.val[0], vrp.val[1], 6);
-      vdest.val[1] = vhadd_u8(vdest.val[0], vtmp2);
-      vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
-
-      vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 6);
-      vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
-
-      vtmp = vld1q_u8(rp + 12);
-      vrpt = png_ptr(uint8x8x2_t,&vtmp);
-      vrp = *vrpt;
-
-      vdest.val[2] = vhadd_u8(vdest.val[1], vtmp2);
-      vdest.val[2] = vadd_u8(vdest.val[2], vtmp3);
-
-      vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
-
-      vdest.val[3] = vhadd_u8(vdest.val[2], vtmp2);
-      vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
-
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
-      rp += 3;
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
-      rp += 3;
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
-      rp += 3;
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
-      rp += 3;
-   }
-}
-
-void
-png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev_row)
-{
-   png_bytep rp = row;
-   png_bytep rp_stop = row + row_info->rowbytes;
-   png_const_bytep pp = prev_row;
-
-   uint8x8x4_t vdest;
-   vdest.val[3] = vdup_n_u8(0);
-
-   png_debug(1, "in png_read_filter_row_avg4_neon");
-
-   for (; rp < rp_stop; rp += 16, pp += 16)
-   {
-      uint32x2x4_t vtmp;
-      uint8x8x4_t *vrpt, *vppt;
-      uint8x8x4_t vrp, vpp;
-      uint32x2x4_t *temp_pointer;
-      uint32x2x4_t vdest_val;
-
-      vtmp = vld4_u32(png_ptr(uint32_t,rp));
-      vrpt = png_ptr(uint8x8x4_t,&vtmp);
-      vrp = *vrpt;
-      vtmp = vld4_u32(png_ptrc(uint32_t,pp));
-      vppt = png_ptr(uint8x8x4_t,&vtmp);
-      vpp = *vppt;
-
-      vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
-      vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
-      vdest.val[1] = vhadd_u8(vdest.val[0], vpp.val[1]);
-      vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
-      vdest.val[2] = vhadd_u8(vdest.val[1], vpp.val[2]);
-      vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
-      vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
-      vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
-
-      vdest_val = png_ldr(uint32x2x4_t, &vdest);
-      vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
-   }
-}
-
-static uint8x8_t
-paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
-{
-   uint8x8_t d, e;
-   uint16x8_t p1, pa, pb, pc;
-
-   p1 = vaddl_u8(a, b); /* a + b */
-   pc = vaddl_u8(c, c); /* c * 2 */
-   pa = vabdl_u8(b, c); /* pa */
-   pb = vabdl_u8(a, c); /* pb */
-   pc = vabdq_u16(p1, pc); /* pc */
-
-   p1 = vcleq_u16(pa, pb); /* pa <= pb */
-   pa = vcleq_u16(pa, pc); /* pa <= pc */
-   pb = vcleq_u16(pb, pc); /* pb <= pc */
-
-   p1 = vandq_u16(p1, pa); /* pa <= pb && pa <= pc */
-
-   d = vmovn_u16(pb);
-   e = vmovn_u16(p1);
-
-   d = vbsl_u8(d, b, c);
-   e = vbsl_u8(e, a, d);
-
-   return e;
-}
-
-void
-png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev_row)
-{
-   png_bytep rp = row;
-   png_const_bytep pp = prev_row;
-   png_bytep rp_stop = row + row_info->rowbytes;
-
-   uint8x16_t vtmp;
-   uint8x8x2_t *vrpt;
-   uint8x8x2_t vrp;
-   uint8x8_t vlast = vdup_n_u8(0);
-   uint8x8x4_t vdest;
-   vdest.val[3] = vdup_n_u8(0);
-
-   vtmp = vld1q_u8(rp);
-   vrpt = png_ptr(uint8x8x2_t,&vtmp);
-   vrp = *vrpt;
-
-   png_debug(1, "in png_read_filter_row_paeth3_neon");
-
-   for (; rp < rp_stop; pp += 12)
-   {
-      uint8x8x2_t *vppt;
-      uint8x8x2_t vpp;
-      uint8x8_t vtmp1, vtmp2, vtmp3;
-      uint32x2_t *temp_pointer;
-
-      vtmp = vld1q_u8(pp);
-      vppt = png_ptr(uint8x8x2_t,&vtmp);
-      vpp = *vppt;
-
-      vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
-      vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
-
-      vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
-      vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
-      vdest.val[1] = paeth(vdest.val[0], vtmp2, vpp.val[0]);
-      vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
-
-      vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 6);
-      vtmp3 = vext_u8(vpp.val[0], vpp.val[1], 6);
-      vdest.val[2] = paeth(vdest.val[1], vtmp3, vtmp2);
-      vdest.val[2] = vadd_u8(vdest.val[2], vtmp1);
-
-      vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
-      vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
-
-      vtmp = vld1q_u8(rp + 12);
-      vrpt = png_ptr(uint8x8x2_t,&vtmp);
-      vrp = *vrpt;
-
-      vdest.val[3] = paeth(vdest.val[2], vtmp2, vtmp3);
-      vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
-
-      vlast = vtmp2;
-
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
-      rp += 3;
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
-      rp += 3;
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
-      rp += 3;
-      vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
-      rp += 3;
-   }
-}
-
-void
-png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev_row)
-{
-   png_bytep rp = row;
-   png_bytep rp_stop = row + row_info->rowbytes;
-   png_const_bytep pp = prev_row;
-
-   uint8x8_t vlast = vdup_n_u8(0);
-   uint8x8x4_t vdest;
-   vdest.val[3] = vdup_n_u8(0);
-
-   png_debug(1, "in png_read_filter_row_paeth4_neon");
-
-   for (; rp < rp_stop; rp += 16, pp += 16)
-   {
-      uint32x2x4_t vtmp;
-      uint8x8x4_t *vrpt, *vppt;
-      uint8x8x4_t vrp, vpp;
-      uint32x2x4_t *temp_pointer;
-      uint32x2x4_t vdest_val;
-
-      vtmp = vld4_u32(png_ptr(uint32_t,rp));
-      vrpt = png_ptr(uint8x8x4_t,&vtmp);
-      vrp = *vrpt;
-      vtmp = vld4_u32(png_ptrc(uint32_t,pp));
-      vppt = png_ptr(uint8x8x4_t,&vtmp);
-      vpp = *vppt;
-
-      vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
-      vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
-      vdest.val[1] = paeth(vdest.val[0], vpp.val[1], vpp.val[0]);
-      vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
-      vdest.val[2] = paeth(vdest.val[1], vpp.val[2], vpp.val[1]);
-      vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
-      vdest.val[3] = paeth(vdest.val[2], vpp.val[3], vpp.val[2]);
-      vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
-
-      vlast = vpp.val[3];
-
-      vdest_val = png_ldr(uint32x2x4_t, &vdest);
-      vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
-   }
-}
-
-#endif /* PNG_ARM_NEON_OPT > 0 */
-#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */
-#endif /* READ */
diff --git a/third_party/libpng16/arm/palette_neon_intrinsics.c b/third_party/libpng16/arm/palette_neon_intrinsics.c
deleted file mode 100644
index 8217d65..0000000
--- a/third_party/libpng16/arm/palette_neon_intrinsics.c
+++ /dev/null
@@ -1,149 +0,0 @@
-
-/* palette_neon_intrinsics.c - NEON optimised palette expansion functions
- *
- * Copyright (c) 2018-2019 Cosmin Truta
- * Copyright (c) 2017-2018 Arm Holdings. All rights reserved.
- * Written by Richard Townsend <Richard.Townsend@arm.com>, February 2017.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include "../pngpriv.h"
-
-#if PNG_ARM_NEON_IMPLEMENTATION == 1
-
-#if defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__)
-#  include <arm64_neon.h>
-#else
-#  include <arm_neon.h>
-#endif
-
-/* Build an RGBA8 palette from the separate RGB and alpha palettes. */
-void
-png_riffle_palette_neon(png_structrp png_ptr)
-{
-   png_const_colorp palette = png_ptr->palette;
-   png_bytep riffled_palette = png_ptr->riffled_palette;
-   png_const_bytep trans_alpha = png_ptr->trans_alpha;
-   int num_trans = png_ptr->num_trans;
-   int i;
-
-   png_debug(1, "in png_riffle_palette_neon");
-
-   /* Initially black, opaque. */
-   uint8x16x4_t w = {{
-      vdupq_n_u8(0x00),
-      vdupq_n_u8(0x00),
-      vdupq_n_u8(0x00),
-      vdupq_n_u8(0xff),
-   }};
-
-   /* First, riffle the RGB colours into an RGBA8 palette.
-    * The alpha component is set to opaque for now.
-    */
-   for (i = 0; i < 256; i += 16)
-   {
-      uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i));
-      w.val[0] = v.val[0];
-      w.val[1] = v.val[1];
-      w.val[2] = v.val[2];
-      vst4q_u8(riffled_palette + (i << 2), w);
-   }
-
-   /* Fix up the missing transparency values. */
-   for (i = 0; i < num_trans; i++)
-      riffled_palette[(i << 2) + 3] = trans_alpha[i];
-}
-
-/* Expands a palettized row into RGBA8. */
-int
-png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info,
-    png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
-{
-   png_uint_32 row_width = row_info->width;
-   const png_uint_32 *riffled_palette =
-      (const png_uint_32 *)png_ptr->riffled_palette;
-   const png_int_32 pixels_per_chunk = 4;
-   int i;
-
-   png_debug(1, "in png_do_expand_palette_rgba8_neon");
-
-   if (row_width < pixels_per_chunk)
-      return 0;
-
-   /* This function originally gets the last byte of the output row.
-    * The NEON part writes forward from a given position, so we have
-    * to seek this back by 4 pixels x 4 bytes.
-    */
-   *ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1);
-
-   for (i = 0; i < row_width; i += pixels_per_chunk)
-   {
-      uint32x4_t cur;
-      png_bytep sp = *ssp - i, dp = *ddp - (i << 2);
-      cur = vld1q_dup_u32 (riffled_palette + *(sp - 3));
-      cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1);
-      cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2);
-      cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3);
-      vst1q_u32((void *)dp, cur);
-   }
-   if (i != row_width)
-   {
-      /* Remove the amount that wasn't processed. */
-      i -= pixels_per_chunk;
-   }
-
-   /* Decrement output pointers. */
-   *ssp = *ssp - i;
-   *ddp = *ddp - (i << 2);
-   return i;
-}
-
-/* Expands a palettized row into RGB8. */
-int
-png_do_expand_palette_rgb8_neon(png_structrp png_ptr, png_row_infop row_info,
-    png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
-{
-   png_uint_32 row_width = row_info->width;
-   png_const_bytep palette = (png_const_bytep)png_ptr->palette;
-   const png_uint_32 pixels_per_chunk = 8;
-   int i;
-
-   png_debug(1, "in png_do_expand_palette_rgb8_neon");
-
-   if (row_width <= pixels_per_chunk)
-      return 0;
-
-   /* Seeking this back by 8 pixels x 3 bytes. */
-   *ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1);
-
-   for (i = 0; i < row_width; i += pixels_per_chunk)
-   {
-      uint8x8x3_t cur;
-      png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i);
-      cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7)));
-      cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1);
-      cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2);
-      cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3);
-      cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4);
-      cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5);
-      cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6);
-      cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7);
-      vst3_u8((void *)dp, cur);
-   }
-
-   if (i != row_width)
-   {
-      /* Remove the amount that wasn't processed. */
-      i -= pixels_per_chunk;
-   }
-
-   /* Decrement output pointers. */
-   *ssp = *ssp - i;
-   *ddp = *ddp - ((i << 1) + i);
-   return i;
-}
-
-#endif /* PNG_ARM_NEON_IMPLEMENTATION */
diff --git a/third_party/libpng16/intel/filter_sse2_intrinsics.c b/third_party/libpng16/intel/filter_sse2_intrinsics.c
deleted file mode 100644
index f52aaa8..0000000
--- a/third_party/libpng16/intel/filter_sse2_intrinsics.c
+++ /dev/null
@@ -1,391 +0,0 @@
-
-/* filter_sse2_intrinsics.c - SSE2 optimized filter functions
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 2016-2017 Glenn Randers-Pehrson
- * Written by Mike Klein and Matt Sarett
- * Derived from arm/filter_neon_intrinsics.c
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include "../pngpriv.h"
-
-#ifdef PNG_READ_SUPPORTED
-
-#if PNG_INTEL_SSE_IMPLEMENTATION > 0
-
-#include <immintrin.h>
-
-/* Functions in this file look at most 3 pixels (a,b,c) to predict the 4th (d).
- * They're positioned like this:
- *    prev:  c b
- *    row:   a d
- * The Sub filter predicts d=a, Avg d=(a+b)/2, and Paeth predicts d to be
- * whichever of a, b, or c is closest to p=a+b-c.
- */
-
-static __m128i load4(const void* p) {
-   int tmp;
-   memcpy(&tmp, p, sizeof(tmp));
-   return _mm_cvtsi32_si128(tmp);
-}
-
-static void store4(void* p, __m128i v) {
-   int tmp = _mm_cvtsi128_si32(v);
-   memcpy(p, &tmp, sizeof(int));
-}
-
-static __m128i load3(const void* p) {
-   png_uint_32 tmp = 0;
-   memcpy(&tmp, p, 3);
-   return _mm_cvtsi32_si128(tmp);
-}
-
-static void store3(void* p, __m128i v) {
-   int tmp = _mm_cvtsi128_si32(v);
-   memcpy(p, &tmp, 3);
-}
-
-void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev)
-{
-   /* The Sub filter predicts each pixel as the previous pixel, a.
-    * There is no pixel to the left of the first pixel.  It's encoded directly.
-    * That works with our main loop if we just say that left pixel was zero.
-    */
-   size_t rb;
-
-   __m128i a, d = _mm_setzero_si128();
-
-   png_debug(1, "in png_read_filter_row_sub3_sse2");
-
-   rb = row_info->rowbytes;
-   while (rb >= 4) {
-      a = d; d = load4(row);
-      d = _mm_add_epi8(d, a);
-      store3(row, d);
-
-      row += 3;
-      rb  -= 3;
-   }
-   if (rb > 0) {
-      a = d; d = load3(row);
-      d = _mm_add_epi8(d, a);
-      store3(row, d);
-
-      row += 3;
-      rb  -= 3;
-   }
-   PNG_UNUSED(prev)
-}
-
-void png_read_filter_row_sub4_sse2(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev)
-{
-   /* The Sub filter predicts each pixel as the previous pixel, a.
-    * There is no pixel to the left of the first pixel.  It's encoded directly.
-    * That works with our main loop if we just say that left pixel was zero.
-    */
-   size_t rb;
-
-   __m128i a, d = _mm_setzero_si128();
-
-   png_debug(1, "in png_read_filter_row_sub4_sse2");
-
-   rb = row_info->rowbytes+4;
-   while (rb > 4) {
-      a = d; d = load4(row);
-      d = _mm_add_epi8(d, a);
-      store4(row, d);
-
-      row += 4;
-      rb  -= 4;
-   }
-   PNG_UNUSED(prev)
-}
-
-void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev)
-{
-   /* The Avg filter predicts each pixel as the (truncated) average of a and b.
-    * There's no pixel to the left of the first pixel.  Luckily, it's
-    * predicted to be half of the pixel above it.  So again, this works
-    * perfectly with our loop if we make sure a starts at zero.
-    */
-
-   size_t rb;
-
-   const __m128i zero = _mm_setzero_si128();
-
-   __m128i    b;
-   __m128i a, d = zero;
-
-   png_debug(1, "in png_read_filter_row_avg3_sse2");
-   rb = row_info->rowbytes;
-   while (rb >= 4) {
-      __m128i avg;
-             b = load4(prev);
-      a = d; d = load4(row );
-
-      /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
-      avg = _mm_avg_epu8(a,b);
-      /* ...but we can fix it up by subtracting off 1 if it rounded up. */
-      avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
-                                            _mm_set1_epi8(1)));
-      d = _mm_add_epi8(d, avg);
-      store3(row, d);
-
-      prev += 3;
-      row  += 3;
-      rb   -= 3;
-   }
-   if (rb > 0) {
-      __m128i avg;
-             b = load3(prev);
-      a = d; d = load3(row );
-
-      /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
-      avg = _mm_avg_epu8(a,b);
-      /* ...but we can fix it up by subtracting off 1 if it rounded up. */
-      avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
-                                            _mm_set1_epi8(1)));
-
-      d = _mm_add_epi8(d, avg);
-      store3(row, d);
-
-      prev += 3;
-      row  += 3;
-      rb   -= 3;
-   }
-}
-
-void png_read_filter_row_avg4_sse2(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev)
-{
-   /* The Avg filter predicts each pixel as the (truncated) average of a and b.
-    * There's no pixel to the left of the first pixel.  Luckily, it's
-    * predicted to be half of the pixel above it.  So again, this works
-    * perfectly with our loop if we make sure a starts at zero.
-    */
-   size_t rb;
-   const __m128i zero = _mm_setzero_si128();
-   __m128i    b;
-   __m128i a, d = zero;
-
-   png_debug(1, "in png_read_filter_row_avg4_sse2");
-
-   rb = row_info->rowbytes+4;
-   while (rb > 4) {
-      __m128i avg;
-             b = load4(prev);
-      a = d; d = load4(row );
-
-      /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
-      avg = _mm_avg_epu8(a,b);
-      /* ...but we can fix it up by subtracting off 1 if it rounded up. */
-      avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
-                                            _mm_set1_epi8(1)));
-
-      d = _mm_add_epi8(d, avg);
-      store4(row, d);
-
-      prev += 4;
-      row  += 4;
-      rb   -= 4;
-   }
-}
-
-/* Returns |x| for 16-bit lanes. */
-static __m128i abs_i16(__m128i x) {
-#if PNG_INTEL_SSE_IMPLEMENTATION >= 2
-   return _mm_abs_epi16(x);
-#else
-   /* Read this all as, return x<0 ? -x : x.
-   * To negate two's complement, you flip all the bits then add 1.
-    */
-   __m128i is_negative = _mm_cmplt_epi16(x, _mm_setzero_si128());
-
-   /* Flip negative lanes. */
-   x = _mm_xor_si128(x, is_negative);
-
-   /* +1 to negative lanes, else +0. */
-   x = _mm_sub_epi16(x, is_negative);
-   return x;
-#endif
-}
-
-/* Bytewise c ? t : e. */
-static __m128i if_then_else(__m128i c, __m128i t, __m128i e) {
-#if PNG_INTEL_SSE_IMPLEMENTATION >= 3
-   return _mm_blendv_epi8(e,t,c);
-#else
-   return _mm_or_si128(_mm_and_si128(c, t), _mm_andnot_si128(c, e));
-#endif
-}
-
-void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev)
-{
-   /* Paeth tries to predict pixel d using the pixel to the left of it, a,
-    * and two pixels from the previous row, b and c:
-    *   prev: c b
-    *   row:  a d
-    * The Paeth function predicts d to be whichever of a, b, or c is nearest to
-    * p=a+b-c.
-    *
-    * The first pixel has no left context, and so uses an Up filter, p = b.
-    * This works naturally with our main loop's p = a+b-c if we force a and c
-    * to zero.
-    * Here we zero b and d, which become c and a respectively at the start of
-    * the loop.
-    */
-   size_t rb;
-   const __m128i zero = _mm_setzero_si128();
-   __m128i c, b = zero,
-           a, d = zero;
-
-   png_debug(1, "in png_read_filter_row_paeth3_sse2");
-
-   rb = row_info->rowbytes;
-   while (rb >= 4) {
-      /* It's easiest to do this math (particularly, deal with pc) with 16-bit
-       * intermediates.
-       */
-      __m128i pa,pb,pc,smallest,nearest;
-      c = b; b = _mm_unpacklo_epi8(load4(prev), zero);
-      a = d; d = _mm_unpacklo_epi8(load4(row ), zero);
-
-      /* (p-a) == (a+b-c - a) == (b-c) */
-   
-      pa = _mm_sub_epi16(b,c);
-
-      /* (p-b) == (a+b-c - b) == (a-c) */
-      pb = _mm_sub_epi16(a,c);
-
-      /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
-      pc = _mm_add_epi16(pa,pb);
-
-      pa = abs_i16(pa);  /* |p-a| */
-      pb = abs_i16(pb);  /* |p-b| */
-      pc = abs_i16(pc);  /* |p-c| */
-
-      smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
-
-      /* Paeth breaks ties favoring a over b over c. */
-      nearest  = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
-                 if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
-                                                             c));
-
-      /* Note `_epi8`: we need addition to wrap modulo 255. */
-      d = _mm_add_epi8(d, nearest);
-      store3(row, _mm_packus_epi16(d,d));
-
-      prev += 3;
-      row  += 3;
-      rb   -= 3;
-   }
-   if (rb > 0) {
-      /* It's easiest to do this math (particularly, deal with pc) with 16-bit
-       * intermediates.
-       */
-      __m128i pa,pb,pc,smallest,nearest;
-      c = b; b = _mm_unpacklo_epi8(load3(prev), zero);
-      a = d; d = _mm_unpacklo_epi8(load3(row ), zero);
-
-      /* (p-a) == (a+b-c - a) == (b-c) */
-      pa = _mm_sub_epi16(b,c);
-
-      /* (p-b) == (a+b-c - b) == (a-c) */
-      pb = _mm_sub_epi16(a,c);
-
-      /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
-      pc = _mm_add_epi16(pa,pb);
-
-      pa = abs_i16(pa);  /* |p-a| */
-      pb = abs_i16(pb);  /* |p-b| */
-      pc = abs_i16(pc);  /* |p-c| */
-
-      smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
-
-      /* Paeth breaks ties favoring a over b over c. */
-      nearest  = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
-                         if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
-                                                                     c));
-
-      /* Note `_epi8`: we need addition to wrap modulo 255. */
-      d = _mm_add_epi8(d, nearest);
-      store3(row, _mm_packus_epi16(d,d));
-
-      prev += 3;
-      row  += 3;
-      rb   -= 3;
-   }
-}
-
-void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row,
-   png_const_bytep prev)
-{
-   /* Paeth tries to predict pixel d using the pixel to the left of it, a,
-    * and two pixels from the previous row, b and c:
-    *   prev: c b
-    *   row:  a d
-    * The Paeth function predicts d to be whichever of a, b, or c is nearest to
-    * p=a+b-c.
-    *
-    * The first pixel has no left context, and so uses an Up filter, p = b.
-    * This works naturally with our main loop's p = a+b-c if we force a and c
-    * to zero.
-    * Here we zero b and d, which become c and a respectively at the start of
-    * the loop.
-    */
-   size_t rb;
-   const __m128i zero = _mm_setzero_si128();
-   __m128i pa,pb,pc,smallest,nearest;
-   __m128i c, b = zero,
-           a, d = zero;
-
-   png_debug(1, "in png_read_filter_row_paeth4_sse2");
-
-   rb = row_info->rowbytes+4;
-   while (rb > 4) {
-      /* It's easiest to do this math (particularly, deal with pc) with 16-bit
-       * intermediates.
-       */
-      c = b; b = _mm_unpacklo_epi8(load4(prev), zero);
-      a = d; d = _mm_unpacklo_epi8(load4(row ), zero);
-
-      /* (p-a) == (a+b-c - a) == (b-c) */
-      pa = _mm_sub_epi16(b,c);
-
-      /* (p-b) == (a+b-c - b) == (a-c) */
-      pb = _mm_sub_epi16(a,c);
-
-      /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
-      pc = _mm_add_epi16(pa,pb);
-
-      pa = abs_i16(pa);  /* |p-a| */
-      pb = abs_i16(pb);  /* |p-b| */
-      pc = abs_i16(pc);  /* |p-c| */
-
-      smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
-
-      /* Paeth breaks ties favoring a over b over c. */
-      nearest  = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
-                         if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
-                                                                     c));
-
-      /* Note `_epi8`: we need addition to wrap modulo 255. */
-      d = _mm_add_epi8(d, nearest);
-      store4(row, _mm_packus_epi16(d,d));
-
-      prev += 4;
-      row  += 4;
-      rb   -= 4;
-   }
-}
-
-#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */
-#endif /* READ */
diff --git a/third_party/libpng16/intel/intel_init.c b/third_party/libpng16/intel/intel_init.c
deleted file mode 100644
index 2f8168b..0000000
--- a/third_party/libpng16/intel/intel_init.c
+++ /dev/null
@@ -1,52 +0,0 @@
-
-/* intel_init.c - SSE2 optimized filter functions
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 2016-2017 Glenn Randers-Pehrson
- * Written by Mike Klein and Matt Sarett, Google, Inc.
- * Derived from arm/arm_init.c
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include "../pngpriv.h"
-
-#ifdef PNG_READ_SUPPORTED
-#if PNG_INTEL_SSE_IMPLEMENTATION > 0
-
-void
-png_init_filter_functions_sse2(png_structp pp, unsigned int bpp)
-{
-   /* The techniques used to implement each of these filters in SSE operate on
-    * one pixel at a time.
-    * So they generally speed up 3bpp images about 3x, 4bpp images about 4x.
-    * They can scale up to 6 and 8 bpp images and down to 2 bpp images,
-    * but they'd not likely have any benefit for 1bpp images.
-    * Most of these can be implemented using only MMX and 64-bit registers,
-    * but they end up a bit slower than using the equally-ubiquitous SSE2.
-   */
-   png_debug(1, "in png_init_filter_functions_sse2");
-   if (bpp == 3)
-   {
-      pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_sse2;
-      pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_sse2;
-      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
-         png_read_filter_row_paeth3_sse2;
-   }
-   else if (bpp == 4)
-   {
-      pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_sse2;
-      pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_sse2;
-      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
-          png_read_filter_row_paeth4_sse2;
-   }
-
-   /* No need optimize PNG_FILTER_VALUE_UP.  The compiler should
-    * autovectorize.
-    */
-}
-
-#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */
-#endif /* PNG_READ_SUPPORTED */
diff --git a/third_party/libpng16/mips/filter_msa_intrinsics.c b/third_party/libpng16/mips/filter_msa_intrinsics.c
deleted file mode 100644
index a579179..0000000
--- a/third_party/libpng16/mips/filter_msa_intrinsics.c
+++ /dev/null
@@ -1,808 +0,0 @@
-
-/* filter_msa_intrinsics.c - MSA optimised filter functions
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 2016 Glenn Randers-Pehrson
- * Written by Mandar Sahastrabuddhe, August 2016.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include <stdio.h>
-#include <stdint.h>
-#include "../pngpriv.h"
-
-#ifdef PNG_READ_SUPPORTED
-
-/* This code requires -mfpu=msa on the command line: */
-#if PNG_MIPS_MSA_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
-
-#include <msa.h>
-
-/* libpng row pointers are not necessarily aligned to any particular boundary,
- * however this code will only work with appropriate alignment. mips/mips_init.c
- * checks for this (and will not compile unless it is done). This code uses
- * variants of png_aligncast to avoid compiler warnings.
- */
-#define png_ptr(type,pointer) png_aligncast(type *,pointer)
-#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
-
-/* The following relies on a variable 'temp_pointer' being declared with type
- * 'type'.  This is written this way just to hide the GCC strict aliasing
- * warning; note that the code is safe because there never is an alias between
- * the input and output pointers.
- */
-#define png_ldr(type,pointer)\
-   (temp_pointer = png_ptr(type,pointer), *temp_pointer)
-
-#if PNG_MIPS_MSA_OPT > 0
-
-#ifdef CLANG_BUILD
-   #define MSA_SRLI_B(a, b)   __msa_srli_b((v16i8) a, b)
-
-   #define LW(psrc)                              \
-   ( {                                           \
-       uint8_t *psrc_lw_m = (uint8_t *) (psrc);  \
-       uint32_t val_m;                           \
-                                                 \
-       asm volatile (                            \
-           "lw  %[val_m],  %[psrc_lw_m]  \n\t"   \
-                                                 \
-           : [val_m] "=r" (val_m)                \
-           : [psrc_lw_m] "m" (*psrc_lw_m)        \
-       );                                        \
-                                                 \
-       val_m;                                    \
-   } )
-
-   #define SH(val, pdst)                         \
-   {                                             \
-       uint8_t *pdst_sh_m = (uint8_t *) (pdst);  \
-       uint16_t val_m = (val);                   \
-                                                 \
-       asm volatile (                            \
-           "sh  %[val_m],  %[pdst_sh_m]  \n\t"   \
-                                                 \
-           : [pdst_sh_m] "=m" (*pdst_sh_m)       \
-           : [val_m] "r" (val_m)                 \
-       );                                        \
-   }
-
-   #define SW(val, pdst)                         \
-   {                                             \
-       uint8_t *pdst_sw_m = (uint8_t *) (pdst);  \
-       uint32_t val_m = (val);                   \
-                                                 \
-       asm volatile (                            \
-           "sw  %[val_m],  %[pdst_sw_m]  \n\t"   \
-                                                 \
-           : [pdst_sw_m] "=m" (*pdst_sw_m)       \
-           : [val_m] "r" (val_m)                 \
-       );                                        \
-   }
-
-       #if (__mips == 64)
-        #define SD(val, pdst)                         \
-        {                                             \
-            uint8_t *pdst_sd_m = (uint8_t *) (pdst);  \
-            uint64_t val_m = (val);                   \
-                                                      \
-            asm volatile (                            \
-                "sd  %[val_m],  %[pdst_sd_m]  \n\t"   \
-                                                      \
-                : [pdst_sd_m] "=m" (*pdst_sd_m)       \
-                : [val_m] "r" (val_m)                 \
-            );                                        \
-        }
-    #else
-        #define SD(val, pdst)                                          \
-        {                                                              \
-            uint8_t *pdst_sd_m = (uint8_t *) (pdst);                   \
-            uint32_t val0_m, val1_m;                                   \
-                                                                       \
-            val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF);          \
-            val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF);  \
-                                                                       \
-            SW(val0_m, pdst_sd_m);                                     \
-            SW(val1_m, pdst_sd_m + 4);                                 \
-        }
-    #endif
-#else
-   #define MSA_SRLI_B(a, b)   (a >> b)
-
-#if (__mips_isa_rev >= 6)
-   #define LW(psrc)                              \
-   ( {                                           \
-       uint8_t *psrc_lw_m = (uint8_t *) (psrc);  \
-       uint32_t val_m;                           \
-                                                 \
-       asm volatile (                            \
-           "lw  %[val_m],  %[psrc_lw_m]  \n\t"   \
-                                                 \
-           : [val_m] "=r" (val_m)                \
-           : [psrc_lw_m] "m" (*psrc_lw_m)        \
-       );                                        \
-                                                 \
-       val_m;                                    \
-   } )
-
-   #define SH(val, pdst)                         \
-   {                                             \
-       uint8_t *pdst_sh_m = (uint8_t *) (pdst);  \
-       uint16_t val_m = (val);                   \
-                                                 \
-       asm volatile (                            \
-           "sh  %[val_m],  %[pdst_sh_m]  \n\t"   \
-                                                 \
-           : [pdst_sh_m] "=m" (*pdst_sh_m)       \
-           : [val_m] "r" (val_m)                 \
-       );                                        \
-   }
-
-   #define SW(val, pdst)                         \
-   {                                             \
-       uint8_t *pdst_sw_m = (uint8_t *) (pdst);  \
-       uint32_t val_m = (val);                   \
-                                                 \
-       asm volatile (                            \
-           "sw  %[val_m],  %[pdst_sw_m]  \n\t"   \
-                                                 \
-           : [pdst_sw_m] "=m" (*pdst_sw_m)       \
-           : [val_m] "r" (val_m)                 \
-       );                                        \
-   }
-
-   #if (__mips == 64)
-        #define SD(val, pdst)                         \
-        {                                             \
-            uint8_t *pdst_sd_m = (uint8_t *) (pdst);  \
-            uint64_t val_m = (val);                   \
-                                                      \
-            asm volatile (                            \
-                "sd  %[val_m],  %[pdst_sd_m]  \n\t"   \
-                                                      \
-                : [pdst_sd_m] "=m" (*pdst_sd_m)       \
-                : [val_m] "r" (val_m)                 \
-            );                                        \
-        }
-    #else
-        #define SD(val, pdst)                                          \
-        {                                                              \
-            uint8_t *pdst_sd_m = (uint8_t *) (pdst);                   \
-            uint32_t val0_m, val1_m;                                   \
-                                                                       \
-            val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF);          \
-            val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF);  \
-                                                                       \
-            SW(val0_m, pdst_sd_m);                                     \
-            SW(val1_m, pdst_sd_m + 4);                                 \
-        }
-    #endif
-#else  // !(__mips_isa_rev >= 6)
-   #define LW(psrc)                              \
-   ( {                                           \
-       uint8_t *psrc_lw_m = (uint8_t *) (psrc);  \
-       uint32_t val_m;                           \
-                                                 \
-       asm volatile (                            \
-           "ulw  %[val_m],  %[psrc_lw_m]  \n\t"  \
-                                                 \
-           : [val_m] "=r" (val_m)                \
-           : [psrc_lw_m] "m" (*psrc_lw_m)        \
-       );                                        \
-                                                 \
-       val_m;                                    \
-   } )
-
-   #define SH(val, pdst)                         \
-   {                                             \
-       uint8_t *pdst_sh_m = (uint8_t *) (pdst);  \
-       uint16_t val_m = (val);                   \
-                                                 \
-       asm volatile (                            \
-           "ush  %[val_m],  %[pdst_sh_m]  \n\t"  \
-                                                 \
-           : [pdst_sh_m] "=m" (*pdst_sh_m)       \
-           : [val_m] "r" (val_m)                 \
-       );                                        \
-   }
-
-   #define SW(val, pdst)                         \
-   {                                             \
-       uint8_t *pdst_sw_m = (uint8_t *) (pdst);  \
-       uint32_t val_m = (val);                   \
-                                                 \
-       asm volatile (                            \
-           "usw  %[val_m],  %[pdst_sw_m]  \n\t"  \
-                                                 \
-           : [pdst_sw_m] "=m" (*pdst_sw_m)       \
-           : [val_m] "r" (val_m)                 \
-       );                                        \
-   }
-
-   #define SD(val, pdst)                                          \
-    {                                                              \
-        uint8_t *pdst_sd_m = (uint8_t *) (pdst);                   \
-        uint32_t val0_m, val1_m;                                   \
-                                                                   \
-        val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF);          \
-        val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF);  \
-                                                                   \
-        SW(val0_m, pdst_sd_m);                                     \
-        SW(val1_m, pdst_sd_m + 4);                                 \
-    }
-
-    #define SW_ZERO(pdst)                      \
-    {                                          \
-        uint8_t *pdst_m = (uint8_t *) (pdst);  \
-                                               \
-        asm volatile (                         \
-            "usw  $0,  %[pdst_m]  \n\t"        \
-                                               \
-            : [pdst_m] "=m" (*pdst_m)          \
-            :                                  \
-        );                                     \
-    }
-#endif  // (__mips_isa_rev >= 6)
-#endif
-
-#define LD_B(RTYPE, psrc) *((RTYPE *) (psrc))
-#define LD_UB(...) LD_B(v16u8, __VA_ARGS__)
-#define LD_B2(RTYPE, psrc, stride, out0, out1)  \
-{                                               \
-    out0 = LD_B(RTYPE, (psrc));                 \
-    out1 = LD_B(RTYPE, (psrc) + stride);        \
-}
-#define LD_UB2(...) LD_B2(v16u8, __VA_ARGS__)
-#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3)   \
-{                                                            \
-    LD_B2(RTYPE, (psrc), stride, out0, out1);                \
-    LD_B2(RTYPE, (psrc) + 2 * stride , stride, out2, out3);  \
-}
-#define LD_UB4(...) LD_B4(v16u8, __VA_ARGS__)
-
-#define ST_B(RTYPE, in, pdst) *((RTYPE *) (pdst)) = (in)
-#define ST_UB(...) ST_B(v16u8, __VA_ARGS__)
-#define ST_B2(RTYPE, in0, in1, pdst, stride)  \
-{                                             \
-    ST_B(RTYPE, in0, (pdst));                 \
-    ST_B(RTYPE, in1, (pdst) + stride);        \
-}
-#define ST_UB2(...) ST_B2(v16u8, __VA_ARGS__)
-#define ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride)    \
-{                                                         \
-    ST_B2(RTYPE, in0, in1, (pdst), stride);               \
-    ST_B2(RTYPE, in2, in3, (pdst) + 2 * stride, stride);  \
-}
-#define ST_UB4(...) ST_B4(v16u8, __VA_ARGS__)
-
-#define ADD2(in0, in1, in2, in3, out0, out1)  \
-{                                             \
-    out0 = in0 + in1;                         \
-    out1 = in2 + in3;                         \
-}
-#define ADD3(in0, in1, in2, in3, in4, in5,  \
-             out0, out1, out2)              \
-{                                           \
-    ADD2(in0, in1, in2, in3, out0, out1);   \
-    out2 = in4 + in5;                       \
-}
-#define ADD4(in0, in1, in2, in3, in4, in5, in6, in7,  \
-             out0, out1, out2, out3)                  \
-{                                                     \
-    ADD2(in0, in1, in2, in3, out0, out1);             \
-    ADD2(in4, in5, in6, in7, out2, out3);             \
-}
-
-#define ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1)      \
-{                                                           \
-    out0 = (RTYPE) __msa_ilvr_b((v16i8) in0, (v16i8) in1);  \
-    out1 = (RTYPE) __msa_ilvr_b((v16i8) in2, (v16i8) in3);  \
-}
-#define ILVR_B2_SH(...) ILVR_B2(v8i16, __VA_ARGS__)
-
-#define HSUB_UB2(RTYPE, in0, in1, out0, out1)                 \
-{                                                             \
-    out0 = (RTYPE) __msa_hsub_u_h((v16u8) in0, (v16u8) in0);  \
-    out1 = (RTYPE) __msa_hsub_u_h((v16u8) in1, (v16u8) in1);  \
-}
-#define HSUB_UB2_SH(...) HSUB_UB2(v8i16, __VA_ARGS__)
-
-#define SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val)                 \
-{                                                                         \
-    v16i8 zero_m = { 0 };                                                 \
-    out0 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in0, slide_val);  \
-    out1 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in1, slide_val);  \
-}
-#define SLDI_B2_0_UB(...) SLDI_B2_0(v16u8, __VA_ARGS__)
-
-#define SLDI_B3_0(RTYPE, in0, in1, in2, out0, out1, out2,  slide_val)     \
-{                                                                         \
-    v16i8 zero_m = { 0 };                                                 \
-    SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val);                    \
-    out2 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in2, slide_val);  \
-}
-#define SLDI_B3_0_UB(...) SLDI_B3_0(v16u8, __VA_ARGS__)
-
-#define ILVEV_W2(RTYPE, in0, in1, in2, in3, out0, out1)      \
-{                                                            \
-    out0 = (RTYPE) __msa_ilvev_w((v4i32) in1, (v4i32) in0);  \
-    out1 = (RTYPE) __msa_ilvev_w((v4i32) in3, (v4i32) in2);  \
-}
-#define ILVEV_W2_UB(...) ILVEV_W2(v16u8, __VA_ARGS__)
-
-#define ADD_ABS_H3(RTYPE, in0, in1, in2, out0, out1, out2)  \
-{                                                           \
-    RTYPE zero = {0};                                       \
-                                                            \
-    out0 = __msa_add_a_h((v8i16) zero, in0);                \
-    out1 = __msa_add_a_h((v8i16) zero, in1);                \
-    out2 = __msa_add_a_h((v8i16) zero, in2);                \
-}
-#define ADD_ABS_H3_SH(...) ADD_ABS_H3(v8i16, __VA_ARGS__)
-
-#define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1)       \
-{                                                                          \
-    out0 = (RTYPE) __msa_vshf_b((v16i8) mask0, (v16i8) in1, (v16i8) in0);  \
-    out1 = (RTYPE) __msa_vshf_b((v16i8) mask1, (v16i8) in3, (v16i8) in2);  \
-}
-#define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__)
-
-#define CMP_AND_SELECT(inp0, inp1, inp2, inp3, inp4, inp5, out0)              \
-{                                                                             \
-   v8i16 _sel_h0, _sel_h1;                                                    \
-   v16u8 _sel_b0, _sel_b1;                                                    \
-   _sel_h0 = (v8i16) __msa_clt_u_h((v8u16) inp1, (v8u16) inp0);               \
-   _sel_b0 = (v16u8) __msa_pckev_b((v16i8) _sel_h0, (v16i8) _sel_h0);         \
-   inp0 = (v8i16) __msa_bmnz_v((v16u8) inp0, (v16u8) inp1, (v16u8) _sel_h0);  \
-   inp4 = (v16u8) __msa_bmnz_v(inp3, inp4, _sel_b0);                          \
-   _sel_h1 = (v8i16) __msa_clt_u_h((v8u16) inp2, (v8u16) inp0);               \
-   _sel_b1 = (v16u8) __msa_pckev_b((v16i8) _sel_h1, (v16i8) _sel_h1);         \
-   inp4 = (v16u8) __msa_bmnz_v(inp4, inp5, _sel_b1);                          \
-   out0 += inp4;                                                              \
-}
-
-void png_read_filter_row_up_msa(png_row_infop row_info, png_bytep row,
-                                png_const_bytep prev_row)
-{
-   size_t i, cnt, cnt16, cnt32;
-   size_t istop = row_info->rowbytes;
-   png_bytep rp = row;
-   png_const_bytep pp = prev_row;
-   v16u8 src0, src1, src2, src3, src4, src5, src6, src7;
-
-   for (i = 0; i < (istop >> 6); i++)
-   {
-      LD_UB4(rp, 16, src0, src1, src2, src3);
-      LD_UB4(pp, 16, src4, src5, src6, src7);
-      pp += 64;
-
-	  ADD4(src0, src4, src1, src5, src2, src6, src3, src7,
-	       src0, src1, src2, src3);
-
-      ST_UB4(src0, src1, src2, src3, rp, 16);
-      rp += 64;
-   }
-
-   if (istop & 0x3F)
-   {
-      cnt32 = istop & 0x20;
-      cnt16 = istop & 0x10;
-      cnt = istop & 0xF;
-
-      if(cnt32)
-      {
-         if (cnt16 && cnt)
-         {
-            LD_UB4(rp, 16, src0, src1, src2, src3);
-            LD_UB4(pp, 16, src4, src5, src6, src7);
-
-            ADD4(src0, src4, src1, src5, src2, src6, src3, src7,
-	             src0, src1, src2, src3);
-
-            ST_UB4(src0, src1, src2, src3, rp, 16);
-            rp += 64;
-         }
-         else if (cnt16 || cnt)
-         {
-            LD_UB2(rp, 16, src0, src1);
-            LD_UB2(pp, 16, src4, src5);
-            pp += 32;
-            src2 = LD_UB(rp + 32);
-            src6 = LD_UB(pp);
-
-            ADD3(src0, src4, src1, src5, src2, src6, src0, src1, src2);
-
-            ST_UB2(src0, src1, rp, 16);
-            rp += 32;
-            ST_UB(src2, rp);
-            rp += 16;
-         }
-         else
-         {
-            LD_UB2(rp, 16, src0, src1);
-            LD_UB2(pp, 16, src4, src5);
-
-			ADD2(src0, src4, src1, src5, src0, src1);
-
-            ST_UB2(src0, src1, rp, 16);
-            rp += 32;
-         }
-      }
-      else if (cnt16 && cnt)
-      {
-         LD_UB2(rp, 16, src0, src1);
-         LD_UB2(pp, 16, src4, src5);
-
-         ADD2(src0, src4, src1, src5, src0, src1);
-
-         ST_UB2(src0, src1, rp, 16);
-         rp += 32;
-      }
-      else if (cnt16 || cnt)
-      {
-         src0 = LD_UB(rp);
-         src4 = LD_UB(pp);
-         pp += 16;
-
-         src0 += src4;
-
-         ST_UB(src0, rp);
-         rp += 16;
-      }
-   }
-}
-
-void png_read_filter_row_sub4_msa(png_row_infop row_info, png_bytep row,
-                                  png_const_bytep prev_row)
-{
-   size_t count;
-   size_t istop = row_info->rowbytes;
-   png_bytep src = row;
-   png_bytep nxt = row + 4;
-   int32_t inp0;
-   v16u8 src0, src1, src2, src3, src4;
-   v16u8 dst0, dst1;
-   v16u8 zero = { 0 };
-
-   istop -= 4;
-
-   inp0 = LW(src);
-   src += 4;
-   src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
-
-   for (count = 0; count < istop; count += 16)
-   {
-      src1 = LD_UB(src);
-      src += 16;
-
-      src2 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 4);
-      src3 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 8);
-      src4 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 12);
-      src1 += src0;
-      src2 += src1;
-      src3 += src2;
-      src4 += src3;
-      src0 = src4;
-      ILVEV_W2_UB(src1, src2, src3, src4, dst0, dst1);
-      dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0);
-
-      ST_UB(dst0, nxt);
-      nxt += 16;
-   }
-}
-
-void png_read_filter_row_sub3_msa(png_row_infop row_info, png_bytep row,
-                                  png_const_bytep prev_row)
-{
-   size_t count;
-   size_t istop = row_info->rowbytes;
-   png_bytep src = row;
-   png_bytep nxt = row + 3;
-   int64_t out0;
-   int32_t inp0, out1;
-   v16u8 src0, src1, src2, src3, src4, dst0, dst1;
-   v16u8 zero = { 0 };
-   v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-   v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 };
-
-   istop -= 3;
-
-   inp0 = LW(src);
-   src += 3;
-   src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
-
-   for (count = 0; count < istop; count += 12)
-   {
-      src1 = LD_UB(src);
-      src += 12;
-
-      src2 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 3);
-      src3 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 6);
-      src4 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 9);
-      src1 += src0;
-      src2 += src1;
-      src3 += src2;
-      src4 += src3;
-      src0 = src4;
-      VSHF_B2_UB(src1, src2, src3, src4, mask0, mask0, dst0, dst1);
-      dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0);
-      out0 = __msa_copy_s_d((v2i64) dst0, 0);
-      out1 = __msa_copy_s_w((v4i32) dst0, 2);
-
-      SD(out0, nxt);
-      nxt += 8;
-      SW(out1, nxt);
-      nxt += 4;
-   }
-}
-
-void png_read_filter_row_avg4_msa(png_row_infop row_info, png_bytep row,
-                                  png_const_bytep prev_row)
-{
-   size_t i;
-   png_bytep src = row;
-   png_bytep nxt = row;
-   png_const_bytep pp = prev_row;
-   size_t istop = row_info->rowbytes - 4;
-   int32_t inp0, inp1, out0;
-   v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1;
-   v16u8 zero = { 0 };
-
-   inp0 = LW(pp);
-   pp += 4;
-   inp1 = LW(src);
-   src += 4;
-   src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
-   src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
-   src0 = (v16u8) MSA_SRLI_B(src0, 1);
-   src1 += src0;
-   out0 = __msa_copy_s_w((v4i32) src1, 0);
-   SW(out0, nxt);
-   nxt += 4;
-
-   for (i = 0; i < istop; i += 16)
-   {
-      src2 = LD_UB(pp);
-      pp += 16;
-      src6 = LD_UB(src);
-      src += 16;
-
-      SLDI_B2_0_UB(src2, src6, src3, src7, 4);
-      SLDI_B2_0_UB(src2, src6, src4, src8, 8);
-      SLDI_B2_0_UB(src2, src6, src5, src9, 12);
-      src2 = __msa_ave_u_b(src2, src1);
-      src6 += src2;
-      src3 = __msa_ave_u_b(src3, src6);
-      src7 += src3;
-      src4 = __msa_ave_u_b(src4, src7);
-      src8 += src4;
-      src5 = __msa_ave_u_b(src5, src8);
-      src9 += src5;
-      src1 = src9;
-      ILVEV_W2_UB(src6, src7, src8, src9, dst0, dst1);
-      dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0);
-
-      ST_UB(dst0, nxt);
-      nxt += 16;
-   }
-}
-
-void png_read_filter_row_avg3_msa(png_row_infop row_info, png_bytep row,
-                                  png_const_bytep prev_row)
-{
-   size_t i;
-   png_bytep src = row;
-   png_bytep nxt = row;
-   png_const_bytep pp = prev_row;
-   size_t istop = row_info->rowbytes - 3;
-   int64_t out0;
-   int32_t inp0, inp1, out1;
-   int16_t out2;
-   v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1;
-   v16u8 zero = { 0 };
-   v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-   v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 };
-
-   inp0 = LW(pp);
-   pp += 3;
-   inp1 = LW(src);
-   src += 3;
-   src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
-   src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
-   src0 = (v16u8) MSA_SRLI_B(src0, 1);
-   src1 += src0;
-   out2 = __msa_copy_s_h((v8i16) src1, 0);
-   SH(out2, nxt);
-   nxt += 2;
-   nxt[0] = src1[2];
-   nxt++;
-
-   for (i = 0; i < istop; i += 12)
-   {
-      src2 = LD_UB(pp);
-      pp += 12;
-      src6 = LD_UB(src);
-      src += 12;
-
-      SLDI_B2_0_UB(src2, src6, src3, src7, 3);
-      SLDI_B2_0_UB(src2, src6, src4, src8, 6);
-      SLDI_B2_0_UB(src2, src6, src5, src9, 9);
-      src2 = __msa_ave_u_b(src2, src1);
-      src6 += src2;
-      src3 = __msa_ave_u_b(src3, src6);
-      src7 += src3;
-      src4 = __msa_ave_u_b(src4, src7);
-      src8 += src4;
-      src5 = __msa_ave_u_b(src5, src8);
-      src9 += src5;
-      src1 = src9;
-      VSHF_B2_UB(src6, src7, src8, src9, mask0, mask0, dst0, dst1);
-      dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0);
-      out0 = __msa_copy_s_d((v2i64) dst0, 0);
-      out1 = __msa_copy_s_w((v4i32) dst0, 2);
-
-      SD(out0, nxt);
-      nxt += 8;
-      SW(out1, nxt);
-      nxt += 4;
-   }
-}
-
-void png_read_filter_row_paeth4_msa(png_row_infop row_info,
-                                    png_bytep row,
-                                    png_const_bytep prev_row)
-{
-   int32_t count, rp_end;
-   png_bytep nxt;
-   png_const_bytep prev_nxt;
-   int32_t inp0, inp1, res0;
-   v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9;
-   v16u8 src10, src11, src12, src13, dst0, dst1;
-   v8i16 vec0, vec1, vec2;
-   v16u8 zero = { 0 };
-
-   nxt = row;
-   prev_nxt = prev_row;
-
-   inp0 = LW(nxt);
-   inp1 = LW(prev_nxt);
-   prev_nxt += 4;
-   src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
-   src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
-
-   src1 += src0;
-   res0 = __msa_copy_s_w((v4i32) src1, 0);
-
-   SW(res0, nxt);
-   nxt += 4;
-
-   /* Remainder */
-   rp_end = row_info->rowbytes - 4;
-
-   for (count = 0; count < rp_end; count += 16)
-   {
-      src2 = LD_UB(prev_nxt);
-      prev_nxt += 16;
-      src6 = LD_UB(prev_row);
-      prev_row += 16;
-      src10 = LD_UB(nxt);
-
-      SLDI_B3_0_UB(src2, src6, src10, src3, src7, src11, 4);
-      SLDI_B3_0_UB(src2, src6, src10, src4, src8, src12, 8);
-      SLDI_B3_0_UB(src2, src6, src10, src5, src9, src13, 12);
-      ILVR_B2_SH(src2, src6, src1, src6, vec0, vec1);
-      HSUB_UB2_SH(vec0, vec1, vec0, vec1);
-      vec2 = vec0 + vec1;
-      ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
-      CMP_AND_SELECT(vec0, vec1, vec2, src1, src2, src6, src10);
-      ILVR_B2_SH(src3, src7, src10, src7, vec0, vec1);
-      HSUB_UB2_SH(vec0, vec1, vec0, vec1);
-      vec2 = vec0 + vec1;
-      ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
-      CMP_AND_SELECT(vec0, vec1, vec2, src10, src3, src7, src11);
-      ILVR_B2_SH(src4, src8, src11, src8, vec0, vec1);
-      HSUB_UB2_SH(vec0, vec1, vec0, vec1);
-      vec2 = vec0 + vec1;
-      ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
-      CMP_AND_SELECT(vec0, vec1, vec2, src11, src4, src8, src12);
-      ILVR_B2_SH(src5, src9, src12, src9, vec0, vec1);
-      HSUB_UB2_SH(vec0, vec1, vec0, vec1);
-      vec2 = vec0 + vec1;
-      ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
-      CMP_AND_SELECT(vec0, vec1, vec2, src12, src5, src9, src13);
-      src1 = src13;
-      ILVEV_W2_UB(src10, src11, src12, src1, dst0, dst1);
-      dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0);
-
-      ST_UB(dst0, nxt);
-      nxt += 16;
-   }
-}
-
-void png_read_filter_row_paeth3_msa(png_row_infop row_info,
-                                    png_bytep row,
-                                    png_const_bytep prev_row)
-{
-   int32_t count, rp_end;
-   png_bytep nxt;
-   png_const_bytep prev_nxt;
-   int64_t out0;
-   int32_t inp0, inp1, out1;
-   int16_t out2;
-   v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1;
-   v16u8 src10, src11, src12, src13;
-   v8i16 vec0, vec1, vec2;
-   v16u8 zero = { 0 };
-   v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
-   v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 };
-
-   nxt = row;
-   prev_nxt = prev_row;
-
-   inp0 = LW(nxt);
-   inp1 = LW(prev_nxt);
-   prev_nxt += 3;
-   src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0);
-   src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1);
-
-   src1 += src0;
-   out2 = __msa_copy_s_h((v8i16) src1, 0);
-
-   SH(out2, nxt);
-   nxt += 2;
-   nxt[0] = src1[2];
-   nxt++;
-
-   /* Remainder */
-   rp_end = row_info->rowbytes - 3;
-
-   for (count = 0; count < rp_end; count += 12)
-   {
-      src2 = LD_UB(prev_nxt);
-      prev_nxt += 12;
-      src6 = LD_UB(prev_row);
-      prev_row += 12;
-      src10 = LD_UB(nxt);
-
-      SLDI_B3_0_UB(src2, src6, src10, src3, src7, src11, 3);
-      SLDI_B3_0_UB(src2, src6, src10, src4, src8, src12, 6);
-      SLDI_B3_0_UB(src2, src6, src10, src5, src9, src13, 9);
-      ILVR_B2_SH(src2, src6, src1, src6, vec0, vec1);
-      HSUB_UB2_SH(vec0, vec1, vec0, vec1);
-      vec2 = vec0 + vec1;
-      ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
-      CMP_AND_SELECT(vec0, vec1, vec2, src1, src2, src6, src10);
-      ILVR_B2_SH(src3, src7, src10, src7, vec0, vec1);
-      HSUB_UB2_SH(vec0, vec1, vec0, vec1);
-      vec2 = vec0 + vec1;
-      ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
-      CMP_AND_SELECT(vec0, vec1, vec2, src10, src3, src7, src11);
-      ILVR_B2_SH(src4, src8, src11, src8, vec0, vec1);
-      HSUB_UB2_SH(vec0, vec1, vec0, vec1);
-      vec2 = vec0 + vec1;
-      ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
-      CMP_AND_SELECT(vec0, vec1, vec2, src11, src4, src8, src12);
-      ILVR_B2_SH(src5, src9, src12, src9, vec0, vec1);
-      HSUB_UB2_SH(vec0, vec1, vec0, vec1);
-      vec2 = vec0 + vec1;
-      ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2);
-      CMP_AND_SELECT(vec0, vec1, vec2, src12, src5, src9, src13);
-      src1 = src13;
-      VSHF_B2_UB(src10, src11, src12, src13, mask0, mask0, dst0, dst1);
-      dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0);
-      out0 = __msa_copy_s_d((v2i64) dst0, 0);
-      out1 = __msa_copy_s_w((v4i32) dst0, 2);
-
-      SD(out0, nxt);
-      nxt += 8;
-      SW(out1, nxt);
-      nxt += 4;
-   }
-}
-
-#endif /* PNG_MIPS_MSA_OPT > 0 */
-#endif /* PNG_MIPS_MSA_IMPLEMENTATION == 1 (intrinsics) */
-#endif /* READ */
diff --git a/third_party/libpng16/mips/mips_init.c b/third_party/libpng16/mips/mips_init.c
deleted file mode 100644
index 8dd283d..0000000
--- a/third_party/libpng16/mips/mips_init.c
+++ /dev/null
@@ -1,130 +0,0 @@
-
-/* mips_init.c - MSA optimised filter functions
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 2016 Glenn Randers-Pehrson
- * Written by Mandar Sahastrabuddhe, 2016.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
- * called.
- */
-#define _POSIX_SOURCE 1
-
-#include <stdio.h>
-#include "../pngpriv.h"
-
-#ifdef PNG_READ_SUPPORTED
-
-#if PNG_MIPS_MSA_OPT > 0
-#ifdef PNG_MIPS_MSA_CHECK_SUPPORTED /* Do run-time checks */
-/* WARNING: it is strongly recommended that you do not build libpng with
- * run-time checks for CPU features if at all possible.  In the case of the MIPS
- * MSA instructions there is no processor-specific way of detecting the
- * presence of the required support, therefore run-time detection is extremely
- * OS specific.
- *
- * You may set the macro PNG_MIPS_MSA_FILE to the file name of file containing
- * a fragment of C source code which defines the png_have_msa function.  There
- * are a number of implementations in contrib/mips-msa, but the only one that
- * has partial support is contrib/mips-msa/linux.c - a generic Linux
- * implementation which reads /proc/cpufino.
- */
-#ifndef PNG_MIPS_MSA_FILE
-#  ifdef __linux__
-#     define PNG_MIPS_MSA_FILE "contrib/mips-msa/linux.c"
-#  endif
-#endif
-
-#ifdef PNG_MIPS_MSA_FILE
-
-#include <signal.h> /* for sig_atomic_t */
-static int png_have_msa(png_structp png_ptr);
-#include PNG_MIPS_MSA_FILE
-
-#else  /* PNG_MIPS_MSA_FILE */
-#  error "PNG_MIPS_MSA_FILE undefined: no support for run-time MIPS MSA checks"
-#endif /* PNG_MIPS_MSA_FILE */
-#endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */
-
-#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
-#  error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
-#endif
-
-void
-png_init_filter_functions_msa(png_structp pp, unsigned int bpp)
-{
-   /* The switch statement is compiled in for MIPS_MSA_API, the call to
-    * png_have_msa is compiled in for MIPS_MSA_CHECK. If both are defined
-    * the check is only performed if the API has not set the MSA option on
-    * or off explicitly. In this case the check controls what happens.
-    */
-
-#ifdef PNG_MIPS_MSA_API_SUPPORTED
-   switch ((pp->options >> PNG_MIPS_MSA) & 3)
-   {
-      case PNG_OPTION_UNSET:
-         /* Allow the run-time check to execute if it has been enabled -
-          * thus both API and CHECK can be turned on.  If it isn't supported
-          * this case will fall through to the 'default' below, which just
-          * returns.
-          */
-#endif /* PNG_MIPS_MSA_API_SUPPORTED */
-#ifdef PNG_MIPS_MSA_CHECK_SUPPORTED
-         {
-            static volatile sig_atomic_t no_msa = -1; /* not checked */
-
-            if (no_msa < 0)
-               no_msa = !png_have_msa(pp);
-
-            if (no_msa)
-               return;
-         }
-#ifdef PNG_MIPS_MSA_API_SUPPORTED
-         break;
-#endif
-#endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */
-
-#ifdef PNG_MIPS_MSA_API_SUPPORTED
-      default: /* OFF or INVALID */
-         return;
-
-      case PNG_OPTION_ON:
-         /* Option turned on */
-         break;
-   }
-#endif
-
-   /* IMPORTANT: any new external functions used here must be declared using
-    * PNG_INTERNAL_FUNCTION in ../pngpriv.h.  This is required so that the
-    * 'prefix' option to configure works:
-    *
-    *    ./configure --with-libpng-prefix=foobar_
-    *
-    * Verify you have got this right by running the above command, doing a build
-    * and examining pngprefix.h; it must contain a #define for every external
-    * function you add.  (Notice that this happens automatically for the
-    * initialization function.)
-    */
-   pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_msa;
-
-   if (bpp == 3)
-   {
-      pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_msa;
-      pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_msa;
-      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_msa;
-   }
-
-   else if (bpp == 4)
-   {
-      pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_msa;
-      pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_msa;
-      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_msa;
-   }
-}
-#endif /* PNG_MIPS_MSA_OPT > 0 */
-#endif /* READ */
diff --git a/third_party/libpng16/png.c b/third_party/libpng16/png.c
deleted file mode 100644
index ddf7a2f..0000000
--- a/third_party/libpng16/png.c
+++ /dev/null
@@ -1,4608 +0,0 @@
-
-/* png.c - location for general purpose libpng functions
- *
- * Copyright (c) 2018-2019 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include "pngpriv.h"
-
-/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_37 Your_png_h_is_not_version_1_6_37;
-
-#ifdef __GNUC__
-/* The version tests may need to be added to, but the problem warning has
- * consistently been fixed in GCC versions which obtain wide-spread release.
- * The problem is that many versions of GCC rearrange comparison expressions in
- * the optimizer in such a way that the results of the comparison will change
- * if signed integer overflow occurs.  Such comparisons are not permitted in
- * ANSI C90, however GCC isn't clever enough to work out that that do not occur
- * below in png_ascii_from_fp and png_muldiv, so it produces a warning with
- * -Wextra.  Unfortunately this is highly dependent on the optimizer and the
- * machine architecture so the warning comes and goes unpredictably and is
- * impossible to "fix", even were that a good idea.
- */
-#if __GNUC__ == 7 && __GNUC_MINOR__ == 1
-#define GCC_STRICT_OVERFLOW 1
-#endif /* GNU 7.1.x */
-#endif /* GNU */
-#ifndef GCC_STRICT_OVERFLOW
-#define GCC_STRICT_OVERFLOW 0
-#endif
-
-/* Tells libpng that we have already handled the first "num_bytes" bytes
- * of the PNG file signature.  If the PNG data is embedded into another
- * stream we can set num_bytes = 8 so that libpng will not attempt to read
- * or write any of the magic bytes before it starts on the IHDR.
- */
-
-#ifdef PNG_READ_SUPPORTED
-void PNGAPI
-png_set_sig_bytes(png_structrp png_ptr, int num_bytes)
-{
-   unsigned int nb = (unsigned int)num_bytes;
-
-   png_debug(1, "in png_set_sig_bytes");
-
-   if (png_ptr == NULL)
-      return;
-
-   if (num_bytes < 0)
-      nb = 0;
-
-   if (nb > 8)
-      png_error(png_ptr, "Too many bytes for PNG signature");
-
-   png_ptr->sig_bytes = (png_byte)nb;
-}
-
-/* Checks whether the supplied bytes match the PNG signature.  We allow
- * checking less than the full 8-byte signature so that those apps that
- * already read the first few bytes of a file to determine the file type
- * can simply check the remaining bytes for extra assurance.  Returns
- * an integer less than, equal to, or greater than zero if sig is found,
- * respectively, to be less than, to match, or be greater than the correct
- * PNG signature (this is the same behavior as strcmp, memcmp, etc).
- */
-int PNGAPI
-png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check)
-{
-   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
-
-   if (num_to_check > 8)
-      num_to_check = 8;
-
-   else if (num_to_check < 1)
-      return (-1);
-
-   if (start > 7)
-      return (-1);
-
-   if (start + num_to_check > 8)
-      num_to_check = 8 - start;
-
-   return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
-}
-
-#endif /* READ */
-
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-/* Function to allocate memory for zlib */
-PNG_FUNCTION(voidpf /* PRIVATE */,
-png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
-{
-   png_alloc_size_t num_bytes = size;
-
-   if (png_ptr == NULL)
-      return NULL;
-
-   if (items >= (~(png_alloc_size_t)0)/size)
-   {
-      png_warning (png_voidcast(png_structrp, png_ptr),
-          "Potential overflow in png_zalloc()");
-      return NULL;
-   }
-
-   num_bytes *= items;
-   return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes);
-}
-
-/* Function to free memory for zlib */
-void /* PRIVATE */
-png_zfree(voidpf png_ptr, voidpf ptr)
-{
-   png_free(png_voidcast(png_const_structrp,png_ptr), ptr);
-}
-
-/* Reset the CRC variable to 32 bits of 1's.  Care must be taken
- * in case CRC is > 32 bits to leave the top bits 0.
- */
-void /* PRIVATE */
-png_reset_crc(png_structrp png_ptr)
-{
-   /* The cast is safe because the crc is a 32-bit value. */
-   png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0);
-}
-
-/* Calculate the CRC over a section of data.  We can only pass as
- * much data to this routine as the largest single buffer size.  We
- * also check that this data will actually be used before going to the
- * trouble of calculating it.
- */
-void /* PRIVATE */
-png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, size_t length)
-{
-   int need_crc = 1;
-
-   if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
-   {
-      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
-          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
-         need_crc = 0;
-   }
-
-   else /* critical */
-   {
-      if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
-         need_crc = 0;
-   }
-
-   /* 'uLong' is defined in zlib.h as unsigned long; this means that on some
-    * systems it is a 64-bit value.  crc32, however, returns 32 bits so the
-    * following cast is safe.  'uInt' may be no more than 16 bits, so it is
-    * necessary to perform a loop here.
-    */
-   if (need_crc != 0 && length > 0)
-   {
-      uLong crc = png_ptr->crc; /* Should never issue a warning */
-
-      do
-      {
-         uInt safe_length = (uInt)length;
-#ifndef __COVERITY__
-         if (safe_length == 0)
-            safe_length = (uInt)-1; /* evil, but safe */
-#endif
-
-         crc = crc32(crc, ptr, safe_length);
-
-         /* The following should never issue compiler warnings; if they do the
-          * target system has characteristics that will probably violate other
-          * assumptions within the libpng code.
-          */
-         ptr += safe_length;
-         length -= safe_length;
-      }
-      while (length > 0);
-
-      /* And the following is always safe because the crc is only 32 bits. */
-      png_ptr->crc = (png_uint_32)crc;
-   }
-}
-
-/* Check a user supplied version number, called from both read and write
- * functions that create a png_struct.
- */
-int
-png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
-{
-   /* Libpng versions 1.0.0 and later are binary compatible if the version
-    * string matches through the second '.'; we must recompile any
-    * applications that use any older library version.
-    */
-
-   if (user_png_ver != NULL)
-   {
-      int i = -1;
-      int found_dots = 0;
-
-      do
-      {
-         i++;
-         if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i])
-            png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
-         if (user_png_ver[i] == '.')
-            found_dots++;
-      } while (found_dots < 2 && user_png_ver[i] != 0 &&
-            PNG_LIBPNG_VER_STRING[i] != 0);
-   }
-
-   else
-      png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
-
-   if ((png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) != 0)
-   {
-#ifdef PNG_WARNINGS_SUPPORTED
-      size_t pos = 0;
-      char m[128];
-
-      pos = png_safecat(m, (sizeof m), pos,
-          "Application built with libpng-");
-      pos = png_safecat(m, (sizeof m), pos, user_png_ver);
-      pos = png_safecat(m, (sizeof m), pos, " but running with ");
-      pos = png_safecat(m, (sizeof m), pos, PNG_LIBPNG_VER_STRING);
-      PNG_UNUSED(pos)
-
-      png_warning(png_ptr, m);
-#endif
-
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-      png_ptr->flags = 0;
-#endif
-
-      return 0;
-   }
-
-   /* Success return. */
-   return 1;
-}
-
-/* Generic function to create a png_struct for either read or write - this
- * contains the common initialization.
- */
-PNG_FUNCTION(png_structp /* PRIVATE */,
-png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
-    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
-{
-   png_struct create_struct;
-#  ifdef PNG_SETJMP_SUPPORTED
-      jmp_buf create_jmp_buf;
-#  endif
-
-   /* This temporary stack-allocated structure is used to provide a place to
-    * build enough context to allow the user provided memory allocator (if any)
-    * to be called.
-    */
-   memset(&create_struct, 0, (sizeof create_struct));
-
-   /* Added at libpng-1.2.6 */
-#  ifdef PNG_USER_LIMITS_SUPPORTED
-      create_struct.user_width_max = PNG_USER_WIDTH_MAX;
-      create_struct.user_height_max = PNG_USER_HEIGHT_MAX;
-
-#     ifdef PNG_USER_CHUNK_CACHE_MAX
-      /* Added at libpng-1.2.43 and 1.4.0 */
-      create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
-#     endif
-
-#     ifdef PNG_USER_CHUNK_MALLOC_MAX
-      /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists
-       * in png_struct regardless.
-       */
-      create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
-#     endif
-#  endif
-
-   /* The following two API calls simply set fields in png_struct, so it is safe
-    * to do them now even though error handling is not yet set up.
-    */
-#  ifdef PNG_USER_MEM_SUPPORTED
-      png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn);
-#  else
-      PNG_UNUSED(mem_ptr)
-      PNG_UNUSED(malloc_fn)
-      PNG_UNUSED(free_fn)
-#  endif
-
-   /* (*error_fn) can return control to the caller after the error_ptr is set,
-    * this will result in a memory leak unless the error_fn does something
-    * extremely sophisticated.  The design lacks merit but is implicit in the
-    * API.
-    */
-   png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn);
-
-#  ifdef PNG_SETJMP_SUPPORTED
-      if (!setjmp(create_jmp_buf))
-#  endif
-      {
-#  ifdef PNG_SETJMP_SUPPORTED
-         /* Temporarily fake out the longjmp information until we have
-          * successfully completed this function.  This only works if we have
-          * setjmp() support compiled in, but it is safe - this stuff should
-          * never happen.
-          */
-         create_struct.jmp_buf_ptr = &create_jmp_buf;
-         create_struct.jmp_buf_size = 0; /*stack allocation*/
-         create_struct.longjmp_fn = longjmp;
-#  endif
-         /* Call the general version checker (shared with read and write code):
-          */
-         if (png_user_version_check(&create_struct, user_png_ver) != 0)
-         {
-            png_structrp png_ptr = png_voidcast(png_structrp,
-                png_malloc_warn(&create_struct, (sizeof *png_ptr)));
-
-            if (png_ptr != NULL)
-            {
-               /* png_ptr->zstream holds a back-pointer to the png_struct, so
-                * this can only be done now:
-                */
-               create_struct.zstream.zalloc = png_zalloc;
-               create_struct.zstream.zfree = png_zfree;
-               create_struct.zstream.opaque = png_ptr;
-
-#              ifdef PNG_SETJMP_SUPPORTED
-               /* Eliminate the local error handling: */
-               create_struct.jmp_buf_ptr = NULL;
-               create_struct.jmp_buf_size = 0;
-               create_struct.longjmp_fn = 0;
-#              endif
-
-               *png_ptr = create_struct;
-
-               /* This is the successful return point */
-               return png_ptr;
-            }
-         }
-      }
-
-   /* A longjmp because of a bug in the application storage allocator or a
-    * simple failure to allocate the png_struct.
-    */
-   return NULL;
-}
-
-/* Allocate the memory for an info_struct for the application. */
-PNG_FUNCTION(png_infop,PNGAPI
-png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED)
-{
-   png_inforp info_ptr;
-
-   png_debug(1, "in png_create_info_struct");
-
-   if (png_ptr == NULL)
-      return NULL;
-
-   /* Use the internal API that does not (or at least should not) error out, so
-    * that this call always returns ok.  The application typically sets up the
-    * error handling *after* creating the info_struct because this is the way it
-    * has always been done in 'example.c'.
-    */
-   info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,
-       (sizeof *info_ptr)));
-
-   if (info_ptr != NULL)
-      memset(info_ptr, 0, (sizeof *info_ptr));
-
-   return info_ptr;
-}
-
-/* This function frees the memory associated with a single info struct.
- * Normally, one would use either png_destroy_read_struct() or
- * png_destroy_write_struct() to free an info struct, but this may be
- * useful for some applications.  From libpng 1.6.0 this function is also used
- * internally to implement the png_info release part of the 'struct' destroy
- * APIs.  This ensures that all possible approaches free the same data (all of
- * it).
- */
-void PNGAPI
-png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr)
-{
-   png_inforp info_ptr = NULL;
-
-   png_debug(1, "in png_destroy_info_struct");
-
-   if (png_ptr == NULL)
-      return;
-
-   if (info_ptr_ptr != NULL)
-      info_ptr = *info_ptr_ptr;
-
-   if (info_ptr != NULL)
-   {
-      /* Do this first in case of an error below; if the app implements its own
-       * memory management this can lead to png_free calling png_error, which
-       * will abort this routine and return control to the app error handler.
-       * An infinite loop may result if it then tries to free the same info
-       * ptr.
-       */
-      *info_ptr_ptr = NULL;
-
-      png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
-      memset(info_ptr, 0, (sizeof *info_ptr));
-      png_free(png_ptr, info_ptr);
-   }
-}
-
-/* Initialize the info structure.  This is now an internal function (0.89)
- * and applications using it are urged to use png_create_info_struct()
- * instead.  Use deprecated in 1.6.0, internal use removed (used internally it
- * is just a memset).
- *
- * NOTE: it is almost inconceivable that this API is used because it bypasses
- * the user-memory mechanism and the user error handling/warning mechanisms in
- * those cases where it does anything other than a memset.
- */
-PNG_FUNCTION(void,PNGAPI
-png_info_init_3,(png_infopp ptr_ptr, size_t png_info_struct_size),
-    PNG_DEPRECATED)
-{
-   png_inforp info_ptr = *ptr_ptr;
-
-   png_debug(1, "in png_info_init_3");
-
-   if (info_ptr == NULL)
-      return;
-
-   if ((sizeof (png_info)) > png_info_struct_size)
-   {
-      *ptr_ptr = NULL;
-      /* The following line is why this API should not be used: */
-      free(info_ptr);
-      info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL,
-          (sizeof *info_ptr)));
-      if (info_ptr == NULL)
-         return;
-      *ptr_ptr = info_ptr;
-   }
-
-   /* Set everything to 0 */
-   memset(info_ptr, 0, (sizeof *info_ptr));
-}
-
-/* The following API is not called internally */
-void PNGAPI
-png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
-    int freer, png_uint_32 mask)
-{
-   png_debug(1, "in png_data_freer");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   if (freer == PNG_DESTROY_WILL_FREE_DATA)
-      info_ptr->free_me |= mask;
-
-   else if (freer == PNG_USER_WILL_FREE_DATA)
-      info_ptr->free_me &= ~mask;
-
-   else
-      png_error(png_ptr, "Unknown freer parameter in png_data_freer");
-}
-
-void PNGAPI
-png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
-    int num)
-{
-   png_debug(1, "in png_free_data");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-#ifdef PNG_TEXT_SUPPORTED
-   /* Free text item num or (if num == -1) all text items */
-   if (info_ptr->text != NULL &&
-       ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0)
-   {
-      if (num != -1)
-      {
-         png_free(png_ptr, info_ptr->text[num].key);
-         info_ptr->text[num].key = NULL;
-      }
-
-      else
-      {
-         int i;
-
-         for (i = 0; i < info_ptr->num_text; i++)
-            png_free(png_ptr, info_ptr->text[i].key);
-
-         png_free(png_ptr, info_ptr->text);
-         info_ptr->text = NULL;
-         info_ptr->num_text = 0;
-         info_ptr->max_text = 0;
-      }
-   }
-#endif
-
-#ifdef PNG_tRNS_SUPPORTED
-   /* Free any tRNS entry */
-   if (((mask & PNG_FREE_TRNS) & info_ptr->free_me) != 0)
-   {
-      info_ptr->valid &= ~PNG_INFO_tRNS;
-      png_free(png_ptr, info_ptr->trans_alpha);
-      info_ptr->trans_alpha = NULL;
-      info_ptr->num_trans = 0;
-   }
-#endif
-
-#ifdef PNG_sCAL_SUPPORTED
-   /* Free any sCAL entry */
-   if (((mask & PNG_FREE_SCAL) & info_ptr->free_me) != 0)
-   {
-      png_free(png_ptr, info_ptr->scal_s_width);
-      png_free(png_ptr, info_ptr->scal_s_height);
-      info_ptr->scal_s_width = NULL;
-      info_ptr->scal_s_height = NULL;
-      info_ptr->valid &= ~PNG_INFO_sCAL;
-   }
-#endif
-
-#ifdef PNG_pCAL_SUPPORTED
-   /* Free any pCAL entry */
-   if (((mask & PNG_FREE_PCAL) & info_ptr->free_me) != 0)
-   {
-      png_free(png_ptr, info_ptr->pcal_purpose);
-      png_free(png_ptr, info_ptr->pcal_units);
-      info_ptr->pcal_purpose = NULL;
-      info_ptr->pcal_units = NULL;
-
-      if (info_ptr->pcal_params != NULL)
-         {
-            int i;
-
-            for (i = 0; i < info_ptr->pcal_nparams; i++)
-               png_free(png_ptr, info_ptr->pcal_params[i]);
-
-            png_free(png_ptr, info_ptr->pcal_params);
-            info_ptr->pcal_params = NULL;
-         }
-      info_ptr->valid &= ~PNG_INFO_pCAL;
-   }
-#endif
-
-#ifdef PNG_iCCP_SUPPORTED
-   /* Free any profile entry */
-   if (((mask & PNG_FREE_ICCP) & info_ptr->free_me) != 0)
-   {
-      png_free(png_ptr, info_ptr->iccp_name);
-      png_free(png_ptr, info_ptr->iccp_profile);
-      info_ptr->iccp_name = NULL;
-      info_ptr->iccp_profile = NULL;
-      info_ptr->valid &= ~PNG_INFO_iCCP;
-   }
-#endif
-
-#ifdef PNG_sPLT_SUPPORTED
-   /* Free a given sPLT entry, or (if num == -1) all sPLT entries */
-   if (info_ptr->splt_palettes != NULL &&
-       ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0)
-   {
-      if (num != -1)
-      {
-         png_free(png_ptr, info_ptr->splt_palettes[num].name);
-         png_free(png_ptr, info_ptr->splt_palettes[num].entries);
-         info_ptr->splt_palettes[num].name = NULL;
-         info_ptr->splt_palettes[num].entries = NULL;
-      }
-
-      else
-      {
-         int i;
-
-         for (i = 0; i < info_ptr->splt_palettes_num; i++)
-         {
-            png_free(png_ptr, info_ptr->splt_palettes[i].name);
-            png_free(png_ptr, info_ptr->splt_palettes[i].entries);
-         }
-
-         png_free(png_ptr, info_ptr->splt_palettes);
-         info_ptr->splt_palettes = NULL;
-         info_ptr->splt_palettes_num = 0;
-         info_ptr->valid &= ~PNG_INFO_sPLT;
-      }
-   }
-#endif
-
-#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-   if (info_ptr->unknown_chunks != NULL &&
-       ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0)
-   {
-      if (num != -1)
-      {
-          png_free(png_ptr, info_ptr->unknown_chunks[num].data);
-          info_ptr->unknown_chunks[num].data = NULL;
-      }
-
-      else
-      {
-         int i;
-
-         for (i = 0; i < info_ptr->unknown_chunks_num; i++)
-            png_free(png_ptr, info_ptr->unknown_chunks[i].data);
-
-         png_free(png_ptr, info_ptr->unknown_chunks);
-         info_ptr->unknown_chunks = NULL;
-         info_ptr->unknown_chunks_num = 0;
-      }
-   }
-#endif
-
-#ifdef PNG_eXIf_SUPPORTED
-   /* Free any eXIf entry */
-   if (((mask & PNG_FREE_EXIF) & info_ptr->free_me) != 0)
-   {
-# ifdef PNG_READ_eXIf_SUPPORTED
-      if (info_ptr->eXIf_buf)
-      {
-         png_free(png_ptr, info_ptr->eXIf_buf);
-         info_ptr->eXIf_buf = NULL;
-      }
-# endif
-      if (info_ptr->exif)
-      {
-         png_free(png_ptr, info_ptr->exif);
-         info_ptr->exif = NULL;
-      }
-      info_ptr->valid &= ~PNG_INFO_eXIf;
-   }
-#endif
-
-#ifdef PNG_hIST_SUPPORTED
-   /* Free any hIST entry */
-   if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0)
-   {
-      png_free(png_ptr, info_ptr->hist);
-      info_ptr->hist = NULL;
-      info_ptr->valid &= ~PNG_INFO_hIST;
-   }
-#endif
-
-   /* Free any PLTE entry that was internally allocated */
-   if (((mask & PNG_FREE_PLTE) & info_ptr->free_me) != 0)
-   {
-      png_free(png_ptr, info_ptr->palette);
-      info_ptr->palette = NULL;
-      info_ptr->valid &= ~PNG_INFO_PLTE;
-      info_ptr->num_palette = 0;
-   }
-
-#ifdef PNG_INFO_IMAGE_SUPPORTED
-   /* Free any image bits attached to the info structure */
-   if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0)
-   {
-      if (info_ptr->row_pointers != NULL)
-      {
-         png_uint_32 row;
-         for (row = 0; row < info_ptr->height; row++)
-            png_free(png_ptr, info_ptr->row_pointers[row]);
-
-         png_free(png_ptr, info_ptr->row_pointers);
-         info_ptr->row_pointers = NULL;
-      }
-      info_ptr->valid &= ~PNG_INFO_IDAT;
-   }
-#endif
-
-   if (num != -1)
-      mask &= ~PNG_FREE_MUL;
-
-   info_ptr->free_me &= ~mask;
-}
-#endif /* READ || WRITE */
-
-/* This function returns a pointer to the io_ptr associated with the user
- * functions.  The application should free any memory associated with this
- * pointer before png_write_destroy() or png_read_destroy() are called.
- */
-png_voidp PNGAPI
-png_get_io_ptr(png_const_structrp png_ptr)
-{
-   if (png_ptr == NULL)
-      return (NULL);
-
-   return (png_ptr->io_ptr);
-}
-
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-#  ifdef PNG_STDIO_SUPPORTED
-/* Initialize the default input/output functions for the PNG file.  If you
- * use your own read or write routines, you can call either png_set_read_fn()
- * or png_set_write_fn() instead of png_init_io().  If you have defined
- * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a
- * function of your own because "FILE *" isn't necessarily available.
- */
-void PNGAPI
-png_init_io(png_structrp png_ptr, png_FILE_p fp)
-{
-   png_debug(1, "in png_init_io");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->io_ptr = (png_voidp)fp;
-}
-#  endif
-
-#  ifdef PNG_SAVE_INT_32_SUPPORTED
-/* PNG signed integers are saved in 32-bit 2's complement format.  ANSI C-90
- * defines a cast of a signed integer to an unsigned integer either to preserve
- * the value, if it is positive, or to calculate:
- *
- *     (UNSIGNED_MAX+1) + integer
- *
- * Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the
- * negative integral value is added the result will be an unsigned value
- * correspnding to the 2's complement representation.
- */
-void PNGAPI
-png_save_int_32(png_bytep buf, png_int_32 i)
-{
-   png_save_uint_32(buf, (png_uint_32)i);
-}
-#  endif
-
-#  ifdef PNG_TIME_RFC1123_SUPPORTED
-/* Convert the supplied time into an RFC 1123 string suitable for use in
- * a "Creation Time" or other text-based time string.
- */
-int PNGAPI
-png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
-{
-   static const char short_months[12][4] =
-        {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
-         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
-
-   if (out == NULL)
-      return 0;
-
-   if (ptime->year > 9999 /* RFC1123 limitation */ ||
-       ptime->month == 0    ||  ptime->month > 12  ||
-       ptime->day   == 0    ||  ptime->day   > 31  ||
-       ptime->hour  > 23    ||  ptime->minute > 59 ||
-       ptime->second > 60)
-      return 0;
-
-   {
-      size_t pos = 0;
-      char number_buf[5]; /* enough for a four-digit year */
-
-#     define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))
-#     define APPEND_NUMBER(format, value)\
-         APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))
-#     define APPEND(ch) if (pos < 28) out[pos++] = (ch)
-
-      APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);
-      APPEND(' ');
-      APPEND_STRING(short_months[(ptime->month - 1)]);
-      APPEND(' ');
-      APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year);
-      APPEND(' ');
-      APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour);
-      APPEND(':');
-      APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute);
-      APPEND(':');
-      APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second);
-      APPEND_STRING(" +0000"); /* This reliably terminates the buffer */
-      PNG_UNUSED (pos)
-
-#     undef APPEND
-#     undef APPEND_NUMBER
-#     undef APPEND_STRING
-   }
-
-   return 1;
-}
-
-#    if PNG_LIBPNG_VER < 10700
-/* To do: remove the following from libpng-1.7 */
-/* Original API that uses a private buffer in png_struct.
- * Deprecated because it causes png_struct to carry a spurious temporary
- * buffer (png_struct::time_buffer), better to have the caller pass this in.
- */
-png_const_charp PNGAPI
-png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime)
-{
-   if (png_ptr != NULL)
-   {
-      /* The only failure above if png_ptr != NULL is from an invalid ptime */
-      if (png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime) == 0)
-         png_warning(png_ptr, "Ignoring invalid time value");
-
-      else
-         return png_ptr->time_buffer;
-   }
-
-   return NULL;
-}
-#    endif /* LIBPNG_VER < 10700 */
-#  endif /* TIME_RFC1123 */
-
-#endif /* READ || WRITE */
-
-png_const_charp PNGAPI
-png_get_copyright(png_const_structrp png_ptr)
-{
-   PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
-#ifdef PNG_STRING_COPYRIGHT
-   return PNG_STRING_COPYRIGHT
-#else
-   return PNG_STRING_NEWLINE \
-      "libpng version 1.6.37" PNG_STRING_NEWLINE \
-      "Copyright (c) 2018-2019 Cosmin Truta" PNG_STRING_NEWLINE \
-      "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
-      PNG_STRING_NEWLINE \
-      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
-      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
-      PNG_STRING_NEWLINE;
-#endif
-}
-
-/* The following return the library version as a short string in the
- * format 1.0.0 through 99.99.99zz.  To get the version of *.h files
- * used with your application, print out PNG_LIBPNG_VER_STRING, which
- * is defined in png.h.
- * Note: now there is no difference between png_get_libpng_ver() and
- * png_get_header_ver().  Due to the version_nn_nn_nn typedef guard,
- * it is guaranteed that png.c uses the correct version of png.h.
- */
-png_const_charp PNGAPI
-png_get_libpng_ver(png_const_structrp png_ptr)
-{
-   /* Version of *.c files used when building libpng */
-   return png_get_header_ver(png_ptr);
-}
-
-png_const_charp PNGAPI
-png_get_header_ver(png_const_structrp png_ptr)
-{
-   /* Version of *.h files used when building libpng */
-   PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
-   return PNG_LIBPNG_VER_STRING;
-}
-
-png_const_charp PNGAPI
-png_get_header_version(png_const_structrp png_ptr)
-{
-   /* Returns longer string containing both version and date */
-   PNG_UNUSED(png_ptr)  /* Silence compiler warning about unused png_ptr */
-#ifdef __STDC__
-   return PNG_HEADER_VERSION_STRING
-#  ifndef PNG_READ_SUPPORTED
-      " (NO READ SUPPORT)"
-#  endif
-      PNG_STRING_NEWLINE;
-#else
-   return PNG_HEADER_VERSION_STRING;
-#endif
-}
-
-#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
-/* NOTE: this routine is not used internally! */
-/* Build a grayscale palette.  Palette is assumed to be 1 << bit_depth
- * large of png_color.  This lets grayscale images be treated as
- * paletted.  Most useful for gamma correction and simplification
- * of code.  This API is not used internally.
- */
-void PNGAPI
-png_build_grayscale_palette(int bit_depth, png_colorp palette)
-{
-   int num_palette;
-   int color_inc;
-   int i;
-   int v;
-
-   png_debug(1, "in png_do_build_grayscale_palette");
-
-   if (palette == NULL)
-      return;
-
-   switch (bit_depth)
-   {
-      case 1:
-         num_palette = 2;
-         color_inc = 0xff;
-         break;
-
-      case 2:
-         num_palette = 4;
-         color_inc = 0x55;
-         break;
-
-      case 4:
-         num_palette = 16;
-         color_inc = 0x11;
-         break;
-
-      case 8:
-         num_palette = 256;
-         color_inc = 1;
-         break;
-
-      default:
-         num_palette = 0;
-         color_inc = 0;
-         break;
-   }
-
-   for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
-   {
-      palette[i].red = (png_byte)(v & 0xff);
-      palette[i].green = (png_byte)(v & 0xff);
-      palette[i].blue = (png_byte)(v & 0xff);
-   }
-}
-#endif
-
-#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-int PNGAPI
-png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name)
-{
-   /* Check chunk_name and return "keep" value if it's on the list, else 0 */
-   png_const_bytep p, p_end;
-
-   if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0)
-      return PNG_HANDLE_CHUNK_AS_DEFAULT;
-
-   p_end = png_ptr->chunk_list;
-   p = p_end + png_ptr->num_chunk_list*5; /* beyond end */
-
-   /* The code is the fifth byte after each four byte string.  Historically this
-    * code was always searched from the end of the list, this is no longer
-    * necessary because the 'set' routine handles duplicate entries correctly.
-    */
-   do /* num_chunk_list > 0, so at least one */
-   {
-      p -= 5;
-
-      if (memcmp(chunk_name, p, 4) == 0)
-         return p[4];
-   }
-   while (p > p_end);
-
-   /* This means that known chunks should be processed and unknown chunks should
-    * be handled according to the value of png_ptr->unknown_default; this can be
-    * confusing because, as a result, there are two levels of defaulting for
-    * unknown chunks.
-    */
-   return PNG_HANDLE_CHUNK_AS_DEFAULT;
-}
-
-#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
-   defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
-int /* PRIVATE */
-png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name)
-{
-   png_byte chunk_string[5];
-
-   PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
-   return png_handle_as_unknown(png_ptr, chunk_string);
-}
-#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
-#endif /* SET_UNKNOWN_CHUNKS */
-
-#ifdef PNG_READ_SUPPORTED
-/* This function, added to libpng-1.0.6g, is untested. */
-int PNGAPI
-png_reset_zstream(png_structrp png_ptr)
-{
-   if (png_ptr == NULL)
-      return Z_STREAM_ERROR;
-
-   /* WARNING: this resets the window bits to the maximum! */
-   return (inflateReset(&png_ptr->zstream));
-}
-#endif /* READ */
-
-/* This function was added to libpng-1.0.7 */
-png_uint_32 PNGAPI
-png_access_version_number(void)
-{
-   /* Version of *.c files used when building libpng */
-   return((png_uint_32)PNG_LIBPNG_VER);
-}
-
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-/* Ensure that png_ptr->zstream.msg holds some appropriate error message string.
- * If it doesn't 'ret' is used to set it to something appropriate, even in cases
- * like Z_OK or Z_STREAM_END where the error code is apparently a success code.
- */
-void /* PRIVATE */
-png_zstream_error(png_structrp png_ptr, int ret)
-{
-   /* Translate 'ret' into an appropriate error string, priority is given to the
-    * one in zstream if set.  This always returns a string, even in cases like
-    * Z_OK or Z_STREAM_END where the error code is a success code.
-    */
-   if (png_ptr->zstream.msg == NULL) switch (ret)
-   {
-      default:
-      case Z_OK:
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code");
-         break;
-
-      case Z_STREAM_END:
-         /* Normal exit */
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream");
-         break;
-
-      case Z_NEED_DICT:
-         /* This means the deflate stream did not have a dictionary; this
-          * indicates a bogus PNG.
-          */
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary");
-         break;
-
-      case Z_ERRNO:
-         /* gz APIs only: should not happen */
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error");
-         break;
-
-      case Z_STREAM_ERROR:
-         /* internal libpng error */
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib");
-         break;
-
-      case Z_DATA_ERROR:
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream");
-         break;
-
-      case Z_MEM_ERROR:
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory");
-         break;
-
-      case Z_BUF_ERROR:
-         /* End of input or output; not a problem if the caller is doing
-          * incremental read or write.
-          */
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated");
-         break;
-
-      case Z_VERSION_ERROR:
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version");
-         break;
-
-      case PNG_UNEXPECTED_ZLIB_RETURN:
-         /* Compile errors here mean that zlib now uses the value co-opted in
-          * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above
-          * and change pngpriv.h.  Note that this message is "... return",
-          * whereas the default/Z_OK one is "... return code".
-          */
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return");
-         break;
-   }
-}
-
-/* png_convert_size: a PNGAPI but no longer in png.h, so deleted
- * at libpng 1.5.5!
- */
-
-/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
-#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
-static int
-png_colorspace_check_gamma(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, png_fixed_point gAMA, int from)
-   /* This is called to check a new gamma value against an existing one.  The
-    * routine returns false if the new gamma value should not be written.
-    *
-    * 'from' says where the new gamma value comes from:
-    *
-    *    0: the new gamma value is the libpng estimate for an ICC profile
-    *    1: the new gamma value comes from a gAMA chunk
-    *    2: the new gamma value comes from an sRGB chunk
-    */
-{
-   png_fixed_point gtest;
-
-   if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
-       (png_muldiv(&gtest, colorspace->gamma, PNG_FP_1, gAMA) == 0  ||
-      png_gamma_significant(gtest) != 0))
-   {
-      /* Either this is an sRGB image, in which case the calculated gamma
-       * approximation should match, or this is an image with a profile and the
-       * value libpng calculates for the gamma of the profile does not match the
-       * value recorded in the file.  The former, sRGB, case is an error, the
-       * latter is just a warning.
-       */
-      if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)
-      {
-         png_chunk_report(png_ptr, "gamma value does not match sRGB",
-             PNG_CHUNK_ERROR);
-         /* Do not overwrite an sRGB value */
-         return from == 2;
-      }
-
-      else /* sRGB tag not involved */
-      {
-         png_chunk_report(png_ptr, "gamma value does not match libpng estimate",
-             PNG_CHUNK_WARNING);
-         return from == 1;
-      }
-   }
-
-   return 1;
-}
-
-void /* PRIVATE */
-png_colorspace_set_gamma(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, png_fixed_point gAMA)
-{
-   /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
-    * occur.  Since the fixed point representation is asymmetrical it is
-    * possible for 1/gamma to overflow the limit of 21474 and this means the
-    * gamma value must be at least 5/100000 and hence at most 20000.0.  For
-    * safety the limits here are a little narrower.  The values are 0.00016 to
-    * 6250.0, which are truly ridiculous gamma values (and will produce
-    * displays that are all black or all white.)
-    *
-    * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
-    * handling code, which only required the value to be >0.
-    */
-   png_const_charp errmsg;
-
-   if (gAMA < 16 || gAMA > 625000000)
-      errmsg = "gamma value out of range";
-
-#  ifdef PNG_READ_gAMA_SUPPORTED
-   /* Allow the application to set the gamma value more than once */
-   else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
-      (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
-      errmsg = "duplicate";
-#  endif
-
-   /* Do nothing if the colorspace is already invalid */
-   else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-      return;
-
-   else
-   {
-      if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA,
-          1/*from gAMA*/) != 0)
-      {
-         /* Store this gamma value. */
-         colorspace->gamma = gAMA;
-         colorspace->flags |=
-            (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA);
-      }
-
-      /* At present if the check_gamma test fails the gamma of the colorspace is
-       * not updated however the colorspace is not invalidated.  This
-       * corresponds to the case where the existing gamma comes from an sRGB
-       * chunk or profile.  An error message has already been output.
-       */
-      return;
-   }
-
-   /* Error exit - errmsg has been set. */
-   colorspace->flags |= PNG_COLORSPACE_INVALID;
-   png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);
-}
-
-void /* PRIVATE */
-png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)
-{
-   if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
-   {
-      /* Everything is invalid */
-      info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB|
-         PNG_INFO_iCCP);
-
-#     ifdef PNG_COLORSPACE_SUPPORTED
-      /* Clean up the iCCP profile now if it won't be used. */
-      png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/);
-#     else
-      PNG_UNUSED(png_ptr)
-#     endif
-   }
-
-   else
-   {
-#     ifdef PNG_COLORSPACE_SUPPORTED
-      /* Leave the INFO_iCCP flag set if the pngset.c code has already set
-       * it; this allows a PNG to contain a profile which matches sRGB and
-       * yet still have that profile retrievable by the application.
-       */
-      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) != 0)
-         info_ptr->valid |= PNG_INFO_sRGB;
-
-      else
-         info_ptr->valid &= ~PNG_INFO_sRGB;
-
-      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-         info_ptr->valid |= PNG_INFO_cHRM;
-
-      else
-         info_ptr->valid &= ~PNG_INFO_cHRM;
-#     endif
-
-      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0)
-         info_ptr->valid |= PNG_INFO_gAMA;
-
-      else
-         info_ptr->valid &= ~PNG_INFO_gAMA;
-   }
-}
-
-#ifdef PNG_READ_SUPPORTED
-void /* PRIVATE */
-png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
-{
-   if (info_ptr == NULL) /* reduce code size; check here not in the caller */
-      return;
-
-   info_ptr->colorspace = png_ptr->colorspace;
-   png_colorspace_sync_info(png_ptr, info_ptr);
-}
-#endif
-#endif /* GAMMA */
-
-#ifdef PNG_COLORSPACE_SUPPORTED
-/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
- * cHRM, as opposed to using chromaticities.  These internal APIs return
- * non-zero on a parameter error.  The X, Y and Z values are required to be
- * positive and less than 1.0.
- */
-static int
-png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
-{
-   png_int_32 d, dwhite, whiteX, whiteY;
-
-   d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
-   if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
-      return 1;
-   if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
-      return 1;
-   dwhite = d;
-   whiteX = XYZ->red_X;
-   whiteY = XYZ->red_Y;
-
-   d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
-   if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
-      return 1;
-   if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
-      return 1;
-   dwhite += d;
-   whiteX += XYZ->green_X;
-   whiteY += XYZ->green_Y;
-
-   d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
-   if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
-      return 1;
-   if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
-      return 1;
-   dwhite += d;
-   whiteX += XYZ->blue_X;
-   whiteY += XYZ->blue_Y;
-
-   /* The reference white is simply the sum of the end-point (X,Y,Z) vectors,
-    * thus:
-    */
-   if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0)
-      return 1;
-   if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0)
-      return 1;
-
-   return 0;
-}
-
-static int
-png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
-{
-   png_fixed_point red_inverse, green_inverse, blue_scale;
-   png_fixed_point left, right, denominator;
-
-   /* Check xy and, implicitly, z.  Note that wide gamut color spaces typically
-    * have end points with 0 tristimulus values (these are impossible end
-    * points, but they are used to cover the possible colors).  We check
-    * xy->whitey against 5, not 0, to avoid a possible integer overflow.
-    */
-   if (xy->redx   < 0 || xy->redx > PNG_FP_1) return 1;
-   if (xy->redy   < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
-   if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
-   if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
-   if (xy->bluex  < 0 || xy->bluex > PNG_FP_1) return 1;
-   if (xy->bluey  < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
-   if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
-   if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
-
-   /* The reverse calculation is more difficult because the original tristimulus
-    * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
-    * derived values were recorded in the cHRM chunk;
-    * (red,green,blue,white)x(x,y).  This loses one degree of freedom and
-    * therefore an arbitrary ninth value has to be introduced to undo the
-    * original transformations.
-    *
-    * Think of the original end-points as points in (X,Y,Z) space.  The
-    * chromaticity values (c) have the property:
-    *
-    *           C
-    *   c = ---------
-    *       X + Y + Z
-    *
-    * For each c (x,y,z) from the corresponding original C (X,Y,Z).  Thus the
-    * three chromaticity values (x,y,z) for each end-point obey the
-    * relationship:
-    *
-    *   x + y + z = 1
-    *
-    * This describes the plane in (X,Y,Z) space that intersects each axis at the
-    * value 1.0; call this the chromaticity plane.  Thus the chromaticity
-    * calculation has scaled each end-point so that it is on the x+y+z=1 plane
-    * and chromaticity is the intersection of the vector from the origin to the
-    * (X,Y,Z) value with the chromaticity plane.
-    *
-    * To fully invert the chromaticity calculation we would need the three
-    * end-point scale factors, (red-scale, green-scale, blue-scale), but these
-    * were not recorded.  Instead we calculated the reference white (X,Y,Z) and
-    * recorded the chromaticity of this.  The reference white (X,Y,Z) would have
-    * given all three of the scale factors since:
-    *
-    *    color-C = color-c * color-scale
-    *    white-C = red-C + green-C + blue-C
-    *            = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
-    *
-    * But cHRM records only white-x and white-y, so we have lost the white scale
-    * factor:
-    *
-    *    white-C = white-c*white-scale
-    *
-    * To handle this the inverse transformation makes an arbitrary assumption
-    * about white-scale:
-    *
-    *    Assume: white-Y = 1.0
-    *    Hence:  white-scale = 1/white-y
-    *    Or:     red-Y + green-Y + blue-Y = 1.0
-    *
-    * Notice the last statement of the assumption gives an equation in three of
-    * the nine values we want to calculate.  8 more equations come from the
-    * above routine as summarised at the top above (the chromaticity
-    * calculation):
-    *
-    *    Given: color-x = color-X / (color-X + color-Y + color-Z)
-    *    Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0
-    *
-    * This is 9 simultaneous equations in the 9 variables "color-C" and can be
-    * solved by Cramer's rule.  Cramer's rule requires calculating 10 9x9 matrix
-    * determinants, however this is not as bad as it seems because only 28 of
-    * the total of 90 terms in the various matrices are non-zero.  Nevertheless
-    * Cramer's rule is notoriously numerically unstable because the determinant
-    * calculation involves the difference of large, but similar, numbers.  It is
-    * difficult to be sure that the calculation is stable for real world values
-    * and it is certain that it becomes unstable where the end points are close
-    * together.
-    *
-    * So this code uses the perhaps slightly less optimal but more
-    * understandable and totally obvious approach of calculating color-scale.
-    *
-    * This algorithm depends on the precision in white-scale and that is
-    * (1/white-y), so we can immediately see that as white-y approaches 0 the
-    * accuracy inherent in the cHRM chunk drops off substantially.
-    *
-    * libpng arithmetic: a simple inversion of the above equations
-    * ------------------------------------------------------------
-    *
-    *    white_scale = 1/white-y
-    *    white-X = white-x * white-scale
-    *    white-Y = 1.0
-    *    white-Z = (1 - white-x - white-y) * white_scale
-    *
-    *    white-C = red-C + green-C + blue-C
-    *            = red-c*red-scale + green-c*green-scale + blue-c*blue-scale
-    *
-    * This gives us three equations in (red-scale,green-scale,blue-scale) where
-    * all the coefficients are now known:
-    *
-    *    red-x*red-scale + green-x*green-scale + blue-x*blue-scale
-    *       = white-x/white-y
-    *    red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1
-    *    red-z*red-scale + green-z*green-scale + blue-z*blue-scale
-    *       = (1 - white-x - white-y)/white-y
-    *
-    * In the last equation color-z is (1 - color-x - color-y) so we can add all
-    * three equations together to get an alternative third:
-    *
-    *    red-scale + green-scale + blue-scale = 1/white-y = white-scale
-    *
-    * So now we have a Cramer's rule solution where the determinants are just
-    * 3x3 - far more tractible.  Unfortunately 3x3 determinants still involve
-    * multiplication of three coefficients so we can't guarantee to avoid
-    * overflow in the libpng fixed point representation.  Using Cramer's rule in
-    * floating point is probably a good choice here, but it's not an option for
-    * fixed point.  Instead proceed to simplify the first two equations by
-    * eliminating what is likely to be the largest value, blue-scale:
-    *
-    *    blue-scale = white-scale - red-scale - green-scale
-    *
-    * Hence:
-    *
-    *    (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale =
-    *                (white-x - blue-x)*white-scale
-    *
-    *    (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale =
-    *                1 - blue-y*white-scale
-    *
-    * And now we can trivially solve for (red-scale,green-scale):
-    *
-    *    green-scale =
-    *                (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale
-    *                -----------------------------------------------------------
-    *                                  green-x - blue-x
-    *
-    *    red-scale =
-    *                1 - blue-y*white-scale - (green-y - blue-y) * green-scale
-    *                ---------------------------------------------------------
-    *                                  red-y - blue-y
-    *
-    * Hence:
-    *
-    *    red-scale =
-    *          ( (green-x - blue-x) * (white-y - blue-y) -
-    *            (green-y - blue-y) * (white-x - blue-x) ) / white-y
-    * -------------------------------------------------------------------------
-    *  (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
-    *
-    *    green-scale =
-    *          ( (red-y - blue-y) * (white-x - blue-x) -
-    *            (red-x - blue-x) * (white-y - blue-y) ) / white-y
-    * -------------------------------------------------------------------------
-    *  (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
-    *
-    * Accuracy:
-    * The input values have 5 decimal digits of accuracy.  The values are all in
-    * the range 0 < value < 1, so simple products are in the same range but may
-    * need up to 10 decimal digits to preserve the original precision and avoid
-    * underflow.  Because we are using a 32-bit signed representation we cannot
-    * match this; the best is a little over 9 decimal digits, less than 10.
-    *
-    * The approach used here is to preserve the maximum precision within the
-    * signed representation.  Because the red-scale calculation above uses the
-    * difference between two products of values that must be in the range -1..+1
-    * it is sufficient to divide the product by 7; ceil(100,000/32767*2).  The
-    * factor is irrelevant in the calculation because it is applied to both
-    * numerator and denominator.
-    *
-    * Note that the values of the differences of the products of the
-    * chromaticities in the above equations tend to be small, for example for
-    * the sRGB chromaticities they are:
-    *
-    * red numerator:    -0.04751
-    * green numerator:  -0.08788
-    * denominator:      -0.2241 (without white-y multiplication)
-    *
-    *  The resultant Y coefficients from the chromaticities of some widely used
-    *  color space definitions are (to 15 decimal places):
-    *
-    *  sRGB
-    *    0.212639005871510 0.715168678767756 0.072192315360734
-    *  Kodak ProPhoto
-    *    0.288071128229293 0.711843217810102 0.000085653960605
-    *  Adobe RGB
-    *    0.297344975250536 0.627363566255466 0.075291458493998
-    *  Adobe Wide Gamut RGB
-    *    0.258728243040113 0.724682314948566 0.016589442011321
-    */
-   /* By the argument, above overflow should be impossible here. The return
-    * value of 2 indicates an internal error to the caller.
-    */
-   if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0)
-      return 2;
-   if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
-      return 2;
-   denominator = left - right;
-
-   /* Now find the red numerator. */
-   if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
-      return 2;
-   if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
-      return 2;
-
-   /* Overflow is possible here and it indicates an extreme set of PNG cHRM
-    * chunk values.  This calculation actually returns the reciprocal of the
-    * scale value because this allows us to delay the multiplication of white-y
-    * into the denominator, which tends to produce a small number.
-    */
-   if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 ||
-       red_inverse <= xy->whitey /* r+g+b scales = white scale */)
-      return 1;
-
-   /* Similarly for green_inverse: */
-   if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
-      return 2;
-   if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
-      return 2;
-   if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
-       green_inverse <= xy->whitey)
-      return 1;
-
-   /* And the blue scale, the checks above guarantee this can't overflow but it
-    * can still produce 0 for extreme cHRM values.
-    */
-   blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
-       png_reciprocal(green_inverse);
-   if (blue_scale <= 0)
-      return 1;
-
-
-   /* And fill in the png_XYZ: */
-   if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0)
-      return 1;
-   if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0)
-      return 1;
-   if (png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1,
-       red_inverse) == 0)
-      return 1;
-
-   if (png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse) == 0)
-      return 1;
-   if (png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse) == 0)
-      return 1;
-   if (png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1,
-       green_inverse) == 0)
-      return 1;
-
-   if (png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1) == 0)
-      return 1;
-   if (png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1) == 0)
-      return 1;
-   if (png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale,
-       PNG_FP_1) == 0)
-      return 1;
-
-   return 0; /*success*/
-}
-
-static int
-png_XYZ_normalize(png_XYZ *XYZ)
-{
-   png_int_32 Y;
-
-   if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
-      XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
-      XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
-      return 1;
-
-   /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
-    * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
-    * relying on addition of two positive values producing a negative one is not
-    * safe.
-    */
-   Y = XYZ->red_Y;
-   if (0x7fffffff - Y < XYZ->green_X)
-      return 1;
-   Y += XYZ->green_Y;
-   if (0x7fffffff - Y < XYZ->blue_X)
-      return 1;
-   Y += XYZ->blue_Y;
-
-   if (Y != PNG_FP_1)
-   {
-      if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0)
-         return 1;
-
-      if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0)
-         return 1;
-
-      if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0)
-         return 1;
-      if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0)
-         return 1;
-   }
-
-   return 0;
-}
-
-static int
-png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta)
-{
-   /* Allow an error of +/-0.01 (absolute value) on each chromaticity */
-   if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||
-       PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||
-       PNG_OUT_OF_RANGE(xy1->redx,   xy2->redx,  delta) ||
-       PNG_OUT_OF_RANGE(xy1->redy,   xy2->redy,  delta) ||
-       PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||
-       PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||
-       PNG_OUT_OF_RANGE(xy1->bluex,  xy2->bluex, delta) ||
-       PNG_OUT_OF_RANGE(xy1->bluey,  xy2->bluey, delta))
-      return 0;
-   return 1;
-}
-
-/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM
- * chunk chromaticities.  Earlier checks used to simply look for the overflow
- * condition (where the determinant of the matrix to solve for XYZ ends up zero
- * because the chromaticity values are not all distinct.)  Despite this it is
- * theoretically possible to produce chromaticities that are apparently valid
- * but that rapidly degrade to invalid, potentially crashing, sets because of
- * arithmetic inaccuracies when calculations are performed on them.  The new
- * check is to round-trip xy -> XYZ -> xy and then check that the result is
- * within a small percentage of the original.
- */
-static int
-png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy)
-{
-   int result;
-   png_xy xy_test;
-
-   /* As a side-effect this routine also returns the XYZ endpoints. */
-   result = png_XYZ_from_xy(XYZ, xy);
-   if (result != 0)
-      return result;
-
-   result = png_xy_from_XYZ(&xy_test, XYZ);
-   if (result != 0)
-      return result;
-
-   if (png_colorspace_endpoints_match(xy, &xy_test,
-       5/*actually, the math is pretty accurate*/) != 0)
-      return 0;
-
-   /* Too much slip */
-   return 1;
-}
-
-/* This is the check going the other way.  The XYZ is modified to normalize it
- * (another side-effect) and the xy chromaticities are returned.
- */
-static int
-png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ)
-{
-   int result;
-   png_XYZ XYZtemp;
-
-   result = png_XYZ_normalize(XYZ);
-   if (result != 0)
-      return result;
-
-   result = png_xy_from_XYZ(xy, XYZ);
-   if (result != 0)
-      return result;
-
-   XYZtemp = *XYZ;
-   return png_colorspace_check_xy(&XYZtemp, xy);
-}
-
-/* Used to check for an endpoint match against sRGB */
-static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
-{
-   /* color      x       y */
-   /* red   */ 64000, 33000,
-   /* green */ 30000, 60000,
-   /* blue  */ 15000,  6000,
-   /* white */ 31270, 32900
-};
-
-static int
-png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
-    int preferred)
-{
-   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-      return 0;
-
-   /* The consistency check is performed on the chromaticities; this factors out
-    * variations because of the normalization (or not) of the end point Y
-    * values.
-    */
-   if (preferred < 2 &&
-       (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-   {
-      /* The end points must be reasonably close to any we already have.  The
-       * following allows an error of up to +/-.001
-       */
-      if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy,
-          100) == 0)
-      {
-         colorspace->flags |= PNG_COLORSPACE_INVALID;
-         png_benign_error(png_ptr, "inconsistent chromaticities");
-         return 0; /* failed */
-      }
-
-      /* Only overwrite with preferred values */
-      if (preferred == 0)
-         return 1; /* ok, but no change */
-   }
-
-   colorspace->end_points_xy = *xy;
-   colorspace->end_points_XYZ = *XYZ;
-   colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;
-
-   /* The end points are normally quoted to two decimal digits, so allow +/-0.01
-    * on this test.
-    */
-   if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0)
-      colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
-
-   else
-      colorspace->flags &= PNG_COLORSPACE_CANCEL(
-         PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
-
-   return 2; /* ok and changed */
-}
-
-int /* PRIVATE */
-png_colorspace_set_chromaticities(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, const png_xy *xy, int preferred)
-{
-   /* We must check the end points to ensure they are reasonable - in the past
-    * color management systems have crashed as a result of getting bogus
-    * colorant values, while this isn't the fault of libpng it is the
-    * responsibility of libpng because PNG carries the bomb and libpng is in a
-    * position to protect against it.
-    */
-   png_XYZ XYZ;
-
-   switch (png_colorspace_check_xy(&XYZ, xy))
-   {
-      case 0: /* success */
-         return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
-             preferred);
-
-      case 1:
-         /* We can't invert the chromaticities so we can't produce value XYZ
-          * values.  Likely as not a color management system will fail too.
-          */
-         colorspace->flags |= PNG_COLORSPACE_INVALID;
-         png_benign_error(png_ptr, "invalid chromaticities");
-         break;
-
-      default:
-         /* libpng is broken; this should be a warning but if it happens we
-          * want error reports so for the moment it is an error.
-          */
-         colorspace->flags |= PNG_COLORSPACE_INVALID;
-         png_error(png_ptr, "internal error checking chromaticities");
-   }
-
-   return 0; /* failed */
-}
-
-int /* PRIVATE */
-png_colorspace_set_endpoints(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
-{
-   png_XYZ XYZ = *XYZ_in;
-   png_xy xy;
-
-   switch (png_colorspace_check_XYZ(&xy, &XYZ))
-   {
-      case 0:
-         return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
-             preferred);
-
-      case 1:
-         /* End points are invalid. */
-         colorspace->flags |= PNG_COLORSPACE_INVALID;
-         png_benign_error(png_ptr, "invalid end points");
-         break;
-
-      default:
-         colorspace->flags |= PNG_COLORSPACE_INVALID;
-         png_error(png_ptr, "internal error checking chromaticities");
-   }
-
-   return 0; /* failed */
-}
-
-#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED)
-/* Error message generation */
-static char
-png_icc_tag_char(png_uint_32 byte)
-{
-   byte &= 0xff;
-   if (byte >= 32 && byte <= 126)
-      return (char)byte;
-   else
-      return '?';
-}
-
-static void
-png_icc_tag_name(char *name, png_uint_32 tag)
-{
-   name[0] = '\'';
-   name[1] = png_icc_tag_char(tag >> 24);
-   name[2] = png_icc_tag_char(tag >> 16);
-   name[3] = png_icc_tag_char(tag >>  8);
-   name[4] = png_icc_tag_char(tag      );
-   name[5] = '\'';
-}
-
-static int
-is_ICC_signature_char(png_alloc_size_t it)
-{
-   return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) ||
-      (it >= 97 && it <= 122);
-}
-
-static int
-is_ICC_signature(png_alloc_size_t it)
-{
-   return is_ICC_signature_char(it >> 24) /* checks all the top bits */ &&
-      is_ICC_signature_char((it >> 16) & 0xff) &&
-      is_ICC_signature_char((it >> 8) & 0xff) &&
-      is_ICC_signature_char(it & 0xff);
-}
-
-static int
-png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_alloc_size_t value, png_const_charp reason)
-{
-   size_t pos;
-   char message[196]; /* see below for calculation */
-
-   if (colorspace != NULL)
-      colorspace->flags |= PNG_COLORSPACE_INVALID;
-
-   pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */
-   pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */
-   pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */
-   if (is_ICC_signature(value) != 0)
-   {
-      /* So 'value' is at most 4 bytes and the following cast is safe */
-      png_icc_tag_name(message+pos, (png_uint_32)value);
-      pos += 6; /* total +8; less than the else clause */
-      message[pos++] = ':';
-      message[pos++] = ' ';
-   }
-#  ifdef PNG_WARNINGS_SUPPORTED
-   else
-      {
-         char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/
-
-         pos = png_safecat(message, (sizeof message), pos,
-             png_format_number(number, number+(sizeof number),
-             PNG_NUMBER_FORMAT_x, value));
-         pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/
-      }
-#  endif
-   /* The 'reason' is an arbitrary message, allow +79 maximum 195 */
-   pos = png_safecat(message, (sizeof message), pos, reason);
-   PNG_UNUSED(pos)
-
-   /* This is recoverable, but make it unconditionally an app_error on write to
-    * avoid writing invalid ICC profiles into PNG files (i.e., we handle them
-    * on read, with a warning, but on write unless the app turns off
-    * application errors the PNG won't be written.)
-    */
-   png_chunk_report(png_ptr, message,
-       (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
-
-   return 0;
-}
-#endif /* sRGB || iCCP */
-
-#ifdef PNG_sRGB_SUPPORTED
-int /* PRIVATE */
-png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    int intent)
-{
-   /* sRGB sets known gamma, end points and (from the chunk) intent. */
-   /* IMPORTANT: these are not necessarily the values found in an ICC profile
-    * because ICC profiles store values adapted to a D50 environment; it is
-    * expected that the ICC profile mediaWhitePointTag will be D50; see the
-    * checks and code elsewhere to understand this better.
-    *
-    * These XYZ values, which are accurate to 5dp, produce rgb to gray
-    * coefficients of (6968,23435,2366), which are reduced (because they add up
-    * to 32769 not 32768) to (6968,23434,2366).  These are the values that
-    * libpng has traditionally used (and are the best values given the 15bit
-    * algorithm used by the rgb to gray code.)
-    */
-   static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */
-   {
-      /* color      X      Y      Z */
-      /* red   */ 41239, 21264,  1933,
-      /* green */ 35758, 71517, 11919,
-      /* blue  */ 18048,  7219, 95053
-   };
-
-   /* Do nothing if the colorspace is already invalidated. */
-   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-      return 0;
-
-   /* Check the intent, then check for existing settings.  It is valid for the
-    * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must
-    * be consistent with the correct values.  If, however, this function is
-    * called below because an iCCP chunk matches sRGB then it is quite
-    * conceivable that an older app recorded incorrect gAMA and cHRM because of
-    * an incorrect calculation based on the values in the profile - this does
-    * *not* invalidate the profile (though it still produces an error, which can
-    * be ignored.)
-    */
-   if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
-      return png_icc_profile_error(png_ptr, colorspace, "sRGB",
-          (png_alloc_size_t)intent, "invalid sRGB rendering intent");
-
-   if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&
-       colorspace->rendering_intent != intent)
-      return png_icc_profile_error(png_ptr, colorspace, "sRGB",
-         (png_alloc_size_t)intent, "inconsistent rendering intents");
-
-   if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)
-   {
-      png_benign_error(png_ptr, "duplicate sRGB information ignored");
-      return 0;
-   }
-
-   /* If the standard sRGB cHRM chunk does not match the one from the PNG file
-    * warn but overwrite the value with the correct one.
-    */
-   if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 &&
-       !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
-       100))
-      png_chunk_report(png_ptr, "cHRM chunk does not match sRGB",
-         PNG_CHUNK_ERROR);
-
-   /* This check is just done for the error reporting - the routine always
-    * returns true when the 'from' argument corresponds to sRGB (2).
-    */
-   (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE,
-       2/*from sRGB*/);
-
-   /* intent: bugs in GCC force 'int' to be used as the parameter type. */
-   colorspace->rendering_intent = (png_uint_16)intent;
-   colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT;
-
-   /* endpoints */
-   colorspace->end_points_xy = sRGB_xy;
-   colorspace->end_points_XYZ = sRGB_XYZ;
-   colorspace->flags |=
-      (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
-
-   /* gamma */
-   colorspace->gamma = PNG_GAMMA_sRGB_INVERSE;
-   colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA;
-
-   /* Finally record that we have an sRGB profile */
-   colorspace->flags |=
-      (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB);
-
-   return 1; /* set */
-}
-#endif /* sRGB */
-
-#ifdef PNG_iCCP_SUPPORTED
-/* Encoded value of D50 as an ICC XYZNumber.  From the ICC 2010 spec the value
- * is XYZ(0.9642,1.0,0.8249), which scales to:
- *
- *    (63189.8112, 65536, 54060.6464)
- */
-static const png_byte D50_nCIEXYZ[12] =
-   { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d };
-
-static int /* bool */
-icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_uint_32 profile_length)
-{
-   if (profile_length < 132)
-      return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-          "too short");
-   return 1;
-}
-
-#ifdef PNG_READ_iCCP_SUPPORTED
-int /* PRIVATE */
-png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_uint_32 profile_length)
-{
-   if (!icc_check_length(png_ptr, colorspace, name, profile_length))
-      return 0;
-
-   /* This needs to be here because the 'normal' check is in
-    * png_decompress_chunk, yet this happens after the attempt to
-    * png_malloc_base the required data.  We only need this on read; on write
-    * the caller supplies the profile buffer so libpng doesn't allocate it.  See
-    * the call to icc_check_length below (the write case).
-    */
-#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
-      else if (png_ptr->user_chunk_malloc_max > 0 &&
-               png_ptr->user_chunk_malloc_max < profile_length)
-         return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-             "exceeds application limits");
-#  elif PNG_USER_CHUNK_MALLOC_MAX > 0
-      else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length)
-         return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-             "exceeds libpng limits");
-#  else /* !SET_USER_LIMITS */
-      /* This will get compiled out on all 32-bit and better systems. */
-      else if (PNG_SIZE_MAX < profile_length)
-         return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-             "exceeds system limits");
-#  endif /* !SET_USER_LIMITS */
-
-   return 1;
-}
-#endif /* READ_iCCP */
-
-int /* PRIVATE */
-png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_uint_32 profile_length,
-    png_const_bytep profile/* first 132 bytes only */, int color_type)
-{
-   png_uint_32 temp;
-
-   /* Length check; this cannot be ignored in this code because profile_length
-    * is used later to check the tag table, so even if the profile seems over
-    * long profile_length from the caller must be correct.  The caller can fix
-    * this up on read or write by just passing in the profile header length.
-    */
-   temp = png_get_uint_32(profile);
-   if (temp != profile_length)
-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
-          "length does not match profile");
-
-   temp = (png_uint_32) (*(profile+8));
-   if (temp > 3 && (profile_length & 3))
-      return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
-          "invalid length");
-
-   temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
-   if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */
-      profile_length < 132+12*temp) /* truncated tag table */
-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
-          "tag count too large");
-
-   /* The 'intent' must be valid or we can't store it, ICC limits the intent to
-    * 16 bits.
-    */
-   temp = png_get_uint_32(profile+64);
-   if (temp >= 0xffff) /* The ICC limit */
-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
-          "invalid rendering intent");
-
-   /* This is just a warning because the profile may be valid in future
-    * versions.
-    */
-   if (temp >= PNG_sRGB_INTENT_LAST)
-      (void)png_icc_profile_error(png_ptr, NULL, name, temp,
-          "intent outside defined range");
-
-   /* At this point the tag table can't be checked because it hasn't necessarily
-    * been loaded; however, various header fields can be checked.  These checks
-    * are for values permitted by the PNG spec in an ICC profile; the PNG spec
-    * restricts the profiles that can be passed in an iCCP chunk (they must be
-    * appropriate to processing PNG data!)
-    */
-
-   /* Data checks (could be skipped).  These checks must be independent of the
-    * version number; however, the version number doesn't accommodate changes in
-    * the header fields (just the known tags and the interpretation of the
-    * data.)
-    */
-   temp = png_get_uint_32(profile+36); /* signature 'ascp' */
-   if (temp != 0x61637370)
-      return png_icc_profile_error(png_ptr, colorspace, name, temp,
-          "invalid signature");
-
-   /* Currently the PCS illuminant/adopted white point (the computational
-    * white point) are required to be D50,
-    * however the profile contains a record of the illuminant so perhaps ICC
-    * expects to be able to change this in the future (despite the rationale in
-    * the introduction for using a fixed PCS adopted white.)  Consequently the
-    * following is just a warning.
-    */
-   if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)
-      (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,
-          "PCS illuminant is not D50");
-
-   /* The PNG spec requires this:
-    * "If the iCCP chunk is present, the image samples conform to the colour
-    * space represented by the embedded ICC profile as defined by the
-    * International Color Consortium [ICC]. The colour space of the ICC profile
-    * shall be an RGB colour space for colour images (PNG colour types 2, 3, and
-    * 6), or a greyscale colour space for greyscale images (PNG colour types 0
-    * and 4)."
-    *
-    * This checking code ensures the embedded profile (on either read or write)
-    * conforms to the specification requirements.  Notice that an ICC 'gray'
-    * color-space profile contains the information to transform the monochrome
-    * data to XYZ or L*a*b (according to which PCS the profile uses) and this
-    * should be used in preference to the standard libpng K channel replication
-    * into R, G and B channels.
-    *
-    * Previously it was suggested that an RGB profile on grayscale data could be
-    * handled.  However it it is clear that using an RGB profile in this context
-    * must be an error - there is no specification of what it means.  Thus it is
-    * almost certainly more correct to ignore the profile.
-    */
-   temp = png_get_uint_32(profile+16); /* data colour space field */
-   switch (temp)
-   {
-      case 0x52474220: /* 'RGB ' */
-         if ((color_type & PNG_COLOR_MASK_COLOR) == 0)
-            return png_icc_profile_error(png_ptr, colorspace, name, temp,
-                "RGB color space not permitted on grayscale PNG");
-         break;
-
-      case 0x47524159: /* 'GRAY' */
-         if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
-            return png_icc_profile_error(png_ptr, colorspace, name, temp,
-                "Gray color space not permitted on RGB PNG");
-         break;
-
-      default:
-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
-             "invalid ICC profile color space");
-   }
-
-   /* It is up to the application to check that the profile class matches the
-    * application requirements; the spec provides no guidance, but it's pretty
-    * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer
-    * ('prtr') or 'spac' (for generic color spaces).  Issue a warning in these
-    * cases.  Issue an error for device link or abstract profiles - these don't
-    * contain the records necessary to transform the color-space to anything
-    * other than the target device (and not even that for an abstract profile).
-    * Profiles of these classes may not be embedded in images.
-    */
-   temp = png_get_uint_32(profile+12); /* profile/device class */
-   switch (temp)
-   {
-      case 0x73636e72: /* 'scnr' */
-      case 0x6d6e7472: /* 'mntr' */
-      case 0x70727472: /* 'prtr' */
-      case 0x73706163: /* 'spac' */
-         /* All supported */
-         break;
-
-      case 0x61627374: /* 'abst' */
-         /* May not be embedded in an image */
-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
-             "invalid embedded Abstract ICC profile");
-
-      case 0x6c696e6b: /* 'link' */
-         /* DeviceLink profiles cannot be interpreted in a non-device specific
-          * fashion, if an app uses the AToB0Tag in the profile the results are
-          * undefined unless the result is sent to the intended device,
-          * therefore a DeviceLink profile should not be found embedded in a
-          * PNG.
-          */
-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
-             "unexpected DeviceLink ICC profile class");
-
-      case 0x6e6d636c: /* 'nmcl' */
-         /* A NamedColor profile is also device specific, however it doesn't
-          * contain an AToB0 tag that is open to misinterpretation.  Almost
-          * certainly it will fail the tests below.
-          */
-         (void)png_icc_profile_error(png_ptr, NULL, name, temp,
-             "unexpected NamedColor ICC profile class");
-         break;
-
-      default:
-         /* To allow for future enhancements to the profile accept unrecognized
-          * profile classes with a warning, these then hit the test below on the
-          * tag content to ensure they are backward compatible with one of the
-          * understood profiles.
-          */
-         (void)png_icc_profile_error(png_ptr, NULL, name, temp,
-             "unrecognized ICC profile class");
-         break;
-   }
-
-   /* For any profile other than a device link one the PCS must be encoded
-    * either in XYZ or Lab.
-    */
-   temp = png_get_uint_32(profile+20);
-   switch (temp)
-   {
-      case 0x58595a20: /* 'XYZ ' */
-      case 0x4c616220: /* 'Lab ' */
-         break;
-
-      default:
-         return png_icc_profile_error(png_ptr, colorspace, name, temp,
-             "unexpected ICC PCS encoding");
-   }
-
-   return 1;
-}
-
-int /* PRIVATE */
-png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_uint_32 profile_length,
-    png_const_bytep profile /* header plus whole tag table */)
-{
-   png_uint_32 tag_count = png_get_uint_32(profile+128);
-   png_uint_32 itag;
-   png_const_bytep tag = profile+132; /* The first tag */
-
-   /* First scan all the tags in the table and add bits to the icc_info value
-    * (temporarily in 'tags').
-    */
-   for (itag=0; itag < tag_count; ++itag, tag += 12)
-   {
-      png_uint_32 tag_id = png_get_uint_32(tag+0);
-      png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */
-      png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */
-
-      /* The ICC specification does not exclude zero length tags, therefore the
-       * start might actually be anywhere if there is no data, but this would be
-       * a clear abuse of the intent of the standard so the start is checked for
-       * being in range.  All defined tag types have an 8 byte header - a 4 byte
-       * type signature then 0.
-       */
-
-      /* This is a hard error; potentially it can cause read outside the
-       * profile.
-       */
-      if (tag_start > profile_length || tag_length > profile_length - tag_start)
-         return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
-             "ICC profile tag outside profile");
-
-      if ((tag_start & 3) != 0)
-      {
-         /* CNHP730S.icc shipped with Microsoft Windows 64 violates this; it is
-          * only a warning here because libpng does not care about the
-          * alignment.
-          */
-         (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
-             "ICC profile tag start not a multiple of 4");
-      }
-   }
-
-   return 1; /* success, maybe with warnings */
-}
-
-#ifdef PNG_sRGB_SUPPORTED
-#if PNG_sRGB_PROFILE_CHECKS >= 0
-/* Information about the known ICC sRGB profiles */
-static const struct
-{
-   png_uint_32 adler, crc, length;
-   png_uint_32 md5[4];
-   png_byte    have_md5;
-   png_byte    is_broken;
-   png_uint_16 intent;
-
-#  define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)
-#  define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\
-      { adler, crc, length, md5, broke, intent },
-
-} png_sRGB_checks[] =
-{
-   /* This data comes from contrib/tools/checksum-icc run on downloads of
-    * all four ICC sRGB profiles from www.color.org.
-    */
-   /* adler32, crc32, MD5[4], intent, date, length, file-name */
-   PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
-       PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
-       "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
-
-   /* ICC sRGB v2 perceptual no black-compensation: */
-   PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
-       PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
-       "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
-
-   PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
-       PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
-       "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
-
-   /* ICC sRGB v4 perceptual */
-   PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
-       PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
-       "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
-
-   /* The following profiles have no known MD5 checksum. If there is a match
-    * on the (empty) MD5 the other fields are used to attempt a match and
-    * a warning is produced.  The first two of these profiles have a 'cprt' tag
-    * which suggests that they were also made by Hewlett Packard.
-    */
-   PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
-       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
-       "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
-
-   /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not
-    * match the D50 PCS illuminant in the header (it is in fact the D65 values,
-    * so the white point is recorded as the un-adapted value.)  The profiles
-    * below only differ in one byte - the intent - and are basically the same as
-    * the previous profile except for the mediaWhitePointTag error and a missing
-    * chromaticAdaptationTag.
-    */
-   PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
-       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
-       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
-
-   PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
-       PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
-       "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
-};
-
-static int
-png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
-    png_const_bytep profile, uLong adler)
-{
-   /* The quick check is to verify just the MD5 signature and trust the
-    * rest of the data.  Because the profile has already been verified for
-    * correctness this is safe.  png_colorspace_set_sRGB will check the 'intent'
-    * field too, so if the profile has been edited with an intent not defined
-    * by sRGB (but maybe defined by a later ICC specification) the read of
-    * the profile will fail at that point.
-    */
-
-   png_uint_32 length = 0;
-   png_uint_32 intent = 0x10000; /* invalid */
-#if PNG_sRGB_PROFILE_CHECKS > 1
-   uLong crc = 0; /* the value for 0 length data */
-#endif
-   unsigned int i;
-
-#ifdef PNG_SET_OPTION_SUPPORTED
-   /* First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on" */
-   if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) ==
-               PNG_OPTION_ON)
-      return 0;
-#endif
-
-   for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)
-   {
-      if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&
-         png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&
-         png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&
-         png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])
-      {
-         /* This may be one of the old HP profiles without an MD5, in that
-          * case we can only use the length and Adler32 (note that these
-          * are not used by default if there is an MD5!)
-          */
-#        if PNG_sRGB_PROFILE_CHECKS == 0
-            if (png_sRGB_checks[i].have_md5 != 0)
-               return 1+png_sRGB_checks[i].is_broken;
-#        endif
-
-         /* Profile is unsigned or more checks have been configured in. */
-         if (length == 0)
-         {
-            length = png_get_uint_32(profile);
-            intent = png_get_uint_32(profile+64);
-         }
-
-         /* Length *and* intent must match */
-         if (length == (png_uint_32) png_sRGB_checks[i].length &&
-            intent == (png_uint_32) png_sRGB_checks[i].intent)
-         {
-            /* Now calculate the adler32 if not done already. */
-            if (adler == 0)
-            {
-               adler = adler32(0, NULL, 0);
-               adler = adler32(adler, profile, length);
-            }
-
-            if (adler == png_sRGB_checks[i].adler)
-            {
-               /* These basic checks suggest that the data has not been
-                * modified, but if the check level is more than 1 perform
-                * our own crc32 checksum on the data.
-                */
-#              if PNG_sRGB_PROFILE_CHECKS > 1
-                  if (crc == 0)
-                  {
-                     crc = crc32(0, NULL, 0);
-                     crc = crc32(crc, profile, length);
-                  }
-
-                  /* So this check must pass for the 'return' below to happen.
-                   */
-                  if (crc == png_sRGB_checks[i].crc)
-#              endif
-               {
-                  if (png_sRGB_checks[i].is_broken != 0)
-                  {
-                     /* These profiles are known to have bad data that may cause
-                      * problems if they are used, therefore attempt to
-                      * discourage their use, skip the 'have_md5' warning below,
-                      * which is made irrelevant by this error.
-                      */
-                     png_chunk_report(png_ptr, "known incorrect sRGB profile",
-                         PNG_CHUNK_ERROR);
-                  }
-
-                  /* Warn that this being done; this isn't even an error since
-                   * the profile is perfectly valid, but it would be nice if
-                   * people used the up-to-date ones.
-                   */
-                  else if (png_sRGB_checks[i].have_md5 == 0)
-                  {
-                     png_chunk_report(png_ptr,
-                         "out-of-date sRGB profile with no signature",
-                         PNG_CHUNK_WARNING);
-                  }
-
-                  return 1+png_sRGB_checks[i].is_broken;
-               }
-            }
-
-# if PNG_sRGB_PROFILE_CHECKS > 0
-         /* The signature matched, but the profile had been changed in some
-          * way.  This probably indicates a data error or uninformed hacking.
-          * Fall through to "no match".
-          */
-         png_chunk_report(png_ptr,
-             "Not recognizing known sRGB profile that has been edited",
-             PNG_CHUNK_WARNING);
-         break;
-# endif
-         }
-      }
-   }
-
-   return 0; /* no match */
-}
-
-void /* PRIVATE */
-png_icc_set_sRGB(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, png_const_bytep profile, uLong adler)
-{
-   /* Is this profile one of the known ICC sRGB profiles?  If it is, just set
-    * the sRGB information.
-    */
-   if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0)
-      (void)png_colorspace_set_sRGB(png_ptr, colorspace,
-         (int)/*already checked*/png_get_uint_32(profile+64));
-}
-#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */
-#endif /* sRGB */
-
-int /* PRIVATE */
-png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
-    png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,
-    int color_type)
-{
-   if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
-      return 0;
-
-   if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 &&
-       png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
-           color_type) != 0 &&
-       png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
-           profile) != 0)
-   {
-#     if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0
-         /* If no sRGB support, don't try storing sRGB information */
-         png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
-#     endif
-      return 1;
-   }
-
-   /* Failure case */
-   return 0;
-}
-#endif /* iCCP */
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-void /* PRIVATE */
-png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
-{
-   /* Set the rgb_to_gray coefficients from the colorspace. */
-   if (png_ptr->rgb_to_gray_coefficients_set == 0 &&
-      (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-   {
-      /* png_set_background has not been called, get the coefficients from the Y
-       * values of the colorspace colorants.
-       */
-      png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
-      png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
-      png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
-      png_fixed_point total = r+g+b;
-
-      if (total > 0 &&
-         r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
-         g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
-         b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
-         r+g+b <= 32769)
-      {
-         /* We allow 0 coefficients here.  r+g+b may be 32769 if two or
-          * all of the coefficients were rounded up.  Handle this by
-          * reducing the *largest* coefficient by 1; this matches the
-          * approach used for the default coefficients in pngrtran.c
-          */
-         int add = 0;
-
-         if (r+g+b > 32768)
-            add = -1;
-         else if (r+g+b < 32768)
-            add = 1;
-
-         if (add != 0)
-         {
-            if (g >= r && g >= b)
-               g += add;
-            else if (r >= g && r >= b)
-               r += add;
-            else
-               b += add;
-         }
-
-         /* Check for an internal error. */
-         if (r+g+b != 32768)
-            png_error(png_ptr,
-                "internal error handling cHRM coefficients");
-
-         else
-         {
-            png_ptr->rgb_to_gray_red_coeff   = (png_uint_16)r;
-            png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
-         }
-      }
-
-      /* This is a png_error at present even though it could be ignored -
-       * it should never happen, but it is important that if it does, the
-       * bug is fixed.
-       */
-      else
-         png_error(png_ptr, "internal error handling cHRM->XYZ");
-   }
-}
-#endif /* READ_RGB_TO_GRAY */
-
-#endif /* COLORSPACE */
-
-/* #ifdef __GNUC__ */
-#if 1
-/* This exists solely to work round a warning from GNU C. */
-static int /* PRIVATE */
-png_gt(size_t a, size_t b)
-{
-   return a > b;
-}
-#else
-#   define png_gt(a,b) ((a) > (b))
-#endif
-
-void /* PRIVATE */
-png_check_IHDR(png_const_structrp png_ptr,
-    png_uint_32 width, png_uint_32 height, int bit_depth,
-    int color_type, int interlace_type, int compression_type,
-    int filter_type)
-{
-   int error = 0;
-
-   /* Check for width and height valid values */
-   if (width == 0)
-   {
-      png_warning(png_ptr, "Image width is zero in IHDR");
-      error = 1;
-   }
-
-   if (width > PNG_UINT_31_MAX)
-   {
-      png_warning(png_ptr, "Invalid image width in IHDR");
-      error = 1;
-   }
-
-   if (png_gt(((width + 7) & (~7U)),
-       ((PNG_SIZE_MAX
-           - 48        /* big_row_buf hack */
-           - 1)        /* filter byte */
-           / 8)        /* 8-byte RGBA pixels */
-           - 1))       /* extra max_pixel_depth pad */
-   {
-      /* The size of the row must be within the limits of this architecture.
-       * Because the read code can perform arbitrary transformations the
-       * maximum size is checked here.  Because the code in png_read_start_row
-       * adds extra space "for safety's sake" in several places a conservative
-       * limit is used here.
-       *
-       * NOTE: it would be far better to check the size that is actually used,
-       * but the effect in the real world is minor and the changes are more
-       * extensive, therefore much more dangerous and much more difficult to
-       * write in a way that avoids compiler warnings.
-       */
-      png_warning(png_ptr, "Image width is too large for this architecture");
-      error = 1;
-   }
-
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (width > png_ptr->user_width_max)
-#else
-   if (width > PNG_USER_WIDTH_MAX)
-#endif
-   {
-      png_warning(png_ptr, "Image width exceeds user limit in IHDR");
-      error = 1;
-   }
-
-   if (height == 0)
-   {
-      png_warning(png_ptr, "Image height is zero in IHDR");
-      error = 1;
-   }
-
-   if (height > PNG_UINT_31_MAX)
-   {
-      png_warning(png_ptr, "Invalid image height in IHDR");
-      error = 1;
-   }
-
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (height > png_ptr->user_height_max)
-#else
-   if (height > PNG_USER_HEIGHT_MAX)
-#endif
-   {
-      png_warning(png_ptr, "Image height exceeds user limit in IHDR");
-      error = 1;
-   }
-
-   /* Check other values */
-   if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
-       bit_depth != 8 && bit_depth != 16)
-   {
-      png_warning(png_ptr, "Invalid bit depth in IHDR");
-      error = 1;
-   }
-
-   if (color_type < 0 || color_type == 1 ||
-       color_type == 5 || color_type > 6)
-   {
-      png_warning(png_ptr, "Invalid color type in IHDR");
-      error = 1;
-   }
-
-   if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
-       ((color_type == PNG_COLOR_TYPE_RGB ||
-         color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
-         color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
-   {
-      png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR");
-      error = 1;
-   }
-
-   if (interlace_type >= PNG_INTERLACE_LAST)
-   {
-      png_warning(png_ptr, "Unknown interlace method in IHDR");
-      error = 1;
-   }
-
-   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
-   {
-      png_warning(png_ptr, "Unknown compression method in IHDR");
-      error = 1;
-   }
-
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-   /* Accept filter_method 64 (intrapixel differencing) only if
-    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
-    * 2. Libpng did not read a PNG signature (this filter_method is only
-    *    used in PNG datastreams that are embedded in MNG datastreams) and
-    * 3. The application called png_permit_mng_features with a mask that
-    *    included PNG_FLAG_MNG_FILTER_64 and
-    * 4. The filter_method is 64 and
-    * 5. The color_type is RGB or RGBA
-    */
-   if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 &&
-       png_ptr->mng_features_permitted != 0)
-      png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
-
-   if (filter_type != PNG_FILTER_TYPE_BASE)
-   {
-      if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
-          (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
-          ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
-          (color_type == PNG_COLOR_TYPE_RGB ||
-          color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
-      {
-         png_warning(png_ptr, "Unknown filter method in IHDR");
-         error = 1;
-      }
-
-      if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0)
-      {
-         png_warning(png_ptr, "Invalid filter method in IHDR");
-         error = 1;
-      }
-   }
-
-#else
-   if (filter_type != PNG_FILTER_TYPE_BASE)
-   {
-      png_warning(png_ptr, "Unknown filter method in IHDR");
-      error = 1;
-   }
-#endif
-
-   if (error == 1)
-      png_error(png_ptr, "Invalid IHDR data");
-}
-
-#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
-/* ASCII to fp functions */
-/* Check an ASCII formatted floating point value, see the more detailed
- * comments in pngpriv.h
- */
-/* The following is used internally to preserve the sticky flags */
-#define png_fp_add(state, flags) ((state) |= (flags))
-#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))
-
-int /* PRIVATE */
-png_check_fp_number(png_const_charp string, size_t size, int *statep,
-    png_size_tp whereami)
-{
-   int state = *statep;
-   size_t i = *whereami;
-
-   while (i < size)
-   {
-      int type;
-      /* First find the type of the next character */
-      switch (string[i])
-      {
-      case 43:  type = PNG_FP_SAW_SIGN;                   break;
-      case 45:  type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break;
-      case 46:  type = PNG_FP_SAW_DOT;                    break;
-      case 48:  type = PNG_FP_SAW_DIGIT;                  break;
-      case 49: case 50: case 51: case 52:
-      case 53: case 54: case 55: case 56:
-      case 57:  type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break;
-      case 69:
-      case 101: type = PNG_FP_SAW_E;                      break;
-      default:  goto PNG_FP_End;
-      }
-
-      /* Now deal with this type according to the current
-       * state, the type is arranged to not overlap the
-       * bits of the PNG_FP_STATE.
-       */
-      switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))
-      {
-      case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:
-         if ((state & PNG_FP_SAW_ANY) != 0)
-            goto PNG_FP_End; /* not a part of the number */
-
-         png_fp_add(state, type);
-         break;
-
-      case PNG_FP_INTEGER + PNG_FP_SAW_DOT:
-         /* Ok as trailer, ok as lead of fraction. */
-         if ((state & PNG_FP_SAW_DOT) != 0) /* two dots */
-            goto PNG_FP_End;
-
-         else if ((state & PNG_FP_SAW_DIGIT) != 0) /* trailing dot? */
-            png_fp_add(state, type);
-
-         else
-            png_fp_set(state, PNG_FP_FRACTION | type);
-
-         break;
-
-      case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:
-         if ((state & PNG_FP_SAW_DOT) != 0) /* delayed fraction */
-            png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
-
-         png_fp_add(state, type | PNG_FP_WAS_VALID);
-
-         break;
-
-      case PNG_FP_INTEGER + PNG_FP_SAW_E:
-         if ((state & PNG_FP_SAW_DIGIT) == 0)
-            goto PNG_FP_End;
-
-         png_fp_set(state, PNG_FP_EXPONENT);
-
-         break;
-
-   /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN:
-         goto PNG_FP_End; ** no sign in fraction */
-
-   /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT:
-         goto PNG_FP_End; ** Because SAW_DOT is always set */
-
-      case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT:
-         png_fp_add(state, type | PNG_FP_WAS_VALID);
-         break;
-
-      case PNG_FP_FRACTION + PNG_FP_SAW_E:
-         /* This is correct because the trailing '.' on an
-          * integer is handled above - so we can only get here
-          * with the sequence ".E" (with no preceding digits).
-          */
-         if ((state & PNG_FP_SAW_DIGIT) == 0)
-            goto PNG_FP_End;
-
-         png_fp_set(state, PNG_FP_EXPONENT);
-
-         break;
-
-      case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:
-         if ((state & PNG_FP_SAW_ANY) != 0)
-            goto PNG_FP_End; /* not a part of the number */
-
-         png_fp_add(state, PNG_FP_SAW_SIGN);
-
-         break;
-
-   /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT:
-         goto PNG_FP_End; */
-
-      case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT:
-         png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID);
-
-         break;
-
-   /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E:
-         goto PNG_FP_End; */
-
-      default: goto PNG_FP_End; /* I.e. break 2 */
-      }
-
-      /* The character seems ok, continue. */
-      ++i;
-   }
-
-PNG_FP_End:
-   /* Here at the end, update the state and return the correct
-    * return code.
-    */
-   *statep = state;
-   *whereami = i;
-
-   return (state & PNG_FP_SAW_DIGIT) != 0;
-}
-
-
-/* The same but for a complete string. */
-int
-png_check_fp_string(png_const_charp string, size_t size)
-{
-   int        state=0;
-   size_t char_index=0;
-
-   if (png_check_fp_number(string, size, &state, &char_index) != 0 &&
-      (char_index == size || string[char_index] == 0))
-      return state /* must be non-zero - see above */;
-
-   return 0; /* i.e. fail */
-}
-#endif /* pCAL || sCAL */
-
-#ifdef PNG_sCAL_SUPPORTED
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-/* Utility used below - a simple accurate power of ten from an integral
- * exponent.
- */
-static double
-png_pow10(int power)
-{
-   int recip = 0;
-   double d = 1;
-
-   /* Handle negative exponent with a reciprocal at the end because
-    * 10 is exact whereas .1 is inexact in base 2
-    */
-   if (power < 0)
-   {
-      if (power < DBL_MIN_10_EXP) return 0;
-      recip = 1; power = -power;
-   }
-
-   if (power > 0)
-   {
-      /* Decompose power bitwise. */
-      double mult = 10;
-      do
-      {
-         if (power & 1) d *= mult;
-         mult *= mult;
-         power >>= 1;
-      }
-      while (power > 0);
-
-      if (recip != 0) d = 1/d;
-   }
-   /* else power is 0 and d is 1 */
-
-   return d;
-}
-
-/* Function to format a floating point value in ASCII with a given
- * precision.
- */
-#if GCC_STRICT_OVERFLOW
-#pragma GCC diagnostic push
-/* The problem arises below with exp_b10, which can never overflow because it
- * comes, originally, from frexp and is therefore limited to a range which is
- * typically +/-710 (log2(DBL_MAX)/log2(DBL_MIN)).
- */
-#pragma GCC diagnostic warning "-Wstrict-overflow=2"
-#endif /* GCC_STRICT_OVERFLOW */
-void /* PRIVATE */
-png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size,
-    double fp, unsigned int precision)
-{
-   /* We use standard functions from math.h, but not printf because
-    * that would require stdio.  The caller must supply a buffer of
-    * sufficient size or we will png_error.  The tests on size and
-    * the space in ascii[] consumed are indicated below.
-    */
-   if (precision < 1)
-      precision = DBL_DIG;
-
-   /* Enforce the limit of the implementation precision too. */
-   if (precision > DBL_DIG+1)
-      precision = DBL_DIG+1;
-
-   /* Basic sanity checks */
-   if (size >= precision+5) /* See the requirements below. */
-   {
-      if (fp < 0)
-      {
-         fp = -fp;
-         *ascii++ = 45; /* '-'  PLUS 1 TOTAL 1 */
-         --size;
-      }
-
-      if (fp >= DBL_MIN && fp <= DBL_MAX)
-      {
-         int exp_b10;   /* A base 10 exponent */
-         double base;   /* 10^exp_b10 */
-
-         /* First extract a base 10 exponent of the number,
-          * the calculation below rounds down when converting
-          * from base 2 to base 10 (multiply by log10(2) -
-          * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to
-          * be increased.  Note that the arithmetic shift
-          * performs a floor() unlike C arithmetic - using a
-          * C multiply would break the following for negative
-          * exponents.
-          */
-         (void)frexp(fp, &exp_b10); /* exponent to base 2 */
-
-         exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */
-
-         /* Avoid underflow here. */
-         base = png_pow10(exp_b10); /* May underflow */
-
-         while (base < DBL_MIN || base < fp)
-         {
-            /* And this may overflow. */
-            double test = png_pow10(exp_b10+1);
-
-            if (test <= DBL_MAX)
-            {
-               ++exp_b10; base = test;
-            }
-
-            else
-               break;
-         }
-
-         /* Normalize fp and correct exp_b10, after this fp is in the
-          * range [.1,1) and exp_b10 is both the exponent and the digit
-          * *before* which the decimal point should be inserted
-          * (starting with 0 for the first digit).  Note that this
-          * works even if 10^exp_b10 is out of range because of the
-          * test on DBL_MAX above.
-          */
-         fp /= base;
-         while (fp >= 1)
-         {
-            fp /= 10; ++exp_b10;
-         }
-
-         /* Because of the code above fp may, at this point, be
-          * less than .1, this is ok because the code below can
-          * handle the leading zeros this generates, so no attempt
-          * is made to correct that here.
-          */
-
-         {
-            unsigned int czero, clead, cdigits;
-            char exponent[10];
-
-            /* Allow up to two leading zeros - this will not lengthen
-             * the number compared to using E-n.
-             */
-            if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */
-            {
-               czero = 0U-exp_b10; /* PLUS 2 digits: TOTAL 3 */
-               exp_b10 = 0;      /* Dot added below before first output. */
-            }
-            else
-               czero = 0;    /* No zeros to add */
-
-            /* Generate the digit list, stripping trailing zeros and
-             * inserting a '.' before a digit if the exponent is 0.
-             */
-            clead = czero; /* Count of leading zeros */
-            cdigits = 0;   /* Count of digits in list. */
-
-            do
-            {
-               double d;
-
-               fp *= 10;
-               /* Use modf here, not floor and subtract, so that
-                * the separation is done in one step.  At the end
-                * of the loop don't break the number into parts so
-                * that the final digit is rounded.
-                */
-               if (cdigits+czero+1 < precision+clead)
-                  fp = modf(fp, &d);
-
-               else
-               {
-                  d = floor(fp + .5);
-
-                  if (d > 9)
-                  {
-                     /* Rounding up to 10, handle that here. */
-                     if (czero > 0)
-                     {
-                        --czero; d = 1;
-                        if (cdigits == 0) --clead;
-                     }
-                     else
-                     {
-                        while (cdigits > 0 && d > 9)
-                        {
-                           int ch = *--ascii;
-
-                           if (exp_b10 != (-1))
-                              ++exp_b10;
-
-                           else if (ch == 46)
-                           {
-                              ch = *--ascii; ++size;
-                              /* Advance exp_b10 to '1', so that the
-                               * decimal point happens after the
-                               * previous digit.
-                               */
-                              exp_b10 = 1;
-                           }
-
-                           --cdigits;
-                           d = ch - 47;  /* I.e. 1+(ch-48) */
-                        }
-
-                        /* Did we reach the beginning? If so adjust the
-                         * exponent but take into account the leading
-                         * decimal point.
-                         */
-                        if (d > 9)  /* cdigits == 0 */
-                        {
-                           if (exp_b10 == (-1))
-                           {
-                              /* Leading decimal point (plus zeros?), if
-                               * we lose the decimal point here it must
-                               * be reentered below.
-                               */
-                              int ch = *--ascii;
-
-                              if (ch == 46)
-                              {
-                                 ++size; exp_b10 = 1;
-                              }
-
-                              /* Else lost a leading zero, so 'exp_b10' is
-                               * still ok at (-1)
-                               */
-                           }
-                           else
-                              ++exp_b10;
-
-                           /* In all cases we output a '1' */
-                           d = 1;
-                        }
-                     }
-                  }
-                  fp = 0; /* Guarantees termination below. */
-               }
-
-               if (d == 0)
-               {
-                  ++czero;
-                  if (cdigits == 0) ++clead;
-               }
-               else
-               {
-                  /* Included embedded zeros in the digit count. */
-                  cdigits += czero - clead;
-                  clead = 0;
-
-                  while (czero > 0)
-                  {
-                     /* exp_b10 == (-1) means we just output the decimal
-                      * place - after the DP don't adjust 'exp_b10' any
-                      * more!
-                      */
-                     if (exp_b10 != (-1))
-                     {
-                        if (exp_b10 == 0)
-                        {
-                           *ascii++ = 46; --size;
-                        }
-                        /* PLUS 1: TOTAL 4 */
-                        --exp_b10;
-                     }
-                     *ascii++ = 48; --czero;
-                  }
-
-                  if (exp_b10 != (-1))
-                  {
-                     if (exp_b10 == 0)
-                     {
-                        *ascii++ = 46; --size; /* counted above */
-                     }
-
-                     --exp_b10;
-                  }
-                  *ascii++ = (char)(48 + (int)d); ++cdigits;
-               }
-            }
-            while (cdigits+czero < precision+clead && fp > DBL_MIN);
-
-            /* The total output count (max) is now 4+precision */
-
-            /* Check for an exponent, if we don't need one we are
-             * done and just need to terminate the string.  At this
-             * point, exp_b10==(-1) is effectively a flag: it got
-             * to '-1' because of the decrement, after outputting
-             * the decimal point above. (The exponent required is
-             * *not* -1.)
-             */
-            if (exp_b10 >= (-1) && exp_b10 <= 2)
-            {
-               /* The following only happens if we didn't output the
-                * leading zeros above for negative exponent, so this
-                * doesn't add to the digit requirement.  Note that the
-                * two zeros here can only be output if the two leading
-                * zeros were *not* output, so this doesn't increase
-                * the output count.
-                */
-               while (exp_b10-- > 0) *ascii++ = 48;
-
-               *ascii = 0;
-
-               /* Total buffer requirement (including the '\0') is
-                * 5+precision - see check at the start.
-                */
-               return;
-            }
-
-            /* Here if an exponent is required, adjust size for
-             * the digits we output but did not count.  The total
-             * digit output here so far is at most 1+precision - no
-             * decimal point and no leading or trailing zeros have
-             * been output.
-             */
-            size -= cdigits;
-
-            *ascii++ = 69; --size;    /* 'E': PLUS 1 TOTAL 2+precision */
-
-            /* The following use of an unsigned temporary avoids ambiguities in
-             * the signed arithmetic on exp_b10 and permits GCC at least to do
-             * better optimization.
-             */
-            {
-               unsigned int uexp_b10;
-
-               if (exp_b10 < 0)
-               {
-                  *ascii++ = 45; --size; /* '-': PLUS 1 TOTAL 3+precision */
-                  uexp_b10 = 0U-exp_b10;
-               }
-
-               else
-                  uexp_b10 = 0U+exp_b10;
-
-               cdigits = 0;
-
-               while (uexp_b10 > 0)
-               {
-                  exponent[cdigits++] = (char)(48 + uexp_b10 % 10);
-                  uexp_b10 /= 10;
-               }
-            }
-
-            /* Need another size check here for the exponent digits, so
-             * this need not be considered above.
-             */
-            if (size > cdigits)
-            {
-               while (cdigits > 0) *ascii++ = exponent[--cdigits];
-
-               *ascii = 0;
-
-               return;
-            }
-         }
-      }
-      else if (!(fp >= DBL_MIN))
-      {
-         *ascii++ = 48; /* '0' */
-         *ascii = 0;
-         return;
-      }
-      else
-      {
-         *ascii++ = 105; /* 'i' */
-         *ascii++ = 110; /* 'n' */
-         *ascii++ = 102; /* 'f' */
-         *ascii = 0;
-         return;
-      }
-   }
-
-   /* Here on buffer too small. */
-   png_error(png_ptr, "ASCII conversion buffer too small");
-}
-#if GCC_STRICT_OVERFLOW
-#pragma GCC diagnostic pop
-#endif /* GCC_STRICT_OVERFLOW */
-
-#  endif /* FLOATING_POINT */
-
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-/* Function to format a fixed point value in ASCII.
- */
-void /* PRIVATE */
-png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
-    size_t size, png_fixed_point fp)
-{
-   /* Require space for 10 decimal digits, a decimal point, a minus sign and a
-    * trailing \0, 13 characters:
-    */
-   if (size > 12)
-   {
-      png_uint_32 num;
-
-      /* Avoid overflow here on the minimum integer. */
-      if (fp < 0)
-      {
-         *ascii++ = 45; num = (png_uint_32)(-fp);
-      }
-      else
-         num = (png_uint_32)fp;
-
-      if (num <= 0x80000000) /* else overflowed */
-      {
-         unsigned int ndigits = 0, first = 16 /* flag value */;
-         char digits[10];
-
-         while (num)
-         {
-            /* Split the low digit off num: */
-            unsigned int tmp = num/10;
-            num -= tmp*10;
-            digits[ndigits++] = (char)(48 + num);
-            /* Record the first non-zero digit, note that this is a number
-             * starting at 1, it's not actually the array index.
-             */
-            if (first == 16 && num > 0)
-               first = ndigits;
-            num = tmp;
-         }
-
-         if (ndigits > 0)
-         {
-            while (ndigits > 5) *ascii++ = digits[--ndigits];
-            /* The remaining digits are fractional digits, ndigits is '5' or
-             * smaller at this point.  It is certainly not zero.  Check for a
-             * non-zero fractional digit:
-             */
-            if (first <= 5)
-            {
-               unsigned int i;
-               *ascii++ = 46; /* decimal point */
-               /* ndigits may be <5 for small numbers, output leading zeros
-                * then ndigits digits to first:
-                */
-               i = 5;
-               while (ndigits < i)
-               {
-                  *ascii++ = 48; --i;
-               }
-               while (ndigits >= first) *ascii++ = digits[--ndigits];
-               /* Don't output the trailing zeros! */
-            }
-         }
-         else
-            *ascii++ = 48;
-
-         /* And null terminate the string: */
-         *ascii = 0;
-         return;
-      }
-   }
-
-   /* Here on buffer too small. */
-   png_error(png_ptr, "ASCII conversion buffer too small");
-}
-#   endif /* FIXED_POINT */
-#endif /* SCAL */
-
-#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
-   !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
-   (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
-   defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
-   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
-   (defined(PNG_sCAL_SUPPORTED) && \
-   defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
-png_fixed_point
-png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
-{
-   double r = floor(100000 * fp + .5);
-
-   if (r > 2147483647. || r < -2147483648.)
-      png_fixed_error(png_ptr, text);
-
-#  ifndef PNG_ERROR_TEXT_SUPPORTED
-   PNG_UNUSED(text)
-#  endif
-
-   return (png_fixed_point)r;
-}
-#endif
-
-#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\
-    defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
-/* muldiv functions */
-/* This API takes signed arguments and rounds the result to the nearest
- * integer (or, for a fixed point number - the standard argument - to
- * the nearest .00001).  Overflow and divide by zero are signalled in
- * the result, a boolean - true on success, false on overflow.
- */
-#if GCC_STRICT_OVERFLOW /* from above */
-/* It is not obvious which comparison below gets optimized in such a way that
- * signed overflow would change the result; looking through the code does not
- * reveal any tests which have the form GCC complains about, so presumably the
- * optimizer is moving an add or subtract into the 'if' somewhere.
- */
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-Wstrict-overflow=2"
-#endif /* GCC_STRICT_OVERFLOW */
-int
-png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
-    png_int_32 divisor)
-{
-   /* Return a * times / divisor, rounded. */
-   if (divisor != 0)
-   {
-      if (a == 0 || times == 0)
-      {
-         *res = 0;
-         return 1;
-      }
-      else
-      {
-#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
-         double r = a;
-         r *= times;
-         r /= divisor;
-         r = floor(r+.5);
-
-         /* A png_fixed_point is a 32-bit integer. */
-         if (r <= 2147483647. && r >= -2147483648.)
-         {
-            *res = (png_fixed_point)r;
-            return 1;
-         }
-#else
-         int negative = 0;
-         png_uint_32 A, T, D;
-         png_uint_32 s16, s32, s00;
-
-         if (a < 0)
-            negative = 1, A = -a;
-         else
-            A = a;
-
-         if (times < 0)
-            negative = !negative, T = -times;
-         else
-            T = times;
-
-         if (divisor < 0)
-            negative = !negative, D = -divisor;
-         else
-            D = divisor;
-
-         /* Following can't overflow because the arguments only
-          * have 31 bits each, however the result may be 32 bits.
-          */
-         s16 = (A >> 16) * (T & 0xffff) +
-                           (A & 0xffff) * (T >> 16);
-         /* Can't overflow because the a*times bit is only 30
-          * bits at most.
-          */
-         s32 = (A >> 16) * (T >> 16) + (s16 >> 16);
-         s00 = (A & 0xffff) * (T & 0xffff);
-
-         s16 = (s16 & 0xffff) << 16;
-         s00 += s16;
-
-         if (s00 < s16)
-            ++s32; /* carry */
-
-         if (s32 < D) /* else overflow */
-         {
-            /* s32.s00 is now the 64-bit product, do a standard
-             * division, we know that s32 < D, so the maximum
-             * required shift is 31.
-             */
-            int bitshift = 32;
-            png_fixed_point result = 0; /* NOTE: signed */
-
-            while (--bitshift >= 0)
-            {
-               png_uint_32 d32, d00;
-
-               if (bitshift > 0)
-                  d32 = D >> (32-bitshift), d00 = D << bitshift;
-
-               else
-                  d32 = 0, d00 = D;
-
-               if (s32 > d32)
-               {
-                  if (s00 < d00) --s32; /* carry */
-                  s32 -= d32, s00 -= d00, result += 1<<bitshift;
-               }
-
-               else
-                  if (s32 == d32 && s00 >= d00)
-                     s32 = 0, s00 -= d00, result += 1<<bitshift;
-            }
-
-            /* Handle the rounding. */
-            if (s00 >= (D >> 1))
-               ++result;
-
-            if (negative != 0)
-               result = -result;
-
-            /* Check for overflow. */
-            if ((negative != 0 && result <= 0) ||
-                (negative == 0 && result >= 0))
-            {
-               *res = result;
-               return 1;
-            }
-         }
-#endif
-      }
-   }
-
-   return 0;
-}
-#if GCC_STRICT_OVERFLOW
-#pragma GCC diagnostic pop
-#endif /* GCC_STRICT_OVERFLOW */
-#endif /* READ_GAMMA || INCH_CONVERSIONS */
-
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
-/* The following is for when the caller doesn't much care about the
- * result.
- */
-png_fixed_point
-png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times,
-    png_int_32 divisor)
-{
-   png_fixed_point result;
-
-   if (png_muldiv(&result, a, times, divisor) != 0)
-      return result;
-
-   png_warning(png_ptr, "fixed point overflow ignored");
-   return 0;
-}
-#endif
-
-#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */
-/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
-png_fixed_point
-png_reciprocal(png_fixed_point a)
-{
-#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
-   double r = floor(1E10/a+.5);
-
-   if (r <= 2147483647. && r >= -2147483648.)
-      return (png_fixed_point)r;
-#else
-   png_fixed_point res;
-
-   if (png_muldiv(&res, 100000, 100000, a) != 0)
-      return res;
-#endif
-
-   return 0; /* error/overflow */
-}
-
-/* This is the shared test on whether a gamma value is 'significant' - whether
- * it is worth doing gamma correction.
- */
-int /* PRIVATE */
-png_gamma_significant(png_fixed_point gamma_val)
-{
-   return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
-       gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
-}
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-#ifdef PNG_16BIT_SUPPORTED
-/* A local convenience routine. */
-static png_fixed_point
-png_product2(png_fixed_point a, png_fixed_point b)
-{
-   /* The required result is 1/a * 1/b; the following preserves accuracy. */
-#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
-   double r = a * 1E-5;
-   r *= b;
-   r = floor(r+.5);
-
-   if (r <= 2147483647. && r >= -2147483648.)
-      return (png_fixed_point)r;
-#else
-   png_fixed_point res;
-
-   if (png_muldiv(&res, a, b, 100000) != 0)
-      return res;
-#endif
-
-   return 0; /* overflow */
-}
-#endif /* 16BIT */
-
-/* The inverse of the above. */
-png_fixed_point
-png_reciprocal2(png_fixed_point a, png_fixed_point b)
-{
-   /* The required result is 1/a * 1/b; the following preserves accuracy. */
-#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
-   if (a != 0 && b != 0)
-   {
-      double r = 1E15/a;
-      r /= b;
-      r = floor(r+.5);
-
-      if (r <= 2147483647. && r >= -2147483648.)
-         return (png_fixed_point)r;
-   }
-#else
-   /* This may overflow because the range of png_fixed_point isn't symmetric,
-    * but this API is only used for the product of file and screen gamma so it
-    * doesn't matter that the smallest number it can produce is 1/21474, not
-    * 1/100000
-    */
-   png_fixed_point res = png_product2(a, b);
-
-   if (res != 0)
-      return png_reciprocal(res);
-#endif
-
-   return 0; /* overflow */
-}
-#endif /* READ_GAMMA */
-
-#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */
-#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
-/* Fixed point gamma.
- *
- * The code to calculate the tables used below can be found in the shell script
- * contrib/tools/intgamma.sh
- *
- * To calculate gamma this code implements fast log() and exp() calls using only
- * fixed point arithmetic.  This code has sufficient precision for either 8-bit
- * or 16-bit sample values.
- *
- * The tables used here were calculated using simple 'bc' programs, but C double
- * precision floating point arithmetic would work fine.
- *
- * 8-bit log table
- *   This is a table of -log(value/255)/log(2) for 'value' in the range 128 to
- *   255, so it's the base 2 logarithm of a normalized 8-bit floating point
- *   mantissa.  The numbers are 32-bit fractions.
- */
-static const png_uint_32
-png_8bit_l2[128] =
-{
-   4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
-   3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
-   3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
-   3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U,
-   3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U,
-   2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U,
-   2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U,
-   2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U,
-   2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U,
-   2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U,
-   1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U,
-   1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U,
-   1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U,
-   1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U,
-   1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U,
-   971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U,
-   803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U,
-   639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U,
-   479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U,
-   324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
-   172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
-   24347096U, 0U
-
-#if 0
-   /* The following are the values for 16-bit tables - these work fine for the
-    * 8-bit conversions but produce very slightly larger errors in the 16-bit
-    * log (about 1.2 as opposed to 0.7 absolute error in the final value).  To
-    * use these all the shifts below must be adjusted appropriately.
-    */
-   65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054,
-   57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803,
-   50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068,
-   43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782,
-   37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887,
-   31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339,
-   25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098,
-   20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132,
-   15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415,
-   10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523,
-   6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495,
-   1119, 744, 372
-#endif
-};
-
-static png_int_32
-png_log8bit(unsigned int x)
-{
-   unsigned int lg2 = 0;
-   /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
-    * because the log is actually negate that means adding 1.  The final
-    * returned value thus has the range 0 (for 255 input) to 7.994 (for 1
-    * input), return -1 for the overflow (log 0) case, - so the result is
-    * always at most 19 bits.
-    */
-   if ((x &= 0xff) == 0)
-      return -1;
-
-   if ((x & 0xf0) == 0)
-      lg2  = 4, x <<= 4;
-
-   if ((x & 0xc0) == 0)
-      lg2 += 2, x <<= 2;
-
-   if ((x & 0x80) == 0)
-      lg2 += 1, x <<= 1;
-
-   /* result is at most 19 bits, so this cast is safe: */
-   return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16));
-}
-
-/* The above gives exact (to 16 binary places) log2 values for 8-bit images,
- * for 16-bit images we use the most significant 8 bits of the 16-bit value to
- * get an approximation then multiply the approximation by a correction factor
- * determined by the remaining up to 8 bits.  This requires an additional step
- * in the 16-bit case.
- *
- * We want log2(value/65535), we have log2(v'/255), where:
- *
- *    value = v' * 256 + v''
- *          = v' * f
- *
- * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128
- * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less
- * than 258.  The final factor also needs to correct for the fact that our 8-bit
- * value is scaled by 255, whereas the 16-bit values must be scaled by 65535.
- *
- * This gives a final formula using a calculated value 'x' which is value/v' and
- * scaling by 65536 to match the above table:
- *
- *   log2(x/257) * 65536
- *
- * Since these numbers are so close to '1' we can use simple linear
- * interpolation between the two end values 256/257 (result -368.61) and 258/257
- * (result 367.179).  The values used below are scaled by a further 64 to give
- * 16-bit precision in the interpolation:
- *
- * Start (256): -23591
- * Zero  (257):      0
- * End   (258):  23499
- */
-#ifdef PNG_16BIT_SUPPORTED
-static png_int_32
-png_log16bit(png_uint_32 x)
-{
-   unsigned int lg2 = 0;
-
-   /* As above, but now the input has 16 bits. */
-   if ((x &= 0xffff) == 0)
-      return -1;
-
-   if ((x & 0xff00) == 0)
-      lg2  = 8, x <<= 8;
-
-   if ((x & 0xf000) == 0)
-      lg2 += 4, x <<= 4;
-
-   if ((x & 0xc000) == 0)
-      lg2 += 2, x <<= 2;
-
-   if ((x & 0x8000) == 0)
-      lg2 += 1, x <<= 1;
-
-   /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional
-    * value.
-    */
-   lg2 <<= 28;
-   lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4;
-
-   /* Now we need to interpolate the factor, this requires a division by the top
-    * 8 bits.  Do this with maximum precision.
-    */
-   x = ((x << 16) + (x >> 9)) / (x >> 8);
-
-   /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24,
-    * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly
-    * 16 bits to interpolate to get the low bits of the result.  Round the
-    * answer.  Note that the end point values are scaled by 64 to retain overall
-    * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust
-    * the overall scaling by 6-12.  Round at every step.
-    */
-   x -= 1U << 24;
-
-   if (x <= 65536U) /* <= '257' */
-      lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12);
-
-   else
-      lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12);
-
-   /* Safe, because the result can't have more than 20 bits: */
-   return (png_int_32)((lg2 + 2048) >> 12);
-}
-#endif /* 16BIT */
-
-/* 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
- * fractional 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] =
-{
-   /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */
-   4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U,
-   3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U,
-   2553802834U, 2445529972U, 2341847524U, 2242560872U
-};
-
-/* Adjustment table; provided to explain the numbers in the code below. */
-#if 0
-for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
-   11 44937.64284865548751208448
-   10 45180.98734845585101160448
-    9 45303.31936980687359311872
-    8 45364.65110595323018870784
-    7 45395.35850361789624614912
-    6 45410.72259715102037508096
-    5 45418.40724413220722311168
-    4 45422.25021786898173001728
-    3 45424.17186732298419044352
-    2 45425.13273269940811464704
-    1 45425.61317555035558641664
-    0 45425.85339951654943850496
-#endif
-
-static png_uint_32
-png_exp(png_fixed_point x)
-{
-   if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */
-   {
-      /* Obtain a 4-bit approximation */
-      png_uint_32 e = png_32bit_exp[(x >> 12) & 0x0f];
-
-      /* Incorporate the low 12 bits - these decrease the returned value by
-       * multiplying by a number less than 1 if the bit is set.  The multiplier
-       * is determined by the above table and the shift. Notice that the values
-       * converge on 45426 and this is used to allow linear interpolation of the
-       * low bits.
-       */
-      if (x & 0x800)
-         e -= (((e >> 16) * 44938U) +  16U) >> 5;
-
-      if (x & 0x400)
-         e -= (((e >> 16) * 45181U) +  32U) >> 6;
-
-      if (x & 0x200)
-         e -= (((e >> 16) * 45303U) +  64U) >> 7;
-
-      if (x & 0x100)
-         e -= (((e >> 16) * 45365U) + 128U) >> 8;
-
-      if (x & 0x080)
-         e -= (((e >> 16) * 45395U) + 256U) >> 9;
-
-      if (x & 0x040)
-         e -= (((e >> 16) * 45410U) + 512U) >> 10;
-
-      /* And handle the low 6 bits in a single block. */
-      e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9;
-
-      /* Handle the upper bits of x. */
-      e >>= x >> 16;
-      return e;
-   }
-
-   /* Check for overflow */
-   if (x <= 0)
-      return png_32bit_exp[0];
-
-   /* Else underflow */
-   return 0;
-}
-
-static png_byte
-png_exp8bit(png_fixed_point lg2)
-{
-   /* Get a 32-bit value: */
-   png_uint_32 x = png_exp(lg2);
-
-   /* Convert the 32-bit value to 0..255 by multiplying by 256-1. Note that the
-    * second, rounding, step can't overflow because of the first, subtraction,
-    * step.
-    */
-   x -= x >> 8;
-   return (png_byte)(((x + 0x7fffffU) >> 24) & 0xff);
-}
-
-#ifdef PNG_16BIT_SUPPORTED
-static png_uint_16
-png_exp16bit(png_fixed_point lg2)
-{
-   /* Get a 32-bit value: */
-   png_uint_32 x = png_exp(lg2);
-
-   /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */
-   x -= x >> 16;
-   return (png_uint_16)((x + 32767U) >> 16);
-}
-#endif /* 16BIT */
-#endif /* FLOATING_ARITHMETIC */
-
-png_byte
-png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val)
-{
-   if (value > 0 && value < 255)
-   {
-#     ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
-         /* 'value' is unsigned, ANSI-C90 requires the compiler to correctly
-          * convert this to a floating point value.  This includes values that
-          * would overflow if 'value' were to be converted to 'int'.
-          *
-          * Apparently GCC, however, does an intermediate conversion to (int)
-          * on some (ARM) but not all (x86) platforms, possibly because of
-          * hardware FP limitations.  (E.g. if the hardware conversion always
-          * assumes the integer register contains a signed value.)  This results
-          * in ANSI-C undefined behavior for large values.
-          *
-          * Other implementations on the same machine might actually be ANSI-C90
-          * conformant and therefore compile spurious extra code for the large
-          * values.
-          *
-          * We can be reasonably sure that an unsigned to float conversion
-          * won't be faster than an int to float one.  Therefore this code
-          * assumes responsibility for the undefined behavior, which it knows
-          * can't happen because of the check above.
-          *
-          * Note the argument to this routine is an (unsigned int) because, on
-          * 16-bit platforms, it is assigned a value which might be out of
-          * range for an (int); that would result in undefined behavior in the
-          * caller if the *argument* ('value') were to be declared (int).
-          */
-         double r = floor(255*pow((int)/*SAFE*/value/255.,gamma_val*.00001)+.5);
-         return (png_byte)r;
-#     else
-         png_int_32 lg2 = png_log8bit(value);
-         png_fixed_point res;
-
-         if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
-            return png_exp8bit(res);
-
-         /* Overflow. */
-         value = 0;
-#     endif
-   }
-
-   return (png_byte)(value & 0xff);
-}
-
-#ifdef PNG_16BIT_SUPPORTED
-png_uint_16
-png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
-{
-   if (value > 0 && value < 65535)
-   {
-# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
-      /* The same (unsigned int)->(double) constraints apply here as above,
-       * however in this case the (unsigned int) to (int) conversion can
-       * overflow on an ANSI-C90 compliant system so the cast needs to ensure
-       * that this is not possible.
-       */
-      double r = floor(65535*pow((png_int_32)value/65535.,
-          gamma_val*.00001)+.5);
-      return (png_uint_16)r;
-# else
-      png_int_32 lg2 = png_log16bit(value);
-      png_fixed_point res;
-
-      if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
-         return png_exp16bit(res);
-
-      /* Overflow. */
-      value = 0;
-# endif
-   }
-
-   return (png_uint_16)value;
-}
-#endif /* 16BIT */
-
-/* This does the right thing based on the bit_depth field of the
- * png_struct, interpreting values as 8-bit or 16-bit.  While the result
- * is nominally a 16-bit value if bit depth is 8 then the result is
- * 8-bit (as are the arguments.)
- */
-png_uint_16 /* PRIVATE */
-png_gamma_correct(png_structrp png_ptr, unsigned int value,
-    png_fixed_point gamma_val)
-{
-   if (png_ptr->bit_depth == 8)
-      return png_gamma_8bit_correct(value, gamma_val);
-
-#ifdef PNG_16BIT_SUPPORTED
-   else
-      return png_gamma_16bit_correct(value, gamma_val);
-#else
-      /* should not reach this */
-      return 0;
-#endif /* 16BIT */
-}
-
-#ifdef PNG_16BIT_SUPPORTED
-/* Internal function to build a single 16-bit table - the table consists of
- * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
- * to shift the input values right (or 16-number_of_signifiant_bits).
- *
- * The caller is responsible for ensuring that the table gets cleaned up on
- * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument
- * should be somewhere that will be cleaned.
- */
-static void
-png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
-    unsigned int shift, png_fixed_point gamma_val)
-{
-   /* Various values derived from 'shift': */
-   unsigned int num = 1U << (8U - shift);
-#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
-   /* CSE the division and work round wacky GCC warnings (see the comments
-    * in png_gamma_8bit_correct for where these come from.)
-    */
-   double fmax = 1.0 / (((png_int_32)1 << (16U - shift)) - 1);
-#endif
-   unsigned int max = (1U << (16U - shift)) - 1U;
-   unsigned int max_by_2 = 1U << (15U - shift);
-   unsigned int i;
-
-   png_uint_16pp table = *ptable =
-       (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
-
-   for (i = 0; i < num; i++)
-   {
-      png_uint_16p sub_table = table[i] =
-          (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16)));
-
-      /* The 'threshold' test is repeated here because it can arise for one of
-       * the 16-bit tables even if the others don't hit it.
-       */
-      if (png_gamma_significant(gamma_val) != 0)
-      {
-         /* The old code would overflow at the end and this would cause the
-          * 'pow' function to return a result >1, resulting in an
-          * arithmetic error.  This code follows the spec exactly; ig is
-          * the recovered input sample, it always has 8-16 bits.
-          *
-          * We want input * 65535/max, rounded, the arithmetic fits in 32
-          * bits (unsigned) so long as max <= 32767.
-          */
-         unsigned int j;
-         for (j = 0; j < 256; j++)
-         {
-            png_uint_32 ig = (j << (8-shift)) + i;
-#           ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
-               /* Inline the 'max' scaling operation: */
-               /* See png_gamma_8bit_correct for why the cast to (int) is
-                * required here.
-                */
-               double d = floor(65535.*pow(ig*fmax, gamma_val*.00001)+.5);
-               sub_table[j] = (png_uint_16)d;
-#           else
-               if (shift != 0)
-                  ig = (ig * 65535U + max_by_2)/max;
-
-               sub_table[j] = png_gamma_16bit_correct(ig, gamma_val);
-#           endif
-         }
-      }
-      else
-      {
-         /* We must still build a table, but do it the fast way. */
-         unsigned int j;
-
-         for (j = 0; j < 256; j++)
-         {
-            png_uint_32 ig = (j << (8-shift)) + i;
-
-            if (shift != 0)
-               ig = (ig * 65535U + max_by_2)/max;
-
-            sub_table[j] = (png_uint_16)ig;
-         }
-      }
-   }
-}
-
-/* NOTE: this function expects the *inverse* of the overall gamma transformation
- * required.
- */
-static void
-png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
-    unsigned int shift, png_fixed_point gamma_val)
-{
-   unsigned int num = 1U << (8U - shift);
-   unsigned int max = (1U << (16U - shift))-1U;
-   unsigned int i;
-   png_uint_32 last;
-
-   png_uint_16pp table = *ptable =
-       (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
-
-   /* 'num' is the number of tables and also the number of low bits of low
-    * bits of the input 16-bit value used to select a table.  Each table is
-    * itself indexed by the high 8 bits of the value.
-    */
-   for (i = 0; i < num; i++)
-      table[i] = (png_uint_16p)png_malloc(png_ptr,
-          256 * (sizeof (png_uint_16)));
-
-   /* 'gamma_val' is set to the reciprocal of the value calculated above, so
-    * pow(out,g) is an *input* value.  'last' is the last input value set.
-    *
-    * In the loop 'i' is used to find output values.  Since the output is
-    * 8-bit there are only 256 possible values.  The tables are set up to
-    * select the closest possible output value for each input by finding
-    * the input value at the boundary between each pair of output values
-    * and filling the table up to that boundary with the lower output
-    * value.
-    *
-    * The boundary values are 0.5,1.5..253.5,254.5.  Since these are 9-bit
-    * values the code below uses a 16-bit value in i; the values start at
-    * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last
-    * entries are filled with 255).  Start i at 128 and fill all 'last'
-    * table entries <= 'max'
-    */
-   last = 0;
-   for (i = 0; i < 255; ++i) /* 8-bit output value */
-   {
-      /* Find the corresponding maximum input value */
-      png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */
-
-      /* Find the boundary value in 16 bits: */
-      png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val);
-
-      /* Adjust (round) to (16-shift) bits: */
-      bound = (bound * max + 32768U)/65535U + 1U;
-
-      while (last < bound)
-      {
-         table[last & (0xffU >> shift)][last >> (8U - shift)] = out;
-         last++;
-      }
-   }
-
-   /* And fill in the final entries. */
-   while (last < (num << 8))
-   {
-      table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U;
-      last++;
-   }
-}
-#endif /* 16BIT */
-
-/* Build a single 8-bit table: same as the 16-bit case but much simpler (and
- * typically much faster).  Note that libpng currently does no sBIT processing
- * (apparently contrary to the spec) so a 256-entry table is always generated.
- */
-static void
-png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
-    png_fixed_point gamma_val)
-{
-   unsigned int i;
-   png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
-
-   if (png_gamma_significant(gamma_val) != 0)
-      for (i=0; i<256; i++)
-         table[i] = png_gamma_8bit_correct(i, gamma_val);
-
-   else
-      for (i=0; i<256; ++i)
-         table[i] = (png_byte)(i & 0xff);
-}
-
-/* Used from png_read_destroy and below to release the memory used by the gamma
- * tables.
- */
-void /* PRIVATE */
-png_destroy_gamma_table(png_structrp png_ptr)
-{
-   png_free(png_ptr, png_ptr->gamma_table);
-   png_ptr->gamma_table = NULL;
-
-#ifdef PNG_16BIT_SUPPORTED
-   if (png_ptr->gamma_16_table != NULL)
-   {
-      int i;
-      int istop = (1 << (8 - png_ptr->gamma_shift));
-      for (i = 0; i < istop; i++)
-      {
-         png_free(png_ptr, png_ptr->gamma_16_table[i]);
-      }
-   png_free(png_ptr, png_ptr->gamma_16_table);
-   png_ptr->gamma_16_table = NULL;
-   }
-#endif /* 16BIT */
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
-   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-   png_free(png_ptr, png_ptr->gamma_from_1);
-   png_ptr->gamma_from_1 = NULL;
-   png_free(png_ptr, png_ptr->gamma_to_1);
-   png_ptr->gamma_to_1 = NULL;
-
-#ifdef PNG_16BIT_SUPPORTED
-   if (png_ptr->gamma_16_from_1 != NULL)
-   {
-      int i;
-      int istop = (1 << (8 - png_ptr->gamma_shift));
-      for (i = 0; i < istop; i++)
-      {
-         png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
-      }
-   png_free(png_ptr, png_ptr->gamma_16_from_1);
-   png_ptr->gamma_16_from_1 = NULL;
-   }
-   if (png_ptr->gamma_16_to_1 != NULL)
-   {
-      int i;
-      int istop = (1 << (8 - png_ptr->gamma_shift));
-      for (i = 0; i < istop; i++)
-      {
-         png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
-      }
-   png_free(png_ptr, png_ptr->gamma_16_to_1);
-   png_ptr->gamma_16_to_1 = NULL;
-   }
-#endif /* 16BIT */
-#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
-}
-
-/* We build the 8- or 16-bit gamma tables here.  Note that for 16-bit
- * tables, we don't make a full table if we are reducing to 8-bit in
- * the future.  Note also how the gamma_16 tables are segmented so that
- * we don't need to allocate > 64K chunks for a full 16-bit table.
- */
-void /* PRIVATE */
-png_build_gamma_table(png_structrp png_ptr, int bit_depth)
-{
-   png_debug(1, "in png_build_gamma_table");
-
-   /* Remove any existing table; this copes with multiple calls to
-    * png_read_update_info. The warning is because building the gamma tables
-    * multiple times is a performance hit - it's harmless but the ability to
-    * call png_read_update_info() multiple times is new in 1.5.6 so it seems
-    * sensible to warn if the app introduces such a hit.
-    */
-   if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
-   {
-      png_warning(png_ptr, "gamma table being rebuilt");
-      png_destroy_gamma_table(png_ptr);
-   }
-
-   if (bit_depth <= 8)
-   {
-      png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
-          png_ptr->screen_gamma > 0 ?
-          png_reciprocal2(png_ptr->colorspace.gamma,
-          png_ptr->screen_gamma) : PNG_FP_1);
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
-   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-      if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
-      {
-         png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
-             png_reciprocal(png_ptr->colorspace.gamma));
-
-         png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
-             png_ptr->screen_gamma > 0 ?
-             png_reciprocal(png_ptr->screen_gamma) :
-             png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
-      }
-#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
-   }
-#ifdef PNG_16BIT_SUPPORTED
-   else
-   {
-      png_byte shift, sig_bit;
-
-      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
-      {
-         sig_bit = png_ptr->sig_bit.red;
-
-         if (png_ptr->sig_bit.green > sig_bit)
-            sig_bit = png_ptr->sig_bit.green;
-
-         if (png_ptr->sig_bit.blue > sig_bit)
-            sig_bit = png_ptr->sig_bit.blue;
-      }
-      else
-         sig_bit = png_ptr->sig_bit.gray;
-
-      /* 16-bit gamma code uses this equation:
-       *
-       *   ov = table[(iv & 0xff) >> gamma_shift][iv >> 8]
-       *
-       * Where 'iv' is the input color value and 'ov' is the output value -
-       * pow(iv, gamma).
-       *
-       * Thus the gamma table consists of up to 256 256-entry tables.  The table
-       * is selected by the (8-gamma_shift) most significant of the low 8 bits
-       * of the color value then indexed by the upper 8 bits:
-       *
-       *   table[low bits][high 8 bits]
-       *
-       * So the table 'n' corresponds to all those 'iv' of:
-       *
-       *   <all high 8-bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1>
-       *
-       */
-      if (sig_bit > 0 && sig_bit < 16U)
-         /* shift == insignificant bits */
-         shift = (png_byte)((16U - sig_bit) & 0xff);
-
-      else
-         shift = 0; /* keep all 16 bits */
-
-      if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
-      {
-         /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
-          * the significant bits in the *input* when the output will
-          * eventually be 8 bits.  By default it is 11.
-          */
-         if (shift < (16U - PNG_MAX_GAMMA_8))
-            shift = (16U - PNG_MAX_GAMMA_8);
-      }
-
-      if (shift > 8U)
-         shift = 8U; /* Guarantees at least one table! */
-
-      png_ptr->gamma_shift = shift;
-
-      /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
-       * PNG_COMPOSE).  This effectively smashed the background calculation for
-       * 16-bit output because the 8-bit table assumes the result will be
-       * reduced to 8 bits.
-       */
-      if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
-          png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
-          png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
-          png_ptr->screen_gamma) : PNG_FP_1);
-
-      else
-          png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
-          png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
-          png_ptr->screen_gamma) : PNG_FP_1);
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
-   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-      if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
-      {
-         png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
-             png_reciprocal(png_ptr->colorspace.gamma));
-
-         /* Notice that the '16 from 1' table should be full precision, however
-          * the lookup on this table still uses gamma_shift, so it can't be.
-          * TODO: fix this.
-          */
-         png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
-             png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
-             png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
-      }
-#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
-   }
-#endif /* 16BIT */
-}
-#endif /* READ_GAMMA */
-
-/* HARDWARE OR SOFTWARE OPTION SUPPORT */
-#ifdef PNG_SET_OPTION_SUPPORTED
-int PNGAPI
-png_set_option(png_structrp png_ptr, int option, int onoff)
-{
-   if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT &&
-      (option & 1) == 0)
-   {
-      png_uint_32 mask = 3U << option;
-      png_uint_32 setting = (2U + (onoff != 0)) << option;
-      png_uint_32 current = png_ptr->options;
-
-      png_ptr->options = (png_uint_32)((current & ~mask) | setting);
-
-      return (int)(current & mask) >> option;
-   }
-
-   return PNG_OPTION_INVALID;
-}
-#endif
-
-/* sRGB support */
-#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
-   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
-/* sRGB conversion tables; these are machine generated with the code in
- * contrib/tools/makesRGB.c.  The actual sRGB transfer curve defined in the
- * specification (see the article at https://en.wikipedia.org/wiki/SRGB)
- * is used, not the gamma=1/2.2 approximation use elsewhere in libpng.
- * The sRGB to linear table is exact (to the nearest 16-bit linear fraction).
- * The inverse (linear to sRGB) table has accuracies as follows:
- *
- * For all possible (255*65535+1) input values:
- *
- *    error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact
- *
- * For the input values corresponding to the 65536 16-bit values:
- *
- *    error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact
- *
- * In all cases the inexact readings are only off by one.
- */
-
-#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
-/* The convert-to-sRGB table is only currently required for read. */
-const png_uint_16 png_sRGB_table[256] =
-{
-   0,20,40,60,80,99,119,139,
-   159,179,199,219,241,264,288,313,
-   340,367,396,427,458,491,526,562,
-   599,637,677,718,761,805,851,898,
-   947,997,1048,1101,1156,1212,1270,1330,
-   1391,1453,1517,1583,1651,1720,1790,1863,
-   1937,2013,2090,2170,2250,2333,2418,2504,
-   2592,2681,2773,2866,2961,3058,3157,3258,
-   3360,3464,3570,3678,3788,3900,4014,4129,
-   4247,4366,4488,4611,4736,4864,4993,5124,
-   5257,5392,5530,5669,5810,5953,6099,6246,
-   6395,6547,6700,6856,7014,7174,7335,7500,
-   7666,7834,8004,8177,8352,8528,8708,8889,
-   9072,9258,9445,9635,9828,10022,10219,10417,
-   10619,10822,11028,11235,11446,11658,11873,12090,
-   12309,12530,12754,12980,13209,13440,13673,13909,
-   14146,14387,14629,14874,15122,15371,15623,15878,
-   16135,16394,16656,16920,17187,17456,17727,18001,
-   18277,18556,18837,19121,19407,19696,19987,20281,
-   20577,20876,21177,21481,21787,22096,22407,22721,
-   23038,23357,23678,24002,24329,24658,24990,25325,
-   25662,26001,26344,26688,27036,27386,27739,28094,
-   28452,28813,29176,29542,29911,30282,30656,31033,
-   31412,31794,32179,32567,32957,33350,33745,34143,
-   34544,34948,35355,35764,36176,36591,37008,37429,
-   37852,38278,38706,39138,39572,40009,40449,40891,
-   41337,41785,42236,42690,43147,43606,44069,44534,
-   45002,45473,45947,46423,46903,47385,47871,48359,
-   48850,49344,49841,50341,50844,51349,51858,52369,
-   52884,53401,53921,54445,54971,55500,56032,56567,
-   57105,57646,58190,58737,59287,59840,60396,60955,
-   61517,62082,62650,63221,63795,64372,64952,65535
-};
-#endif /* SIMPLIFIED_READ */
-
-/* The base/delta tables are required for both read and write (but currently
- * only the simplified versions.)
- */
-const png_uint_16 png_sRGB_base[512] =
-{
-   128,1782,3383,4644,5675,6564,7357,8074,
-   8732,9346,9921,10463,10977,11466,11935,12384,
-   12816,13233,13634,14024,14402,14769,15125,15473,
-   15812,16142,16466,16781,17090,17393,17690,17981,
-   18266,18546,18822,19093,19359,19621,19879,20133,
-   20383,20630,20873,21113,21349,21583,21813,22041,
-   22265,22487,22707,22923,23138,23350,23559,23767,
-   23972,24175,24376,24575,24772,24967,25160,25352,
-   25542,25730,25916,26101,26284,26465,26645,26823,
-   27000,27176,27350,27523,27695,27865,28034,28201,
-   28368,28533,28697,28860,29021,29182,29341,29500,
-   29657,29813,29969,30123,30276,30429,30580,30730,
-   30880,31028,31176,31323,31469,31614,31758,31902,
-   32045,32186,32327,32468,32607,32746,32884,33021,
-   33158,33294,33429,33564,33697,33831,33963,34095,
-   34226,34357,34486,34616,34744,34873,35000,35127,
-   35253,35379,35504,35629,35753,35876,35999,36122,
-   36244,36365,36486,36606,36726,36845,36964,37083,
-   37201,37318,37435,37551,37668,37783,37898,38013,
-   38127,38241,38354,38467,38580,38692,38803,38915,
-   39026,39136,39246,39356,39465,39574,39682,39790,
-   39898,40005,40112,40219,40325,40431,40537,40642,
-   40747,40851,40955,41059,41163,41266,41369,41471,
-   41573,41675,41777,41878,41979,42079,42179,42279,
-   42379,42478,42577,42676,42775,42873,42971,43068,
-   43165,43262,43359,43456,43552,43648,43743,43839,
-   43934,44028,44123,44217,44311,44405,44499,44592,
-   44685,44778,44870,44962,45054,45146,45238,45329,
-   45420,45511,45601,45692,45782,45872,45961,46051,
-   46140,46229,46318,46406,46494,46583,46670,46758,
-   46846,46933,47020,47107,47193,47280,47366,47452,
-   47538,47623,47709,47794,47879,47964,48048,48133,
-   48217,48301,48385,48468,48552,48635,48718,48801,
-   48884,48966,49048,49131,49213,49294,49376,49458,
-   49539,49620,49701,49782,49862,49943,50023,50103,
-   50183,50263,50342,50422,50501,50580,50659,50738,
-   50816,50895,50973,51051,51129,51207,51285,51362,
-   51439,51517,51594,51671,51747,51824,51900,51977,
-   52053,52129,52205,52280,52356,52432,52507,52582,
-   52657,52732,52807,52881,52956,53030,53104,53178,
-   53252,53326,53400,53473,53546,53620,53693,53766,
-   53839,53911,53984,54056,54129,54201,54273,54345,
-   54417,54489,54560,54632,54703,54774,54845,54916,
-   54987,55058,55129,55199,55269,55340,55410,55480,
-   55550,55620,55689,55759,55828,55898,55967,56036,
-   56105,56174,56243,56311,56380,56448,56517,56585,
-   56653,56721,56789,56857,56924,56992,57059,57127,
-   57194,57261,57328,57395,57462,57529,57595,57662,
-   57728,57795,57861,57927,57993,58059,58125,58191,
-   58256,58322,58387,58453,58518,58583,58648,58713,
-   58778,58843,58908,58972,59037,59101,59165,59230,
-   59294,59358,59422,59486,59549,59613,59677,59740,
-   59804,59867,59930,59993,60056,60119,60182,60245,
-   60308,60370,60433,60495,60558,60620,60682,60744,
-   60806,60868,60930,60992,61054,61115,61177,61238,
-   61300,61361,61422,61483,61544,61605,61666,61727,
-   61788,61848,61909,61969,62030,62090,62150,62211,
-   62271,62331,62391,62450,62510,62570,62630,62689,
-   62749,62808,62867,62927,62986,63045,63104,63163,
-   63222,63281,63340,63398,63457,63515,63574,63632,
-   63691,63749,63807,63865,63923,63981,64039,64097,
-   64155,64212,64270,64328,64385,64443,64500,64557,
-   64614,64672,64729,64786,64843,64900,64956,65013,
-   65070,65126,65183,65239,65296,65352,65409,65465
-};
-
-const png_byte png_sRGB_delta[512] =
-{
-   207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54,
-   52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36,
-   35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28,
-   28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24,
-   23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,
-   21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,
-   19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,
-   17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,
-   16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,
-   15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,
-   14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,
-   13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,
-   12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
-   12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,
-   11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
-   11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
-   11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
-   10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
-   10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
-   10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-   9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
-   9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-   8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
-   8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,
-   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
-   7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
-};
-#endif /* SIMPLIFIED READ/WRITE sRGB support */
-
-/* SIMPLIFIED READ/WRITE SUPPORT */
-#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
-   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
-static int
-png_image_free_function(png_voidp argument)
-{
-   png_imagep image = png_voidcast(png_imagep, argument);
-   png_controlp cp = image->opaque;
-   png_control c;
-
-   /* Double check that we have a png_ptr - it should be impossible to get here
-    * without one.
-    */
-   if (cp->png_ptr == NULL)
-      return 0;
-
-   /* First free any data held in the control structure. */
-#  ifdef PNG_STDIO_SUPPORTED
-      if (cp->owned_file != 0)
-      {
-         FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr);
-         cp->owned_file = 0;
-
-         /* Ignore errors here. */
-         if (fp != NULL)
-         {
-            cp->png_ptr->io_ptr = NULL;
-            (void)fclose(fp);
-         }
-      }
-#  endif
-
-   /* Copy the control structure so that the original, allocated, version can be
-    * safely freed.  Notice that a png_error here stops the remainder of the
-    * cleanup, but this is probably fine because that would indicate bad memory
-    * problems anyway.
-    */
-   c = *cp;
-   image->opaque = &c;
-   png_free(c.png_ptr, cp);
-
-   /* Then the structures, calling the correct API. */
-   if (c.for_write != 0)
-   {
-#     ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
-         png_destroy_write_struct(&c.png_ptr, &c.info_ptr);
-#     else
-         png_error(c.png_ptr, "simplified write not supported");
-#     endif
-   }
-   else
-   {
-#     ifdef PNG_SIMPLIFIED_READ_SUPPORTED
-         png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL);
-#     else
-         png_error(c.png_ptr, "simplified read not supported");
-#     endif
-   }
-
-   /* Success. */
-   return 1;
-}
-
-void PNGAPI
-png_image_free(png_imagep image)
-{
-   /* Safely call the real function, but only if doing so is safe at this point
-    * (if not inside an error handling context).  Otherwise assume
-    * png_safe_execute will call this API after the return.
-    */
-   if (image != NULL && image->opaque != NULL &&
-      image->opaque->error_buf == NULL)
-   {
-      png_image_free_function(image);
-      image->opaque = NULL;
-   }
-}
-
-int /* PRIVATE */
-png_image_error(png_imagep image, png_const_charp error_message)
-{
-   /* Utility to log an error. */
-   png_safecat(image->message, (sizeof image->message), 0, error_message);
-   image->warning_or_error |= PNG_IMAGE_ERROR;
-   png_image_free(image);
-   return 0;
-}
-
-#endif /* SIMPLIFIED READ/WRITE */
-#endif /* READ || WRITE */
diff --git a/third_party/libpng16/png.h b/third_party/libpng16/png.h
deleted file mode 100644
index 139eb0d..0000000
--- a/third_party/libpng16/png.h
+++ /dev/null
@@ -1,3247 +0,0 @@
-
-/* png.h - header file for PNG reference library
- *
- * libpng version 1.6.37 - April 14, 2019
- *
- * Copyright (c) 2018-2019 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license. (See LICENSE, below.)
- *
- * Authors and maintainers:
- *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
- *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.6.35, July 2018:
- *     Glenn Randers-Pehrson
- *   libpng versions 1.6.36, December 2018, through 1.6.37, April 2019:
- *     Cosmin Truta
- *   See also "Contributing Authors", below.
- */
-
-/*
- * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
- * =========================================
- *
- * PNG Reference Library License version 2
- * ---------------------------------------
- *
- *  * Copyright (c) 1995-2019 The PNG Reference Library Authors.
- *  * Copyright (c) 2018-2019 Cosmin Truta.
- *  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
- *  * Copyright (c) 1996-1997 Andreas Dilger.
- *  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * The software is supplied "as is", without warranty of any kind,
- * express or implied, including, without limitation, the warranties
- * of merchantability, fitness for a particular purpose, title, and
- * non-infringement.  In no event shall the Copyright owners, or
- * anyone distributing the software, be liable for any damages or
- * other liability, whether in contract, tort or otherwise, arising
- * from, out of, or in connection with the software, or the use or
- * other dealings in the software, even if advised of the possibility
- * of such damage.
- *
- * Permission is hereby granted to use, copy, modify, and distribute
- * this software, or portions hereof, for any purpose, without fee,
- * subject to the following restrictions:
- *
- *  1. The origin of this software must not be misrepresented; you
- *     must not claim that you wrote the original software.  If you
- *     use this software in a product, an acknowledgment in the product
- *     documentation would be appreciated, but is not required.
- *
- *  2. Altered source versions must be plainly marked as such, and must
- *     not be misrepresented as being the original software.
- *
- *  3. This Copyright notice may not be removed or altered from any
- *     source or altered source distribution.
- *
- *
- * PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
- * -----------------------------------------------------------------------
- *
- * libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
- * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
- * derived from libpng-1.0.6, and are distributed according to the same
- * disclaimer and license as libpng-1.0.6 with the following individuals
- * added to the list of Contributing Authors:
- *
- *     Simon-Pierre Cadieux
- *     Eric S. Raymond
- *     Mans Rullgard
- *     Cosmin Truta
- *     Gilles Vollant
- *     James Yu
- *     Mandar Sahastrabuddhe
- *     Google Inc.
- *     Vadim Barkov
- *
- * and with the following additions to the disclaimer:
- *
- *     There is no warranty against interference with your enjoyment of
- *     the library or against infringement.  There is no warranty that our
- *     efforts or the library will fulfill any of your particular purposes
- *     or needs.  This library is provided with all faults, and the entire
- *     risk of satisfactory quality, performance, accuracy, and effort is
- *     with the user.
- *
- * Some files in the "contrib" directory and some configure-generated
- * files that are distributed with libpng have other copyright owners, and
- * are released under other open source licenses.
- *
- * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
- * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
- * libpng-0.96, and are distributed according to the same disclaimer and
- * license as libpng-0.96, with the following individuals added to the
- * list of Contributing Authors:
- *
- *     Tom Lane
- *     Glenn Randers-Pehrson
- *     Willem van Schaik
- *
- * libpng versions 0.89, June 1996, through 0.96, May 1997, are
- * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
- * and are distributed according to the same disclaimer and license as
- * libpng-0.88, with the following individuals added to the list of
- * Contributing Authors:
- *
- *     John Bowler
- *     Kevin Bracey
- *     Sam Bushell
- *     Magnus Holmgren
- *     Greg Roelofs
- *     Tom Tanner
- *
- * Some files in the "scripts" directory have other copyright owners,
- * but are released under this license.
- *
- * libpng versions 0.5, May 1995, through 0.88, January 1996, are
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * For the purposes of this copyright and license, "Contributing Authors"
- * is defined as the following set of individuals:
- *
- *     Andreas Dilger
- *     Dave Martindale
- *     Guy Eric Schalnat
- *     Paul Schmidt
- *     Tim Wegner
- *
- * The PNG Reference Library is supplied "AS IS".  The Contributing
- * Authors and Group 42, Inc. disclaim all warranties, expressed or
- * implied, including, without limitation, the warranties of
- * merchantability and of fitness for any purpose.  The Contributing
- * Authors and Group 42, Inc. assume no liability for direct, indirect,
- * incidental, special, exemplary, or consequential damages, which may
- * result from the use of the PNG Reference Library, even if advised of
- * the possibility of such damage.
- *
- * Permission is hereby granted to use, copy, modify, and distribute this
- * source code, or portions hereof, for any purpose, without fee, subject
- * to the following restrictions:
- *
- *  1. The origin of this source code must not be misrepresented.
- *
- *  2. Altered versions must be plainly marked as such and must not
- *     be misrepresented as being the original source.
- *
- *  3. This Copyright notice may not be removed or altered from any
- *     source or altered source distribution.
- *
- * The Contributing Authors and Group 42, Inc. specifically permit,
- * without fee, and encourage the use of this source code as a component
- * to supporting the PNG file format in commercial products.  If you use
- * this source code in a product, acknowledgment is not required but would
- * be appreciated.
- *
- * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
- *
- * TRADEMARK
- * =========
- *
- * The name "libpng" has not been registered by the Copyright owners
- * as a trademark in any jurisdiction.  However, because libpng has
- * been distributed and maintained world-wide, continually since 1995,
- * the Copyright owners claim "common-law trademark protection" in any
- * jurisdiction where common-law trademark is recognized.
- */
-
-/*
- * A "png_get_copyright" function is available, for convenient use in "about"
- * boxes and the like:
- *
- *    printf("%s", png_get_copyright(NULL));
- *
- * Also, the PNG logo (in PNG format, of course) is supplied in the
- * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
- */
-
-/*
- * The contributing authors would like to thank all those who helped
- * with testing, bug fixes, and patience.  This wouldn't have been
- * possible without all of you.
- *
- * Thanks to Frank J. T. Wojcik for helping with the documentation.
- */
-
-/* Note about libpng version numbers:
- *
- *    Due to various miscommunications, unforeseen code incompatibilities
- *    and occasional factors outside the authors' control, version numbering
- *    on the library has not always been consistent and straightforward.
- *    The following table summarizes matters since version 0.89c, which was
- *    the first widely used release:
- *
- *    source                 png.h  png.h  shared-lib
- *    version                string   int  version
- *    -------                ------ -----  ----------
- *    0.89c "1.0 beta 3"     0.89      89  1.0.89
- *    0.90  "1.0 beta 4"     0.90      90  0.90  [should have been 2.0.90]
- *    0.95  "1.0 beta 5"     0.95      95  0.95  [should have been 2.0.95]
- *    0.96  "1.0 beta 6"     0.96      96  0.96  [should have been 2.0.96]
- *    0.97b "1.00.97 beta 7" 1.00.97   97  1.0.1 [should have been 2.0.97]
- *    0.97c                  0.97      97  2.0.97
- *    0.98                   0.98      98  2.0.98
- *    0.99                   0.99      98  2.0.99
- *    0.99a-m                0.99      99  2.0.99
- *    1.00                   1.00     100  2.1.0 [100 should be 10000]
- *    1.0.0      (from here on, the   100  2.1.0 [100 should be 10000]
- *    1.0.1       png.h string is   10001  2.1.0
- *    1.0.1a-e    identical to the  10002  from here on, the shared library
- *    1.0.2       source version)   10002  is 2.V where V is the source code
- *    1.0.2a-b                      10003  version, except as noted.
- *    1.0.3                         10003
- *    1.0.3a-d                      10004
- *    1.0.4                         10004
- *    1.0.4a-f                      10005
- *    1.0.5 (+ 2 patches)           10005
- *    1.0.5a-d                      10006
- *    1.0.5e-r                      10100 (not source compatible)
- *    1.0.5s-v                      10006 (not binary compatible)
- *    1.0.6 (+ 3 patches)           10006 (still binary incompatible)
- *    1.0.6d-f                      10007 (still binary incompatible)
- *    1.0.6g                        10007
- *    1.0.6h                        10007  10.6h (testing xy.z so-numbering)
- *    1.0.6i                        10007  10.6i
- *    1.0.6j                        10007  2.1.0.6j (incompatible with 1.0.0)
- *    1.0.7beta11-14        DLLNUM  10007  2.1.0.7beta11-14 (binary compatible)
- *    1.0.7beta15-18           1    10007  2.1.0.7beta15-18 (binary compatible)
- *    1.0.7rc1-2               1    10007  2.1.0.7rc1-2 (binary compatible)
- *    1.0.7                    1    10007  (still compatible)
- *    ...
- *    1.0.69                  10    10069  10.so.0.69[.0]
- *    ...
- *    1.2.59                  13    10259  12.so.0.59[.0]
- *    ...
- *    1.4.20                  14    10420  14.so.0.20[.0]
- *    ...
- *    1.5.30                  15    10530  15.so.15.30[.0]
- *    ...
- *    1.6.37                  16    10637  16.so.16.37[.0]
- *
- *    Henceforth the source version will match the shared-library major and
- *    minor numbers; the shared-library major version number will be used for
- *    changes in backward compatibility, as it is intended.
- *    The PNG_LIBPNG_VER macro, which is not used within libpng but is
- *    available for applications, is an unsigned integer of the form XYYZZ
- *    corresponding to the source version X.Y.Z (leading zeros in Y and Z).
- *    Beta versions were given the previous public release number plus a
- *    letter, until version 1.0.6j; from then on they were given the upcoming
- *    public release number plus "betaNN" or "rcNN".
- *
- *    Binary incompatibility exists only when applications make direct access
- *    to the info_ptr or png_ptr members through png.h, and the compiled
- *    application is loaded with a different version of the library.
- *
- *    DLLNUM will change each time there are forward or backward changes
- *    in binary compatibility (e.g., when a new feature is added).
- *
- * See libpng.txt or libpng.3 for more information.  The PNG specification
- * is available as a W3C Recommendation and as an ISO/IEC Standard; see
- * <https://www.w3.org/TR/2003/REC-PNG-20031110/>
- */
-
-#ifndef PNG_H
-#define PNG_H
-
-/* This is not the place to learn how to use libpng. The file libpng-manual.txt
- * describes how to use libpng, and the file example.c summarizes it
- * with some code on which to build.  This file is useful for looking
- * at the actual function definitions and structure components.  If that
- * file has been stripped from your copy of libpng, you can find it at
- * <http://www.libpng.org/pub/png/libpng-manual.txt>
- *
- * If you just need to read a PNG file and don't want to read the documentation
- * skip to the end of this file and read the section entitled 'simplified API'.
- */
-
-/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.37"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.37 - April 14, 2019\n"
-
-#define PNG_LIBPNG_VER_SONUM   16
-#define PNG_LIBPNG_VER_DLLNUM  16
-
-/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
-#define PNG_LIBPNG_VER_MAJOR   1
-#define PNG_LIBPNG_VER_MINOR   6
-#define PNG_LIBPNG_VER_RELEASE 37
-
-/* This should be zero for a public release, or non-zero for a
- * development version.  [Deprecated]
- */
-#define PNG_LIBPNG_VER_BUILD  0
-
-/* Release Status */
-#define PNG_LIBPNG_BUILD_ALPHA    1
-#define PNG_LIBPNG_BUILD_BETA     2
-#define PNG_LIBPNG_BUILD_RC       3
-#define PNG_LIBPNG_BUILD_STABLE   4
-#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7
-
-/* Release-Specific Flags */
-#define PNG_LIBPNG_BUILD_PATCH    8 /* Can be OR'ed with
-                                       PNG_LIBPNG_BUILD_STABLE only */
-#define PNG_LIBPNG_BUILD_PRIVATE 16 /* Cannot be OR'ed with
-                                       PNG_LIBPNG_BUILD_SPECIAL */
-#define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with
-                                       PNG_LIBPNG_BUILD_PRIVATE */
-
-#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
-
-/* Careful here.  At one time, Guy wanted to use 082, but that
- * would be octal.  We must not include leading zeros.
- * Versions 0.7 through 1.0.0 were in the range 0 to 100 here
- * (only version 1.0.0 was mis-numbered 100 instead of 10000).
- * From version 1.0.1 it is:
- * XXYYZZ, where XX=major, YY=minor, ZZ=release
- */
-#define PNG_LIBPNG_VER 10637 /* 1.6.37 */
-
-/* Library configuration: these options cannot be changed after
- * the library has been built.
- */
-#ifndef PNGLCONF_H
-/* If pnglibconf.h is missing, you can
- * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h
- */
-#   include "pnglibconf.h"
-#endif
-
-#ifndef PNG_VERSION_INFO_ONLY
-/* Machine specific configuration. */
-#  include "pngconf.h"
-#endif
-
-/*
- * Added at libpng-1.2.8
- *
- * Ref MSDN: Private as priority over Special
- * VS_FF_PRIVATEBUILD File *was not* built using standard release
- * procedures. If this value is given, the StringFileInfo block must
- * contain a PrivateBuild string.
- *
- * VS_FF_SPECIALBUILD File *was* built by the original company using
- * standard release procedures but is a variation of the standard
- * file of the same version number. If this value is given, the
- * StringFileInfo block must contain a SpecialBuild string.
- */
-
-#ifdef PNG_USER_PRIVATEBUILD /* From pnglibconf.h */
-#  define PNG_LIBPNG_BUILD_TYPE \
-       (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_PRIVATE)
-#else
-#  ifdef PNG_LIBPNG_SPECIALBUILD
-#    define PNG_LIBPNG_BUILD_TYPE \
-         (PNG_LIBPNG_BUILD_BASE_TYPE | PNG_LIBPNG_BUILD_SPECIAL)
-#  else
-#    define PNG_LIBPNG_BUILD_TYPE (PNG_LIBPNG_BUILD_BASE_TYPE)
-#  endif
-#endif
-
-#ifndef PNG_VERSION_INFO_ONLY
-
-/* Inhibit C++ name-mangling for libpng functions but not for system calls. */
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Version information for C files, stored in png.c.  This had better match
- * the version above.
- */
-#define png_libpng_ver png_get_header_ver(NULL)
-
-/* This file is arranged in several sections:
- *
- * 1. [omitted]
- * 2. Any configuration options that can be specified by for the application
- *    code when it is built.  (Build time configuration is in pnglibconf.h)
- * 3. Type definitions (base types are defined in pngconf.h), structure
- *    definitions.
- * 4. Exported library functions.
- * 5. Simplified API.
- * 6. Implementation options.
- *
- * The library source code has additional files (principally pngpriv.h) that
- * allow configuration of the library.
- */
-
-/* Section 1: [omitted] */
-
-/* Section 2: run time configuration
- * See pnglibconf.h for build time configuration
- *
- * Run time configuration allows the application to choose between
- * implementations of certain arithmetic APIs.  The default is set
- * at build time and recorded in pnglibconf.h, but it is safe to
- * override these (and only these) settings.  Note that this won't
- * change what the library does, only application code, and the
- * settings can (and probably should) be made on a per-file basis
- * by setting the #defines before including png.h
- *
- * Use macros to read integers from PNG data or use the exported
- * functions?
- *   PNG_USE_READ_MACROS: use the macros (see below)  Note that
- *     the macros evaluate their argument multiple times.
- *   PNG_NO_USE_READ_MACROS: call the relevant library function.
- *
- * Use the alternative algorithm for compositing alpha samples that
- * does not use division?
- *   PNG_READ_COMPOSITE_NODIV_SUPPORTED: use the 'no division'
- *      algorithm.
- *   PNG_NO_READ_COMPOSITE_NODIV: use the 'division' algorithm.
- *
- * How to handle benign errors if PNG_ALLOW_BENIGN_ERRORS is
- * false?
- *   PNG_ALLOW_BENIGN_ERRORS: map calls to the benign error
- *      APIs to png_warning.
- * Otherwise the calls are mapped to png_error.
- */
-
-/* Section 3: type definitions, including structures and compile time
- * constants.
- * See pngconf.h for base types that vary by machine/system
- */
-
-/* This triggers a compiler error in png.c, if png.c and png.h
- * do not agree upon the version number.
- */
-typedef char* png_libpng_version_1_6_37;
-
-/* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
- *
- * png_struct is the cache of information used while reading or writing a single
- * PNG file.  One of these is always required, although the simplified API
- * (below) hides the creation and destruction of it.
- */
-typedef struct png_struct_def png_struct;
-typedef const png_struct * png_const_structp;
-typedef png_struct * png_structp;
-typedef png_struct * * png_structpp;
-
-/* png_info contains information read from or to be written to a PNG file.  One
- * or more of these must exist while reading or creating a PNG file.  The
- * information is not used by libpng during read but is used to control what
- * gets written when a PNG file is created.  "png_get_" function calls read
- * information during read and "png_set_" functions calls write information
- * when creating a PNG.
- * been moved into a separate header file that is not accessible to
- * applications.  Read libpng-manual.txt or libpng.3 for more info.
- */
-typedef struct png_info_def png_info;
-typedef png_info * png_infop;
-typedef const png_info * png_const_infop;
-typedef png_info * * png_infopp;
-
-/* Types with names ending 'p' are pointer types.  The corresponding types with
- * names ending 'rp' are identical pointer types except that the pointer is
- * marked 'restrict', which means that it is the only pointer to the object
- * passed to the function.  Applications should not use the 'restrict' types;
- * it is always valid to pass 'p' to a pointer with a function argument of the
- * corresponding 'rp' type.  Different compilers have different rules with
- * regard to type matching in the presence of 'restrict'.  For backward
- * compatibility libpng callbacks never have 'restrict' in their parameters and,
- * consequentially, writing portable application code is extremely difficult if
- * an attempt is made to use 'restrict'.
- */
-typedef png_struct * PNG_RESTRICT png_structrp;
-typedef const png_struct * PNG_RESTRICT png_const_structrp;
-typedef png_info * PNG_RESTRICT png_inforp;
-typedef const png_info * PNG_RESTRICT png_const_inforp;
-
-/* Three color definitions.  The order of the red, green, and blue, (and the
- * exact size) is not important, although the size of the fields need to
- * be png_byte or png_uint_16 (as defined below).
- */
-typedef struct png_color_struct
-{
-   png_byte red;
-   png_byte green;
-   png_byte blue;
-} png_color;
-typedef png_color * png_colorp;
-typedef const png_color * png_const_colorp;
-typedef png_color * * png_colorpp;
-
-typedef struct png_color_16_struct
-{
-   png_byte index;    /* used for palette files */
-   png_uint_16 red;   /* for use in red green blue files */
-   png_uint_16 green;
-   png_uint_16 blue;
-   png_uint_16 gray;  /* for use in grayscale files */
-} png_color_16;
-typedef png_color_16 * png_color_16p;
-typedef const png_color_16 * png_const_color_16p;
-typedef png_color_16 * * png_color_16pp;
-
-typedef struct png_color_8_struct
-{
-   png_byte red;   /* for use in red green blue files */
-   png_byte green;
-   png_byte blue;
-   png_byte gray;  /* for use in grayscale files */
-   png_byte alpha; /* for alpha channel files */
-} png_color_8;
-typedef png_color_8 * png_color_8p;
-typedef const png_color_8 * png_const_color_8p;
-typedef png_color_8 * * png_color_8pp;
-
-/*
- * The following two structures are used for the in-core representation
- * of sPLT chunks.
- */
-typedef struct png_sPLT_entry_struct
-{
-   png_uint_16 red;
-   png_uint_16 green;
-   png_uint_16 blue;
-   png_uint_16 alpha;
-   png_uint_16 frequency;
-} png_sPLT_entry;
-typedef png_sPLT_entry * png_sPLT_entryp;
-typedef const png_sPLT_entry * png_const_sPLT_entryp;
-typedef png_sPLT_entry * * png_sPLT_entrypp;
-
-/*  When the depth of the sPLT palette is 8 bits, the color and alpha samples
- *  occupy the LSB of their respective members, and the MSB of each member
- *  is zero-filled.  The frequency member always occupies the full 16 bits.
- */
-
-typedef struct png_sPLT_struct
-{
-   png_charp name;           /* palette name */
-   png_byte depth;           /* depth of palette samples */
-   png_sPLT_entryp entries;  /* palette entries */
-   png_int_32 nentries;      /* number of palette entries */
-} png_sPLT_t;
-typedef png_sPLT_t * png_sPLT_tp;
-typedef const png_sPLT_t * png_const_sPLT_tp;
-typedef png_sPLT_t * * png_sPLT_tpp;
-
-#ifdef PNG_TEXT_SUPPORTED
-/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file,
- * and whether that contents is compressed or not.  The "key" field
- * points to a regular zero-terminated C string.  The "text" fields can be a
- * regular C string, an empty string, or a NULL pointer.
- * However, the structure returned by png_get_text() will always contain
- * the "text" field as a regular zero-terminated C string (possibly
- * empty), never a NULL pointer, so it can be safely used in printf() and
- * other string-handling functions.  Note that the "itxt_length", "lang", and
- * "lang_key" members of the structure only exist when the library is built
- * with iTXt chunk support.  Prior to libpng-1.4.0 the library was built by
- * default without iTXt support. Also note that when iTXt *is* supported,
- * the "lang" and "lang_key" fields contain NULL pointers when the
- * "compression" field contains * PNG_TEXT_COMPRESSION_NONE or
- * PNG_TEXT_COMPRESSION_zTXt. Note that the "compression value" is not the
- * same as what appears in the PNG tEXt/zTXt/iTXt chunk's "compression flag"
- * which is always 0 or 1, or its "compression method" which is always 0.
- */
-typedef struct png_text_struct
-{
-   int  compression;       /* compression value:
-                             -1: tEXt, none
-                              0: zTXt, deflate
-                              1: iTXt, none
-                              2: iTXt, deflate  */
-   png_charp key;          /* keyword, 1-79 character description of "text" */
-   png_charp text;         /* comment, may be an empty string (ie "")
-                              or a NULL pointer */
-   size_t text_length;     /* length of the text string */
-   size_t itxt_length;     /* length of the itxt string */
-   png_charp lang;         /* language code, 0-79 characters
-                              or a NULL pointer */
-   png_charp lang_key;     /* keyword translated UTF-8 string, 0 or more
-                              chars or a NULL pointer */
-} png_text;
-typedef png_text * png_textp;
-typedef const png_text * png_const_textp;
-typedef png_text * * png_textpp;
-#endif
-
-/* Supported compression types for text in PNG files (tEXt, and zTXt).
- * The values of the PNG_TEXT_COMPRESSION_ defines should NOT be changed. */
-#define PNG_TEXT_COMPRESSION_NONE_WR -3
-#define PNG_TEXT_COMPRESSION_zTXt_WR -2
-#define PNG_TEXT_COMPRESSION_NONE    -1
-#define PNG_TEXT_COMPRESSION_zTXt     0
-#define PNG_ITXT_COMPRESSION_NONE     1
-#define PNG_ITXT_COMPRESSION_zTXt     2
-#define PNG_TEXT_COMPRESSION_LAST     3  /* Not a valid value */
-
-/* png_time is a way to hold the time in an machine independent way.
- * Two conversions are provided, both from time_t and struct tm.  There
- * is no portable way to convert to either of these structures, as far
- * as I know.  If you know of a portable way, send it to me.  As a side
- * note - PNG has always been Year 2000 compliant!
- */
-typedef struct png_time_struct
-{
-   png_uint_16 year; /* full year, as in, 1995 */
-   png_byte month;   /* month of year, 1 - 12 */
-   png_byte day;     /* day of month, 1 - 31 */
-   png_byte hour;    /* hour of day, 0 - 23 */
-   png_byte minute;  /* minute of hour, 0 - 59 */
-   png_byte second;  /* second of minute, 0 - 60 (for leap seconds) */
-} png_time;
-typedef png_time * png_timep;
-typedef const png_time * png_const_timep;
-typedef png_time * * png_timepp;
-
-#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\
-   defined(PNG_USER_CHUNKS_SUPPORTED)
-/* png_unknown_chunk is a structure to hold queued chunks for which there is
- * no specific support.  The idea is that we can use this to queue
- * up private chunks for output even though the library doesn't actually
- * know about their semantics.
- *
- * The data in the structure is set by libpng on read and used on write.
- */
-typedef struct png_unknown_chunk_t
-{
-   png_byte name[5]; /* Textual chunk name with '\0' terminator */
-   png_byte *data;   /* Data, should not be modified on read! */
-   size_t size;
-
-   /* On write 'location' must be set using the flag values listed below.
-    * Notice that on read it is set by libpng however the values stored have
-    * more bits set than are listed below.  Always treat the value as a
-    * bitmask.  On write set only one bit - setting multiple bits may cause the
-    * chunk to be written in multiple places.
-    */
-   png_byte location; /* mode of operation at read time */
-}
-png_unknown_chunk;
-
-typedef png_unknown_chunk * png_unknown_chunkp;
-typedef const png_unknown_chunk * png_const_unknown_chunkp;
-typedef png_unknown_chunk * * png_unknown_chunkpp;
-#endif
-
-/* Flag values for the unknown chunk location byte. */
-#define PNG_HAVE_IHDR  0x01
-#define PNG_HAVE_PLTE  0x02
-#define PNG_AFTER_IDAT 0x08
-
-/* Maximum positive integer used in PNG is (2^31)-1 */
-#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL)
-#define PNG_UINT_32_MAX ((png_uint_32)(-1))
-#define PNG_SIZE_MAX ((size_t)(-1))
-
-/* These are constants for fixed point values encoded in the
- * PNG specification manner (x100000)
- */
-#define PNG_FP_1    100000
-#define PNG_FP_HALF  50000
-#define PNG_FP_MAX  ((png_fixed_point)0x7fffffffL)
-#define PNG_FP_MIN  (-PNG_FP_MAX)
-
-/* These describe the color_type field in png_info. */
-/* color type masks */
-#define PNG_COLOR_MASK_PALETTE    1
-#define PNG_COLOR_MASK_COLOR      2
-#define PNG_COLOR_MASK_ALPHA      4
-
-/* color types.  Note that not all combinations are legal */
-#define PNG_COLOR_TYPE_GRAY 0
-#define PNG_COLOR_TYPE_PALETTE  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
-#define PNG_COLOR_TYPE_RGB        (PNG_COLOR_MASK_COLOR)
-#define PNG_COLOR_TYPE_RGB_ALPHA  (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
-#define PNG_COLOR_TYPE_GRAY_ALPHA (PNG_COLOR_MASK_ALPHA)
-/* aliases */
-#define PNG_COLOR_TYPE_RGBA  PNG_COLOR_TYPE_RGB_ALPHA
-#define PNG_COLOR_TYPE_GA  PNG_COLOR_TYPE_GRAY_ALPHA
-
-/* This is for compression type. PNG 1.0-1.2 only define the single type. */
-#define PNG_COMPRESSION_TYPE_BASE 0 /* Deflate method 8, 32K window */
-#define PNG_COMPRESSION_TYPE_DEFAULT PNG_COMPRESSION_TYPE_BASE
-
-/* This is for filter type. PNG 1.0-1.2 only define the single type. */
-#define PNG_FILTER_TYPE_BASE      0 /* Single row per-byte filtering */
-#define PNG_INTRAPIXEL_DIFFERENCING 64 /* Used only in MNG datastreams */
-#define PNG_FILTER_TYPE_DEFAULT   PNG_FILTER_TYPE_BASE
-
-/* These are for the interlacing type.  These values should NOT be changed. */
-#define PNG_INTERLACE_NONE        0 /* Non-interlaced image */
-#define PNG_INTERLACE_ADAM7       1 /* Adam7 interlacing */
-#define PNG_INTERLACE_LAST        2 /* Not a valid value */
-
-/* These are for the oFFs chunk.  These values should NOT be changed. */
-#define PNG_OFFSET_PIXEL          0 /* Offset in pixels */
-#define PNG_OFFSET_MICROMETER     1 /* Offset in micrometers (1/10^6 meter) */
-#define PNG_OFFSET_LAST           2 /* Not a valid value */
-
-/* These are for the pCAL chunk.  These values should NOT be changed. */
-#define PNG_EQUATION_LINEAR       0 /* Linear transformation */
-#define PNG_EQUATION_BASE_E       1 /* Exponential base e transform */
-#define PNG_EQUATION_ARBITRARY    2 /* Arbitrary base exponential transform */
-#define PNG_EQUATION_HYPERBOLIC   3 /* Hyperbolic sine transformation */
-#define PNG_EQUATION_LAST         4 /* Not a valid value */
-
-/* These are for the sCAL chunk.  These values should NOT be changed. */
-#define PNG_SCALE_UNKNOWN         0 /* unknown unit (image scale) */
-#define PNG_SCALE_METER           1 /* meters per pixel */
-#define PNG_SCALE_RADIAN          2 /* radians per pixel */
-#define PNG_SCALE_LAST            3 /* Not a valid value */
-
-/* These are for the pHYs chunk.  These values should NOT be changed. */
-#define PNG_RESOLUTION_UNKNOWN    0 /* pixels/unknown unit (aspect ratio) */
-#define PNG_RESOLUTION_METER      1 /* pixels/meter */
-#define PNG_RESOLUTION_LAST       2 /* Not a valid value */
-
-/* These are for the sRGB chunk.  These values should NOT be changed. */
-#define PNG_sRGB_INTENT_PERCEPTUAL 0
-#define PNG_sRGB_INTENT_RELATIVE   1
-#define PNG_sRGB_INTENT_SATURATION 2
-#define PNG_sRGB_INTENT_ABSOLUTE   3
-#define PNG_sRGB_INTENT_LAST       4 /* Not a valid value */
-
-/* This is for text chunks */
-#define PNG_KEYWORD_MAX_LENGTH     79
-
-/* Maximum number of entries in PLTE/sPLT/tRNS arrays */
-#define PNG_MAX_PALETTE_LENGTH    256
-
-/* These determine if an ancillary chunk's data has been successfully read
- * from the PNG header, or if the application has filled in the corresponding
- * data in the info_struct to be written into the output file.  The values
- * of the PNG_INFO_<chunk> defines should NOT be changed.
- */
-#define PNG_INFO_gAMA 0x0001U
-#define PNG_INFO_sBIT 0x0002U
-#define PNG_INFO_cHRM 0x0004U
-#define PNG_INFO_PLTE 0x0008U
-#define PNG_INFO_tRNS 0x0010U
-#define PNG_INFO_bKGD 0x0020U
-#define PNG_INFO_hIST 0x0040U
-#define PNG_INFO_pHYs 0x0080U
-#define PNG_INFO_oFFs 0x0100U
-#define PNG_INFO_tIME 0x0200U
-#define PNG_INFO_pCAL 0x0400U
-#define PNG_INFO_sRGB 0x0800U  /* GR-P, 0.96a */
-#define PNG_INFO_iCCP 0x1000U  /* ESR, 1.0.6 */
-#define PNG_INFO_sPLT 0x2000U  /* ESR, 1.0.6 */
-#define PNG_INFO_sCAL 0x4000U  /* ESR, 1.0.6 */
-#define PNG_INFO_IDAT 0x8000U  /* ESR, 1.0.6 */
-#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */
-
-/* This is used for the transformation routines, as some of them
- * change these values for the row.  It also should enable using
- * the routines for other purposes.
- */
-typedef struct png_row_info_struct
-{
-   png_uint_32 width;    /* width of row */
-   size_t rowbytes;      /* number of bytes in row */
-   png_byte color_type;  /* color type of row */
-   png_byte bit_depth;   /* bit depth of row */
-   png_byte channels;    /* number of channels (1, 2, 3, or 4) */
-   png_byte pixel_depth; /* bits per pixel (depth * channels) */
-} png_row_info;
-
-typedef png_row_info * png_row_infop;
-typedef png_row_info * * png_row_infopp;
-
-/* These are the function types for the I/O functions and for the functions
- * that allow the user to override the default I/O functions with his or her
- * own.  The png_error_ptr type should match that of user-supplied warning
- * and error functions, while the png_rw_ptr type should match that of the
- * user read/write data functions.  Note that the 'write' function must not
- * modify the buffer it is passed. The 'read' function, on the other hand, is
- * expected to return the read data in the buffer.
- */
-typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp));
-typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t));
-typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp));
-typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32,
-    int));
-typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32,
-    int));
-
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
-typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
-
-/* The following callback receives png_uint_32 row_number, int pass for the
- * png_bytep data of the row.  When transforming an interlaced image the
- * row number is the row number within the sub-image of the interlace pass, so
- * the value will increase to the height of the sub-image (not the full image)
- * then reset to 0 for the next pass.
- *
- * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to
- * find the output pixel (x,y) given an interlaced sub-image pixel
- * (row,col,pass).  (See below for these macros.)
- */
-typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep,
-    png_uint_32, int));
-#endif
-
-#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
-    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
-typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop,
-    png_bytep));
-#endif
-
-#ifdef PNG_USER_CHUNKS_SUPPORTED
-typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp,
-    png_unknown_chunkp));
-#endif
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
-/* not used anywhere */
-/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */
-#endif
-
-#ifdef PNG_SETJMP_SUPPORTED
-/* This must match the function definition in <setjmp.h>, and the application
- * must include this before png.h to obtain the definition of jmp_buf.  The
- * function is required to be PNG_NORETURN, but this is not checked.  If the
- * function does return the application will crash via an abort() or similar
- * system level call.
- *
- * If you get a warning here while building the library you may need to make
- * changes to ensure that pnglibconf.h records the calling convention used by
- * your compiler.  This may be very difficult - try using a different compiler
- * to build the library!
- */
-PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef);
-#endif
-
-/* Transform masks for the high-level interface */
-#define PNG_TRANSFORM_IDENTITY       0x0000    /* read and write */
-#define PNG_TRANSFORM_STRIP_16       0x0001    /* read only */
-#define PNG_TRANSFORM_STRIP_ALPHA    0x0002    /* read only */
-#define PNG_TRANSFORM_PACKING        0x0004    /* read and write */
-#define PNG_TRANSFORM_PACKSWAP       0x0008    /* read and write */
-#define PNG_TRANSFORM_EXPAND         0x0010    /* read only */
-#define PNG_TRANSFORM_INVERT_MONO    0x0020    /* read and write */
-#define PNG_TRANSFORM_SHIFT          0x0040    /* read and write */
-#define PNG_TRANSFORM_BGR            0x0080    /* read and write */
-#define PNG_TRANSFORM_SWAP_ALPHA     0x0100    /* read and write */
-#define PNG_TRANSFORM_SWAP_ENDIAN    0x0200    /* read and write */
-#define PNG_TRANSFORM_INVERT_ALPHA   0x0400    /* read and write */
-#define PNG_TRANSFORM_STRIP_FILLER   0x0800    /* write only */
-/* Added to libpng-1.2.34 */
-#define PNG_TRANSFORM_STRIP_FILLER_BEFORE PNG_TRANSFORM_STRIP_FILLER
-#define PNG_TRANSFORM_STRIP_FILLER_AFTER 0x1000 /* write only */
-/* Added to libpng-1.4.0 */
-#define PNG_TRANSFORM_GRAY_TO_RGB   0x2000      /* read only */
-/* Added to libpng-1.5.4 */
-#define PNG_TRANSFORM_EXPAND_16     0x4000      /* read only */
-#if INT_MAX >= 0x8000 /* else this might break */
-#define PNG_TRANSFORM_SCALE_16      0x8000      /* read only */
-#endif
-
-/* Flags for MNG supported features */
-#define PNG_FLAG_MNG_EMPTY_PLTE     0x01
-#define PNG_FLAG_MNG_FILTER_64      0x04
-#define PNG_ALL_MNG_FEATURES        0x05
-
-/* NOTE: prior to 1.5 these functions had no 'API' style declaration,
- * this allowed the zlib default functions to be used on Windows
- * platforms.  In 1.5 the zlib default malloc (which just calls malloc and
- * ignores the first argument) should be completely compatible with the
- * following.
- */
-typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp,
-    png_alloc_size_t));
-typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp));
-
-/* Section 4: exported functions
- * Here are the function definitions most commonly used.  This is not
- * the place to find out how to use libpng.  See libpng-manual.txt for the
- * full explanation, see example.c for the summary.  This just provides
- * a simple one line description of the use of each function.
- *
- * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in
- * pngconf.h and in the *.dfn files in the scripts directory.
- *
- *   PNG_EXPORT(ordinal, type, name, (args));
- *
- *       ordinal:    ordinal that is used while building
- *                   *.def files. The ordinal value is only
- *                   relevant when preprocessing png.h with
- *                   the *.dfn files for building symbol table
- *                   entries, and are removed by pngconf.h.
- *       type:       return type of the function
- *       name:       function name
- *       args:       function arguments, with types
- *
- * When we wish to append attributes to a function prototype we use
- * the PNG_EXPORTA() macro instead.
- *
- *   PNG_EXPORTA(ordinal, type, name, (args), attributes);
- *
- *       ordinal, type, name, and args: same as in PNG_EXPORT().
- *       attributes: function attributes
- */
-
-/* Returns the version number of the library */
-PNG_EXPORT(1, png_uint_32, png_access_version_number, (void));
-
-/* Tell lib we have already handled the first <num_bytes> magic bytes.
- * Handling more than 8 bytes from the beginning of the file is an error.
- */
-PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes));
-
-/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
- * PNG file.  Returns zero if the supplied bytes match the 8-byte PNG
- * signature, and non-zero otherwise.  Having num_to_check == 0 or
- * start > 7 will always fail (ie return non-zero).
- */
-PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start,
-    size_t num_to_check));
-
-/* Simple signature checking function.  This is the same as calling
- * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
- */
-#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n))
-
-/* Allocate and initialize png_ptr struct for reading, and any other memory. */
-PNG_EXPORTA(4, png_structp, png_create_read_struct,
-    (png_const_charp user_png_ver, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warn_fn),
-    PNG_ALLOCATED);
-
-/* Allocate and initialize png_ptr struct for writing, and any other memory */
-PNG_EXPORTA(5, png_structp, png_create_write_struct,
-    (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
-    png_error_ptr warn_fn),
-    PNG_ALLOCATED);
-
-PNG_EXPORT(6, size_t, png_get_compression_buffer_size,
-    (png_const_structrp png_ptr));
-
-PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr,
-    size_t size));
-
-/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp
- * match up.
- */
-#ifdef PNG_SETJMP_SUPPORTED
-/* This function returns the jmp_buf built in to *png_ptr.  It must be
- * supplied with an appropriate 'longjmp' function to use on that jmp_buf
- * unless the default error function is overridden in which case NULL is
- * acceptable.  The size of the jmp_buf is checked against the actual size
- * allocated by the library - the call will return NULL on a mismatch
- * indicating an ABI mismatch.
- */
-PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr,
-    png_longjmp_ptr longjmp_fn, size_t jmp_buf_size));
-#  define png_jmpbuf(png_ptr) \
-      (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf))))
-#else
-#  define png_jmpbuf(png_ptr) \
-      (LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP)
-#endif
-/* This function should be used by libpng applications in place of
- * longjmp(png_ptr->jmpbuf, val).  If longjmp_fn() has been set, it
- * will use it; otherwise it will call PNG_ABORT().  This function was
- * added in libpng-1.5.0.
- */
-PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val),
-    PNG_NORETURN);
-
-#ifdef PNG_READ_SUPPORTED
-/* Reset the compression stream */
-PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED);
-#endif
-
-/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */
-#ifdef PNG_USER_MEM_SUPPORTED
-PNG_EXPORTA(11, png_structp, png_create_read_struct_2,
-    (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
-    png_error_ptr warn_fn,
-    png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn),
-    PNG_ALLOCATED);
-PNG_EXPORTA(12, png_structp, png_create_write_struct_2,
-    (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
-    png_error_ptr warn_fn,
-    png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn),
-    PNG_ALLOCATED);
-#endif
-
-/* Write the PNG file signature. */
-PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr));
-
-/* Write a PNG chunk - size, type, (optional) data, CRC. */
-PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep
-    chunk_name, png_const_bytep data, size_t length));
-
-/* Write the start of a PNG chunk - length and chunk name. */
-PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr,
-    png_const_bytep chunk_name, png_uint_32 length));
-
-/* Write the data of a PNG chunk started with png_write_chunk_start(). */
-PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr,
-    png_const_bytep data, size_t length));
-
-/* Finish a chunk started with png_write_chunk_start() (includes CRC). */
-PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr));
-
-/* Allocate and initialize the info structure */
-PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr),
-    PNG_ALLOCATED);
-
-/* DEPRECATED: this function allowed init structures to be created using the
- * default allocation method (typically malloc).  Use is deprecated in 1.6.0 and
- * the API will be removed in the future.
- */
-PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr,
-    size_t png_info_struct_size), PNG_DEPRECATED);
-
-/* Writes all the PNG information before the image. */
-PNG_EXPORT(20, void, png_write_info_before_PLTE,
-    (png_structrp png_ptr, png_const_inforp info_ptr));
-PNG_EXPORT(21, void, png_write_info,
-    (png_structrp png_ptr, png_const_inforp info_ptr));
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-/* Read the information before the actual image data. */
-PNG_EXPORT(22, void, png_read_info,
-    (png_structrp png_ptr, png_inforp info_ptr));
-#endif
-
-#ifdef PNG_TIME_RFC1123_SUPPORTED
-   /* Convert to a US string format: there is no localization support in this
-    * routine.  The original implementation used a 29 character buffer in
-    * png_struct, this will be removed in future versions.
-    */
-#if PNG_LIBPNG_VER < 10700
-/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */
-PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr,
-    png_const_timep ptime),PNG_DEPRECATED);
-#endif
-PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29],
-    png_const_timep ptime));
-#endif
-
-#ifdef PNG_CONVERT_tIME_SUPPORTED
-/* Convert from a struct tm to png_time */
-PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime,
-    const struct tm * ttime));
-
-/* Convert from time_t to png_time.  Uses gmtime() */
-PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime));
-#endif /* CONVERT_tIME */
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
-/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */
-PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr));
-PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr));
-PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr));
-PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr));
-#endif
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
-/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion
- * of a tRNS chunk if present.
- */
-PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr));
-#endif
-
-#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
-/* Use blue, green, red order for pixels. */
-PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr));
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-/* Expand the grayscale to 24-bit RGB if necessary. */
-PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr));
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-/* Reduce RGB to grayscale. */
-#define PNG_ERROR_ACTION_NONE  1
-#define PNG_ERROR_ACTION_WARN  2
-#define PNG_ERROR_ACTION_ERROR 3
-#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/
-
-PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr,
-    int error_action, double red, double green))
-PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr,
-    int error_action, png_fixed_point red, png_fixed_point green))
-
-PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp
-    png_ptr));
-#endif
-
-#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
-PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
-    png_colorp palette));
-#endif
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-/* How the alpha channel is interpreted - this affects how the color channels
- * of a PNG file are returned to the calling application when an alpha channel,
- * or a tRNS chunk in a palette file, is present.
- *
- * This has no effect on the way pixels are written into a PNG output
- * datastream. The color samples in a PNG datastream are never premultiplied
- * with the alpha samples.
- *
- * The default is to return data according to the PNG specification: the alpha
- * channel is a linear measure of the contribution of the pixel to the
- * corresponding composited pixel, and the color channels are unassociated
- * (not premultiplied).  The gamma encoded color channels must be scaled
- * according to the contribution and to do this it is necessary to undo
- * the encoding, scale the color values, perform the composition and re-encode
- * the values.  This is the 'PNG' mode.
- *
- * The alternative is to 'associate' the alpha with the color information by
- * storing color channel values that have been scaled by the alpha.
- * image.  These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
- * (the latter being the two common names for associated alpha color channels).
- *
- * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha
- * value is equal to the maximum value.
- *
- * The final choice is to gamma encode the alpha channel as well.  This is
- * broken because, in practice, no implementation that uses this choice
- * correctly undoes the encoding before handling alpha composition.  Use this
- * choice only if other serious errors in the software or hardware you use
- * mandate it; the typical serious error is for dark halos to appear around
- * opaque areas of the composited PNG image because of arithmetic overflow.
- *
- * The API function png_set_alpha_mode specifies which of these choices to use
- * with an enumerated 'mode' value and the gamma of the required output:
- */
-#define PNG_ALPHA_PNG           0 /* according to the PNG standard */
-#define PNG_ALPHA_STANDARD      1 /* according to Porter/Duff */
-#define PNG_ALPHA_ASSOCIATED    1 /* as above; this is the normal practice */
-#define PNG_ALPHA_PREMULTIPLIED 1 /* as above */
-#define PNG_ALPHA_OPTIMIZED     2 /* 'PNG' for opaque pixels, else 'STANDARD' */
-#define PNG_ALPHA_BROKEN        3 /* the alpha channel is gamma encoded */
-
-PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode,
-    double output_gamma))
-PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr,
-    int mode, png_fixed_point output_gamma))
-#endif
-
-#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED)
-/* The output_gamma value is a screen gamma in libpng terminology: it expresses
- * how to decode the output values, not how they are encoded.
- */
-#define PNG_DEFAULT_sRGB -1       /* sRGB gamma and color space */
-#define PNG_GAMMA_MAC_18 -2       /* Old Mac '1.8' gamma and color space */
-#define PNG_GAMMA_sRGB   220000   /* Television standards--matches sRGB gamma */
-#define PNG_GAMMA_LINEAR PNG_FP_1 /* Linear */
-#endif
-
-/* The following are examples of calls to png_set_alpha_mode to achieve the
- * required overall gamma correction and, where necessary, alpha
- * premultiplication.
- *
- * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB);
- *    This is the default libpng handling of the alpha channel - it is not
- *    pre-multiplied into the color components.  In addition the call states
- *    that the output is for a sRGB system and causes all PNG files without gAMA
- *    chunks to be assumed to be encoded using sRGB.
- *
- * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC);
- *    In this case the output is assumed to be something like an sRGB conformant
- *    display preceded by a power-law lookup table of power 1.45.  This is how
- *    early Mac systems behaved.
- *
- * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR);
- *    This is the classic Jim Blinn approach and will work in academic
- *    environments where everything is done by the book.  It has the shortcoming
- *    of assuming that input PNG data with no gamma information is linear - this
- *    is unlikely to be correct unless the PNG files where generated locally.
- *    Most of the time the output precision will be so low as to show
- *    significant banding in dark areas of the image.
- *
- * png_set_expand_16(pp);
- * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB);
- *    This is a somewhat more realistic Jim Blinn inspired approach.  PNG files
- *    are assumed to have the sRGB encoding if not marked with a gamma value and
- *    the output is always 16 bits per component.  This permits accurate scaling
- *    and processing of the data.  If you know that your input PNG files were
- *    generated locally you might need to replace PNG_DEFAULT_sRGB with the
- *    correct value for your system.
- *
- * png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB);
- *    If you just need to composite the PNG image onto an existing background
- *    and if you control the code that does this you can use the optimization
- *    setting.  In this case you just copy completely opaque pixels to the
- *    output.  For pixels that are not completely transparent (you just skip
- *    those) you do the composition math using png_composite or png_composite_16
- *    below then encode the resultant 8-bit or 16-bit values to match the output
- *    encoding.
- *
- * Other cases
- *    If neither the PNG nor the standard linear encoding work for you because
- *    of the software or hardware you use then you have a big problem.  The PNG
- *    case will probably result in halos around the image.  The linear encoding
- *    will probably result in a washed out, too bright, image (it's actually too
- *    contrasty.)  Try the ALPHA_OPTIMIZED mode above - this will probably
- *    substantially reduce the halos.  Alternatively try:
- *
- * png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB);
- *    This option will also reduce the halos, but there will be slight dark
- *    halos round the opaque parts of the image where the background is light.
- *    In the OPTIMIZED mode the halos will be light halos where the background
- *    is dark.  Take your pick - the halos are unavoidable unless you can get
- *    your hardware/software fixed!  (The OPTIMIZED approach is slightly
- *    faster.)
- *
- * When the default gamma of PNG files doesn't match the output gamma.
- *    If you have PNG files with no gamma information png_set_alpha_mode allows
- *    you to provide a default gamma, but it also sets the output gamma to the
- *    matching value.  If you know your PNG files have a gamma that doesn't
- *    match the output you can take advantage of the fact that
- *    png_set_alpha_mode always sets the output gamma but only sets the PNG
- *    default if it is not already set:
- *
- * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB);
- * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC);
- *    The first call sets both the default and the output gamma values, the
- *    second call overrides the output gamma without changing the default.  This
- *    is easier than achieving the same effect with png_set_gamma.  You must use
- *    PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will
- *    fire if more than one call to png_set_alpha_mode and png_set_background is
- *    made in the same read operation, however multiple calls with PNG_ALPHA_PNG
- *    are ignored.
- */
-
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr));
-#endif
-
-#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
-    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
-PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr));
-#endif
-
-#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
-    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
-PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr));
-#endif
-
-#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
-/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */
-PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler,
-    int flags));
-/* The values of the PNG_FILLER_ defines should NOT be changed */
-#  define PNG_FILLER_BEFORE 0
-#  define PNG_FILLER_AFTER 1
-/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */
-PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr,
-    png_uint_32 filler, int flags));
-#endif /* READ_FILLER || WRITE_FILLER */
-
-#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-/* Swap bytes in 16-bit depth files. */
-PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr));
-#endif
-
-#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
-/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
-PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr));
-#endif
-
-#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \
-    defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-/* Swap packing order of pixels in bytes. */
-PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr));
-#endif
-
-#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
-/* Converts files to legal bit depths. */
-PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p
-    true_bits));
-#endif
-
-#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
-    defined(PNG_WRITE_INTERLACING_SUPPORTED)
-/* Have the code handle the interlacing.  Returns the number of passes.
- * MUST be called before png_read_update_info or png_start_read_image,
- * otherwise it will not have the desired effect.  Note that it is still
- * necessary to call png_read_row or png_read_rows png_get_image_height
- * times for each pass.
-*/
-PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr));
-#endif
-
-#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
-/* Invert monochrome files */
-PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr));
-#endif
-
-#ifdef PNG_READ_BACKGROUND_SUPPORTED
-/* Handle alpha and tRNS by replacing with a background color.  Prior to
- * libpng-1.5.4 this API must not be called before the PNG file header has been
- * read.  Doing so will result in unexpected behavior and possible warnings or
- * errors if the PNG file contains a bKGD chunk.
- */
-PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr,
-    png_const_color_16p background_color, int background_gamma_code,
-    int need_expand, double background_gamma))
-PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr,
-    png_const_color_16p background_color, int background_gamma_code,
-    int need_expand, png_fixed_point background_gamma))
-#endif
-#ifdef PNG_READ_BACKGROUND_SUPPORTED
-#  define PNG_BACKGROUND_GAMMA_UNKNOWN 0
-#  define PNG_BACKGROUND_GAMMA_SCREEN  1
-#  define PNG_BACKGROUND_GAMMA_FILE    2
-#  define PNG_BACKGROUND_GAMMA_UNIQUE  3
-#endif
-
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
-/* Scale a 16-bit depth file down to 8-bit, accurately. */
-PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr));
-#endif
-
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */
-/* Strip the second byte of information from a 16-bit depth file. */
-PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr));
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-/* Turn on quantizing, and reduce the palette to the number of colors
- * available.
- */
-PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr,
-    png_colorp palette, int num_palette, int maximum_colors,
-    png_const_uint_16p histogram, int full_quantize));
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-/* The threshold on gamma processing is configurable but hard-wired into the
- * library.  The following is the floating point variant.
- */
-#define PNG_GAMMA_THRESHOLD (PNG_GAMMA_THRESHOLD_FIXED*.00001)
-
-/* Handle gamma correction. Screen_gamma=(display_exponent).
- * NOTE: this API simply sets the screen and file gamma values. It will
- * therefore override the value for gamma in a PNG file if it is called after
- * the file header has been read - use with care  - call before reading the PNG
- * file for best results!
- *
- * These routines accept the same gamma values as png_set_alpha_mode (described
- * above).  The PNG_GAMMA_ defines and PNG_DEFAULT_sRGB can be passed to either
- * API (floating point or fixed.)  Notice, however, that the 'file_gamma' value
- * is the inverse of a 'screen gamma' value.
- */
-PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr,
-    double screen_gamma, double override_file_gamma))
-PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr,
-    png_fixed_point screen_gamma, png_fixed_point override_file_gamma))
-#endif
-
-#ifdef PNG_WRITE_FLUSH_SUPPORTED
-/* Set how many lines between output flushes - 0 for no flushing */
-PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows));
-/* Flush the current PNG output buffer */
-PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr));
-#endif
-
-/* Optional update palette with requested transformations */
-PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr));
-
-/* Optional call to update the users info structure */
-PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr,
-    png_inforp info_ptr));
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-/* Read one or more rows of image data. */
-PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row,
-    png_bytepp display_row, png_uint_32 num_rows));
-#endif
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-/* Read a row of data. */
-PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row,
-    png_bytep display_row));
-#endif
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-/* Read the whole image into memory at once. */
-PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image));
-#endif
-
-/* Write a row of image data */
-PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr,
-    png_const_bytep row));
-
-/* Write a few rows of image data: (*row) is not written; however, the type
- * is declared as writeable to maintain compatibility with previous versions
- * of libpng and to allow the 'display_row' array from read_rows to be passed
- * unchanged to write_rows.
- */
-PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row,
-    png_uint_32 num_rows));
-
-/* Write the image data */
-PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image));
-
-/* Write the end of the PNG file. */
-PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr,
-    png_inforp info_ptr));
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-/* Read the end of the PNG file. */
-PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr));
-#endif
-
-/* Free any memory associated with the png_info_struct */
-PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr,
-    png_infopp info_ptr_ptr));
-
-/* Free any memory associated with the png_struct and the png_info_structs */
-PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr,
-    png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr));
-
-/* Free any memory associated with the png_struct and the png_info_structs */
-PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr,
-    png_infopp info_ptr_ptr));
-
-/* Set the libpng method of handling chunk CRC errors */
-PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action,
-    int ancil_action));
-
-/* Values for png_set_crc_action() say how to handle CRC errors in
- * ancillary and critical chunks, and whether to use the data contained
- * therein.  Note that it is impossible to "discard" data in a critical
- * chunk.  For versions prior to 0.90, the action was always error/quit,
- * whereas in version 0.90 and later, the action for CRC errors in ancillary
- * chunks is warn/discard.  These values should NOT be changed.
- *
- *      value                       action:critical     action:ancillary
- */
-#define PNG_CRC_DEFAULT       0  /* error/quit          warn/discard data */
-#define PNG_CRC_ERROR_QUIT    1  /* error/quit          error/quit        */
-#define PNG_CRC_WARN_DISCARD  2  /* (INVALID)           warn/discard data */
-#define PNG_CRC_WARN_USE      3  /* warn/use data       warn/use data     */
-#define PNG_CRC_QUIET_USE     4  /* quiet/use data      quiet/use data    */
-#define PNG_CRC_NO_CHANGE     5  /* use current value   use current value */
-
-#ifdef PNG_WRITE_SUPPORTED
-/* These functions give the user control over the scan-line filtering in
- * libpng and the compression methods used by zlib.  These functions are
- * mainly useful for testing, as the defaults should work with most users.
- * Those users who are tight on memory or want faster performance at the
- * expense of compression can modify them.  See the compression library
- * header file (zlib.h) for an explination of the compression functions.
- */
-
-/* Set the filtering method(s) used by libpng.  Currently, the only valid
- * value for "method" is 0.
- */
-PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
-    int filters));
-#endif /* WRITE */
-
-/* Flags for png_set_filter() to say which filters to use.  The flags
- * are chosen so that they don't conflict with real filter types
- * below, in case they are supplied instead of the #defined constants.
- * These values should NOT be changed.
- */
-#define PNG_NO_FILTERS     0x00
-#define PNG_FILTER_NONE    0x08
-#define PNG_FILTER_SUB     0x10
-#define PNG_FILTER_UP      0x20
-#define PNG_FILTER_AVG     0x40
-#define PNG_FILTER_PAETH   0x80
-#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP)
-#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH)
-
-/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
- * These defines should NOT be changed.
- */
-#define PNG_FILTER_VALUE_NONE  0
-#define PNG_FILTER_VALUE_SUB   1
-#define PNG_FILTER_VALUE_UP    2
-#define PNG_FILTER_VALUE_AVG   3
-#define PNG_FILTER_VALUE_PAETH 4
-#define PNG_FILTER_VALUE_LAST  5
-
-#ifdef PNG_WRITE_SUPPORTED
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
-PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr,
-    int heuristic_method, int num_weights, png_const_doublep filter_weights,
-    png_const_doublep filter_costs))
-PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
-    (png_structrp png_ptr, int heuristic_method, int num_weights,
-    png_const_fixed_point_p filter_weights,
-    png_const_fixed_point_p filter_costs))
-#endif /* WRITE_WEIGHTED_FILTER */
-
-/* The following are no longer used and will be removed from libpng-1.7: */
-#define PNG_FILTER_HEURISTIC_DEFAULT    0  /* Currently "UNWEIGHTED" */
-#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1  /* Used by libpng < 0.95 */
-#define PNG_FILTER_HEURISTIC_WEIGHTED   2  /* Experimental feature */
-#define PNG_FILTER_HEURISTIC_LAST       3  /* Not a valid value */
-
-/* Set the library compression level.  Currently, valid values range from
- * 0 - 9, corresponding directly to the zlib compression levels 0 - 9
- * (0 - no compression, 9 - "maximal" compression).  Note that tests have
- * shown that zlib compression levels 3-6 usually perform as well as level 9
- * for PNG images, and do considerably fewer caclulations.  In the future,
- * these values may not correspond directly to the zlib compression levels.
- */
-#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
-PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr,
-    int level));
-
-PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr,
-    int mem_level));
-
-PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr,
-    int strategy));
-
-/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
- * smaller value of window_bits if it can do so safely.
- */
-PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr,
-    int window_bits));
-
-PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr,
-    int method));
-#endif /* WRITE_CUSTOMIZE_COMPRESSION */
-
-#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
-/* Also set zlib parameters for compressing non-IDAT chunks */
-PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr,
-    int level));
-
-PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr,
-    int mem_level));
-
-PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr,
-    int strategy));
-
-/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
- * smaller value of window_bits if it can do so safely.
- */
-PNG_EXPORT(225, void, png_set_text_compression_window_bits,
-    (png_structrp png_ptr, int window_bits));
-
-PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr,
-    int method));
-#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
-#endif /* WRITE */
-
-/* These next functions are called for input/output, memory, and error
- * handling.  They are in the file pngrio.c, pngwio.c, and pngerror.c,
- * and call standard C I/O routines such as fread(), fwrite(), and
- * fprintf().  These functions can be made to use other I/O routines
- * at run time for those applications that need to handle I/O in a
- * different manner by calling png_set_???_fn().  See libpng-manual.txt for
- * more information.
- */
-
-#ifdef PNG_STDIO_SUPPORTED
-/* Initialize the input/output for the PNG file to the default functions. */
-PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp));
-#endif
-
-/* Replace the (error and abort), and warning functions with user
- * supplied functions.  If no messages are to be printed you must still
- * write and use replacement functions. The replacement error_fn should
- * still do a longjmp to the last setjmp location if you are using this
- * method of error handling.  If error_fn or warning_fn is NULL, the
- * default function will be used.
- */
-
-PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr,
-    png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn));
-
-/* Return the user pointer associated with the error functions */
-PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr));
-
-/* Replace the default data output functions with a user supplied one(s).
- * If buffered output is not used, then output_flush_fn can be set to NULL.
- * If PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile time
- * output_flush_fn will be ignored (and thus can be NULL).
- * It is probably a mistake to use NULL for output_flush_fn if
- * write_data_fn is not also NULL unless you have built libpng with
- * PNG_WRITE_FLUSH_SUPPORTED undefined, because in this case libpng's
- * default flush function, which uses the standard *FILE structure, will
- * be used.
- */
-PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr,
-    png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn));
-
-/* Replace the default data input function with a user supplied one. */
-PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr,
-    png_rw_ptr read_data_fn));
-
-/* Return the user pointer associated with the I/O functions */
-PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr));
-
-PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr,
-    png_read_status_ptr read_row_fn));
-
-PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr,
-    png_write_status_ptr write_row_fn));
-
-#ifdef PNG_USER_MEM_SUPPORTED
-/* Replace the default memory allocation functions with user supplied one(s). */
-PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr,
-    png_malloc_ptr malloc_fn, png_free_ptr free_fn));
-/* Return the user pointer associated with the memory functions */
-PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr));
-#endif
-
-#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
-PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr,
-    png_user_transform_ptr read_user_transform_fn));
-#endif
-
-#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
-PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr,
-    png_user_transform_ptr write_user_transform_fn));
-#endif
-
-#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
-PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr,
-    png_voidp user_transform_ptr, int user_transform_depth,
-    int user_transform_channels));
-/* Return the user pointer associated with the user transform functions */
-PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr,
-    (png_const_structrp png_ptr));
-#endif
-
-#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
-/* Return information about the row currently being processed.  Note that these
- * APIs do not fail but will return unexpected results if called outside a user
- * transform callback.  Also note that when transforming an interlaced image the
- * row number is the row number within the sub-image of the interlace pass, so
- * the value will increase to the height of the sub-image (not the full image)
- * then reset to 0 for the next pass.
- *
- * Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to
- * find the output pixel (x,y) given an interlaced sub-image pixel
- * (row,col,pass).  (See below for these macros.)
- */
-PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp));
-PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp));
-#endif
-
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
-/* This callback is called only for *unknown* chunks.  If
- * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known
- * chunks to be treated as unknown, however in this case the callback must do
- * any processing required by the chunk (e.g. by calling the appropriate
- * png_set_ APIs.)
- *
- * There is no write support - on write, by default, all the chunks in the
- * 'unknown' list are written in the specified position.
- *
- * The integer return from the callback function is interpreted thus:
- *
- * negative: An error occurred; png_chunk_error will be called.
- *     zero: The chunk was not handled, the chunk will be saved. A critical
- *           chunk will cause an error at this point unless it is to be saved.
- * positive: The chunk was handled, libpng will ignore/discard it.
- *
- * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about
- * how this behavior will change in libpng 1.7
- */
-PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr,
-    png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn));
-#endif
-
-#ifdef PNG_USER_CHUNKS_SUPPORTED
-PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr));
-#endif
-
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-/* Sets the function callbacks for the push reader, and a pointer to a
- * user-defined structure available to the callback functions.
- */
-PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr,
-    png_voidp progressive_ptr, png_progressive_info_ptr info_fn,
-    png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn));
-
-/* Returns the user pointer associated with the push read functions */
-PNG_EXPORT(91, png_voidp, png_get_progressive_ptr,
-    (png_const_structrp png_ptr));
-
-/* Function to be called when data becomes available */
-PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr,
-    png_inforp info_ptr, png_bytep buffer, size_t buffer_size));
-
-/* A function which may be called *only* within png_process_data to stop the
- * processing of any more data.  The function returns the number of bytes
- * remaining, excluding any that libpng has cached internally.  A subsequent
- * call to png_process_data must supply these bytes again.  If the argument
- * 'save' is set to true the routine will first save all the pending data and
- * will always return 0.
- */
-PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save));
-
-/* A function which may be called *only* outside (after) a call to
- * png_process_data.  It returns the number of bytes of data to skip in the
- * input.  Normally it will return 0, but if it returns a non-zero value the
- * application must skip than number of bytes of input data and pass the
- * following data to the next call to png_process_data.
- */
-PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp));
-
-/* Function that combines rows.  'new_row' is a flag that should come from
- * the callback and be non-NULL if anything needs to be done; the library
- * stores its own version of the new data internally and ignores the passed
- * in value.
- */
-PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr,
-    png_bytep old_row, png_const_bytep new_row));
-#endif /* PROGRESSIVE_READ */
-
-PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr,
-    png_alloc_size_t size), PNG_ALLOCATED);
-/* Added at libpng version 1.4.0 */
-PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr,
-    png_alloc_size_t size), PNG_ALLOCATED);
-
-/* Added at libpng version 1.2.4 */
-PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr,
-    png_alloc_size_t size), PNG_ALLOCATED);
-
-/* Frees a pointer allocated by png_malloc() */
-PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr));
-
-/* Free data that was allocated internally */
-PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 free_me, int num));
-
-/* Reassign responsibility for freeing existing data, whether allocated
- * by libpng or by the application; this works on the png_info structure passed
- * in, it does not change the state for other png_info structures.
- *
- * It is unlikely that this function works correctly as of 1.6.0 and using it
- * may result either in memory leaks or double free of allocated data.
- */
-PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int freer, png_uint_32 mask));
-
-/* Assignments for png_data_freer */
-#define PNG_DESTROY_WILL_FREE_DATA 1
-#define PNG_SET_WILL_FREE_DATA 1
-#define PNG_USER_WILL_FREE_DATA 2
-/* Flags for png_ptr->free_me and info_ptr->free_me */
-#define PNG_FREE_HIST 0x0008U
-#define PNG_FREE_ICCP 0x0010U
-#define PNG_FREE_SPLT 0x0020U
-#define PNG_FREE_ROWS 0x0040U
-#define PNG_FREE_PCAL 0x0080U
-#define PNG_FREE_SCAL 0x0100U
-#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-#  define PNG_FREE_UNKN 0x0200U
-#endif
-/*      PNG_FREE_LIST 0x0400U   removed in 1.6.0 because it is ignored */
-#define PNG_FREE_PLTE 0x1000U
-#define PNG_FREE_TRNS 0x2000U
-#define PNG_FREE_TEXT 0x4000U
-#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */
-#define PNG_FREE_ALL  0xffffU
-#define PNG_FREE_MUL  0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
-
-#ifdef PNG_USER_MEM_SUPPORTED
-PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr,
-    png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED);
-PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr,
-    png_voidp ptr), PNG_DEPRECATED);
-#endif
-
-#ifdef PNG_ERROR_TEXT_SUPPORTED
-/* Fatal error in PNG image of libpng - can't continue */
-PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr,
-    png_const_charp error_message), PNG_NORETURN);
-
-/* The same, but the chunk name is prepended to the error string. */
-PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr,
-    png_const_charp error_message), PNG_NORETURN);
-
-#else
-/* Fatal error in PNG image of libpng - can't continue */
-PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN);
-#  define png_error(s1,s2) png_err(s1)
-#  define png_chunk_error(s1,s2) png_err(s1)
-#endif
-
-#ifdef PNG_WARNINGS_SUPPORTED
-/* Non-fatal error in libpng.  Can continue, but may have a problem. */
-PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr,
-    png_const_charp warning_message));
-
-/* Non-fatal error in libpng, chunk name is prepended to message. */
-PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr,
-    png_const_charp warning_message));
-#else
-#  define png_warning(s1,s2) ((void)(s1))
-#  define png_chunk_warning(s1,s2) ((void)(s1))
-#endif
-
-#ifdef PNG_BENIGN_ERRORS_SUPPORTED
-/* Benign error in libpng.  Can continue, but may have a problem.
- * User can choose whether to handle as a fatal error or as a warning. */
-PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr,
-    png_const_charp warning_message));
-
-#ifdef PNG_READ_SUPPORTED
-/* Same, chunk name is prepended to message (only during read) */
-PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr,
-    png_const_charp warning_message));
-#endif
-
-PNG_EXPORT(109, void, png_set_benign_errors,
-    (png_structrp png_ptr, int allowed));
-#else
-#  ifdef PNG_ALLOW_BENIGN_ERRORS
-#    define png_benign_error png_warning
-#    define png_chunk_benign_error png_chunk_warning
-#  else
-#    define png_benign_error png_error
-#    define png_chunk_benign_error png_chunk_error
-#  endif
-#endif
-
-/* The png_set_<chunk> functions are for storing values in the png_info_struct.
- * Similarly, the png_get_<chunk> calls are used to read values from the
- * png_info_struct, either storing the parameters in the passed variables, or
- * setting pointers into the png_info_struct where the data is stored.  The
- * png_get_<chunk> functions return a non-zero value if the data was available
- * in info_ptr, or return zero and do not change any of the parameters if the
- * data was not available.
- *
- * These functions should be used instead of directly accessing png_info
- * to avoid problems with future changes in the size and internal layout of
- * png_info_struct.
- */
-/* Returns "flag" if chunk data is valid in info_ptr. */
-PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_uint_32 flag));
-
-/* Returns number of bytes needed to hold a transformed row. */
-PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-
-#ifdef PNG_INFO_IMAGE_SUPPORTED
-/* Returns row_pointers, which is an array of pointers to scanlines that was
- * returned from png_read_png().
- */
-PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-
-/* Set row_pointers, which is an array of pointers to scanlines for use
- * by png_write_png().
- */
-PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_bytepp row_pointers));
-#endif
-
-/* Returns number of color channels in image. */
-PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-
-#ifdef PNG_EASY_ACCESS_SUPPORTED
-/* Returns image width in pixels. */
-PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-
-/* Returns image height in pixels. */
-PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-
-/* Returns image bit_depth. */
-PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-
-/* Returns image color_type. */
-PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-
-/* Returns image filter_type. */
-PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-
-/* Returns image interlace_type. */
-PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-
-/* Returns image compression_type. */
-PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-
-/* Returns image resolution in pixels per meter, from pHYs chunk data. */
-PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
-PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
-PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
-
-/* Returns pixel aspect ratio, computed from pHYs chunk data.  */
-PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr))
-PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr))
-
-/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
-PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
-PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
-PNG_EXPORT(128, png_int_32, png_get_x_offset_microns,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
-PNG_EXPORT(129, png_int_32, png_get_y_offset_microns,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
-
-#endif /* EASY_ACCESS */
-
-#ifdef PNG_READ_SUPPORTED
-/* Returns pointer to signature string read from PNG header */
-PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr));
-#endif
-
-#ifdef PNG_bKGD_SUPPORTED
-PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_color_16p *background));
-#endif
-
-#ifdef PNG_bKGD_SUPPORTED
-PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_color_16p background));
-#endif
-
-#ifdef PNG_cHRM_SUPPORTED
-PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x,
-    double *red_y, double *green_x, double *green_y, double *blue_x,
-    double *blue_y))
-PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z,
-    double *green_X, double *green_Y, double *green_Z, double *blue_X,
-    double *blue_Y, double *blue_Z))
-PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_fixed_point *int_white_x, png_fixed_point *int_white_y,
-    png_fixed_point *int_red_x, png_fixed_point *int_red_y,
-    png_fixed_point *int_green_x, png_fixed_point *int_green_y,
-    png_fixed_point *int_blue_x, png_fixed_point *int_blue_y))
-PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
-    png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
-    png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
-    png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
-    png_fixed_point *int_blue_Z))
-#endif
-
-#ifdef PNG_cHRM_SUPPORTED
-PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr,
-    png_inforp info_ptr,
-    double white_x, double white_y, double red_x, double red_y, double green_x,
-    double green_y, double blue_x, double blue_y))
-PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr,
-    png_inforp info_ptr, double red_X, double red_Y, double red_Z,
-    double green_X, double green_Y, double green_Z, double blue_X,
-    double blue_Y, double blue_Z))
-PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_fixed_point int_white_x,
-    png_fixed_point int_white_y, png_fixed_point int_red_x,
-    png_fixed_point int_red_y, png_fixed_point int_green_x,
-    png_fixed_point int_green_y, png_fixed_point int_blue_x,
-    png_fixed_point int_blue_y))
-PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y,
-    png_fixed_point int_red_Z, png_fixed_point int_green_X,
-    png_fixed_point int_green_Y, png_fixed_point int_green_Z,
-    png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
-    png_fixed_point int_blue_Z))
-#endif
-
-#ifdef PNG_eXIf_SUPPORTED
-PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_bytep *exif));
-PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_bytep exif));
-
-PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif));
-PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif));
-#endif
-
-#ifdef PNG_gAMA_SUPPORTED
-PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, double *file_gamma))
-PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_fixed_point *int_file_gamma))
-#endif
-
-#ifdef PNG_gAMA_SUPPORTED
-PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr,
-    png_inforp info_ptr, double file_gamma))
-PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_fixed_point int_file_gamma))
-#endif
-
-#ifdef PNG_hIST_SUPPORTED
-PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_uint_16p *hist));
-PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_uint_16p hist));
-#endif
-
-PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height,
-    int *bit_depth, int *color_type, int *interlace_method,
-    int *compression_method, int *filter_method));
-
-PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth,
-    int color_type, int interlace_method, int compression_method,
-    int filter_method));
-
-#ifdef PNG_oFFs_SUPPORTED
-PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr,
-   png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
-   int *unit_type));
-#endif
-
-#ifdef PNG_oFFs_SUPPORTED
-PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y,
-    int unit_type));
-#endif
-
-#ifdef PNG_pCAL_SUPPORTED
-PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_charp *purpose, png_int_32 *X0,
-    png_int_32 *X1, int *type, int *nparams, png_charp *units,
-    png_charpp *params));
-#endif
-
-#ifdef PNG_pCAL_SUPPORTED
-PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1,
-    int type, int nparams, png_const_charp units, png_charpp params));
-#endif
-
-#ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
-    int *unit_type));
-#endif
-
-#ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type));
-#endif
-
-PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr,
-   png_inforp info_ptr, png_colorp *palette, int *num_palette));
-
-PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr,
-    png_inforp info_ptr, png_const_colorp palette, int num_palette));
-
-#ifdef PNG_sBIT_SUPPORTED
-PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_color_8p *sig_bit));
-#endif
-
-#ifdef PNG_sBIT_SUPPORTED
-PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_color_8p sig_bit));
-#endif
-
-#ifdef PNG_sRGB_SUPPORTED
-PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, int *file_srgb_intent));
-#endif
-
-#ifdef PNG_sRGB_SUPPORTED
-PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int srgb_intent));
-PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int srgb_intent));
-#endif
-
-#ifdef PNG_iCCP_SUPPORTED
-PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_charpp name, int *compression_type,
-    png_bytepp profile, png_uint_32 *proflen));
-#endif
-
-#ifdef PNG_iCCP_SUPPORTED
-PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_charp name, int compression_type,
-    png_const_bytep profile, png_uint_32 proflen));
-#endif
-
-#ifdef PNG_sPLT_SUPPORTED
-PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_sPLT_tpp entries));
-#endif
-
-#ifdef PNG_sPLT_SUPPORTED
-PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_sPLT_tp entries, int nentries));
-#endif
-
-#ifdef PNG_TEXT_SUPPORTED
-/* png_get_text also returns the number of text chunks in *num_text */
-PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_textp *text_ptr, int *num_text));
-#endif
-
-/* Note while png_set_text() will accept a structure whose text,
- * language, and  translated keywords are NULL pointers, the structure
- * returned by png_get_text will always contain regular
- * zero-terminated C strings.  They might be empty strings but
- * they will never be NULL pointers.
- */
-
-#ifdef PNG_TEXT_SUPPORTED
-PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_textp text_ptr, int num_text));
-#endif
-
-#ifdef PNG_tIME_SUPPORTED
-PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_timep *mod_time));
-#endif
-
-#ifdef PNG_tIME_SUPPORTED
-PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_timep mod_time));
-#endif
-
-#ifdef PNG_tRNS_SUPPORTED
-PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans,
-    png_color_16p *trans_color));
-#endif
-
-#ifdef PNG_tRNS_SUPPORTED
-PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr,
-    png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans,
-    png_const_color_16p trans_color));
-#endif
-
-#ifdef PNG_sCAL_SUPPORTED
-PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, int *unit, double *width, double *height))
-#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
-   defined(PNG_FLOATING_POINT_SUPPORTED)
-/* NOTE: this API is currently implemented using floating point arithmetic,
- * consequently it can only be used on systems with floating point support.
- * In any case the range of values supported by png_fixed_point is small and it
- * is highly recommended that png_get_sCAL_s be used instead.
- */
-PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit,
-    png_fixed_point *width, png_fixed_point *height))
-#endif
-PNG_EXPORT(169, png_uint_32, png_get_sCAL_s,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit,
-    png_charpp swidth, png_charpp sheight));
-
-PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int unit, double width, double height))
-PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr,
-   png_inforp info_ptr, int unit, png_fixed_point width,
-   png_fixed_point height))
-PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int unit,
-    png_const_charp swidth, png_const_charp sheight));
-#endif /* sCAL */
-
-#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-/* Provide the default handling for all unknown chunks or, optionally, for
- * specific unknown chunks.
- *
- * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was
- * ignored and the default was used, the per-chunk setting only had an effect on
- * write.  If you wish to have chunk-specific handling on read in code that must
- * work on earlier versions you must use a user chunk callback to specify the
- * desired handling (keep or discard.)
- *
- * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below.  The
- * parameter is interpreted as follows:
- *
- * READ:
- *    PNG_HANDLE_CHUNK_AS_DEFAULT:
- *       Known chunks: do normal libpng processing, do not keep the chunk (but
- *          see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
- *       Unknown chunks: for a specific chunk use the global default, when used
- *          as the default discard the chunk data.
- *    PNG_HANDLE_CHUNK_NEVER:
- *       Discard the chunk data.
- *    PNG_HANDLE_CHUNK_IF_SAFE:
- *       Keep the chunk data if the chunk is not critical else raise a chunk
- *       error.
- *    PNG_HANDLE_CHUNK_ALWAYS:
- *       Keep the chunk data.
- *
- * If the chunk data is saved it can be retrieved using png_get_unknown_chunks,
- * below.  Notice that specifying "AS_DEFAULT" as a global default is equivalent
- * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks
- * it simply resets the behavior to the libpng default.
- *
- * INTERACTION WITH USER CHUNK CALLBACKS:
- * The per-chunk handling is always used when there is a png_user_chunk_ptr
- * callback and the callback returns 0; the chunk is then always stored *unless*
- * it is critical and the per-chunk setting is other than ALWAYS.  Notice that
- * the global default is *not* used in this case.  (In effect the per-chunk
- * value is incremented to at least IF_SAFE.)
- *
- * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and
- * per-chunk defaults will be honored.  If you want to preserve the current
- * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE
- * as the default - if you don't do this libpng 1.6 will issue a warning.
- *
- * If you want unhandled unknown chunks to be discarded in libpng 1.6 and
- * earlier simply return '1' (handled).
- *
- * PNG_HANDLE_AS_UNKNOWN_SUPPORTED:
- *    If this is *not* set known chunks will always be handled by libpng and
- *    will never be stored in the unknown chunk list.  Known chunks listed to
- *    png_set_keep_unknown_chunks will have no effect.  If it is set then known
- *    chunks listed with a keep other than AS_DEFAULT will *never* be processed
- *    by libpng, in addition critical chunks must either be processed by the
- *    callback or saved.
- *
- *    The IHDR and IEND chunks must not be listed.  Because this turns off the
- *    default handling for chunks that would otherwise be recognized the
- *    behavior of libpng transformations may well become incorrect!
- *
- * WRITE:
- *    When writing chunks the options only apply to the chunks specified by
- *    png_set_unknown_chunks (below), libpng will *always* write known chunks
- *    required by png_set_ calls and will always write the core critical chunks
- *    (as required for PLTE).
- *
- *    Each chunk in the png_set_unknown_chunks list is looked up in the
- *    png_set_keep_unknown_chunks list to find the keep setting, this is then
- *    interpreted as follows:
- *
- *    PNG_HANDLE_CHUNK_AS_DEFAULT:
- *       Write safe-to-copy chunks and write other chunks if the global
- *       default is set to _ALWAYS, otherwise don't write this chunk.
- *    PNG_HANDLE_CHUNK_NEVER:
- *       Do not write the chunk.
- *    PNG_HANDLE_CHUNK_IF_SAFE:
- *       Write the chunk if it is safe-to-copy, otherwise do not write it.
- *    PNG_HANDLE_CHUNK_ALWAYS:
- *       Write the chunk.
- *
- * Note that the default behavior is effectively the opposite of the read case -
- * in read unknown chunks are not stored by default, in write they are written
- * by default.  Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different
- * - on write the safe-to-copy bit is checked, on read the critical bit is
- * checked and on read if the chunk is critical an error will be raised.
- *
- * num_chunks:
- * ===========
- *    If num_chunks is positive, then the "keep" parameter specifies the manner
- *    for handling only those chunks appearing in the chunk_list array,
- *    otherwise the chunk list array is ignored.
- *
- *    If num_chunks is 0 the "keep" parameter specifies the default behavior for
- *    unknown chunks, as described above.
- *
- *    If num_chunks is negative, then the "keep" parameter specifies the manner
- *    for handling all unknown chunks plus all chunks recognized by libpng
- *    except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to
- *    be processed by libpng.
- */
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr,
-    int keep, png_const_bytep chunk_list, int num_chunks));
-#endif /* HANDLE_AS_UNKNOWN */
-
-/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned;
- * the result is therefore true (non-zero) if special handling is required,
- * false for the default handling.
- */
-PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr,
-    png_const_bytep chunk_name));
-#endif /* SET_UNKNOWN_CHUNKS */
-
-#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_unknown_chunkp unknowns,
-    int num_unknowns));
-   /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added
-    * unknowns to the location currently stored in the png_struct.  This is
-    * invariably the wrong value on write.  To fix this call the following API
-    * for each chunk in the list with the correct location.  If you know your
-    * code won't be compiled on earlier versions you can rely on
-    * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing
-    * the correct thing.
-    */
-
-PNG_EXPORT(175, void, png_set_unknown_chunk_location,
-    (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location));
-
-PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr,
-    png_inforp info_ptr, png_unknown_chunkpp entries));
-#endif
-
-/* Png_free_data() will turn off the "valid" flag for anything it frees.
- * If you need to turn it off for a chunk that your application has freed,
- * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK);
- */
-PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int mask));
-
-#ifdef PNG_INFO_IMAGE_SUPPORTED
-/* The "params" pointer is currently not used and is for future expansion. */
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr,
-    int transforms, png_voidp params));
-#endif
-#ifdef PNG_WRITE_SUPPORTED
-PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr,
-    int transforms, png_voidp params));
-#endif
-#endif
-
-PNG_EXPORT(180, png_const_charp, png_get_copyright,
-    (png_const_structrp png_ptr));
-PNG_EXPORT(181, png_const_charp, png_get_header_ver,
-    (png_const_structrp png_ptr));
-PNG_EXPORT(182, png_const_charp, png_get_header_version,
-    (png_const_structrp png_ptr));
-PNG_EXPORT(183, png_const_charp, png_get_libpng_ver,
-    (png_const_structrp png_ptr));
-
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr,
-    png_uint_32 mng_features_permitted));
-#endif
-
-/* For use in png_set_keep_unknown, added to version 1.2.6 */
-#define PNG_HANDLE_CHUNK_AS_DEFAULT   0
-#define PNG_HANDLE_CHUNK_NEVER        1
-#define PNG_HANDLE_CHUNK_IF_SAFE      2
-#define PNG_HANDLE_CHUNK_ALWAYS       3
-#define PNG_HANDLE_CHUNK_LAST         4
-
-/* Strip the prepended error numbers ("#nnn ") from error and warning
- * messages before passing them to the error or warning handler.
- */
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr,
-    png_uint_32 strip_mode));
-#endif
-
-/* Added in libpng-1.2.6 */
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr,
-    png_uint_32 user_width_max, png_uint_32 user_height_max));
-PNG_EXPORT(187, png_uint_32, png_get_user_width_max,
-    (png_const_structrp png_ptr));
-PNG_EXPORT(188, png_uint_32, png_get_user_height_max,
-    (png_const_structrp png_ptr));
-/* Added in libpng-1.4.0 */
-PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr,
-    png_uint_32 user_chunk_cache_max));
-PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max,
-    (png_const_structrp png_ptr));
-/* Added in libpng-1.4.1 */
-PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr,
-    png_alloc_size_t user_chunk_cache_max));
-PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max,
-    (png_const_structrp png_ptr));
-#endif
-
-#if defined(PNG_INCH_CONVERSIONS_SUPPORTED)
-PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
-
-PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
-
-PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr));
-
-PNG_FP_EXPORT(196, float, png_get_x_offset_inches,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr))
-#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
-PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr))
-#endif
-
-PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr))
-#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
-PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed,
-    (png_const_structrp png_ptr, png_const_inforp info_ptr))
-#endif
-
-#  ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr,
-    png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
-    int *unit_type));
-#  endif /* pHYs */
-#endif  /* INCH_CONVERSIONS */
-
-/* Added in libpng-1.4.0 */
-#ifdef PNG_IO_STATE_SUPPORTED
-PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr));
-
-/* Removed from libpng 1.6; use png_get_io_chunk_type. */
-PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr),
-    PNG_DEPRECATED)
-
-PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
-    (png_const_structrp png_ptr));
-
-/* The flags returned by png_get_io_state() are the following: */
-#  define PNG_IO_NONE        0x0000   /* no I/O at this moment */
-#  define PNG_IO_READING     0x0001   /* currently reading */
-#  define PNG_IO_WRITING     0x0002   /* currently writing */
-#  define PNG_IO_SIGNATURE   0x0010   /* currently at the file signature */
-#  define PNG_IO_CHUNK_HDR   0x0020   /* currently at the chunk header */
-#  define PNG_IO_CHUNK_DATA  0x0040   /* currently at the chunk data */
-#  define PNG_IO_CHUNK_CRC   0x0080   /* currently at the chunk crc */
-#  define PNG_IO_MASK_OP     0x000f   /* current operation: reading/writing */
-#  define PNG_IO_MASK_LOC    0x00f0   /* current location: sig/hdr/data/crc */
-#endif /* IO_STATE */
-
-/* Interlace support.  The following macros are always defined so that if
- * libpng interlace handling is turned off the macros may be used to handle
- * interlaced images within the application.
- */
-#define PNG_INTERLACE_ADAM7_PASSES 7
-
-/* Two macros to return the first row and first column of the original,
- * full, image which appears in a given pass.  'pass' is in the range 0
- * to 6 and the result is in the range 0 to 7.
- */
-#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7)
-#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7)
-
-/* A macro to return the offset between pixels in the output row for a pair of
- * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that
- * follows.  Note that ROW_OFFSET is the offset from one row to the next whereas
- * COL_OFFSET is from one column to the next, within a row.
- */
-#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8)
-#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1))
-
-/* Two macros to help evaluate the number of rows or columns in each
- * pass.  This is expressed as a shift - effectively log2 of the number or
- * rows or columns in each 8x8 tile of the original image.
- */
-#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3)
-#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3)
-
-/* Hence two macros to determine the number of rows or columns in a given
- * pass of an image given its height or width.  In fact these macros may
- * return non-zero even though the sub-image is empty, because the other
- * dimension may be empty for a small image.
- */
-#define PNG_PASS_ROWS(height, pass) (((height)+(((1<<PNG_PASS_ROW_SHIFT(pass))\
-   -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass))
-#define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\
-   -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass))
-
-/* For the reader row callbacks (both progressive and sequential) it is
- * necessary to find the row in the output image given a row in an interlaced
- * image, so two more macros:
- */
-#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \
-   (((y_in)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
-#define PNG_COL_FROM_PASS_COL(x_in, pass) \
-   (((x_in)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
-
-/* Two macros which return a boolean (0 or 1) saying whether the given row
- * or column is in a particular pass.  These use a common utility macro that
- * returns a mask for a given pass - the offset 'off' selects the row or
- * column version.  The mask has the appropriate bit set for each column in
- * the tile.
- */
-#define PNG_PASS_MASK(pass,off) ( \
-   ((0x110145AF>>(((7-(off))-(pass))<<2)) & 0xF) | \
-   ((0x01145AF0>>(((7-(off))-(pass))<<2)) & 0xF0))
-
-#define PNG_ROW_IN_INTERLACE_PASS(y, pass) \
-   ((PNG_PASS_MASK(pass,0) >> ((y)&7)) & 1)
-#define PNG_COL_IN_INTERLACE_PASS(x, pass) \
-   ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1)
-
-#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
-/* With these routines we avoid an integer divide, which will be slower on
- * most machines.  However, it does take more operations than the corresponding
- * divide method, so it may be slower on a few RISC systems.  There are two
- * shifts (by 8 or 16 bits) and an addition, versus a single integer divide.
- *
- * Note that the rounding factors are NOT supposed to be the same!  128 and
- * 32768 are correct for the NODIV code; 127 and 32767 are correct for the
- * standard method.
- *
- * [Optimized code by Greg Roelofs and Mark Adler...blame us for bugs. :-) ]
- */
-
- /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */
-
-#  define png_composite(composite, fg, alpha, bg)        \
-   {                                                     \
-      png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \
-          * (png_uint_16)(alpha)                         \
-          + (png_uint_16)(bg)*(png_uint_16)(255          \
-          - (png_uint_16)(alpha)) + 128);                \
-      (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \
-   }
-
-#  define png_composite_16(composite, fg, alpha, bg)     \
-   {                                                     \
-      png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \
-          * (png_uint_32)(alpha)                         \
-          + (png_uint_32)(bg)*(65535                     \
-          - (png_uint_32)(alpha)) + 32768);              \
-      (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \
-   }
-
-#else  /* Standard method using integer division */
-
-#  define png_composite(composite, fg, alpha, bg)                      \
-   (composite) =                                                       \
-       (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) +  \
-       (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
-       127) / 255))
-
-#  define png_composite_16(composite, fg, alpha, bg)                       \
-   (composite) =                                                           \
-       (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \
-       (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) +     \
-       32767) / 65535))
-#endif /* READ_COMPOSITE_NODIV */
-
-#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
-PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf));
-PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf));
-PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf));
-#endif
-
-PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr,
-    png_const_bytep buf));
-/* No png_get_int_16 -- may be added if there's a real need for it. */
-
-/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */
-#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
-PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i));
-#endif
-#ifdef PNG_SAVE_INT_32_SUPPORTED
-PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i));
-#endif
-
-/* Place a 16-bit number into a buffer in PNG byte order.
- * The parameter is declared unsigned int, not png_uint_16,
- * just to avoid potential problems on pre-ANSI C compilers.
- */
-#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
-PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
-/* No png_save_int_16 -- may be added if there's a real need for it. */
-#endif
-
-#ifdef PNG_USE_READ_MACROS
-/* Inline macros to do direct reads of bytes from the input buffer.
- * The png_get_int_32() routine assumes we are using two's complement
- * format for negative values, which is almost certainly true.
- */
-#  define PNG_get_uint_32(buf) \
-   (((png_uint_32)(*(buf)) << 24) + \
-    ((png_uint_32)(*((buf) + 1)) << 16) + \
-    ((png_uint_32)(*((buf) + 2)) << 8) + \
-    ((png_uint_32)(*((buf) + 3))))
-
-   /* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the
-    * function) incorrectly returned a value of type png_uint_32.
-    */
-#  define PNG_get_uint_16(buf) \
-   ((png_uint_16) \
-    (((unsigned int)(*(buf)) << 8) + \
-    ((unsigned int)(*((buf) + 1)))))
-
-#  define PNG_get_int_32(buf) \
-   ((png_int_32)((*(buf) & 0x80) \
-    ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \
-    : (png_int_32)png_get_uint_32(buf)))
-
-/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h,
- * but defining a macro name prefixed with PNG_PREFIX.
- */
-#  ifndef PNG_PREFIX
-#    define png_get_uint_32(buf) PNG_get_uint_32(buf)
-#    define png_get_uint_16(buf) PNG_get_uint_16(buf)
-#    define png_get_int_32(buf)  PNG_get_int_32(buf)
-#  endif
-#else
-#  ifdef PNG_PREFIX
-   /* No macros; revert to the (redefined) function */
-#    define PNG_get_uint_32 (png_get_uint_32)
-#    define PNG_get_uint_16 (png_get_uint_16)
-#    define PNG_get_int_32  (png_get_int_32)
-#  endif
-#endif
-
-#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
-PNG_EXPORT(242, void, png_set_check_for_invalid_index,
-    (png_structrp png_ptr, int allowed));
-#  ifdef PNG_GET_PALETTE_MAX_SUPPORTED
-PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr,
-    png_const_infop info_ptr));
-#  endif
-#endif /* CHECK_FOR_INVALID_INDEX */
-
-/*******************************************************************************
- * Section 5: SIMPLIFIED API
- *******************************************************************************
- *
- * Please read the documentation in libpng-manual.txt (TODO: write said
- * documentation) if you don't understand what follows.
- *
- * The simplified API hides the details of both libpng and the PNG file format
- * itself.  It allows PNG files to be read into a very limited number of
- * in-memory bitmap formats or to be written from the same formats.  If these
- * formats do not accommodate your needs then you can, and should, use the more
- * sophisticated APIs above - these support a wide variety of in-memory formats
- * and a wide variety of sophisticated transformations to those formats as well
- * as a wide variety of APIs to manipulate ancillary information.
- *
- * To read a PNG file using the simplified API:
- *
- * 1) Declare a 'png_image' structure (see below) on the stack, set the
- *    version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL
- *    (this is REQUIRED, your program may crash if you don't do it.)
- * 2) Call the appropriate png_image_begin_read... function.
- * 3) Set the png_image 'format' member to the required sample format.
- * 4) Allocate a buffer for the image and, if required, the color-map.
- * 5) Call png_image_finish_read to read the image and, if required, the
- *    color-map into your buffers.
- *
- * There are no restrictions on the format of the PNG input itself; all valid
- * color types, bit depths, and interlace methods are acceptable, and the
- * input image is transformed as necessary to the requested in-memory format
- * during the png_image_finish_read() step.  The only caveat is that if you
- * request a color-mapped image from a PNG that is full-color or makes
- * complex use of an alpha channel the transformation is extremely lossy and the
- * result may look terrible.
- *
- * To write a PNG file using the simplified API:
- *
- * 1) Declare a 'png_image' structure on the stack and memset() it to all zero.
- * 2) Initialize the members of the structure that describe the image, setting
- *    the 'format' member to the format of the image samples.
- * 3) Call the appropriate png_image_write... function with a pointer to the
- *    image and, if necessary, the color-map to write the PNG data.
- *
- * png_image is a structure that describes the in-memory format of an image
- * when it is being read or defines the in-memory format of an image that you
- * need to write:
- */
-#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \
-    defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
-
-#define PNG_IMAGE_VERSION 1
-
-typedef struct png_control *png_controlp;
-typedef struct
-{
-   png_controlp opaque;    /* Initialize to NULL, free with png_image_free */
-   png_uint_32  version;   /* Set to PNG_IMAGE_VERSION */
-   png_uint_32  width;     /* Image width in pixels (columns) */
-   png_uint_32  height;    /* Image height in pixels (rows) */
-   png_uint_32  format;    /* Image format as defined below */
-   png_uint_32  flags;     /* A bit mask containing informational flags */
-   png_uint_32  colormap_entries;
-                           /* Number of entries in the color-map */
-
-   /* In the event of an error or warning the following field will be set to a
-    * non-zero value and the 'message' field will contain a '\0' terminated
-    * string with the libpng error or warning message.  If both warnings and
-    * an error were encountered, only the error is recorded.  If there
-    * are multiple warnings, only the first one is recorded.
-    *
-    * The upper 30 bits of this value are reserved, the low two bits contain
-    * a value as follows:
-    */
-#  define PNG_IMAGE_WARNING 1
-#  define PNG_IMAGE_ERROR 2
-   /*
-    * The result is a two-bit code such that a value more than 1 indicates
-    * a failure in the API just called:
-    *
-    *    0 - no warning or error
-    *    1 - warning
-    *    2 - error
-    *    3 - error preceded by warning
-    */
-#  define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1)
-
-   png_uint_32  warning_or_error;
-
-   char         message[64];
-} png_image, *png_imagep;
-
-/* The samples of the image have one to four channels whose components have
- * original values in the range 0 to 1.0:
- *
- * 1: A single gray or luminance channel (G).
- * 2: A gray/luminance channel and an alpha channel (GA).
- * 3: Three red, green, blue color channels (RGB).
- * 4: Three color channels and an alpha channel (RGBA).
- *
- * The components are encoded in one of two ways:
- *
- * a) As a small integer, value 0..255, contained in a single byte.  For the
- * alpha channel the original value is simply value/255.  For the color or
- * luminance channels the value is encoded according to the sRGB specification
- * and matches the 8-bit format expected by typical display devices.
- *
- * The color/gray channels are not scaled (pre-multiplied) by the alpha
- * channel and are suitable for passing to color management software.
- *
- * b) As a value in the range 0..65535, contained in a 2-byte integer.  All
- * channels can be converted to the original value by dividing by 65535; all
- * channels are linear.  Color channels use the RGB encoding (RGB end-points) of
- * the sRGB specification.  This encoding is identified by the
- * PNG_FORMAT_FLAG_LINEAR flag below.
- *
- * When the simplified API needs to convert between sRGB and linear colorspaces,
- * the actual sRGB transfer curve defined in the sRGB specification (see the
- * article at <https://en.wikipedia.org/wiki/SRGB>) is used, not the gamma=1/2.2
- * approximation used elsewhere in libpng.
- *
- * When an alpha channel is present it is expected to denote pixel coverage
- * of the color or luminance channels and is returned as an associated alpha
- * channel: the color/gray channels are scaled (pre-multiplied) by the alpha
- * value.
- *
- * The samples are either contained directly in the image data, between 1 and 8
- * bytes per pixel according to the encoding, or are held in a color-map indexed
- * by bytes in the image data.  In the case of a color-map the color-map entries
- * are individual samples, encoded as above, and the image data has one byte per
- * pixel to select the relevant sample from the color-map.
- */
-
-/* PNG_FORMAT_*
- *
- * #defines to be used in png_image::format.  Each #define identifies a
- * particular layout of sample data and, if present, alpha values.  There are
- * separate defines for each of the two component encodings.
- *
- * A format is built up using single bit flag values.  All combinations are
- * valid.  Formats can be built up from the flag values or you can use one of
- * the predefined values below.  When testing formats always use the FORMAT_FLAG
- * macros to test for individual features - future versions of the library may
- * add new flags.
- *
- * When reading or writing color-mapped images the format should be set to the
- * format of the entries in the color-map then png_image_{read,write}_colormap
- * called to read or write the color-map and set the format correctly for the
- * image data.  Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly!
- *
- * NOTE: libpng can be built with particular features disabled. If you see
- * compiler errors because the definition of one of the following flags has been
- * compiled out it is because libpng does not have the required support.  It is
- * possible, however, for the libpng configuration to enable the format on just
- * read or just write; in that case you may see an error at run time.  You can
- * guard against this by checking for the definition of the appropriate
- * "_SUPPORTED" macro, one of:
- *
- *    PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED
- */
-#define PNG_FORMAT_FLAG_ALPHA    0x01U /* format with an alpha channel */
-#define PNG_FORMAT_FLAG_COLOR    0x02U /* color format: otherwise grayscale */
-#define PNG_FORMAT_FLAG_LINEAR   0x04U /* 2-byte channels else 1-byte */
-#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */
-
-#ifdef PNG_FORMAT_BGR_SUPPORTED
-#  define PNG_FORMAT_FLAG_BGR    0x10U /* BGR colors, else order is RGB */
-#endif
-
-#ifdef PNG_FORMAT_AFIRST_SUPPORTED
-#  define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */
-#endif
-
-#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */
-
-/* Commonly used formats have predefined macros.
- *
- * First the single byte (sRGB) formats:
- */
-#define PNG_FORMAT_GRAY 0
-#define PNG_FORMAT_GA   PNG_FORMAT_FLAG_ALPHA
-#define PNG_FORMAT_AG   (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST)
-#define PNG_FORMAT_RGB  PNG_FORMAT_FLAG_COLOR
-#define PNG_FORMAT_BGR  (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR)
-#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA)
-#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST)
-#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA)
-#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST)
-
-/* Then the linear 2-byte formats.  When naming these "Y" is used to
- * indicate a luminance (gray) channel.
- */
-#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR
-#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA)
-#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR)
-#define PNG_FORMAT_LINEAR_RGB_ALPHA \
-   (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA)
-
-/* With color-mapped formats the image data is one byte for each pixel, the byte
- * is an index into the color-map which is formatted as above.  To obtain a
- * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP
- * to one of the above definitions, or you can use one of the definitions below.
- */
-#define PNG_FORMAT_RGB_COLORMAP  (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP)
-#define PNG_FORMAT_BGR_COLORMAP  (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP)
-#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP)
-#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP)
-#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP)
-#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP)
-
-/* PNG_IMAGE macros
- *
- * These are convenience macros to derive information from a png_image
- * structure.  The PNG_IMAGE_SAMPLE_ macros return values appropriate to the
- * actual image sample values - either the entries in the color-map or the
- * pixels in the image.  The PNG_IMAGE_PIXEL_ macros return corresponding values
- * for the pixels and will always return 1 for color-mapped formats.  The
- * remaining macros return information about the rows in the image and the
- * complete image.
- *
- * NOTE: All the macros that take a png_image::format parameter are compile time
- * constants if the format parameter is, itself, a constant.  Therefore these
- * macros can be used in array declarations and case labels where required.
- * Similarly the macros are also pre-processor constants (sizeof is not used) so
- * they can be used in #if tests.
- *
- * First the information about the samples.
- */
-#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\
-   (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1)
-   /* Return the total number of channels in a given format: 1..4 */
-
-#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\
-   ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1)
-   /* Return the size in bytes of a single component of a pixel or color-map
-    * entry (as appropriate) in the image: 1 or 2.
-    */
-
-#define PNG_IMAGE_SAMPLE_SIZE(fmt)\
-   (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt))
-   /* This is the size of the sample data for one sample.  If the image is
-    * color-mapped it is the size of one color-map entry (and image pixels are
-    * one byte in size), otherwise it is the size of one image pixel.
-    */
-
-#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\
-   (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256)
-   /* The maximum size of the color-map required by the format expressed in a
-    * count of components.  This can be used to compile-time allocate a
-    * color-map:
-    *
-    * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)];
-    *
-    * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)];
-    *
-    * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the
-    * information from one of the png_image_begin_read_ APIs and dynamically
-    * allocate the required memory.
-    */
-
-/* Corresponding information about the pixels */
-#define PNG_IMAGE_PIXEL_(test,fmt)\
-   (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt))
-
-#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\
-   PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt)
-   /* The number of separate channels (components) in a pixel; 1 for a
-    * color-mapped image.
-    */
-
-#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\
-   PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt)
-   /* The size, in bytes, of each component in a pixel; 1 for a color-mapped
-    * image.
-    */
-
-#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt)
-   /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */
-
-/* Information about the whole row, or whole image */
-#define PNG_IMAGE_ROW_STRIDE(image)\
-   (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width)
-   /* Return the total number of components in a single row of the image; this
-    * is the minimum 'row stride', the minimum count of components between each
-    * row.  For a color-mapped image this is the minimum number of bytes in a
-    * row.
-    *
-    * WARNING: this macro overflows for some images with more than one component
-    * and very large image widths.  libpng will refuse to process an image where
-    * this macro would overflow.
-    */
-
-#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
-   (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
-   /* Return the size, in bytes, of an image buffer given a png_image and a row
-    * stride - the number of components to leave space for in each row.
-    *
-    * WARNING: this macro overflows a 32-bit integer for some large PNG images,
-    * libpng will refuse to process an image where such an overflow would occur.
-    */
-
-#define PNG_IMAGE_SIZE(image)\
-   PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image))
-   /* Return the size, in bytes, of the image in memory given just a png_image;
-    * the row stride is the minimum stride required for the image.
-    */
-
-#define PNG_IMAGE_COLORMAP_SIZE(image)\
-   (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries)
-   /* Return the size, in bytes, of the color-map of this image.  If the image
-    * format is not a color-map format this will return a size sufficient for
-    * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if
-    * you don't want to allocate a color-map in this case.
-    */
-
-/* PNG_IMAGE_FLAG_*
- *
- * Flags containing additional information about the image are held in the
- * 'flags' field of png_image.
- */
-#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01
-   /* This indicates that the RGB values of the in-memory bitmap do not
-    * correspond to the red, green and blue end-points defined by sRGB.
-    */
-
-#define PNG_IMAGE_FLAG_FAST 0x02
-   /* On write emphasise speed over compression; the resultant PNG file will be
-    * larger but will be produced significantly faster, particular for large
-    * images.  Do not use this option for images which will be distributed, only
-    * used it when producing intermediate files that will be read back in
-    * repeatedly.  For a typical 24-bit image the option will double the read
-    * speed at the cost of increasing the image size by 25%, however for many
-    * more compressible images the PNG file can be 10 times larger with only a
-    * slight speed gain.
-    */
-
-#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04
-   /* On read if the image is a 16-bit per component image and there is no gAMA
-    * or sRGB chunk assume that the components are sRGB encoded.  Notice that
-    * images output by the simplified API always have gamma information; setting
-    * this flag only affects the interpretation of 16-bit images from an
-    * external source.  It is recommended that the application expose this flag
-    * to the user; the user can normally easily recognize the difference between
-    * linear and sRGB encoding.  This flag has no effect on write - the data
-    * passed to the write APIs must have the correct encoding (as defined
-    * above.)
-    *
-    * If the flag is not set (the default) input 16-bit per component data is
-    * assumed to be linear.
-    *
-    * NOTE: the flag can only be set after the png_image_begin_read_ call,
-    * because that call initializes the 'flags' field.
-    */
-
-#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
-/* READ APIs
- * ---------
- *
- * The png_image passed to the read APIs must have been initialized by setting
- * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.)
- */
-#ifdef PNG_STDIO_SUPPORTED
-PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image,
-   const char *file_name));
-   /* The named file is opened for read and the image header is filled in
-    * from the PNG header in the file.
-    */
-
-PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image,
-   FILE* file));
-   /* The PNG header is read from the stdio FILE object. */
-#endif /* STDIO */
-
-PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image,
-   png_const_voidp memory, size_t size));
-   /* The PNG header is read from the given memory buffer. */
-
-PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
-   png_const_colorp background, void *buffer, png_int_32 row_stride,
-   void *colormap));
-   /* Finish reading the image into the supplied buffer and clean up the
-    * png_image structure.
-    *
-    * row_stride is the step, in byte or 2-byte units as appropriate,
-    * between adjacent rows.  A positive stride indicates that the top-most row
-    * is first in the buffer - the normal top-down arrangement.  A negative
-    * stride indicates that the bottom-most row is first in the buffer.
-    *
-    * background need only be supplied if an alpha channel must be removed from
-    * a png_byte format and the removal is to be done by compositing on a solid
-    * color; otherwise it may be NULL and any composition will be done directly
-    * onto the buffer.  The value is an sRGB color to use for the background,
-    * for grayscale output the green channel is used.
-    *
-    * background must be supplied when an alpha channel must be removed from a
-    * single byte color-mapped output format, in other words if:
-    *
-    * 1) The original format from png_image_begin_read_from_* had
-    *    PNG_FORMAT_FLAG_ALPHA set.
-    * 2) The format set by the application does not.
-    * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and
-    *    PNG_FORMAT_FLAG_LINEAR *not* set.
-    *
-    * For linear output removing the alpha channel is always done by compositing
-    * on black and background is ignored.
-    *
-    * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set.  It must
-    * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE.
-    * image->colormap_entries will be updated to the actual number of entries
-    * written to the colormap; this may be less than the original value.
-    */
-
-PNG_EXPORT(238, void, png_image_free, (png_imagep image));
-   /* Free any data allocated by libpng in image->opaque, setting the pointer to
-    * NULL.  May be called at any time after the structure is initialized.
-    */
-#endif /* SIMPLIFIED_READ */
-
-#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
-/* WRITE APIS
- * ----------
- * For write you must initialize a png_image structure to describe the image to
- * be written.  To do this use memset to set the whole structure to 0 then
- * initialize fields describing your image.
- *
- * version: must be set to PNG_IMAGE_VERSION
- * opaque: must be initialized to NULL
- * width: image width in pixels
- * height: image height in rows
- * format: the format of the data (image and color-map) you wish to write
- * flags: set to 0 unless one of the defined flags applies; set
- *    PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB
- *    values do not correspond to the colors in sRGB.
- * colormap_entries: set to the number of entries in the color-map (0 to 256)
- */
-#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
-PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
-   const char *file, int convert_to_8bit, const void *buffer,
-   png_int_32 row_stride, const void *colormap));
-   /* Write the image to the named file. */
-
-PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
-   int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
-   const void *colormap));
-   /* Write the image to the given (FILE*). */
-#endif /* SIMPLIFIED_WRITE_STDIO */
-
-/* With all write APIs if image is in one of the linear formats with 16-bit
- * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
- * gamma encoded according to the sRGB specification, otherwise a 16-bit linear
- * encoded PNG file is written.
- *
- * With color-mapped data formats the colormap parameter point to a color-map
- * with at least image->colormap_entries encoded in the specified format.  If
- * the format is linear the written PNG color-map will be converted to sRGB
- * regardless of the convert_to_8_bit flag.
- *
- * With all APIs row_stride is handled as in the read APIs - it is the spacing
- * from one row to the next in component sized units (1 or 2 bytes) and if
- * negative indicates a bottom-up row layout in the buffer.  If row_stride is
- * zero, libpng will calculate it for you from the image width and number of
- * channels.
- *
- * Note that the write API does not support interlacing, sub-8-bit pixels or
- * most ancillary chunks.  If you need to write text chunks (e.g. for copyright
- * notices) you need to use one of the other APIs.
- */
-
-PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
-   png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit,
-   const void *buffer, png_int_32 row_stride, const void *colormap));
-   /* Write the image to the given memory buffer.  The function both writes the
-    * whole PNG data stream to *memory and updates *memory_bytes with the count
-    * of bytes written.
-    *
-    * 'memory' may be NULL.  In this case *memory_bytes is not read however on
-    * success the number of bytes which would have been written will still be
-    * stored in *memory_bytes.  On failure *memory_bytes will contain 0.
-    *
-    * If 'memory' is not NULL it must point to memory[*memory_bytes] of
-    * writeable memory.
-    *
-    * If the function returns success memory[*memory_bytes] (if 'memory' is not
-    * NULL) contains the written PNG data.  *memory_bytes will always be less
-    * than or equal to the original value.
-    *
-    * If the function returns false and *memory_bytes was not changed an error
-    * occurred during write.  If *memory_bytes was changed, or is not 0 if
-    * 'memory' was NULL, the write would have succeeded but for the memory
-    * buffer being too small.  *memory_bytes contains the required number of
-    * bytes and will be bigger that the original value.
-    */
-
-#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\
-   row_stride, colormap)\
-   png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\
-         row_stride, colormap)
-   /* Return the amount of memory in 'size' required to compress this image.
-    * The png_image structure 'image' must be filled in as in the above
-    * function and must not be changed before the actual write call, the buffer
-    * and all other parameters must also be identical to that in the final
-    * write call.  The 'size' variable need not be initialized.
-    *
-    * NOTE: the macro returns true/false, if false is returned 'size' will be
-    * set to zero and the write failed and probably will fail if tried again.
-    */
-
-/* You can pre-allocate the buffer by making sure it is of sufficient size
- * regardless of the amount of compression achieved.  The buffer size will
- * always be bigger than the original image and it will never be filled.  The
- * following macros are provided to assist in allocating the buffer.
- */
-#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height)
-   /* The number of uncompressed bytes in the PNG byte encoding of the image;
-    * uncompressing the PNG IDAT data will give this number of bytes.
-    *
-    * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this
-    * macro can because of the extra bytes used in the PNG byte encoding.  You
-    * need to avoid this macro if your image size approaches 2^30 in width or
-    * height.  The same goes for the remainder of these macros; they all produce
-    * bigger numbers than the actual in-memory image size.
-    */
-#ifndef PNG_ZLIB_MAX_SIZE
-#  define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U)
-   /* An upper bound on the number of compressed bytes given 'b' uncompressed
-    * bytes.  This is based on deflateBounds() in zlib; different
-    * implementations of zlib compression may conceivably produce more data so
-    * if your zlib implementation is not zlib itself redefine this macro
-    * appropriately.
-    */
-#endif
-
-#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\
-   PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image))
-   /* An upper bound on the size of the data in the PNG IDAT chunks. */
-
-#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\
-   ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\
-    (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\
-    12U+3U*(image).colormap_entries/*PLTE data*/+\
-    (((image).format&PNG_FORMAT_FLAG_ALPHA)?\
-    12U/*tRNS*/+(image).colormap_entries:0U):0U)+\
-    12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size))
-   /* A helper for the following macro; if your compiler cannot handle the
-    * following macro use this one with the result of
-    * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most
-    * compilers should handle this just fine.)
-    */
-
-#define PNG_IMAGE_PNG_SIZE_MAX(image)\
-   PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image))
-   /* An upper bound on the total length of the PNG data stream for 'image'.
-    * The result is of type png_alloc_size_t, on 32-bit systems this may
-    * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will
-    * run out of buffer space but return a corrected size which should work.
-    */
-#endif /* SIMPLIFIED_WRITE */
-/*******************************************************************************
- *  END OF SIMPLIFIED API
- ******************************************************************************/
-#endif /* SIMPLIFIED_{READ|WRITE} */
-
-/*******************************************************************************
- * Section 6: IMPLEMENTATION OPTIONS
- *******************************************************************************
- *
- * Support for arbitrary implementation-specific optimizations.  The API allows
- * particular options to be turned on or off.  'Option' is the number of the
- * option and 'onoff' is 0 (off) or non-0 (on).  The value returned is given
- * by the PNG_OPTION_ defines below.
- *
- * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions,
- *           are detected at run time, however sometimes it may be impossible
- *           to do this in user mode, in which case it is necessary to discover
- *           the capabilities in an OS specific way.  Such capabilities are
- *           listed here when libpng has support for them and must be turned
- *           ON by the application if present.
- *
- * SOFTWARE: sometimes software optimizations actually result in performance
- *           decrease on some architectures or systems, or with some sets of
- *           PNG images.  'Software' options allow such optimizations to be
- *           selected at run time.
- */
-#ifdef PNG_SET_OPTION_SUPPORTED
-#ifdef PNG_ARM_NEON_API_SUPPORTED
-#  define PNG_ARM_NEON   0 /* HARDWARE: ARM Neon SIMD instructions supported */
-#endif
-#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */
-#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */
-#ifdef PNG_MIPS_MSA_API_SUPPORTED
-#  define PNG_MIPS_MSA   6 /* HARDWARE: MIPS Msa SIMD instructions supported */
-#endif
-#define PNG_IGNORE_ADLER32 8
-#ifdef PNG_POWERPC_VSX_API_SUPPORTED
-#  define PNG_POWERPC_VSX   10 /* HARDWARE: PowerPC VSX SIMD instructions supported */
-#endif
-#define PNG_OPTION_NEXT  12 /* Next option - numbers must be even */
-
-/* Return values: NOTE: there are four values and 'off' is *not* zero */
-#define PNG_OPTION_UNSET   0 /* Unset - defaults to off */
-#define PNG_OPTION_INVALID 1 /* Option number out of range */
-#define PNG_OPTION_OFF     2
-#define PNG_OPTION_ON      3
-
-PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
-   int onoff));
-#endif /* SET_OPTION */
-
-/*******************************************************************************
- *  END OF HARDWARE AND SOFTWARE OPTIONS
- ******************************************************************************/
-
-/* Maintainer: Put new public prototypes here ^, in libpng.3, in project
- * defs, and in scripts/symbols.def.
- */
-
-/* The last ordinal number (this is the *last* one already used; the next
- * one to use is one more than this.)
- */
-#ifdef PNG_EXPORT_LAST_ORDINAL
-  PNG_EXPORT_LAST_ORDINAL(249);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* PNG_VERSION_INFO_ONLY */
-/* Do not put anything past this line */
-#endif /* PNG_H */
diff --git a/third_party/libpng16/pngconf.h b/third_party/libpng16/pngconf.h
deleted file mode 100644
index 927a769..0000000
--- a/third_party/libpng16/pngconf.h
+++ /dev/null
@@ -1,623 +0,0 @@
-
-/* pngconf.h - machine-configurable file for libpng
- *
- * libpng version 1.6.37
- *
- * Copyright (c) 2018-2019 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- *
- * Any machine specific code is near the front of this file, so if you
- * are configuring libpng for a machine, you may want to read the section
- * starting here down to where it starts to typedef png_color, png_text,
- * and png_info.
- */
-
-#ifndef PNGCONF_H
-#define PNGCONF_H
-
-#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */
-
-/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C
- * compiler for correct compilation.  The following header files are required by
- * the standard.  If your compiler doesn't provide these header files, or they
- * do not match the standard, you will need to provide/improve them.
- */
-#include <limits.h>
-#include <stddef.h>
-
-/* Library header files.  These header files are all defined by ISOC90; libpng
- * expects conformant implementations, however, an ISOC90 conformant system need
- * not provide these header files if the functionality cannot be implemented.
- * In this case it will be necessary to disable the relevant parts of libpng in
- * the build of pnglibconf.h.
- *
- * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not
- * include this unnecessary header file.
- */
-
-#ifdef PNG_STDIO_SUPPORTED
-   /* Required for the definition of FILE: */
-#  include <stdio.h>
-#endif
-
-#ifdef PNG_SETJMP_SUPPORTED
-   /* Required for the definition of jmp_buf and the declaration of longjmp: */
-#  include <setjmp.h>
-#endif
-
-#ifdef PNG_CONVERT_tIME_SUPPORTED
-   /* Required for struct tm: */
-#  include <time.h>
-#endif
-
-#endif /* PNG_BUILDING_SYMBOL_TABLE */
-
-/* Prior to 1.6.0, it was possible to turn off 'const' in declarations,
- * using PNG_NO_CONST.  This is no longer supported.
- */
-#define PNG_CONST const /* backward compatibility only */
-
-/* This controls optimization of the reading of 16-bit and 32-bit
- * values from PNG files.  It can be set on a per-app-file basis: it
- * just changes whether a macro is used when the function is called.
- * The library builder sets the default; if read functions are not
- * built into the library the macro implementation is forced on.
- */
-#ifndef PNG_READ_INT_FUNCTIONS_SUPPORTED
-#  define PNG_USE_READ_MACROS
-#endif
-#if !defined(PNG_NO_USE_READ_MACROS) && !defined(PNG_USE_READ_MACROS)
-#  if PNG_DEFAULT_READ_MACROS
-#    define PNG_USE_READ_MACROS
-#  endif
-#endif
-
-/* COMPILER SPECIFIC OPTIONS.
- *
- * These options are provided so that a variety of difficult compilers
- * can be used.  Some are fixed at build time (e.g. PNG_API_RULE
- * below) but still have compiler specific implementations, others
- * may be changed on a per-file basis when compiling against libpng.
- */
-
-/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect
- * against legacy (pre ISOC90) compilers that did not understand function
- * prototypes.  It is not required for modern C compilers.
- */
-#ifndef PNGARG
-#  define PNGARG(arglist) arglist
-#endif
-
-/* Function calling conventions.
- * =============================
- * Normally it is not necessary to specify to the compiler how to call
- * a function - it just does it - however on x86 systems derived from
- * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems
- * and some others) there are multiple ways to call a function and the
- * default can be changed on the compiler command line.  For this reason
- * libpng specifies the calling convention of every exported function and
- * every function called via a user supplied function pointer.  This is
- * done in this file by defining the following macros:
- *
- * PNGAPI    Calling convention for exported functions.
- * PNGCBAPI  Calling convention for user provided (callback) functions.
- * PNGCAPI   Calling convention used by the ANSI-C library (required
- *           for longjmp callbacks and sometimes used internally to
- *           specify the calling convention for zlib).
- *
- * These macros should never be overridden.  If it is necessary to
- * change calling convention in a private build this can be done
- * by setting PNG_API_RULE (which defaults to 0) to one of the values
- * below to select the correct 'API' variants.
- *
- * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout.
- *                This is correct in every known environment.
- * PNG_API_RULE=1 Use the operating system convention for PNGAPI and
- *                the 'C' calling convention (from PNGCAPI) for
- *                callbacks (PNGCBAPI).  This is no longer required
- *                in any known environment - if it has to be used
- *                please post an explanation of the problem to the
- *                libpng mailing list.
- *
- * These cases only differ if the operating system does not use the C
- * calling convention, at present this just means the above cases
- * (x86 DOS/Windows systems) and, even then, this does not apply to
- * Cygwin running on those systems.
- *
- * Note that the value must be defined in pnglibconf.h so that what
- * the application uses to call the library matches the conventions
- * set when building the library.
- */
-
-/* Symbol export
- * =============
- * When building a shared library it is almost always necessary to tell
- * the compiler which symbols to export.  The png.h macro 'PNG_EXPORT'
- * is used to mark the symbols.  On some systems these symbols can be
- * extracted at link time and need no special processing by the compiler,
- * on other systems the symbols are flagged by the compiler and just
- * the declaration requires a special tag applied (unfortunately) in a
- * compiler dependent way.  Some systems can do either.
- *
- * A small number of older systems also require a symbol from a DLL to
- * be flagged to the program that calls it.  This is a problem because
- * we do not know in the header file included by application code that
- * the symbol will come from a shared library, as opposed to a statically
- * linked one.  For this reason the application must tell us by setting
- * the magic flag PNG_USE_DLL to turn on the special processing before
- * it includes png.h.
- *
- * Four additional macros are used to make this happen:
- *
- * PNG_IMPEXP The magic (if any) to cause a symbol to be exported from
- *            the build or imported if PNG_USE_DLL is set - compiler
- *            and system specific.
- *
- * PNG_EXPORT_TYPE(type) A macro that pre or appends PNG_IMPEXP to
- *                       'type', compiler specific.
- *
- * PNG_DLL_EXPORT Set to the magic to use during a libpng build to
- *                make a symbol exported from the DLL.  Not used in the
- *                public header files; see pngpriv.h for how it is used
- *                in the libpng build.
- *
- * PNG_DLL_IMPORT Set to the magic to force the libpng symbols to come
- *                from a DLL - used to define PNG_IMPEXP when
- *                PNG_USE_DLL is set.
- */
-
-/* System specific discovery.
- * ==========================
- * This code is used at build time to find PNG_IMPEXP, the API settings
- * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL
- * import processing is possible.  On Windows systems it also sets
- * compiler-specific macros to the values required to change the calling
- * conventions of the various functions.
- */
-#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
-    defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
-  /* Windows system (DOS doesn't support DLLs).  Includes builds under Cygwin or
-   * MinGW on any architecture currently supported by Windows.  Also includes
-   * Watcom builds but these need special treatment because they are not
-   * compatible with GCC or Visual C because of different calling conventions.
-   */
-#  if PNG_API_RULE == 2
-   /* If this line results in an error, either because __watcall is not
-    * understood or because of a redefine just below you cannot use *this*
-    * build of the library with the compiler you are using.  *This* build was
-    * build using Watcom and applications must also be built using Watcom!
-    */
-#    define PNGCAPI __watcall
-#  endif
-
-#  if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800))
-#    define PNGCAPI __cdecl
-#    if PNG_API_RULE == 1
-   /* If this line results in an error __stdcall is not understood and
-    * PNG_API_RULE should not have been set to '1'.
-    */
-#      define PNGAPI __stdcall
-#    endif
-#  else
-   /* An older compiler, or one not detected (erroneously) above,
-    * if necessary override on the command line to get the correct
-    * variants for the compiler.
-    */
-#    ifndef PNGCAPI
-#      define PNGCAPI _cdecl
-#    endif
-#    if PNG_API_RULE == 1 && !defined(PNGAPI)
-#      define PNGAPI _stdcall
-#    endif
-#  endif /* compiler/api */
-
-  /* NOTE: PNGCBAPI always defaults to PNGCAPI. */
-
-#  if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD)
-#     error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed"
-#  endif
-
-#  if (defined(_MSC_VER) && _MSC_VER < 800) ||\
-      (defined(__BORLANDC__) && __BORLANDC__ < 0x500)
-   /* older Borland and MSC
-    * compilers used '__export' and required this to be after
-    * the type.
-    */
-#    ifndef PNG_EXPORT_TYPE
-#      define PNG_EXPORT_TYPE(type) type PNG_IMPEXP
-#    endif
-#    define PNG_DLL_EXPORT __export
-#  else /* newer compiler */
-#    define PNG_DLL_EXPORT __declspec(dllexport)
-#    ifndef PNG_DLL_IMPORT
-#      define PNG_DLL_IMPORT __declspec(dllimport)
-#    endif
-#  endif /* compiler */
-
-#else /* !Windows */
-#  if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
-#    define PNGAPI _System
-#  else /* !Windows/x86 && !OS/2 */
-   /* Use the defaults, or define PNG*API on the command line (but
-    * this will have to be done for every compile!)
-    */
-#  endif /* other system, !OS/2 */
-#endif /* !Windows/x86 */
-
-/* Now do all the defaulting . */
-#ifndef PNGCAPI
-#  define PNGCAPI
-#endif
-#ifndef PNGCBAPI
-#  define PNGCBAPI PNGCAPI
-#endif
-#ifndef PNGAPI
-#  define PNGAPI PNGCAPI
-#endif
-
-/* PNG_IMPEXP may be set on the compilation system command line or (if not set)
- * then in an internal header file when building the library, otherwise (when
- * using the library) it is set here.
- */
-#ifndef PNG_IMPEXP
-#  if defined(PNG_USE_DLL) && defined(PNG_DLL_IMPORT)
-   /* This forces use of a DLL, disallowing static linking */
-#    define PNG_IMPEXP PNG_DLL_IMPORT
-#  endif
-
-#  ifndef PNG_IMPEXP
-#    define PNG_IMPEXP
-#  endif
-#endif
-
-/* In 1.5.2 the definition of PNG_FUNCTION has been changed to always treat
- * 'attributes' as a storage class - the attributes go at the start of the
- * function definition, and attributes are always appended regardless of the
- * compiler.  This considerably simplifies these macros but may cause problems
- * if any compilers both need function attributes and fail to handle them as
- * a storage class (this is unlikely.)
- */
-#ifndef PNG_FUNCTION
-#  define PNG_FUNCTION(type, name, args, attributes) attributes type name args
-#endif
-
-#ifndef PNG_EXPORT_TYPE
-#  define PNG_EXPORT_TYPE(type) PNG_IMPEXP type
-#endif
-
-   /* The ordinal value is only relevant when preprocessing png.h for symbol
-    * table entries, so we discard it here.  See the .dfn files in the
-    * scripts directory.
-    */
-
-#ifndef PNG_EXPORTA
-#  define PNG_EXPORTA(ordinal, type, name, args, attributes) \
-      PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \
-      PNG_LINKAGE_API attributes)
-#endif
-
-/* ANSI-C (C90) does not permit a macro to be invoked with an empty argument,
- * so make something non-empty to satisfy the requirement:
- */
-#define PNG_EMPTY /*empty list*/
-
-#define PNG_EXPORT(ordinal, type, name, args) \
-   PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY)
-
-/* Use PNG_REMOVED to comment out a removed interface. */
-#ifndef PNG_REMOVED
-#  define PNG_REMOVED(ordinal, type, name, args, attributes)
-#endif
-
-#ifndef PNG_CALLBACK
-#  define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args)
-#endif
-
-/* Support for compiler specific function attributes.  These are used
- * so that where compiler support is available incorrect use of API
- * functions in png.h will generate compiler warnings.
- *
- * Added at libpng-1.2.41.
- */
-
-#ifndef PNG_NO_PEDANTIC_WARNINGS
-#  ifndef PNG_PEDANTIC_WARNINGS_SUPPORTED
-#    define PNG_PEDANTIC_WARNINGS_SUPPORTED
-#  endif
-#endif
-
-#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED
-  /* Support for compiler specific function attributes.  These are used
-   * so that where compiler support is available, incorrect use of API
-   * functions in png.h will generate compiler warnings.  Added at libpng
-   * version 1.2.41.  Disabling these removes the warnings but may also produce
-   * less efficient code.
-   */
-#  if defined(__clang__) && defined(__has_attribute)
-   /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */
-#    if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__)
-#      define PNG_USE_RESULT __attribute__((__warn_unused_result__))
-#    endif
-#    if !defined(PNG_NORETURN) && __has_attribute(__noreturn__)
-#      define PNG_NORETURN __attribute__((__noreturn__))
-#    endif
-#    if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__)
-#      define PNG_ALLOCATED __attribute__((__malloc__))
-#    endif
-#    if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__)
-#      define PNG_DEPRECATED __attribute__((__deprecated__))
-#    endif
-#    if !defined(PNG_PRIVATE)
-#      ifdef __has_extension
-#        if __has_extension(attribute_unavailable_with_message)
-#          define PNG_PRIVATE __attribute__((__unavailable__(\
-             "This function is not exported by libpng.")))
-#        endif
-#      endif
-#    endif
-#    ifndef PNG_RESTRICT
-#      define PNG_RESTRICT __restrict
-#    endif
-
-#  elif defined(__GNUC__)
-#    ifndef PNG_USE_RESULT
-#      define PNG_USE_RESULT __attribute__((__warn_unused_result__))
-#    endif
-#    ifndef PNG_NORETURN
-#      define PNG_NORETURN   __attribute__((__noreturn__))
-#    endif
-#    if __GNUC__ >= 3
-#      ifndef PNG_ALLOCATED
-#        define PNG_ALLOCATED  __attribute__((__malloc__))
-#      endif
-#      ifndef PNG_DEPRECATED
-#        define PNG_DEPRECATED __attribute__((__deprecated__))
-#      endif
-#      ifndef PNG_PRIVATE
-#        if 0 /* Doesn't work so we use deprecated instead*/
-#          define PNG_PRIVATE \
-            __attribute__((warning("This function is not exported by libpng.")))
-#        else
-#          define PNG_PRIVATE \
-            __attribute__((__deprecated__))
-#        endif
-#      endif
-#      if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1))
-#        ifndef PNG_RESTRICT
-#          define PNG_RESTRICT __restrict
-#        endif
-#      endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */
-#    endif /* __GNUC__ >= 3 */
-
-#  elif defined(_MSC_VER)  && (_MSC_VER >= 1300)
-#    ifndef PNG_USE_RESULT
-#      define PNG_USE_RESULT /* not supported */
-#    endif
-#    ifndef PNG_NORETURN
-#      define PNG_NORETURN   __declspec(noreturn)
-#    endif
-#    ifndef PNG_ALLOCATED
-#      if (_MSC_VER >= 1400)
-#        define PNG_ALLOCATED __declspec(restrict)
-#      endif
-#    endif
-#    ifndef PNG_DEPRECATED
-#      define PNG_DEPRECATED __declspec(deprecated)
-#    endif
-#    ifndef PNG_PRIVATE
-#      define PNG_PRIVATE __declspec(deprecated)
-#    endif
-#    ifndef PNG_RESTRICT
-#      if (_MSC_VER >= 1400)
-#        define PNG_RESTRICT __restrict
-#      endif
-#    endif
-
-#  elif defined(__WATCOMC__)
-#    ifndef PNG_RESTRICT
-#      define PNG_RESTRICT __restrict
-#    endif
-#  endif
-#endif /* PNG_PEDANTIC_WARNINGS */
-
-#ifndef PNG_DEPRECATED
-#  define PNG_DEPRECATED  /* Use of this function is deprecated */
-#endif
-#ifndef PNG_USE_RESULT
-#  define PNG_USE_RESULT  /* The result of this function must be checked */
-#endif
-#ifndef PNG_NORETURN
-#  define PNG_NORETURN    /* This function does not return */
-#endif
-#ifndef PNG_ALLOCATED
-#  define PNG_ALLOCATED   /* The result of the function is new memory */
-#endif
-#ifndef PNG_PRIVATE
-#  define PNG_PRIVATE     /* This is a private libpng function */
-#endif
-#ifndef PNG_RESTRICT
-#  define PNG_RESTRICT    /* The C99 "restrict" feature */
-#endif
-
-#ifndef PNG_FP_EXPORT     /* A floating point API. */
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-#     define PNG_FP_EXPORT(ordinal, type, name, args)\
-         PNG_EXPORT(ordinal, type, name, args);
-#  else                   /* No floating point APIs */
-#     define PNG_FP_EXPORT(ordinal, type, name, args)
-#  endif
-#endif
-#ifndef PNG_FIXED_EXPORT  /* A fixed point API. */
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-#     define PNG_FIXED_EXPORT(ordinal, type, name, args)\
-         PNG_EXPORT(ordinal, type, name, args);
-#  else                   /* No fixed point APIs */
-#     define PNG_FIXED_EXPORT(ordinal, type, name, args)
-#  endif
-#endif
-
-#ifndef PNG_BUILDING_SYMBOL_TABLE
-/* Some typedefs to get us started.  These should be safe on most of the common
- * platforms.
- *
- * png_uint_32 and png_int_32 may, currently, be larger than required to hold a
- * 32-bit value however this is not normally advisable.
- *
- * png_uint_16 and png_int_16 should always be two bytes in size - this is
- * verified at library build time.
- *
- * png_byte must always be one byte in size.
- *
- * The checks below use constants from limits.h, as defined by the ISOC90
- * standard.
- */
-#if CHAR_BIT == 8 && UCHAR_MAX == 255
-   typedef unsigned char png_byte;
-#else
-#  error "libpng requires 8-bit bytes"
-#endif
-
-#if INT_MIN == -32768 && INT_MAX == 32767
-   typedef int png_int_16;
-#elif SHRT_MIN == -32768 && SHRT_MAX == 32767
-   typedef short png_int_16;
-#else
-#  error "libpng requires a signed 16-bit type"
-#endif
-
-#if UINT_MAX == 65535
-   typedef unsigned int png_uint_16;
-#elif USHRT_MAX == 65535
-   typedef unsigned short png_uint_16;
-#else
-#  error "libpng requires an unsigned 16-bit type"
-#endif
-
-#if INT_MIN < -2147483646 && INT_MAX > 2147483646
-   typedef int png_int_32;
-#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646
-   typedef long int png_int_32;
-#else
-#  error "libpng requires a signed 32-bit (or more) type"
-#endif
-
-#if UINT_MAX > 4294967294U
-   typedef unsigned int png_uint_32;
-#elif ULONG_MAX > 4294967294U
-   typedef unsigned long int png_uint_32;
-#else
-#  error "libpng requires an unsigned 32-bit (or more) type"
-#endif
-
-/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t.
- * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant
- * behavior of sizeof and ptrdiff_t are required.
- * The legacy typedefs are provided here for backwards compatibility.
- */
-typedef size_t png_size_t;
-typedef ptrdiff_t png_ptrdiff_t;
-
-/* libpng needs to know the maximum value of 'size_t' and this controls the
- * definition of png_alloc_size_t, below.  This maximum value of size_t limits
- * but does not control the maximum allocations the library makes - there is
- * direct application control of this through png_set_user_limits().
- */
-#ifndef PNG_SMALL_SIZE_T
-   /* Compiler specific tests for systems where size_t is known to be less than
-    * 32 bits (some of these systems may no longer work because of the lack of
-    * 'far' support; see above.)
-    */
-#  if (defined(__TURBOC__) && !defined(__FLAT__)) ||\
-   (defined(_MSC_VER) && defined(MAXSEG_64K))
-#     define PNG_SMALL_SIZE_T
-#  endif
-#endif
-
-/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller
- * than png_uint_32.  Casts from size_t or png_uint_32 to png_alloc_size_t are
- * not necessary; in fact, it is recommended not to use them at all, so that
- * the compiler can complain when something turns out to be problematic.
- *
- * Casts in the other direction (from png_alloc_size_t to size_t or
- * png_uint_32) should be explicitly applied; however, we do not expect to
- * encounter practical situations that require such conversions.
- *
- * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than
- * 4294967295 - i.e. less than the maximum value of png_uint_32.
- */
-#ifdef PNG_SMALL_SIZE_T
-   typedef png_uint_32 png_alloc_size_t;
-#else
-   typedef size_t png_alloc_size_t;
-#endif
-
-/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler
- * implementations of Intel CPU specific support of user-mode segmented address
- * spaces, where 16-bit pointers address more than 65536 bytes of memory using
- * separate 'segment' registers.  The implementation requires two different
- * types of pointer (only one of which includes the segment value.)
- *
- * If required this support is available in version 1.2 of libpng and may be
- * available in versions through 1.5, although the correctness of the code has
- * not been verified recently.
- */
-
-/* Typedef for floating-point numbers that are converted to fixed-point with a
- * multiple of 100,000, e.g., gamma
- */
-typedef png_int_32 png_fixed_point;
-
-/* Add typedefs for pointers */
-typedef void                  * png_voidp;
-typedef const void            * png_const_voidp;
-typedef png_byte              * png_bytep;
-typedef const png_byte        * png_const_bytep;
-typedef png_uint_32           * png_uint_32p;
-typedef const png_uint_32     * png_const_uint_32p;
-typedef png_int_32            * png_int_32p;
-typedef const png_int_32      * png_const_int_32p;
-typedef png_uint_16           * png_uint_16p;
-typedef const png_uint_16     * png_const_uint_16p;
-typedef png_int_16            * png_int_16p;
-typedef const png_int_16      * png_const_int_16p;
-typedef char                  * png_charp;
-typedef const char            * png_const_charp;
-typedef png_fixed_point       * png_fixed_point_p;
-typedef const png_fixed_point * png_const_fixed_point_p;
-typedef size_t                * png_size_tp;
-typedef const size_t          * png_const_size_tp;
-
-#ifdef PNG_STDIO_SUPPORTED
-typedef FILE            * png_FILE_p;
-#endif
-
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-typedef double       * png_doublep;
-typedef const double * png_const_doublep;
-#endif
-
-/* Pointers to pointers; i.e. arrays */
-typedef png_byte        * * png_bytepp;
-typedef png_uint_32     * * png_uint_32pp;
-typedef png_int_32      * * png_int_32pp;
-typedef png_uint_16     * * png_uint_16pp;
-typedef png_int_16      * * png_int_16pp;
-typedef const char      * * png_const_charpp;
-typedef char            * * png_charpp;
-typedef png_fixed_point * * png_fixed_point_pp;
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-typedef double          * * png_doublepp;
-#endif
-
-/* Pointers to pointers to pointers; i.e., pointer to array */
-typedef char            * * * png_charppp;
-
-#endif /* PNG_BUILDING_SYMBOL_TABLE */
-
-#endif /* PNGCONF_H */
diff --git a/third_party/libpng16/pngdebug.h b/third_party/libpng16/pngdebug.h
deleted file mode 100644
index 00d5a45..0000000
--- a/third_party/libpng16/pngdebug.h
+++ /dev/null
@@ -1,153 +0,0 @@
-
-/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-/* Define PNG_DEBUG at compile time for debugging information.  Higher
- * numbers for PNG_DEBUG mean more debugging information.  This has
- * only been added since version 0.95 so it is not implemented throughout
- * libpng yet, but more support will be added as needed.
- *
- * png_debug[1-2]?(level, message ,arg{0-2})
- *   Expands to a statement (either a simple expression or a compound
- *   do..while(0) statement) that outputs a message with parameter
- *   substitution if PNG_DEBUG is defined to 2 or more.  If PNG_DEBUG
- *   is undefined, 0 or 1 every png_debug expands to a simple expression
- *   (actually ((void)0)).
- *
- *   level: level of detail of message, starting at 0.  A level 'n'
- *          message is preceded by 'n' 3-space indentations (not implemented
- *          on Microsoft compilers unless PNG_DEBUG_FILE is also
- *          defined, to allow debug DLL compilation with no standard IO).
- *   message: a printf(3) style text string.  A trailing '\n' is added
- *            to the message.
- *   arg: 0 to 2 arguments for printf(3) style substitution in message.
- */
-#ifndef PNGDEBUG_H
-#define PNGDEBUG_H
-/* These settings control the formatting of messages in png.c and pngerror.c */
-/* Moved to pngdebug.h at 1.5.0 */
-#  ifndef PNG_LITERAL_SHARP
-#    define PNG_LITERAL_SHARP 0x23
-#  endif
-#  ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
-#    define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b
-#  endif
-#  ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET
-#    define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d
-#  endif
-#  ifndef PNG_STRING_NEWLINE
-#    define PNG_STRING_NEWLINE "\n"
-#  endif
-
-#ifdef PNG_DEBUG
-#  if (PNG_DEBUG > 0)
-#    if !defined(PNG_DEBUG_FILE) && defined(_MSC_VER)
-#      include <crtdbg.h>
-#      if (PNG_DEBUG > 1)
-#        ifndef _DEBUG
-#          define _DEBUG
-#        endif
-#        ifndef png_debug
-#          define png_debug(l,m)  _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE)
-#        endif
-#        ifndef png_debug1
-#          define png_debug1(l,m,p1)  _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1)
-#        endif
-#        ifndef png_debug2
-#          define png_debug2(l,m,p1,p2) \
-             _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2)
-#        endif
-#      endif
-#    else /* PNG_DEBUG_FILE || !_MSC_VER */
-#      ifndef PNG_STDIO_SUPPORTED
-#        include <stdio.h> /* not included yet */
-#      endif
-#      ifndef PNG_DEBUG_FILE
-#        define PNG_DEBUG_FILE stderr
-#      endif /* PNG_DEBUG_FILE */
-
-#      if (PNG_DEBUG > 1)
-#        ifdef __STDC__
-#          ifndef png_debug
-#            define png_debug(l,m) \
-       do { \
-       int num_tabs=l; \
-       fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "   " : \
-         (num_tabs==2 ? "      " : (num_tabs>2 ? "         " : "")))); \
-       } while (0)
-#          endif
-#          ifndef png_debug1
-#            define png_debug1(l,m,p1) \
-       do { \
-       int num_tabs=l; \
-       fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "   " : \
-         (num_tabs==2 ? "      " : (num_tabs>2 ? "         " : ""))),p1); \
-       } while (0)
-#          endif
-#          ifndef png_debug2
-#            define png_debug2(l,m,p1,p2) \
-       do { \
-       int num_tabs=l; \
-       fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "   " : \
-         (num_tabs==2 ? "      " : (num_tabs>2 ? "         " : ""))),p1,p2);\
-       } while (0)
-#          endif
-#        else /* __STDC __ */
-#          ifndef png_debug
-#            define png_debug(l,m) \
-       do { \
-       int num_tabs=l; \
-       char format[256]; \
-       snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
-         (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
-         m,PNG_STRING_NEWLINE); \
-       fprintf(PNG_DEBUG_FILE,format); \
-       } while (0)
-#          endif
-#          ifndef png_debug1
-#            define png_debug1(l,m,p1) \
-       do { \
-       int num_tabs=l; \
-       char format[256]; \
-       snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
-         (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
-         m,PNG_STRING_NEWLINE); \
-       fprintf(PNG_DEBUG_FILE,format,p1); \
-       } while (0)
-#          endif
-#          ifndef png_debug2
-#            define png_debug2(l,m,p1,p2) \
-       do { \
-       int num_tabs=l; \
-       char format[256]; \
-       snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \
-         (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \
-         m,PNG_STRING_NEWLINE); \
-       fprintf(PNG_DEBUG_FILE,format,p1,p2); \
-       } while (0)
-#          endif
-#        endif /* __STDC __ */
-#      endif /* (PNG_DEBUG > 1) */
-
-#    endif /* _MSC_VER */
-#  endif /* (PNG_DEBUG > 0) */
-#endif /* PNG_DEBUG */
-#ifndef png_debug
-#  define png_debug(l, m) ((void)0)
-#endif
-#ifndef png_debug1
-#  define png_debug1(l, m, p1) ((void)0)
-#endif
-#ifndef png_debug2
-#  define png_debug2(l, m, p1, p2) ((void)0)
-#endif
-#endif /* PNGDEBUG_H */
diff --git a/third_party/libpng16/pngerror.c b/third_party/libpng16/pngerror.c
deleted file mode 100644
index ec3a709..0000000
--- a/third_party/libpng16/pngerror.c
+++ /dev/null
@@ -1,963 +0,0 @@
-
-/* pngerror.c - stub functions for i/o and memory allocation
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- *
- * This file provides a location for all error handling.  Users who
- * need special error handling are expected to write replacement functions
- * and use png_set_error_fn() to use those functions.  See the instructions
- * at each function.
- */
-
-#include "pngpriv.h"
-
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-
-static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr,
-    png_const_charp error_message)),PNG_NORETURN);
-
-#ifdef PNG_WARNINGS_SUPPORTED
-static void /* PRIVATE */
-png_default_warning PNGARG((png_const_structrp png_ptr,
-    png_const_charp warning_message));
-#endif /* WARNINGS */
-
-/* This function is called whenever there is a fatal error.  This function
- * should not be changed.  If there is a need to handle errors differently,
- * you should supply a replacement error function and use png_set_error_fn()
- * to replace the error function at run-time.
- */
-#ifdef PNG_ERROR_TEXT_SUPPORTED
-PNG_FUNCTION(void,PNGAPI
-png_error,(png_const_structrp png_ptr, png_const_charp error_message),
-    PNG_NORETURN)
-{
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   char msg[16];
-   if (png_ptr != NULL)
-   {
-      if ((png_ptr->flags &
-         (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
-      {
-         if (*error_message == PNG_LITERAL_SHARP)
-         {
-            /* Strip "#nnnn " from beginning of error message. */
-            int offset;
-            for (offset = 1; offset<15; offset++)
-               if (error_message[offset] == ' ')
-                  break;
-
-            if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
-            {
-               int i;
-               for (i = 0; i < offset - 1; i++)
-                  msg[i] = error_message[i + 1];
-               msg[i - 1] = '\0';
-               error_message = msg;
-            }
-
-            else
-               error_message += offset;
-         }
-
-         else
-         {
-            if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
-            {
-               msg[0] = '0';
-               msg[1] = '\0';
-               error_message = msg;
-            }
-         }
-      }
-   }
-#endif
-   if (png_ptr != NULL && png_ptr->error_fn != NULL)
-      (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr),
-          error_message);
-
-   /* If the custom handler doesn't exist, or if it returns,
-      use the default handler, which will not return. */
-   png_default_error(png_ptr, error_message);
-}
-#else
-PNG_FUNCTION(void,PNGAPI
-png_err,(png_const_structrp png_ptr),PNG_NORETURN)
-{
-   /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
-    * erroneously as '\0', instead of the empty string "".  This was
-    * apparently an error, introduced in libpng-1.2.20, and png_default_error
-    * will crash in this case.
-    */
-   if (png_ptr != NULL && png_ptr->error_fn != NULL)
-      (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), "");
-
-   /* If the custom handler doesn't exist, or if it returns,
-      use the default handler, which will not return. */
-   png_default_error(png_ptr, "");
-}
-#endif /* ERROR_TEXT */
-
-/* Utility to safely appends strings to a buffer.  This never errors out so
- * error checking is not required in the caller.
- */
-size_t
-png_safecat(png_charp buffer, size_t bufsize, size_t pos,
-    png_const_charp string)
-{
-   if (buffer != NULL && pos < bufsize)
-   {
-      if (string != NULL)
-         while (*string != '\0' && pos < bufsize-1)
-           buffer[pos++] = *string++;
-
-      buffer[pos] = '\0';
-   }
-
-   return pos;
-}
-
-#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED)
-/* Utility to dump an unsigned value into a buffer, given a start pointer and
- * and end pointer (which should point just *beyond* the end of the buffer!)
- * Returns the pointer to the start of the formatted string.
- */
-png_charp
-png_format_number(png_const_charp start, png_charp end, int format,
-    png_alloc_size_t number)
-{
-   int count = 0;    /* number of digits output */
-   int mincount = 1; /* minimum number required */
-   int output = 0;   /* digit output (for the fixed point format) */
-
-   *--end = '\0';
-
-   /* This is written so that the loop always runs at least once, even with
-    * number zero.
-    */
-   while (end > start && (number != 0 || count < mincount))
-   {
-
-      static const char digits[] = "0123456789ABCDEF";
-
-      switch (format)
-      {
-         case PNG_NUMBER_FORMAT_fixed:
-            /* Needs five digits (the fraction) */
-            mincount = 5;
-            if (output != 0 || number % 10 != 0)
-            {
-               *--end = digits[number % 10];
-               output = 1;
-            }
-            number /= 10;
-            break;
-
-         case PNG_NUMBER_FORMAT_02u:
-            /* Expects at least 2 digits. */
-            mincount = 2;
-            /* FALLTHROUGH */
-
-         case PNG_NUMBER_FORMAT_u:
-            *--end = digits[number % 10];
-            number /= 10;
-            break;
-
-         case PNG_NUMBER_FORMAT_02x:
-            /* This format expects at least two digits */
-            mincount = 2;
-            /* FALLTHROUGH */
-
-         case PNG_NUMBER_FORMAT_x:
-            *--end = digits[number & 0xf];
-            number >>= 4;
-            break;
-
-         default: /* an error */
-            number = 0;
-            break;
-      }
-
-      /* Keep track of the number of digits added */
-      ++count;
-
-      /* Float a fixed number here: */
-      if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start))
-      {
-         /* End of the fraction, but maybe nothing was output?  In that case
-          * drop the decimal point.  If the number is a true zero handle that
-          * here.
-          */
-         if (output != 0)
-            *--end = '.';
-         else if (number == 0) /* and !output */
-            *--end = '0';
-      }
-   }
-
-   return end;
-}
-#endif
-
-#ifdef PNG_WARNINGS_SUPPORTED
-/* This function is called whenever there is a non-fatal error.  This function
- * should not be changed.  If there is a need to handle warnings differently,
- * you should supply a replacement warning function and use
- * png_set_error_fn() to replace the warning function at run-time.
- */
-void PNGAPI
-png_warning(png_const_structrp png_ptr, png_const_charp warning_message)
-{
-   int offset = 0;
-   if (png_ptr != NULL)
-   {
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   if ((png_ptr->flags &
-       (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
-#endif
-      {
-         if (*warning_message == PNG_LITERAL_SHARP)
-         {
-            for (offset = 1; offset < 15; offset++)
-               if (warning_message[offset] == ' ')
-                  break;
-         }
-      }
-   }
-   if (png_ptr != NULL && png_ptr->warning_fn != NULL)
-      (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr),
-          warning_message + offset);
-   else
-      png_default_warning(png_ptr, warning_message + offset);
-}
-
-/* These functions support 'formatted' warning messages with up to
- * PNG_WARNING_PARAMETER_COUNT parameters.  In the format string the parameter
- * is introduced by @<number>, where 'number' starts at 1.  This follows the
- * standard established by X/Open for internationalizable error messages.
- */
-void
-png_warning_parameter(png_warning_parameters p, int number,
-    png_const_charp string)
-{
-   if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT)
-      (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string);
-}
-
-void
-png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
-    png_alloc_size_t value)
-{
-   char buffer[PNG_NUMBER_BUFFER_SIZE];
-   png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
-}
-
-void
-png_warning_parameter_signed(png_warning_parameters p, int number, int format,
-    png_int_32 value)
-{
-   png_alloc_size_t u;
-   png_charp str;
-   char buffer[PNG_NUMBER_BUFFER_SIZE];
-
-   /* Avoid overflow by doing the negate in a png_alloc_size_t: */
-   u = (png_alloc_size_t)value;
-   if (value < 0)
-      u = ~u + 1;
-
-   str = PNG_FORMAT_NUMBER(buffer, format, u);
-
-   if (value < 0 && str > buffer)
-      *--str = '-';
-
-   png_warning_parameter(p, number, str);
-}
-
-void
-png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p,
-    png_const_charp message)
-{
-   /* The internal buffer is just 192 bytes - enough for all our messages,
-    * overflow doesn't happen because this code checks!  If someone figures
-    * out how to send us a message longer than 192 bytes, all that will
-    * happen is that the message will be truncated appropriately.
-    */
-   size_t i = 0; /* Index in the msg[] buffer: */
-   char msg[192];
-
-   /* Each iteration through the following loop writes at most one character
-    * to msg[i++] then returns here to validate that there is still space for
-    * the trailing '\0'.  It may (in the case of a parameter) read more than
-    * one character from message[]; it must check for '\0' and continue to the
-    * test if it finds the end of string.
-    */
-   while (i<(sizeof msg)-1 && *message != '\0')
-   {
-      /* '@' at end of string is now just printed (previously it was skipped);
-       * it is an error in the calling code to terminate the string with @.
-       */
-      if (p != NULL && *message == '@' && message[1] != '\0')
-      {
-         int parameter_char = *++message; /* Consume the '@' */
-         static const char valid_parameters[] = "123456789";
-         int parameter = 0;
-
-         /* Search for the parameter digit, the index in the string is the
-          * parameter to use.
-          */
-         while (valid_parameters[parameter] != parameter_char &&
-            valid_parameters[parameter] != '\0')
-            ++parameter;
-
-         /* If the parameter digit is out of range it will just get printed. */
-         if (parameter < PNG_WARNING_PARAMETER_COUNT)
-         {
-            /* Append this parameter */
-            png_const_charp parm = p[parameter];
-            png_const_charp pend = p[parameter] + (sizeof p[parameter]);
-
-            /* No need to copy the trailing '\0' here, but there is no guarantee
-             * that parm[] has been initialized, so there is no guarantee of a
-             * trailing '\0':
-             */
-            while (i<(sizeof msg)-1 && *parm != '\0' && parm < pend)
-               msg[i++] = *parm++;
-
-            /* Consume the parameter digit too: */
-            ++message;
-            continue;
-         }
-
-         /* else not a parameter and there is a character after the @ sign; just
-          * copy that.  This is known not to be '\0' because of the test above.
-          */
-      }
-
-      /* At this point *message can't be '\0', even in the bad parameter case
-       * above where there is a lone '@' at the end of the message string.
-       */
-      msg[i++] = *message++;
-   }
-
-   /* i is always less than (sizeof msg), so: */
-   msg[i] = '\0';
-
-   /* And this is the formatted message. It may be larger than
-    * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these
-    * are not (currently) formatted.
-    */
-   png_warning(png_ptr, msg);
-}
-#endif /* WARNINGS */
-
-#ifdef PNG_BENIGN_ERRORS_SUPPORTED
-void PNGAPI
-png_benign_error(png_const_structrp png_ptr, png_const_charp error_message)
-{
-   if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
-   {
-#     ifdef PNG_READ_SUPPORTED
-         if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
-            png_ptr->chunk_name != 0)
-            png_chunk_warning(png_ptr, error_message);
-         else
-#     endif
-      png_warning(png_ptr, error_message);
-   }
-
-   else
-   {
-#     ifdef PNG_READ_SUPPORTED
-         if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
-            png_ptr->chunk_name != 0)
-            png_chunk_error(png_ptr, error_message);
-         else
-#     endif
-      png_error(png_ptr, error_message);
-   }
-
-#  ifndef PNG_ERROR_TEXT_SUPPORTED
-      PNG_UNUSED(error_message)
-#  endif
-}
-
-void /* PRIVATE */
-png_app_warning(png_const_structrp png_ptr, png_const_charp error_message)
-{
-   if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0)
-      png_warning(png_ptr, error_message);
-   else
-      png_error(png_ptr, error_message);
-
-#  ifndef PNG_ERROR_TEXT_SUPPORTED
-      PNG_UNUSED(error_message)
-#  endif
-}
-
-void /* PRIVATE */
-png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
-{
-   if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0)
-      png_warning(png_ptr, error_message);
-   else
-      png_error(png_ptr, error_message);
-
-#  ifndef PNG_ERROR_TEXT_SUPPORTED
-      PNG_UNUSED(error_message)
-#  endif
-}
-#endif /* BENIGN_ERRORS */
-
-#define PNG_MAX_ERROR_TEXT 196 /* Currently limited by profile_error in png.c */
-#if defined(PNG_WARNINGS_SUPPORTED) || \
-   (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED))
-/* These utilities are used internally to build an error message that relates
- * to the current chunk.  The chunk name comes from png_ptr->chunk_name,
- * which is used to prefix the message.  The message is limited in length
- * to 63 bytes. The name characters are output as hex digits wrapped in []
- * if the character is invalid.
- */
-#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
-static const char png_digit[16] = {
-   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
-   'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-static void /* PRIVATE */
-png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
-    error_message)
-{
-   png_uint_32 chunk_name = png_ptr->chunk_name;
-   int iout = 0, ishift = 24;
-
-   while (ishift >= 0)
-   {
-      int c = (int)(chunk_name >> ishift) & 0xff;
-
-      ishift -= 8;
-      if (isnonalpha(c) != 0)
-      {
-         buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
-         buffer[iout++] = png_digit[(c & 0xf0) >> 4];
-         buffer[iout++] = png_digit[c & 0x0f];
-         buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET;
-      }
-
-      else
-      {
-         buffer[iout++] = (char)c;
-      }
-   }
-
-   if (error_message == NULL)
-      buffer[iout] = '\0';
-
-   else
-   {
-      int iin = 0;
-
-      buffer[iout++] = ':';
-      buffer[iout++] = ' ';
-
-      while (iin < PNG_MAX_ERROR_TEXT-1 && error_message[iin] != '\0')
-         buffer[iout++] = error_message[iin++];
-
-      /* iin < PNG_MAX_ERROR_TEXT, so the following is safe: */
-      buffer[iout] = '\0';
-   }
-}
-#endif /* WARNINGS || ERROR_TEXT */
-
-#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
-PNG_FUNCTION(void,PNGAPI
-png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message),
-    PNG_NORETURN)
-{
-   char msg[18+PNG_MAX_ERROR_TEXT];
-   if (png_ptr == NULL)
-      png_error(png_ptr, error_message);
-
-   else
-   {
-      png_format_buffer(png_ptr, msg, error_message);
-      png_error(png_ptr, msg);
-   }
-}
-#endif /* READ && ERROR_TEXT */
-
-#ifdef PNG_WARNINGS_SUPPORTED
-void PNGAPI
-png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message)
-{
-   char msg[18+PNG_MAX_ERROR_TEXT];
-   if (png_ptr == NULL)
-      png_warning(png_ptr, warning_message);
-
-   else
-   {
-      png_format_buffer(png_ptr, msg, warning_message);
-      png_warning(png_ptr, msg);
-   }
-}
-#endif /* WARNINGS */
-
-#ifdef PNG_READ_SUPPORTED
-#ifdef PNG_BENIGN_ERRORS_SUPPORTED
-void PNGAPI
-png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp
-    error_message)
-{
-   if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
-      png_chunk_warning(png_ptr, error_message);
-
-   else
-      png_chunk_error(png_ptr, error_message);
-
-#  ifndef PNG_ERROR_TEXT_SUPPORTED
-      PNG_UNUSED(error_message)
-#  endif
-}
-#endif
-#endif /* READ */
-
-void /* PRIVATE */
-png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
-{
-#  ifndef PNG_WARNINGS_SUPPORTED
-      PNG_UNUSED(message)
-#  endif
-
-   /* This is always supported, but for just read or just write it
-    * unconditionally does the right thing.
-    */
-#  if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
-      if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
-#  endif
-
-#  ifdef PNG_READ_SUPPORTED
-      {
-         if (error < PNG_CHUNK_ERROR)
-            png_chunk_warning(png_ptr, message);
-
-         else
-            png_chunk_benign_error(png_ptr, message);
-      }
-#  endif
-
-#  if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
-      else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
-#  endif
-
-#  ifdef PNG_WRITE_SUPPORTED
-      {
-         if (error < PNG_CHUNK_WRITE_ERROR)
-            png_app_warning(png_ptr, message);
-
-         else
-            png_app_error(png_ptr, message);
-      }
-#  endif
-}
-
-#ifdef PNG_ERROR_TEXT_SUPPORTED
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_FUNCTION(void,
-png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN)
-{
-#  define fixed_message "fixed point overflow in "
-#  define fixed_message_ln ((sizeof fixed_message)-1)
-   unsigned int  iin;
-   char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
-   memcpy(msg, fixed_message, fixed_message_ln);
-   iin = 0;
-   if (name != NULL)
-      while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
-      {
-         msg[fixed_message_ln + iin] = name[iin];
-         ++iin;
-      }
-   msg[fixed_message_ln + iin] = 0;
-   png_error(png_ptr, msg);
-}
-#endif
-#endif
-
-#ifdef PNG_SETJMP_SUPPORTED
-/* This API only exists if ANSI-C style error handling is used,
- * otherwise it is necessary for png_default_error to be overridden.
- */
-jmp_buf* PNGAPI
-png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn,
-    size_t jmp_buf_size)
-{
-   /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
-    * and it must not change after that.  Libpng doesn't care how big the
-    * buffer is, just that it doesn't change.
-    *
-    * If the buffer size is no *larger* than the size of jmp_buf when libpng is
-    * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
-    * semantics that this call will not fail.  If the size is larger, however,
-    * the buffer is allocated and this may fail, causing the function to return
-    * NULL.
-    */
-   if (png_ptr == NULL)
-      return NULL;
-
-   if (png_ptr->jmp_buf_ptr == NULL)
-   {
-      png_ptr->jmp_buf_size = 0; /* not allocated */
-
-      if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local))
-         png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
-
-      else
-      {
-         png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *,
-             png_malloc_warn(png_ptr, jmp_buf_size));
-
-         if (png_ptr->jmp_buf_ptr == NULL)
-            return NULL; /* new NULL return on OOM */
-
-         png_ptr->jmp_buf_size = jmp_buf_size;
-      }
-   }
-
-   else /* Already allocated: check the size */
-   {
-      size_t size = png_ptr->jmp_buf_size;
-
-      if (size == 0)
-      {
-         size = (sizeof png_ptr->jmp_buf_local);
-         if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
-         {
-            /* This is an internal error in libpng: somehow we have been left
-             * with a stack allocated jmp_buf when the application regained
-             * control.  It's always possible to fix this up, but for the moment
-             * this is a png_error because that makes it easy to detect.
-             */
-            png_error(png_ptr, "Libpng jmp_buf still allocated");
-            /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
-         }
-      }
-
-      if (size != jmp_buf_size)
-      {
-         png_warning(png_ptr, "Application jmp_buf size changed");
-         return NULL; /* caller will probably crash: no choice here */
-      }
-   }
-
-   /* Finally fill in the function, now we have a satisfactory buffer. It is
-    * valid to change the function on every call.
-    */
-   png_ptr->longjmp_fn = longjmp_fn;
-   return png_ptr->jmp_buf_ptr;
-}
-
-void /* PRIVATE */
-png_free_jmpbuf(png_structrp png_ptr)
-{
-   if (png_ptr != NULL)
-   {
-      jmp_buf *jb = png_ptr->jmp_buf_ptr;
-
-      /* A size of 0 is used to indicate a local, stack, allocation of the
-       * pointer; used here and in png.c
-       */
-      if (jb != NULL && png_ptr->jmp_buf_size > 0)
-      {
-
-         /* This stuff is so that a failure to free the error control structure
-          * does not leave libpng in a state with no valid error handling: the
-          * free always succeeds, if there is an error it gets ignored.
-          */
-         if (jb != &png_ptr->jmp_buf_local)
-         {
-            /* Make an internal, libpng, jmp_buf to return here */
-            jmp_buf free_jmp_buf;
-
-            if (!setjmp(free_jmp_buf))
-            {
-               png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
-               png_ptr->jmp_buf_size = 0; /* stack allocation */
-               png_ptr->longjmp_fn = longjmp;
-               png_free(png_ptr, jb); /* Return to setjmp on error */
-            }
-         }
-      }
-
-      /* *Always* cancel everything out: */
-      png_ptr->jmp_buf_size = 0;
-      png_ptr->jmp_buf_ptr = NULL;
-      png_ptr->longjmp_fn = 0;
-   }
-}
-#endif
-
-/* This is the default error handling function.  Note that replacements for
- * this function MUST NOT RETURN, or the program will likely crash.  This
- * function is used by default, or if the program supplies NULL for the
- * error function pointer in png_set_error_fn().
- */
-static PNG_FUNCTION(void /* PRIVATE */,
-png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
-    PNG_NORETURN)
-{
-#ifdef PNG_CONSOLE_IO_SUPPORTED
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   /* Check on NULL only added in 1.5.4 */
-   if (error_message != NULL && *error_message == PNG_LITERAL_SHARP)
-   {
-      /* Strip "#nnnn " from beginning of error message. */
-      int offset;
-      char error_number[16];
-      for (offset = 0; offset<15; offset++)
-      {
-         error_number[offset] = error_message[offset + 1];
-         if (error_message[offset] == ' ')
-            break;
-      }
-
-      if ((offset > 1) && (offset < 15))
-      {
-         error_number[offset - 1] = '\0';
-         fprintf(stderr, "libpng error no. %s: %s",
-             error_number, error_message + offset + 1);
-         fprintf(stderr, PNG_STRING_NEWLINE);
-      }
-
-      else
-      {
-         fprintf(stderr, "libpng error: %s, offset=%d",
-             error_message, offset);
-         fprintf(stderr, PNG_STRING_NEWLINE);
-      }
-   }
-   else
-#endif
-   {
-      fprintf(stderr, "libpng error: %s", error_message ? error_message :
-         "undefined");
-      fprintf(stderr, PNG_STRING_NEWLINE);
-   }
-#else
-   PNG_UNUSED(error_message) /* Make compiler happy */
-#endif
-   png_longjmp(png_ptr, 1);
-}
-
-PNG_FUNCTION(void,PNGAPI
-png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN)
-{
-#ifdef PNG_SETJMP_SUPPORTED
-   if (png_ptr != NULL && png_ptr->longjmp_fn != NULL &&
-       png_ptr->jmp_buf_ptr != NULL)
-      png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val);
-#else
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(val)
-#endif
-
-   /* If control reaches this point, png_longjmp() must not return. The only
-    * choice is to terminate the whole process (or maybe the thread); to do
-    * this the ANSI-C abort() function is used unless a different method is
-    * implemented by overriding the default configuration setting for
-    * PNG_ABORT().
-    */
-   PNG_ABORT();
-}
-
-#ifdef PNG_WARNINGS_SUPPORTED
-/* This function is called when there is a warning, but the library thinks
- * it can continue anyway.  Replacement functions don't have to do anything
- * here if you don't want them to.  In the default configuration, png_ptr is
- * not used, but it is passed in case it may be useful.
- */
-static void /* PRIVATE */
-png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message)
-{
-#ifdef PNG_CONSOLE_IO_SUPPORTED
-#  ifdef PNG_ERROR_NUMBERS_SUPPORTED
-   if (*warning_message == PNG_LITERAL_SHARP)
-   {
-      int offset;
-      char warning_number[16];
-      for (offset = 0; offset < 15; offset++)
-      {
-         warning_number[offset] = warning_message[offset + 1];
-         if (warning_message[offset] == ' ')
-            break;
-      }
-
-      if ((offset > 1) && (offset < 15))
-      {
-         warning_number[offset + 1] = '\0';
-         fprintf(stderr, "libpng warning no. %s: %s",
-             warning_number, warning_message + offset);
-         fprintf(stderr, PNG_STRING_NEWLINE);
-      }
-
-      else
-      {
-         fprintf(stderr, "libpng warning: %s",
-             warning_message);
-         fprintf(stderr, PNG_STRING_NEWLINE);
-      }
-   }
-   else
-#  endif
-
-   {
-      fprintf(stderr, "libpng warning: %s", warning_message);
-      fprintf(stderr, PNG_STRING_NEWLINE);
-   }
-#else
-   PNG_UNUSED(warning_message) /* Make compiler happy */
-#endif
-   PNG_UNUSED(png_ptr) /* Make compiler happy */
-}
-#endif /* WARNINGS */
-
-/* This function is called when the application wants to use another method
- * of handling errors and warnings.  Note that the error function MUST NOT
- * return to the calling routine or serious problems will occur.  The return
- * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1)
- */
-void PNGAPI
-png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warning_fn)
-{
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->error_ptr = error_ptr;
-   png_ptr->error_fn = error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
-   png_ptr->warning_fn = warning_fn;
-#else
-   PNG_UNUSED(warning_fn)
-#endif
-}
-
-
-/* This function returns a pointer to the error_ptr associated with the user
- * functions.  The application should free any memory associated with this
- * pointer before png_write_destroy and png_read_destroy are called.
- */
-png_voidp PNGAPI
-png_get_error_ptr(png_const_structrp png_ptr)
-{
-   if (png_ptr == NULL)
-      return NULL;
-
-   return ((png_voidp)png_ptr->error_ptr);
-}
-
-
-#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-void PNGAPI
-png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
-{
-   if (png_ptr != NULL)
-   {
-      png_ptr->flags &=
-         ((~(PNG_FLAG_STRIP_ERROR_NUMBERS |
-         PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
-   }
-}
-#endif
-
-#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
-   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
-   /* Currently the above both depend on SETJMP_SUPPORTED, however it would be
-    * possible to implement without setjmp support just so long as there is some
-    * way to handle the error return here:
-    */
-PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
-png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
-    PNG_NORETURN)
-{
-   png_const_structrp png_ptr = png_nonconst_ptr;
-   png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
-
-   /* An error is always logged here, overwriting anything (typically a warning)
-    * that is already there:
-    */
-   if (image != NULL)
-   {
-      png_safecat(image->message, (sizeof image->message), 0, error_message);
-      image->warning_or_error |= PNG_IMAGE_ERROR;
-
-      /* Retrieve the jmp_buf from within the png_control, making this work for
-       * C++ compilation too is pretty tricky: C++ wants a pointer to the first
-       * element of a jmp_buf, but C doesn't tell us the type of that.
-       */
-      if (image->opaque != NULL && image->opaque->error_buf != NULL)
-         longjmp(png_control_jmp_buf(image->opaque), 1);
-
-      /* Missing longjmp buffer, the following is to help debugging: */
-      {
-         size_t pos = png_safecat(image->message, (sizeof image->message), 0,
-             "bad longjmp: ");
-         png_safecat(image->message, (sizeof image->message), pos,
-             error_message);
-      }
-   }
-
-   /* Here on an internal programming error. */
-   abort();
-}
-
-#ifdef PNG_WARNINGS_SUPPORTED
-void /* PRIVATE */ PNGCBAPI
-png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
-{
-   png_const_structrp png_ptr = png_nonconst_ptr;
-   png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
-
-   /* A warning is only logged if there is no prior warning or error. */
-   if (image->warning_or_error == 0)
-   {
-      png_safecat(image->message, (sizeof image->message), 0, warning_message);
-      image->warning_or_error |= PNG_IMAGE_WARNING;
-   }
-}
-#endif
-
-int /* PRIVATE */
-png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
-{
-   volatile png_imagep image = image_in;
-   volatile int result;
-   volatile png_voidp saved_error_buf;
-   jmp_buf safe_jmpbuf;
-
-   /* Safely execute function(arg) with png_error returning to this function. */
-   saved_error_buf = image->opaque->error_buf;
-   result = setjmp(safe_jmpbuf) == 0;
-
-   if (result != 0)
-   {
-
-      image->opaque->error_buf = safe_jmpbuf;
-      result = function(arg);
-   }
-
-   image->opaque->error_buf = saved_error_buf;
-
-   /* And do the cleanup prior to any failure return. */
-   if (result == 0)
-      png_image_free(image);
-
-   return result;
-}
-#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
-#endif /* READ || WRITE */
diff --git a/third_party/libpng16/pngget.c b/third_party/libpng16/pngget.c
deleted file mode 100644
index 5abf1ef..0000000
--- a/third_party/libpng16/pngget.c
+++ /dev/null
@@ -1,1249 +0,0 @@
-
-/* pngget.c - retrieval of values from info struct
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- *
- */
-
-#include "pngpriv.h"
-
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-
-png_uint_32 PNGAPI
-png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_uint_32 flag)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->valid & flag);
-
-   return(0);
-}
-
-size_t PNGAPI
-png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->rowbytes);
-
-   return(0);
-}
-
-#ifdef PNG_INFO_IMAGE_SUPPORTED
-png_bytepp PNGAPI
-png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->row_pointers);
-
-   return(0);
-}
-#endif
-
-#ifdef PNG_EASY_ACCESS_SUPPORTED
-/* Easy access to info, added in libpng-0.99 */
-png_uint_32 PNGAPI
-png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return info_ptr->width;
-
-   return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return info_ptr->height;
-
-   return (0);
-}
-
-png_byte PNGAPI
-png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return info_ptr->bit_depth;
-
-   return (0);
-}
-
-png_byte PNGAPI
-png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return info_ptr->color_type;
-
-   return (0);
-}
-
-png_byte PNGAPI
-png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return info_ptr->filter_type;
-
-   return (0);
-}
-
-png_byte PNGAPI
-png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return info_ptr->interlace_type;
-
-   return (0);
-}
-
-png_byte PNGAPI
-png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return info_ptr->compression_type;
-
-   return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
-   info_ptr)
-{
-#ifdef PNG_pHYs_SUPPORTED
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_pHYs) != 0)
-      {
-         png_debug1(1, "in %s retrieval function",
-             "png_get_x_pixels_per_meter");
-
-         if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
-            return (info_ptr->x_pixels_per_unit);
-      }
-#else
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(info_ptr)
-#endif
-
-   return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
-    info_ptr)
-{
-#ifdef PNG_pHYs_SUPPORTED
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_pHYs) != 0)
-   {
-      png_debug1(1, "in %s retrieval function",
-          "png_get_y_pixels_per_meter");
-
-      if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
-         return (info_ptr->y_pixels_per_unit);
-   }
-#else
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(info_ptr)
-#endif
-
-   return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-#ifdef PNG_pHYs_SUPPORTED
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_pHYs) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter");
-
-      if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER &&
-          info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit)
-         return (info_ptr->x_pixels_per_unit);
-   }
-#else
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(info_ptr)
-#endif
-
-   return (0);
-}
-
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-float PNGAPI
-png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp
-   info_ptr)
-{
-#ifdef PNG_READ_pHYs_SUPPORTED
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_pHYs) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio");
-
-      if (info_ptr->x_pixels_per_unit != 0)
-         return ((float)((float)info_ptr->y_pixels_per_unit
-             /(float)info_ptr->x_pixels_per_unit));
-   }
-#else
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(info_ptr)
-#endif
-
-   return ((float)0.0);
-}
-#endif
-
-#ifdef PNG_FIXED_POINT_SUPPORTED
-png_fixed_point PNGAPI
-png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr,
-    png_const_inforp info_ptr)
-{
-#ifdef PNG_READ_pHYs_SUPPORTED
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_pHYs) != 0 &&
-       info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 &&
-       info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX &&
-       info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX)
-   {
-      png_fixed_point res;
-
-      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed");
-
-      /* The following casts work because a PNG 4 byte integer only has a valid
-       * range of 0..2^31-1; otherwise the cast might overflow.
-       */
-      if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1,
-          (png_int_32)info_ptr->x_pixels_per_unit) != 0)
-         return res;
-   }
-#else
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(info_ptr)
-#endif
-
-   return 0;
-}
-#endif
-
-png_int_32 PNGAPI
-png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-#ifdef PNG_oFFs_SUPPORTED
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_oFFs) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
-
-      if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
-         return (info_ptr->x_offset);
-   }
-#else
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(info_ptr)
-#endif
-
-   return (0);
-}
-
-png_int_32 PNGAPI
-png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-#ifdef PNG_oFFs_SUPPORTED
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_oFFs) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
-
-      if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
-         return (info_ptr->y_offset);
-   }
-#else
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(info_ptr)
-#endif
-
-   return (0);
-}
-
-png_int_32 PNGAPI
-png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-#ifdef PNG_oFFs_SUPPORTED
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_oFFs) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels");
-
-      if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
-         return (info_ptr->x_offset);
-   }
-#else
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(info_ptr)
-#endif
-
-   return (0);
-}
-
-png_int_32 PNGAPI
-png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-#ifdef PNG_oFFs_SUPPORTED
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_oFFs) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels");
-
-      if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
-         return (info_ptr->y_offset);
-   }
-#else
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(info_ptr)
-#endif
-
-   return (0);
-}
-
-#ifdef PNG_INCH_CONVERSIONS_SUPPORTED
-static png_uint_32
-ppi_from_ppm(png_uint_32 ppm)
-{
-#if 0
-   /* The conversion is *(2.54/100), in binary (32 digits):
-    * .00000110100000001001110101001001
-    */
-   png_uint_32 t1001, t1101;
-   ppm >>= 1;                  /* .1 */
-   t1001 = ppm + (ppm >> 3);   /* .1001 */
-   t1101 = t1001 + (ppm >> 1); /* .1101 */
-   ppm >>= 20;                 /* .000000000000000000001 */
-   t1101 += t1101 >> 15;       /* .1101000000000001101 */
-   t1001 >>= 11;               /* .000000000001001 */
-   t1001 += t1001 >> 12;       /* .000000000001001000000001001 */
-   ppm += t1001;               /* .000000000001001000001001001 */
-   ppm += t1101;               /* .110100000001001110101001001 */
-   return (ppm + 16) >> 5;/* .00000110100000001001110101001001 */
-#else
-   /* The argument is a PNG unsigned integer, so it is not permitted
-    * to be bigger than 2^31.
-    */
-   png_fixed_point result;
-   if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127,
-       5000) != 0)
-      return (png_uint_32)result;
-
-   /* Overflow. */
-   return 0;
-#endif
-}
-
-png_uint_32 PNGAPI
-png_get_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr));
-}
-
-png_uint_32 PNGAPI
-png_get_x_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr));
-}
-
-png_uint_32 PNGAPI
-png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr));
-}
-
-#ifdef PNG_FIXED_POINT_SUPPORTED
-static png_fixed_point
-png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns)
-{
-   /* Convert from meters * 1,000,000 to inches * 100,000, meters to
-    * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127.
-    * Notice that this can overflow - a warning is output and 0 is
-    * returned.
-    */
-   return png_muldiv_warn(png_ptr, microns, 500, 127);
-}
-
-png_fixed_point PNGAPI
-png_get_x_offset_inches_fixed(png_const_structrp png_ptr,
-    png_const_inforp info_ptr)
-{
-   return png_fixed_inches_from_microns(png_ptr,
-       png_get_x_offset_microns(png_ptr, info_ptr));
-}
-#endif
-
-#ifdef PNG_FIXED_POINT_SUPPORTED
-png_fixed_point PNGAPI
-png_get_y_offset_inches_fixed(png_const_structrp png_ptr,
-    png_const_inforp info_ptr)
-{
-   return png_fixed_inches_from_microns(png_ptr,
-       png_get_y_offset_microns(png_ptr, info_ptr));
-}
-#endif
-
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-float PNGAPI
-png_get_x_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   /* To avoid the overflow do the conversion directly in floating
-    * point.
-    */
-   return (float)(png_get_x_offset_microns(png_ptr, info_ptr) * .00003937);
-}
-#endif
-
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-float PNGAPI
-png_get_y_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   /* To avoid the overflow do the conversion directly in floating
-    * point.
-    */
-   return (float)(png_get_y_offset_microns(png_ptr, info_ptr) * .00003937);
-}
-#endif
-
-#ifdef PNG_pHYs_SUPPORTED
-png_uint_32 PNGAPI
-png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
-{
-   png_uint_32 retval = 0;
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_pHYs) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "pHYs");
-
-      if (res_x != NULL)
-      {
-         *res_x = info_ptr->x_pixels_per_unit;
-         retval |= PNG_INFO_pHYs;
-      }
-
-      if (res_y != NULL)
-      {
-         *res_y = info_ptr->y_pixels_per_unit;
-         retval |= PNG_INFO_pHYs;
-      }
-
-      if (unit_type != NULL)
-      {
-         *unit_type = (int)info_ptr->phys_unit_type;
-         retval |= PNG_INFO_pHYs;
-
-         if (*unit_type == 1)
-         {
-            if (res_x != NULL) *res_x = (png_uint_32)(*res_x * .0254 + .50);
-            if (res_y != NULL) *res_y = (png_uint_32)(*res_y * .0254 + .50);
-         }
-      }
-   }
-
-   return (retval);
-}
-#endif /* pHYs */
-#endif /* INCH_CONVERSIONS */
-
-/* png_get_channels really belongs in here, too, but it's been around longer */
-
-#endif /* EASY_ACCESS */
-
-
-png_byte PNGAPI
-png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->channels);
-
-   return (0);
-}
-
-#ifdef PNG_READ_SUPPORTED
-png_const_bytep PNGAPI
-png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return(info_ptr->signature);
-
-   return (NULL);
-}
-#endif
-
-#ifdef PNG_bKGD_SUPPORTED
-png_uint_32 PNGAPI
-png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_color_16p *background)
-{
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_bKGD) != 0 &&
-       background != NULL)
-   {
-      png_debug1(1, "in %s retrieval function", "bKGD");
-
-      *background = &(info_ptr->background);
-      return (PNG_INFO_bKGD);
-   }
-
-   return (0);
-}
-#endif
-
-#ifdef PNG_cHRM_SUPPORTED
-/* The XYZ APIs were added in 1.5.5 to take advantage of the code added at the
- * same time to correct the rgb grayscale coefficient defaults obtained from the
- * cHRM chunk in 1.5.4
- */
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    double *white_x, double *white_y, double *red_x, double *red_y,
-    double *green_x, double *green_y, double *blue_x, double *blue_y)
-{
-   /* Quiet API change: this code used to only return the end points if a cHRM
-    * chunk was present, but the end points can also come from iCCP or sRGB
-    * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
-    * the png_set_ APIs merely check that set end points are mutually
-    * consistent.
-    */
-   if (png_ptr != NULL && info_ptr != NULL &&
-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "cHRM");
-
-      if (white_x != NULL)
-         *white_x = png_float(png_ptr,
-             info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
-      if (white_y != NULL)
-         *white_y = png_float(png_ptr,
-             info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y");
-      if (red_x != NULL)
-         *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx,
-             "cHRM red X");
-      if (red_y != NULL)
-         *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy,
-             "cHRM red Y");
-      if (green_x != NULL)
-         *green_x = png_float(png_ptr,
-             info_ptr->colorspace.end_points_xy.greenx, "cHRM green X");
-      if (green_y != NULL)
-         *green_y = png_float(png_ptr,
-             info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y");
-      if (blue_x != NULL)
-         *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex,
-             "cHRM blue X");
-      if (blue_y != NULL)
-         *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
-             "cHRM blue Y");
-      return (PNG_INFO_cHRM);
-   }
-
-   return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    double *red_X, double *red_Y, double *red_Z, double *green_X,
-    double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
-    double *blue_Z)
-{
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
-
-      if (red_X != NULL)
-         *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
-             "cHRM red X");
-      if (red_Y != NULL)
-         *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y,
-             "cHRM red Y");
-      if (red_Z != NULL)
-         *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z,
-             "cHRM red Z");
-      if (green_X != NULL)
-         *green_X = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X");
-      if (green_Y != NULL)
-         *green_Y = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y");
-      if (green_Z != NULL)
-         *green_Z = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z");
-      if (blue_X != NULL)
-         *blue_X = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X");
-      if (blue_Y != NULL)
-         *blue_Y = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y");
-      if (blue_Z != NULL)
-         *blue_Z = png_float(png_ptr,
-             info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
-      return (PNG_INFO_cHRM);
-   }
-
-   return (0);
-}
-#  endif
-
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
-    png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
-    png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
-    png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
-    png_fixed_point *int_blue_Z)
-{
-   if (png_ptr != NULL && info_ptr != NULL &&
-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
-
-      if (int_red_X != NULL)
-         *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
-      if (int_red_Y != NULL)
-         *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y;
-      if (int_red_Z != NULL)
-         *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z;
-      if (int_green_X != NULL)
-         *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X;
-      if (int_green_Y != NULL)
-         *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y;
-      if (int_green_Z != NULL)
-         *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z;
-      if (int_blue_X != NULL)
-         *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X;
-      if (int_blue_Y != NULL)
-         *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
-      if (int_blue_Z != NULL)
-         *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
-      return (PNG_INFO_cHRM);
-   }
-
-   return (0);
-}
-
-png_uint_32 PNGAPI
-png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
-    png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
-    png_fixed_point *blue_x, png_fixed_point *blue_y)
-{
-   png_debug1(1, "in %s retrieval function", "cHRM");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
-   {
-      if (white_x != NULL)
-         *white_x = info_ptr->colorspace.end_points_xy.whitex;
-      if (white_y != NULL)
-         *white_y = info_ptr->colorspace.end_points_xy.whitey;
-      if (red_x != NULL)
-         *red_x = info_ptr->colorspace.end_points_xy.redx;
-      if (red_y != NULL)
-         *red_y = info_ptr->colorspace.end_points_xy.redy;
-      if (green_x != NULL)
-         *green_x = info_ptr->colorspace.end_points_xy.greenx;
-      if (green_y != NULL)
-         *green_y = info_ptr->colorspace.end_points_xy.greeny;
-      if (blue_x != NULL)
-         *blue_x = info_ptr->colorspace.end_points_xy.bluex;
-      if (blue_y != NULL)
-         *blue_y = info_ptr->colorspace.end_points_xy.bluey;
-      return (PNG_INFO_cHRM);
-   }
-
-   return (0);
-}
-#  endif
-#endif
-
-#ifdef PNG_gAMA_SUPPORTED
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_fixed_point *file_gamma)
-{
-   png_debug1(1, "in %s retrieval function", "gAMA");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
-       file_gamma != NULL)
-   {
-      *file_gamma = info_ptr->colorspace.gamma;
-      return (PNG_INFO_gAMA);
-   }
-
-   return (0);
-}
-#  endif
-
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    double *file_gamma)
-{
-   png_debug1(1, "in %s retrieval function", "gAMA(float)");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-      (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
-      file_gamma != NULL)
-   {
-      *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
-          "png_get_gAMA");
-      return (PNG_INFO_gAMA);
-   }
-
-   return (0);
-}
-#  endif
-#endif
-
-#ifdef PNG_sRGB_SUPPORTED
-png_uint_32 PNGAPI
-png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    int *file_srgb_intent)
-{
-   png_debug1(1, "in %s retrieval function", "sRGB");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-      (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
-   {
-      *file_srgb_intent = info_ptr->colorspace.rendering_intent;
-      return (PNG_INFO_sRGB);
-   }
-
-   return (0);
-}
-#endif
-
-#ifdef PNG_iCCP_SUPPORTED
-png_uint_32 PNGAPI
-png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_charpp name, int *compression_type,
-    png_bytepp profile, png_uint_32 *proflen)
-{
-   png_debug1(1, "in %s retrieval function", "iCCP");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_iCCP) != 0 &&
-       name != NULL && profile != NULL && proflen != NULL)
-   {
-      *name = info_ptr->iccp_name;
-      *profile = info_ptr->iccp_profile;
-      *proflen = png_get_uint_32(info_ptr->iccp_profile);
-      /* This is somewhat irrelevant since the profile data returned has
-       * actually been uncompressed.
-       */
-      if (compression_type != NULL)
-         *compression_type = PNG_COMPRESSION_TYPE_BASE;
-      return (PNG_INFO_iCCP);
-   }
-
-   return (0);
-
-}
-#endif
-
-#ifdef PNG_sPLT_SUPPORTED
-int PNGAPI
-png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_sPLT_tpp spalettes)
-{
-   if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
-   {
-      *spalettes = info_ptr->splt_palettes;
-      return info_ptr->splt_palettes_num;
-   }
-
-   return (0);
-}
-#endif
-
-#ifdef PNG_eXIf_SUPPORTED
-png_uint_32 PNGAPI
-png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_bytep *exif)
-{
-  png_warning(png_ptr, "png_get_eXIf does not work; use png_get_eXIf_1");
-  PNG_UNUSED(info_ptr)
-  PNG_UNUSED(exif)
-  return 0;
-}
-
-png_uint_32 PNGAPI
-png_get_eXIf_1(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_uint_32 *num_exif, png_bytep *exif)
-{
-   png_debug1(1, "in %s retrieval function", "eXIf");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_eXIf) != 0 && exif != NULL)
-   {
-      *num_exif = info_ptr->num_exif;
-      *exif = info_ptr->exif;
-      return (PNG_INFO_eXIf);
-   }
-
-   return (0);
-}
-#endif
-
-#ifdef PNG_hIST_SUPPORTED
-png_uint_32 PNGAPI
-png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_uint_16p *hist)
-{
-   png_debug1(1, "in %s retrieval function", "hIST");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_hIST) != 0 && hist != NULL)
-   {
-      *hist = info_ptr->hist;
-      return (PNG_INFO_hIST);
-   }
-
-   return (0);
-}
-#endif
-
-png_uint_32 PNGAPI
-png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_uint_32 *width, png_uint_32 *height, int *bit_depth,
-    int *color_type, int *interlace_type, int *compression_type,
-    int *filter_type)
-{
-   png_debug1(1, "in %s retrieval function", "IHDR");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return (0);
-
-   if (width != NULL)
-       *width = info_ptr->width;
-
-   if (height != NULL)
-       *height = info_ptr->height;
-
-   if (bit_depth != NULL)
-       *bit_depth = info_ptr->bit_depth;
-
-   if (color_type != NULL)
-       *color_type = info_ptr->color_type;
-
-   if (compression_type != NULL)
-      *compression_type = info_ptr->compression_type;
-
-   if (filter_type != NULL)
-      *filter_type = info_ptr->filter_type;
-
-   if (interlace_type != NULL)
-      *interlace_type = info_ptr->interlace_type;
-
-   /* This is redundant if we can be sure that the info_ptr values were all
-    * assigned in png_set_IHDR().  We do the check anyhow in case an
-    * application has ignored our advice not to mess with the members
-    * of info_ptr directly.
-    */
-   png_check_IHDR(png_ptr, info_ptr->width, info_ptr->height,
-       info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
-       info_ptr->compression_type, info_ptr->filter_type);
-
-   return (1);
-}
-
-#ifdef PNG_oFFs_SUPPORTED
-png_uint_32 PNGAPI
-png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)
-{
-   png_debug1(1, "in %s retrieval function", "oFFs");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_oFFs) != 0 &&
-       offset_x != NULL && offset_y != NULL && unit_type != NULL)
-   {
-      *offset_x = info_ptr->x_offset;
-      *offset_y = info_ptr->y_offset;
-      *unit_type = (int)info_ptr->offset_unit_type;
-      return (PNG_INFO_oFFs);
-   }
-
-   return (0);
-}
-#endif
-
-#ifdef PNG_pCAL_SUPPORTED
-png_uint_32 PNGAPI
-png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
-    png_charp *units, png_charpp *params)
-{
-   png_debug1(1, "in %s retrieval function", "pCAL");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_pCAL) != 0 &&
-       purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
-       nparams != NULL && units != NULL && params != NULL)
-   {
-      *purpose = info_ptr->pcal_purpose;
-      *X0 = info_ptr->pcal_X0;
-      *X1 = info_ptr->pcal_X1;
-      *type = (int)info_ptr->pcal_type;
-      *nparams = (int)info_ptr->pcal_nparams;
-      *units = info_ptr->pcal_units;
-      *params = info_ptr->pcal_params;
-      return (PNG_INFO_pCAL);
-   }
-
-   return (0);
-}
-#endif
-
-#ifdef PNG_sCAL_SUPPORTED
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-#    if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
-         defined(PNG_FLOATING_POINT_SUPPORTED)
-png_uint_32 PNGAPI
-png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    int *unit, png_fixed_point *width, png_fixed_point *height)
-{
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_sCAL) != 0)
-   {
-      *unit = info_ptr->scal_unit;
-      /*TODO: make this work without FP support; the API is currently eliminated
-       * if neither floating point APIs nor internal floating point arithmetic
-       * are enabled.
-       */
-      *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width");
-      *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height),
-          "sCAL height");
-      return (PNG_INFO_sCAL);
-   }
-
-   return(0);
-}
-#    endif /* FLOATING_ARITHMETIC */
-#  endif /* FIXED_POINT */
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    int *unit, double *width, double *height)
-{
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_sCAL) != 0)
-   {
-      *unit = info_ptr->scal_unit;
-      *width = atof(info_ptr->scal_s_width);
-      *height = atof(info_ptr->scal_s_height);
-      return (PNG_INFO_sCAL);
-   }
-
-   return(0);
-}
-#  endif /* FLOATING POINT */
-png_uint_32 PNGAPI
-png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    int *unit, png_charpp width, png_charpp height)
-{
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_sCAL) != 0)
-   {
-      *unit = info_ptr->scal_unit;
-      *width = info_ptr->scal_s_width;
-      *height = info_ptr->scal_s_height;
-      return (PNG_INFO_sCAL);
-   }
-
-   return(0);
-}
-#endif /* sCAL */
-
-#ifdef PNG_pHYs_SUPPORTED
-png_uint_32 PNGAPI
-png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr,
-    png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
-{
-   png_uint_32 retval = 0;
-
-   png_debug1(1, "in %s retrieval function", "pHYs");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_pHYs) != 0)
-   {
-      if (res_x != NULL)
-      {
-         *res_x = info_ptr->x_pixels_per_unit;
-         retval |= PNG_INFO_pHYs;
-      }
-
-      if (res_y != NULL)
-      {
-         *res_y = info_ptr->y_pixels_per_unit;
-         retval |= PNG_INFO_pHYs;
-      }
-
-      if (unit_type != NULL)
-      {
-         *unit_type = (int)info_ptr->phys_unit_type;
-         retval |= PNG_INFO_pHYs;
-      }
-   }
-
-   return (retval);
-}
-#endif /* pHYs */
-
-png_uint_32 PNGAPI
-png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_colorp *palette, int *num_palette)
-{
-   png_debug1(1, "in %s retrieval function", "PLTE");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_PLTE) != 0 && palette != NULL)
-   {
-      *palette = info_ptr->palette;
-      *num_palette = info_ptr->num_palette;
-      png_debug1(3, "num_palette = %d", *num_palette);
-      return (PNG_INFO_PLTE);
-   }
-
-   return (0);
-}
-
-#ifdef PNG_sBIT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_color_8p *sig_bit)
-{
-   png_debug1(1, "in %s retrieval function", "sBIT");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_sBIT) != 0 && sig_bit != NULL)
-   {
-      *sig_bit = &(info_ptr->sig_bit);
-      return (PNG_INFO_sBIT);
-   }
-
-   return (0);
-}
-#endif
-
-#ifdef PNG_TEXT_SUPPORTED
-int PNGAPI
-png_get_text(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_textp *text_ptr, int *num_text)
-{
-   if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
-   {
-      png_debug1(1, "in 0x%lx retrieval function",
-         (unsigned long)png_ptr->chunk_name);
-
-      if (text_ptr != NULL)
-         *text_ptr = info_ptr->text;
-
-      if (num_text != NULL)
-         *num_text = info_ptr->num_text;
-
-      return info_ptr->num_text;
-   }
-
-   if (num_text != NULL)
-      *num_text = 0;
-
-   return(0);
-}
-#endif
-
-#ifdef PNG_tIME_SUPPORTED
-png_uint_32 PNGAPI
-png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_timep *mod_time)
-{
-   png_debug1(1, "in %s retrieval function", "tIME");
-
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_tIME) != 0 && mod_time != NULL)
-   {
-      *mod_time = &(info_ptr->mod_time);
-      return (PNG_INFO_tIME);
-   }
-
-   return (0);
-}
-#endif
-
-#ifdef PNG_tRNS_SUPPORTED
-png_uint_32 PNGAPI
-png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)
-{
-   png_uint_32 retval = 0;
-   if (png_ptr != NULL && info_ptr != NULL &&
-       (info_ptr->valid & PNG_INFO_tRNS) != 0)
-   {
-      png_debug1(1, "in %s retrieval function", "tRNS");
-
-      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      {
-         if (trans_alpha != NULL)
-         {
-            *trans_alpha = info_ptr->trans_alpha;
-            retval |= PNG_INFO_tRNS;
-         }
-
-         if (trans_color != NULL)
-            *trans_color = &(info_ptr->trans_color);
-      }
-
-      else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */
-      {
-         if (trans_color != NULL)
-         {
-            *trans_color = &(info_ptr->trans_color);
-            retval |= PNG_INFO_tRNS;
-         }
-
-         if (trans_alpha != NULL)
-            *trans_alpha = NULL;
-      }
-
-      if (num_trans != NULL)
-      {
-         *num_trans = info_ptr->num_trans;
-         retval |= PNG_INFO_tRNS;
-      }
-   }
-
-   return (retval);
-}
-#endif
-
-#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-int PNGAPI
-png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_unknown_chunkpp unknowns)
-{
-   if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL)
-   {
-      *unknowns = info_ptr->unknown_chunks;
-      return info_ptr->unknown_chunks_num;
-   }
-
-   return (0);
-}
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-png_byte PNGAPI
-png_get_rgb_to_gray_status (png_const_structrp png_ptr)
-{
-   return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0);
-}
-#endif
-
-#ifdef PNG_USER_CHUNKS_SUPPORTED
-png_voidp PNGAPI
-png_get_user_chunk_ptr(png_const_structrp png_ptr)
-{
-   return (png_ptr ? png_ptr->user_chunk_ptr : NULL);
-}
-#endif
-
-size_t PNGAPI
-png_get_compression_buffer_size(png_const_structrp png_ptr)
-{
-   if (png_ptr == NULL)
-      return 0;
-
-#ifdef PNG_WRITE_SUPPORTED
-   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
-#endif
-   {
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-      return png_ptr->IDAT_read_size;
-#else
-      return PNG_IDAT_READ_SIZE;
-#endif
-   }
-
-#ifdef PNG_WRITE_SUPPORTED
-   else
-      return png_ptr->zbuffer_size;
-#endif
-}
-
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-/* These functions were added to libpng 1.2.6 and were enabled
- * by default in libpng-1.4.0 */
-png_uint_32 PNGAPI
-png_get_user_width_max (png_const_structrp png_ptr)
-{
-   return (png_ptr ? png_ptr->user_width_max : 0);
-}
-
-png_uint_32 PNGAPI
-png_get_user_height_max (png_const_structrp png_ptr)
-{
-   return (png_ptr ? png_ptr->user_height_max : 0);
-}
-
-/* This function was added to libpng 1.4.0 */
-png_uint_32 PNGAPI
-png_get_chunk_cache_max (png_const_structrp png_ptr)
-{
-   return (png_ptr ? png_ptr->user_chunk_cache_max : 0);
-}
-
-/* This function was added to libpng 1.4.1 */
-png_alloc_size_t PNGAPI
-png_get_chunk_malloc_max (png_const_structrp png_ptr)
-{
-   return (png_ptr ? png_ptr->user_chunk_malloc_max : 0);
-}
-#endif /* SET_USER_LIMITS */
-
-/* These functions were added to libpng 1.4.0 */
-#ifdef PNG_IO_STATE_SUPPORTED
-png_uint_32 PNGAPI
-png_get_io_state (png_const_structrp png_ptr)
-{
-   return png_ptr->io_state;
-}
-
-png_uint_32 PNGAPI
-png_get_io_chunk_type (png_const_structrp png_ptr)
-{
-   return png_ptr->chunk_name;
-}
-#endif /* IO_STATE */
-
-#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
-#  ifdef PNG_GET_PALETTE_MAX_SUPPORTED
-int PNGAPI
-png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      return png_ptr->num_palette_max;
-
-   return (-1);
-}
-#  endif
-#endif
-
-#endif /* READ || WRITE */
diff --git a/third_party/libpng16/pnginfo.h b/third_party/libpng16/pnginfo.h
deleted file mode 100644
index 1f98ded..0000000
--- a/third_party/libpng16/pnginfo.h
+++ /dev/null
@@ -1,267 +0,0 @@
-
-/* pnginfo.h - header file for PNG reference library
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
- /* png_info is a structure that holds the information in a PNG file so
- * that the application can find out the characteristics of the image.
- * If you are reading the file, this structure will tell you what is
- * in the PNG file.  If you are writing the file, fill in the information
- * you want to put into the PNG file, using png_set_*() functions, then
- * call png_write_info().
- *
- * The names chosen should be very close to the PNG specification, so
- * consult that document for information about the meaning of each field.
- *
- * With libpng < 0.95, it was only possible to directly set and read the
- * the values in the png_info_struct, which meant that the contents and
- * order of the values had to remain fixed.  With libpng 0.95 and later,
- * however, there are now functions that abstract the contents of
- * png_info_struct from the application, so this makes it easier to use
- * libpng with dynamic libraries, and even makes it possible to use
- * libraries that don't have all of the libpng ancillary chunk-handing
- * functionality.  In libpng-1.5.0 this was moved into a separate private
- * file that is not visible to applications.
- *
- * The following members may have allocated storage attached that should be
- * cleaned up before the structure is discarded: palette, trans, text,
- * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile,
- * splt_palettes, scal_unit, row_pointers, and unknowns.   By default, these
- * are automatically freed when the info structure is deallocated, if they were
- * allocated internally by libpng.  This behavior can be changed by means
- * of the png_data_freer() function.
- *
- * More allocation details: all the chunk-reading functions that
- * change these members go through the corresponding png_set_*
- * functions.  A function to clear these members is available: see
- * png_free_data().  The png_set_* functions do not depend on being
- * able to point info structure members to any of the storage they are
- * passed (they make their own copies), EXCEPT that the png_set_text
- * functions use the same storage passed to them in the text_ptr or
- * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns
- * functions do not make their own copies.
- */
-#ifndef PNGINFO_H
-#define PNGINFO_H
-
-struct png_info_def
-{
-   /* The following are necessary for every PNG file */
-   png_uint_32 width;       /* width of image in pixels (from IHDR) */
-   png_uint_32 height;      /* height of image in pixels (from IHDR) */
-   png_uint_32 valid;       /* valid chunk data (see PNG_INFO_ below) */
-   size_t rowbytes;         /* bytes needed to hold an untransformed row */
-   png_colorp palette;      /* array of color values (valid & PNG_INFO_PLTE) */
-   png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */
-   png_uint_16 num_trans;   /* number of transparent palette color (tRNS) */
-   png_byte bit_depth;      /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */
-   png_byte color_type;     /* see PNG_COLOR_TYPE_ below (from IHDR) */
-   /* The following three should have been named *_method not *_type */
-   png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */
-   png_byte filter_type;    /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
-   png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
-
-   /* The following are set by png_set_IHDR, called from the application on
-    * write, but the are never actually used by the write code.
-    */
-   png_byte channels;       /* number of data channels per pixel (1, 2, 3, 4) */
-   png_byte pixel_depth;    /* number of bits per pixel */
-   png_byte spare_byte;     /* to align the data, and for future use */
-
-#ifdef PNG_READ_SUPPORTED
-   /* This is never set during write */
-   png_byte signature[8];   /* magic bytes read by libpng from start of file */
-#endif
-
-   /* The rest of the data is optional.  If you are reading, check the
-    * valid field to see if the information in these are valid.  If you
-    * are writing, set the valid field to those chunks you want written,
-    * and initialize the appropriate fields below.
-    */
-
-#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
-   /* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
-    * defined.  When COLORSPACE is switched on all the colorspace-defining
-    * chunks should be enabled, when GAMMA is switched on all the gamma-defining
-    * chunks should be enabled.  If this is not done it becomes possible to read
-    * inconsistent PNG files and assign a probably incorrect interpretation to
-    * the information.  (In other words, by carefully choosing which chunks to
-    * recognize the system configuration can select an interpretation for PNG
-    * files containing ambiguous data and this will result in inconsistent
-    * behavior between different libpng builds!)
-    */
-   png_colorspace colorspace;
-#endif
-
-#ifdef PNG_iCCP_SUPPORTED
-   /* iCCP chunk data. */
-   png_charp iccp_name;     /* profile name */
-   png_bytep iccp_profile;  /* International Color Consortium profile data */
-   png_uint_32 iccp_proflen;  /* ICC profile data length */
-#endif
-
-#ifdef PNG_TEXT_SUPPORTED
-   /* The tEXt, and zTXt chunks contain human-readable textual data in
-    * uncompressed, compressed, and optionally compressed forms, respectively.
-    * The data in "text" is an array of pointers to uncompressed,
-    * null-terminated C strings. Each chunk has a keyword that describes the
-    * textual data contained in that chunk.  Keywords are not required to be
-    * unique, and the text string may be empty.  Any number of text chunks may
-    * be in an image.
-    */
-   int num_text; /* number of comments read or comments to write */
-   int max_text; /* current size of text array */
-   png_textp text; /* array of comments read or comments to write */
-#endif /* TEXT */
-
-#ifdef PNG_tIME_SUPPORTED
-   /* The tIME chunk holds the last time the displayed image data was
-    * modified.  See the png_time struct for the contents of this struct.
-    */
-   png_time mod_time;
-#endif
-
-#ifdef PNG_sBIT_SUPPORTED
-   /* The sBIT chunk specifies the number of significant high-order bits
-    * in the pixel data.  Values are in the range [1, bit_depth], and are
-    * only specified for the channels in the pixel data.  The contents of
-    * the low-order bits is not specified.  Data is valid if
-    * (valid & PNG_INFO_sBIT) is non-zero.
-    */
-   png_color_8 sig_bit; /* significant bits in color channels */
-#endif
-
-#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_EXPAND_SUPPORTED) || \
-defined(PNG_READ_BACKGROUND_SUPPORTED)
-   /* The tRNS chunk supplies transparency data for paletted images and
-    * other image types that don't need a full alpha channel.  There are
-    * "num_trans" transparency values for a paletted image, stored in the
-    * same order as the palette colors, starting from index 0.  Values
-    * for the data are in the range [0, 255], ranging from fully transparent
-    * to fully opaque, respectively.  For non-paletted images, there is a
-    * single color specified that should be treated as fully transparent.
-    * Data is valid if (valid & PNG_INFO_tRNS) is non-zero.
-    */
-   png_bytep trans_alpha;    /* alpha values for paletted image */
-   png_color_16 trans_color; /* transparent color for non-palette image */
-#endif
-
-#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
-   /* The bKGD chunk gives the suggested image background color if the
-    * display program does not have its own background color and the image
-    * is needs to composited onto a background before display.  The colors
-    * in "background" are normally in the same color space/depth as the
-    * pixel data.  Data is valid if (valid & PNG_INFO_bKGD) is non-zero.
-    */
-   png_color_16 background;
-#endif
-
-#ifdef PNG_oFFs_SUPPORTED
-   /* The oFFs chunk gives the offset in "offset_unit_type" units rightwards
-    * and downwards from the top-left corner of the display, page, or other
-    * application-specific co-ordinate space.  See the PNG_OFFSET_ defines
-    * below for the unit types.  Valid if (valid & PNG_INFO_oFFs) non-zero.
-    */
-   png_int_32 x_offset; /* x offset on page */
-   png_int_32 y_offset; /* y offset on page */
-   png_byte offset_unit_type; /* offset units type */
-#endif
-
-#ifdef PNG_pHYs_SUPPORTED
-   /* The pHYs chunk gives the physical pixel density of the image for
-    * display or printing in "phys_unit_type" units (see PNG_RESOLUTION_
-    * defines below).  Data is valid if (valid & PNG_INFO_pHYs) is non-zero.
-    */
-   png_uint_32 x_pixels_per_unit; /* horizontal pixel density */
-   png_uint_32 y_pixels_per_unit; /* vertical pixel density */
-   png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */
-#endif
-
-#ifdef PNG_eXIf_SUPPORTED
-   int num_exif;  /* Added at libpng-1.6.31 */
-   png_bytep exif;
-# ifdef PNG_READ_eXIf_SUPPORTED
-   png_bytep eXIf_buf;  /* Added at libpng-1.6.32 */
-# endif
-#endif
-
-#ifdef PNG_hIST_SUPPORTED
-   /* The hIST chunk contains the relative frequency or importance of the
-    * various palette entries, so that a viewer can intelligently select a
-    * reduced-color palette, if required.  Data is an array of "num_palette"
-    * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST)
-    * is non-zero.
-    */
-   png_uint_16p hist;
-#endif
-
-#ifdef PNG_pCAL_SUPPORTED
-   /* The pCAL chunk describes a transformation between the stored pixel
-    * values and original physical data values used to create the image.
-    * The integer range [0, 2^bit_depth - 1] maps to the floating-point
-    * range given by [pcal_X0, pcal_X1], and are further transformed by a
-    * (possibly non-linear) transformation function given by "pcal_type"
-    * and "pcal_params" into "pcal_units".  Please see the PNG_EQUATION_
-    * defines below, and the PNG-Group's PNG extensions document for a
-    * complete description of the transformations and how they should be
-    * implemented, and for a description of the ASCII parameter strings.
-    * Data values are valid if (valid & PNG_INFO_pCAL) non-zero.
-    */
-   png_charp pcal_purpose;  /* pCAL chunk description string */
-   png_int_32 pcal_X0;      /* minimum value */
-   png_int_32 pcal_X1;      /* maximum value */
-   png_charp pcal_units;    /* Latin-1 string giving physical units */
-   png_charpp pcal_params;  /* ASCII strings containing parameter values */
-   png_byte pcal_type;      /* equation type (see PNG_EQUATION_ below) */
-   png_byte pcal_nparams;   /* number of parameters given in pcal_params */
-#endif
-
-/* New members added in libpng-1.0.6 */
-   png_uint_32 free_me;     /* flags items libpng is responsible for freeing */
-
-#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-   /* Storage for unknown chunks that the library doesn't recognize. */
-   png_unknown_chunkp unknown_chunks;
-
-   /* The type of this field is limited by the type of
-    * png_struct::user_chunk_cache_max, else overflow can occur.
-    */
-   int                unknown_chunks_num;
-#endif
-
-#ifdef PNG_sPLT_SUPPORTED
-   /* Data on sPLT chunks (there may be more than one). */
-   png_sPLT_tp splt_palettes;
-   int         splt_palettes_num; /* Match type returned by png_get API */
-#endif
-
-#ifdef PNG_sCAL_SUPPORTED
-   /* The sCAL chunk describes the actual physical dimensions of the
-    * subject matter of the graphic.  The chunk contains a unit specification
-    * a byte value, and two ASCII strings representing floating-point
-    * values.  The values are width and height corresponding to one pixel
-    * in the image.  Data values are valid if (valid & PNG_INFO_sCAL) is
-    * non-zero.
-    */
-   png_byte scal_unit;         /* unit of physical scale */
-   png_charp scal_s_width;     /* string containing height */
-   png_charp scal_s_height;    /* string containing width */
-#endif
-
-#ifdef PNG_INFO_IMAGE_SUPPORTED
-   /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS)
-      non-zero */
-   /* Data valid if (valid & PNG_INFO_IDAT) non-zero */
-   png_bytepp row_pointers;        /* the image bits */
-#endif
-
-};
-#endif /* PNGINFO_H */
diff --git a/third_party/libpng16/pnglibconf.h b/third_party/libpng16/pnglibconf.h
deleted file mode 100644
index 308c606..0000000
--- a/third_party/libpng16/pnglibconf.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/* libpng 1.6.22 CUSTOM API DEFINITION */
-
-/* pnglibconf.h - library build configuration */
-
-/* Libpng version 1.6.22 - May 29, 2016 */
-
-/* Copyright (c) 1998-2015 Glenn Randers-Pehrson */
-
-/* This code is released under the libpng license. */
-/* For conditions of distribution and use, see the disclaimer */
-/* and license in png.h */
-
-/* pnglibconf.h */
-/* Derived from: scripts/pnglibconf.dfa */
-#ifndef PNGLCONF_H
-#define PNGLCONF_H
-
-/* default options */
-/* These are PNG options that match the default in scripts/pnglibconf.dfa */
-#define PNG_16BIT_SUPPORTED
-#define PNG_ALIGNED_MEMORY_SUPPORTED
-/*#undef PNG_ARM_NEON_API_SUPPORTED*/
-/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
-#define PNG_BENIGN_ERRORS_SUPPORTED
-#define PNG_BENIGN_READ_ERRORS_SUPPORTED
-/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
-#define PNG_COLORSPACE_SUPPORTED
-#define PNG_EASY_ACCESS_SUPPORTED
-/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
-#define PNG_ERROR_TEXT_SUPPORTED
-#define PNG_FIXED_POINT_SUPPORTED
-#define PNG_FLOATING_ARITHMETIC_SUPPORTED
-#define PNG_FLOATING_POINT_SUPPORTED
-#define PNG_FORMAT_AFIRST_SUPPORTED
-#define PNG_FORMAT_BGR_SUPPORTED
-#define PNG_GAMMA_SUPPORTED
-#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-#define PNG_INFO_IMAGE_SUPPORTED
-#define PNG_POINTER_INDEXING_SUPPORTED
-#define PNG_PROGRESSIVE_READ_SUPPORTED
-#define PNG_READ_16BIT_SUPPORTED
-#define PNG_READ_ALPHA_MODE_SUPPORTED
-#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
-#define PNG_READ_BACKGROUND_SUPPORTED
-#define PNG_READ_BGR_SUPPORTED
-#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
-#define PNG_READ_COMPRESSED_TEXT_SUPPORTED
-#define PNG_READ_EXPAND_16_SUPPORTED
-#define PNG_READ_EXPAND_SUPPORTED
-#define PNG_READ_FILLER_SUPPORTED
-#define PNG_READ_GAMMA_SUPPORTED
-#define PNG_READ_GRAY_TO_RGB_SUPPORTED
-#define PNG_READ_INTERLACING_SUPPORTED
-#define PNG_READ_INT_FUNCTIONS_SUPPORTED
-#define PNG_READ_PACKSWAP_SUPPORTED
-#define PNG_READ_PACK_SUPPORTED
-#define PNG_READ_RGB_TO_GRAY_SUPPORTED
-#define PNG_READ_SCALE_16_TO_8_SUPPORTED
-#define PNG_READ_SHIFT_SUPPORTED
-#define PNG_READ_STRIP_16_TO_8_SUPPORTED
-#define PNG_READ_STRIP_ALPHA_SUPPORTED
-#define PNG_READ_SUPPORTED
-#define PNG_READ_SWAP_ALPHA_SUPPORTED
-#define PNG_READ_SWAP_SUPPORTED
-#define PNG_READ_TEXT_SUPPORTED
-#define PNG_READ_TRANSFORMS_SUPPORTED
-#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_READ_USER_CHUNKS_SUPPORTED
-#define PNG_READ_USER_TRANSFORM_SUPPORTED
-#define PNG_READ_cHRM_SUPPORTED
-#define PNG_READ_gAMA_SUPPORTED
-#define PNG_READ_iCCP_SUPPORTED
-#define PNG_READ_sRGB_SUPPORTED
-#define PNG_READ_tEXt_SUPPORTED
-#define PNG_READ_tRNS_SUPPORTED
-#define PNG_READ_zTXt_SUPPORTED
-#define PNG_SAVE_INT_32_SUPPORTED
-#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_SEQUENTIAL_READ_SUPPORTED
-#define PNG_SETJMP_SUPPORTED
-#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_SET_USER_LIMITS_SUPPORTED
-#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
-#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED
-#define PNG_SIMPLIFIED_READ_SUPPORTED
-#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
-#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
-#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
-#define PNG_SIMPLIFIED_WRITE_SUPPORTED
-#define PNG_STDIO_SUPPORTED
-#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_TEXT_SUPPORTED
-#define PNG_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_USER_CHUNKS_SUPPORTED
-#define PNG_USER_LIMITS_SUPPORTED
-#define PNG_USER_MEM_SUPPORTED
-#define PNG_USER_TRANSFORM_INFO_SUPPORTED
-#define PNG_USER_TRANSFORM_PTR_SUPPORTED
-#define PNG_WARNINGS_SUPPORTED
-#define PNG_WRITE_16BIT_SUPPORTED
-#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
-#define PNG_WRITE_BGR_SUPPORTED
-#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
-#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
-#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
-#define PNG_WRITE_FILLER_SUPPORTED
-#define PNG_WRITE_FILTER_SUPPORTED
-#define PNG_WRITE_FLUSH_SUPPORTED
-#define PNG_WRITE_INTERLACING_SUPPORTED
-#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
-#define PNG_WRITE_PACKSWAP_SUPPORTED
-#define PNG_WRITE_PACK_SUPPORTED
-#define PNG_WRITE_SHIFT_SUPPORTED
-#define PNG_WRITE_SUPPORTED
-#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
-#define PNG_WRITE_SWAP_SUPPORTED
-#define PNG_WRITE_TEXT_SUPPORTED
-#define PNG_WRITE_TRANSFORMS_SUPPORTED
-#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
-#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
-#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
-#define PNG_WRITE_cHRM_SUPPORTED
-#define PNG_WRITE_gAMA_SUPPORTED
-#define PNG_WRITE_iCCP_SUPPORTED
-#define PNG_WRITE_sRGB_SUPPORTED
-#define PNG_WRITE_tEXt_SUPPORTED
-#define PNG_WRITE_tRNS_SUPPORTED
-#define PNG_WRITE_zTXt_SUPPORTED
-#define PNG_cHRM_SUPPORTED
-#define PNG_gAMA_SUPPORTED
-#define PNG_iCCP_SUPPORTED
-#define PNG_sBIT_SUPPORTED
-#define PNG_sRGB_SUPPORTED
-#define PNG_tEXt_SUPPORTED
-#define PNG_tRNS_SUPPORTED
-#define PNG_zTXt_SUPPORTED
-/* end of options */
-
-/* chromium options */
-/* These are PNG options that chromium chooses to explicitly disable */
-/*#undef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED*/
-/*#undef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED*/
-/*#undef PNG_CONSOLE_IO_SUPPORTED*/
-/*#undef PNG_CONVERT_tIME_SUPPORTED*/
-/*#undef PNG_GET_PALETTE_MAX_SUPPORTED*/
-/*#undef PNG_INCH_CONVERSIONS_SUPPORTED*/
-/*#undef PNG_IO_STATE_SUPPORTED*/
-/*#undef PNG_MNG_FEATURES_SUPPORTED*/
-/*#undef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED*/
-/*#undef PNG_READ_GET_PALETTE_MAX_SUPPORTED*/
-/*#undef PNG_READ_INVERT_ALPHA_SUPPORTED*/
-/*#undef PNG_READ_INVERT_SUPPORTED*/
-/*#undef PNG_READ_OPT_PLTE_SUPPORTED*/
-/*#undef PNG_READ_QUANTIZE_SUPPORTED*/
-/*#undef PNG_READ_bKGD_SUPPORTED*/
-/*#undef PNG_READ_hIST_SUPPORTED*/
-/*#undef PNG_READ_iTXt_SUPPORTED*/
-/*#undef PNG_READ_oFFs_SUPPORTED*/
-/*#undef PNG_READ_pCAL_SUPPORTED*/
-/*#undef PNG_READ_pHYs_SUPPORTED*/
-/*#undef PNG_READ_sBIT_SUPPORTED*/
-/*#undef PNG_READ_sCAL_SUPPORTED*/
-/*#undef PNG_READ_sPLT_SUPPORTED*/
-/*#undef PNG_READ_tIME_SUPPORTED*/
-/*#undef PNG_SET_OPTION_SUPPORTED*/
-/*#undef PNG_TIME_RFC1123_SUPPORTED*/
-/*#undef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED*/
-/*#undef PNG_WRITE_GET_PALETTE_MAX_SUPPORTED*/
-/*#undef PNG_WRITE_INVERT_ALPHA_SUPPORTED*/
-/*#undef PNG_WRITE_INVERT_SUPPORTED*/
-/*#undef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED*/
-/*#undef PNG_WRITE_bKGD_SUPPORTED*/
-/*#undef PNG_WRITE_hIST_SUPPORTED*/
-/*#undef PNG_WRITE_iTXt_SUPPORTED*/
-/*#undef PNG_WRITE_oFFs_SUPPORTED*/
-/*#undef PNG_WRITE_pCAL_SUPPORTED*/
-/*#undef PNG_WRITE_pHYs_SUPPORTED*/
-/*#undef PNG_WRITE_sBIT_SUPPORTED*/
-/*#undef PNG_WRITE_sCAL_SUPPORTED*/
-/*#undef PNG_WRITE_sPLT_SUPPORTED*/
-/*#undef PNG_WRITE_tIME_SUPPORTED*/
-/*#undef PNG_bKGD_SUPPORTED*/
-/*#undef PNG_hIST_SUPPORTED*/
-/*#undef PNG_iTXt_SUPPORTED*/
-/*#undef PNG_oFFs_SUPPORTED*/
-/*#undef PNG_pCAL_SUPPORTED*/
-/*#undef PNG_pHYs_SUPPORTED*/
-/*#undef PNG_sCAL_SUPPORTED*/
-/*#undef PNG_sPLT_SUPPORTED*/
-/*#undef PNG_tIME_SUPPORTED*/
-/* end of chromium options */
-
-/* default settings */
-/* These are PNG settings that match the default in scripts/pnglibconf.dfa */
-#define PNG_API_RULE 0
-#define PNG_DEFAULT_READ_MACROS 1
-#define PNG_GAMMA_THRESHOLD_FIXED 5000
-#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
-#define PNG_INFLATE_BUF_SIZE 1024
-#define PNG_LINKAGE_API extern
-#define PNG_LINKAGE_CALLBACK extern
-#define PNG_LINKAGE_DATA extern
-#define PNG_LINKAGE_FUNCTION extern
-#define PNG_MAX_GAMMA_8 11
-#define PNG_QUANTIZE_BLUE_BITS 5
-#define PNG_QUANTIZE_GREEN_BITS 5
-#define PNG_QUANTIZE_RED_BITS 5
-#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1)
-#define PNG_TEXT_Z_DEFAULT_STRATEGY 0
-#define PNG_USER_HEIGHT_MAX 1000000
-#define PNG_USER_WIDTH_MAX 1000000
-#define PNG_ZBUF_SIZE 8192
-#define PNG_ZLIB_VERNUM 0 /* unknown */
-#define PNG_Z_DEFAULT_COMPRESSION (-1)
-#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
-#define PNG_Z_DEFAULT_STRATEGY 1
-#define PNG_sCAL_PRECISION 5
-#define PNG_sRGB_PROFILE_CHECKS 2
-/* end of default settings */
-
-/* chromium settings */
-/* These are PNG setting that chromium has modified */
-/* crbug.com/117369 */
-#define PNG_USER_CHUNK_CACHE_MAX 128
-#define PNG_USER_CHUNK_MALLOC_MAX 4000000L
-/* end of chromium settings */
-
-/* pdfium prefixing */
-/*
- * This is necessary to build multiple copies of libpng.  We need this while pdfium builds
- * its own copy of libpng.
- */
-#include "pngprefix.h"
-/* end of pdfium prefixing */
-
-#endif /* PNGLCONF_H */
diff --git a/third_party/libpng16/pngmem.c b/third_party/libpng16/pngmem.c
deleted file mode 100644
index c624410..0000000
--- a/third_party/libpng16/pngmem.c
+++ /dev/null
@@ -1,286 +0,0 @@
-
-/* pngmem.c - stub functions for memory allocation
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- *
- * This file provides a location for all memory allocation.  Users who
- * need special memory handling are expected to supply replacement
- * functions for png_malloc() and png_free(), and to use
- * png_create_read_struct_2() and png_create_write_struct_2() to
- * identify the replacement functions.
- */
-
-#include "pngpriv.h"
-
-#include "core/fxcrt/fx_memory.h"
-
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-/* Free a png_struct */
-void /* PRIVATE */
-png_destroy_png_struct(png_structrp png_ptr)
-{
-   if (png_ptr != NULL)
-   {
-      /* png_free might call png_error and may certainly call
-       * png_get_mem_ptr, so fake a temporary png_struct to support this.
-       */
-      png_struct dummy_struct = *png_ptr;
-      memset(png_ptr, 0, (sizeof *png_ptr));
-      png_free(&dummy_struct, png_ptr);
-
-#     ifdef PNG_SETJMP_SUPPORTED
-         /* We may have a jmp_buf left to deallocate. */
-         png_free_jmpbuf(&dummy_struct);
-#     endif
-   }
-}
-
-/* Allocate memory.  For reasonable files, size should never exceed
- * 64K.  However, zlib may allocate more than 64K if you don't tell
- * it not to.  See zconf.h and png.h for more information.  zlib does
- * need to allocate exactly 64K, so whatever you call here must
- * have the ability to do that.
- */
-PNG_FUNCTION(png_voidp,PNGAPI
-png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
-{
-   png_voidp ret;
-
-   ret = png_malloc(png_ptr, size);
-
-   if (ret != NULL)
-      memset(ret, 0, size);
-
-   return ret;
-}
-
-/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of
- * allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED.
- * Checking and error handling must happen outside this routine; it returns NULL
- * if the allocation cannot be done (for any reason.)
- */
-PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
-    PNG_ALLOCATED)
-{
-   /* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS
-    * allocators have also been removed in 1.6.0, so any 16-bit system now has
-    * to implement a user memory handler.  This checks to be sure it isn't
-    * called with big numbers.
-    */
-#ifndef PNG_USER_MEM_SUPPORTED
-   PNG_UNUSED(png_ptr)
-#endif
-
-   /* Some compilers complain that this is always true.  However, it
-    * can be false when integer overflow happens.
-    */
-   if (size > 0 && size <= PNG_SIZE_MAX
-#     ifdef PNG_MAX_MALLOC_64K
-         && size <= 65536U
-#     endif
-      )
-   {
-#ifdef PNG_USER_MEM_SUPPORTED
-      if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
-         return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size);
-
-      else
-#endif
-         return FXMEM_DefaultAlloc(size);
-   }
-
-   else
-      return NULL;
-}
-
-#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
-   defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
-/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7
- * that arises because of the checks in png_realloc_array that are repeated in
- * png_malloc_array.
- */
-static png_voidp
-png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
-    size_t element_size)
-{
-   png_alloc_size_t req = (png_alloc_size_t)nelements; /* known to be > 0 */
-
-   if (req <= PNG_SIZE_MAX/element_size)
-      return png_malloc_base(png_ptr, req * element_size);
-
-   /* The failure case when the request is too large */
-   return NULL;
-}
-
-PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_malloc_array,(png_const_structrp png_ptr, int nelements,
-    size_t element_size),PNG_ALLOCATED)
-{
-   if (nelements <= 0 || element_size == 0)
-      png_error(png_ptr, "internal error: array alloc");
-
-   return png_malloc_array_checked(png_ptr, nelements, element_size);
-}
-
-PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
-    int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED)
-{
-   /* These are internal errors: */
-   if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
-      (old_array == NULL && old_elements > 0))
-      png_error(png_ptr, "internal error: array realloc");
-
-   /* Check for overflow on the elements count (so the caller does not have to
-    * check.)
-    */
-   if (add_elements <= INT_MAX - old_elements)
-   {
-      png_voidp new_array = png_malloc_array_checked(png_ptr,
-          old_elements+add_elements, element_size);
-
-      if (new_array != NULL)
-      {
-         /* Because png_malloc_array worked the size calculations below cannot
-          * overflow.
-          */
-         if (old_elements > 0)
-            memcpy(new_array, old_array, element_size*(unsigned)old_elements);
-
-         memset((char*)new_array + element_size*(unsigned)old_elements, 0,
-             element_size*(unsigned)add_elements);
-
-         return new_array;
-      }
-   }
-
-   return NULL; /* error */
-}
-#endif /* TEXT || sPLT || STORE_UNKNOWN_CHUNKS */
-
-/* Various functions that have different error handling are derived from this.
- * png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
- * function png_malloc_default is also provided.
- */
-PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
-{
-   png_voidp ret;
-
-   if (png_ptr == NULL)
-      return NULL;
-
-   ret = png_malloc_base(png_ptr, size);
-
-   if (ret == NULL)
-       png_error(png_ptr, "Out of memory"); /* 'm' means png_malloc */
-
-   return ret;
-}
-
-#ifdef PNG_USER_MEM_SUPPORTED
-PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size),
-    PNG_ALLOCATED PNG_DEPRECATED)
-{
-   png_voidp ret;
-
-   if (png_ptr == NULL)
-      return NULL;
-
-   /* Passing 'NULL' here bypasses the application provided memory handler. */
-   ret = png_malloc_base(NULL/*use malloc*/, size);
-
-   if (ret == NULL)
-      png_error(png_ptr, "Out of Memory"); /* 'M' means png_malloc_default */
-
-   return ret;
-}
-#endif /* USER_MEM */
-
-/* This function was added at libpng version 1.2.3.  The png_malloc_warn()
- * function will issue a png_warning and return NULL instead of issuing a
- * png_error, if it fails to allocate the requested memory.
- */
-PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size),
-    PNG_ALLOCATED)
-{
-   if (png_ptr != NULL)
-   {
-      png_voidp ret = png_malloc_base(png_ptr, size);
-
-      if (ret != NULL)
-         return ret;
-
-      png_warning(png_ptr, "Out of memory");
-   }
-
-   return NULL;
-}
-
-/* Free a pointer allocated by png_malloc().  If ptr is NULL, return
- * without taking any action.
- */
-void PNGAPI
-png_free(png_const_structrp png_ptr, png_voidp ptr)
-{
-   if (png_ptr == NULL || ptr == NULL)
-      return;
-
-#ifdef PNG_USER_MEM_SUPPORTED
-   if (png_ptr->free_fn != NULL)
-      png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr);
-
-   else
-      png_free_default(png_ptr, ptr);
-}
-
-PNG_FUNCTION(void,PNGAPI
-png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
-{
-   if (png_ptr == NULL || ptr == NULL)
-      return;
-#endif /* USER_MEM */
-
-   FXMEM_DefaultFree(ptr);
-}
-
-#ifdef PNG_USER_MEM_SUPPORTED
-/* This function is called when the application wants to use another method
- * of allocating and freeing memory.
- */
-void PNGAPI
-png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr
-  malloc_fn, png_free_ptr free_fn)
-{
-   if (png_ptr != NULL)
-   {
-      png_ptr->mem_ptr = mem_ptr;
-      png_ptr->malloc_fn = malloc_fn;
-      png_ptr->free_fn = free_fn;
-   }
-}
-
-/* This function returns a pointer to the mem_ptr associated with the user
- * functions.  The application should free any memory associated with this
- * pointer before png_write_destroy and png_read_destroy are called.
- */
-png_voidp PNGAPI
-png_get_mem_ptr(png_const_structrp png_ptr)
-{
-   if (png_ptr == NULL)
-      return NULL;
-
-   return png_ptr->mem_ptr;
-}
-#endif /* USER_MEM */
-#endif /* READ || WRITE */
diff --git a/third_party/libpng16/pngpread.c b/third_party/libpng16/pngpread.c
deleted file mode 100644
index e283627..0000000
--- a/third_party/libpng16/pngpread.c
+++ /dev/null
@@ -1,1096 +0,0 @@
-
-/* pngpread.c - read a png file in push mode
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include "pngpriv.h"
-
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-
-/* Push model modes */
-#define PNG_READ_SIG_MODE   0
-#define PNG_READ_CHUNK_MODE 1
-#define PNG_READ_IDAT_MODE  2
-#define PNG_READ_tEXt_MODE  4
-#define PNG_READ_zTXt_MODE  5
-#define PNG_READ_DONE_MODE  6
-#define PNG_READ_iTXt_MODE  7
-#define PNG_ERROR_MODE      8
-
-#define PNG_PUSH_SAVE_BUFFER_IF_FULL \
-if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
-   { png_push_save_buffer(png_ptr); return; }
-#define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \
-if (png_ptr->buffer_size < N) \
-   { png_push_save_buffer(png_ptr); return; }
-
-void PNGAPI
-png_process_data(png_structrp png_ptr, png_inforp info_ptr,
-    png_bytep buffer, size_t buffer_size)
-{
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   png_push_restore_buffer(png_ptr, buffer, buffer_size);
-
-   while (png_ptr->buffer_size)
-   {
-      png_process_some_data(png_ptr, info_ptr);
-   }
-}
-
-size_t PNGAPI
-png_process_data_pause(png_structrp png_ptr, int save)
-{
-   if (png_ptr != NULL)
-   {
-      /* It's easiest for the caller if we do the save; then the caller doesn't
-       * have to supply the same data again:
-       */
-      if (save != 0)
-         png_push_save_buffer(png_ptr);
-      else
-      {
-         /* This includes any pending saved bytes: */
-         size_t remaining = png_ptr->buffer_size;
-         png_ptr->buffer_size = 0;
-
-         /* So subtract the saved buffer size, unless all the data
-          * is actually 'saved', in which case we just return 0
-          */
-         if (png_ptr->save_buffer_size < remaining)
-            return remaining - png_ptr->save_buffer_size;
-      }
-   }
-
-   return 0;
-}
-
-png_uint_32 PNGAPI
-png_process_data_skip(png_structrp png_ptr)
-{
-/* TODO: Deprecate and remove this API.
- * Somewhere the implementation of this seems to have been lost,
- * or abandoned.  It was only to support some internal back-door access
- * to png_struct) in libpng-1.4.x.
- */
-   png_app_warning(png_ptr,
-"png_process_data_skip is not implemented in any current version of libpng");
-   return 0;
-}
-
-/* What we do with the incoming data depends on what we were previously
- * doing before we ran out of data...
- */
-void /* PRIVATE */
-png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
-{
-   if (png_ptr == NULL)
-      return;
-
-   switch (png_ptr->process_mode)
-   {
-      case PNG_READ_SIG_MODE:
-      {
-         png_push_read_sig(png_ptr, info_ptr);
-         break;
-      }
-
-      case PNG_READ_CHUNK_MODE:
-      {
-         png_push_read_chunk(png_ptr, info_ptr);
-         break;
-      }
-
-      case PNG_READ_IDAT_MODE:
-      {
-         png_push_read_IDAT(png_ptr);
-         break;
-      }
-
-      default:
-      {
-         png_ptr->buffer_size = 0;
-         break;
-      }
-   }
-}
-
-/* Read any remaining signature bytes from the stream and compare them with
- * the correct PNG signature.  It is possible that this routine is called
- * with bytes already read from the signature, either because they have been
- * checked by the calling application, or because of multiple calls to this
- * routine.
- */
-void /* PRIVATE */
-png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
-{
-   size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */
-   size_t num_to_check = 8 - num_checked;
-
-   if (png_ptr->buffer_size < num_to_check)
-   {
-      num_to_check = png_ptr->buffer_size;
-   }
-
-   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
-       num_to_check);
-   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
-
-   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
-   {
-      if (num_checked < 4 &&
-          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
-         png_error(png_ptr, "Not a PNG file");
-
-      else
-         png_error(png_ptr, "PNG file corrupted by ASCII conversion");
-   }
-   else
-   {
-      if (png_ptr->sig_bytes >= 8)
-      {
-         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
-      }
-   }
-}
-
-void /* PRIVATE */
-png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
-{
-   png_uint_32 chunk_name;
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-   int keep; /* unknown handling method */
-#endif
-
-   /* First we make sure we have enough data for the 4-byte chunk name
-    * and the 4-byte chunk length before proceeding with decoding the
-    * chunk data.  To fully decode each of these chunks, we also make
-    * sure we have enough data in the buffer for the 4-byte CRC at the
-    * end of every chunk (except IDAT, which is handled separately).
-    */
-   if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
-   {
-      png_byte chunk_length[4];
-      png_byte chunk_tag[4];
-
-      PNG_PUSH_SAVE_BUFFER_IF_LT(8)
-      png_push_fill_buffer(png_ptr, chunk_length, 4);
-      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
-      png_reset_crc(png_ptr);
-      png_crc_read(png_ptr, chunk_tag, 4);
-      png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
-      png_check_chunk_name(png_ptr, png_ptr->chunk_name);
-      png_check_chunk_length(png_ptr, png_ptr->push_length);
-      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
-   }
-
-   chunk_name = png_ptr->chunk_name;
-
-   if (chunk_name == png_IDAT)
-   {
-      if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
-         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
-
-      /* If we reach an IDAT chunk, this means we have read all of the
-       * header chunks, and we can start reading the image (or if this
-       * is called after the image has been read - we have an error).
-       */
-      if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-         png_error(png_ptr, "Missing IHDR before IDAT");
-
-      else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
-          (png_ptr->mode & PNG_HAVE_PLTE) == 0)
-         png_error(png_ptr, "Missing PLTE before IDAT");
-
-      png_ptr->process_mode = PNG_READ_IDAT_MODE;
-
-      if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-         if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
-            if (png_ptr->push_length == 0)
-               return;
-
-      png_ptr->mode |= PNG_HAVE_IDAT;
-
-      if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
-         png_benign_error(png_ptr, "Too many IDATs found");
-   }
-
-   if (chunk_name == png_IHDR)
-   {
-      if (png_ptr->push_length != 13)
-         png_error(png_ptr, "Invalid IHDR length");
-
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-   else if (chunk_name == png_IEND)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
-
-      png_ptr->process_mode = PNG_READ_DONE_MODE;
-      png_push_have_end(png_ptr, info_ptr);
-   }
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-   else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
-
-      if (chunk_name == png_PLTE)
-         png_ptr->mode |= PNG_HAVE_PLTE;
-   }
-#endif
-
-   else if (chunk_name == png_PLTE)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-   else if (chunk_name == png_IDAT)
-   {
-      png_ptr->idat_size = png_ptr->push_length;
-      png_ptr->process_mode = PNG_READ_IDAT_MODE;
-      png_push_have_info(png_ptr, info_ptr);
-      png_ptr->zstream.avail_out =
-          (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
-          png_ptr->iwidth) + 1;
-      png_ptr->zstream.next_out = png_ptr->row_buf;
-      return;
-   }
-
-#ifdef PNG_READ_gAMA_SUPPORTED
-   else if (png_ptr->chunk_name == png_gAMA)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_sBIT_SUPPORTED
-   else if (png_ptr->chunk_name == png_sBIT)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_cHRM_SUPPORTED
-   else if (png_ptr->chunk_name == png_cHRM)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_sRGB_SUPPORTED
-   else if (chunk_name == png_sRGB)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_iCCP_SUPPORTED
-   else if (png_ptr->chunk_name == png_iCCP)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_sPLT_SUPPORTED
-   else if (chunk_name == png_sPLT)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_tRNS_SUPPORTED
-   else if (chunk_name == png_tRNS)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_bKGD_SUPPORTED
-   else if (chunk_name == png_bKGD)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_hIST_SUPPORTED
-   else if (chunk_name == png_hIST)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_pHYs_SUPPORTED
-   else if (chunk_name == png_pHYs)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_oFFs_SUPPORTED
-   else if (chunk_name == png_oFFs)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
-   }
-#endif
-
-#ifdef PNG_READ_pCAL_SUPPORTED
-   else if (chunk_name == png_pCAL)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_sCAL_SUPPORTED
-   else if (chunk_name == png_sCAL)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_tIME_SUPPORTED
-   else if (chunk_name == png_tIME)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_tEXt_SUPPORTED
-   else if (chunk_name == png_tEXt)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_zTXt_SUPPORTED
-   else if (chunk_name == png_zTXt)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
-   }
-
-#endif
-#ifdef PNG_READ_iTXt_SUPPORTED
-   else if (chunk_name == png_iTXt)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
-   }
-#endif
-
-   else
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_FULL
-      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
-          PNG_HANDLE_CHUNK_AS_DEFAULT);
-   }
-
-   png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
-}
-
-void PNGCBAPI
-png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, size_t length)
-{
-   png_bytep ptr;
-
-   if (png_ptr == NULL)
-      return;
-
-   ptr = buffer;
-   if (png_ptr->save_buffer_size != 0)
-   {
-      size_t save_size;
-
-      if (length < png_ptr->save_buffer_size)
-         save_size = length;
-
-      else
-         save_size = png_ptr->save_buffer_size;
-
-      memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
-      length -= save_size;
-      ptr += save_size;
-      png_ptr->buffer_size -= save_size;
-      png_ptr->save_buffer_size -= save_size;
-      png_ptr->save_buffer_ptr += save_size;
-   }
-   if (length != 0 && png_ptr->current_buffer_size != 0)
-   {
-      size_t save_size;
-
-      if (length < png_ptr->current_buffer_size)
-         save_size = length;
-
-      else
-         save_size = png_ptr->current_buffer_size;
-
-      memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
-      png_ptr->buffer_size -= save_size;
-      png_ptr->current_buffer_size -= save_size;
-      png_ptr->current_buffer_ptr += save_size;
-   }
-}
-
-void /* PRIVATE */
-png_push_save_buffer(png_structrp png_ptr)
-{
-   if (png_ptr->save_buffer_size != 0)
-   {
-      if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
-      {
-         size_t i, istop;
-         png_bytep sp;
-         png_bytep dp;
-
-         istop = png_ptr->save_buffer_size;
-         for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
-             i < istop; i++, sp++, dp++)
-         {
-            *dp = *sp;
-         }
-      }
-   }
-   if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
-       png_ptr->save_buffer_max)
-   {
-      size_t new_max;
-      png_bytep old_buffer;
-
-      if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
-          (png_ptr->current_buffer_size + 256))
-      {
-         png_error(png_ptr, "Potential overflow of save_buffer");
-      }
-
-      new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
-      old_buffer = png_ptr->save_buffer;
-      png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
-          (size_t)new_max);
-
-      if (png_ptr->save_buffer == NULL)
-      {
-         png_free(png_ptr, old_buffer);
-         png_error(png_ptr, "Insufficient memory for save_buffer");
-      }
-
-      if (old_buffer)
-         memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
-      else if (png_ptr->save_buffer_size)
-         png_error(png_ptr, "save_buffer error");
-      png_free(png_ptr, old_buffer);
-      png_ptr->save_buffer_max = new_max;
-   }
-   if (png_ptr->current_buffer_size)
-   {
-      memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
-         png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
-      png_ptr->save_buffer_size += png_ptr->current_buffer_size;
-      png_ptr->current_buffer_size = 0;
-   }
-   png_ptr->save_buffer_ptr = png_ptr->save_buffer;
-   png_ptr->buffer_size = 0;
-}
-
-void /* PRIVATE */
-png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
-    size_t buffer_length)
-{
-   png_ptr->current_buffer = buffer;
-   png_ptr->current_buffer_size = buffer_length;
-   png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
-   png_ptr->current_buffer_ptr = png_ptr->current_buffer;
-}
-
-void /* PRIVATE */
-png_push_read_IDAT(png_structrp png_ptr)
-{
-   if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
-   {
-      png_byte chunk_length[4];
-      png_byte chunk_tag[4];
-
-      /* TODO: this code can be commoned up with the same code in push_read */
-      PNG_PUSH_SAVE_BUFFER_IF_LT(8)
-      png_push_fill_buffer(png_ptr, chunk_length, 4);
-      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
-      png_reset_crc(png_ptr);
-      png_crc_read(png_ptr, chunk_tag, 4);
-      png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
-      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
-
-      if (png_ptr->chunk_name != png_IDAT)
-      {
-         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
-
-         if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
-            png_error(png_ptr, "Not enough compressed data");
-
-         return;
-      }
-
-      png_ptr->idat_size = png_ptr->push_length;
-   }
-
-   if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
-   {
-      size_t save_size = png_ptr->save_buffer_size;
-      png_uint_32 idat_size = png_ptr->idat_size;
-
-      /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
-       * are of different types and we don't know which variable has the fewest
-       * bits.  Carefully select the smaller and cast it to the type of the
-       * larger - this cannot overflow.  Do not cast in the following test - it
-       * will break on either 16-bit or 64-bit platforms.
-       */
-      if (idat_size < save_size)
-         save_size = (size_t)idat_size;
-
-      else
-         idat_size = (png_uint_32)save_size;
-
-      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
-
-      png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
-
-      png_ptr->idat_size -= idat_size;
-      png_ptr->buffer_size -= save_size;
-      png_ptr->save_buffer_size -= save_size;
-      png_ptr->save_buffer_ptr += save_size;
-   }
-
-   if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
-   {
-      size_t save_size = png_ptr->current_buffer_size;
-      png_uint_32 idat_size = png_ptr->idat_size;
-
-      /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
-       * are of different types and we don't know which variable has the fewest
-       * bits.  Carefully select the smaller and cast it to the type of the
-       * larger - this cannot overflow.
-       */
-      if (idat_size < save_size)
-         save_size = (size_t)idat_size;
-
-      else
-         idat_size = (png_uint_32)save_size;
-
-      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
-
-      png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
-
-      png_ptr->idat_size -= idat_size;
-      png_ptr->buffer_size -= save_size;
-      png_ptr->current_buffer_size -= save_size;
-      png_ptr->current_buffer_ptr += save_size;
-   }
-
-   if (png_ptr->idat_size == 0)
-   {
-      PNG_PUSH_SAVE_BUFFER_IF_LT(4)
-      png_crc_finish(png_ptr, 0);
-      png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
-      png_ptr->mode |= PNG_AFTER_IDAT;
-      png_ptr->zowner = 0;
-   }
-}
-
-void /* PRIVATE */
-png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
-    size_t buffer_length)
-{
-   /* The caller checks for a non-zero buffer length. */
-   if (!(buffer_length > 0) || buffer == NULL)
-      png_error(png_ptr, "No IDAT data (internal error)");
-
-   /* This routine must process all the data it has been given
-    * before returning, calling the row callback as required to
-    * handle the uncompressed results.
-    */
-   png_ptr->zstream.next_in = buffer;
-   /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
-   png_ptr->zstream.avail_in = (uInt)buffer_length;
-
-   /* Keep going until the decompressed data is all processed
-    * or the stream marked as finished.
-    */
-   while (png_ptr->zstream.avail_in > 0 &&
-      (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
-   {
-      int ret;
-
-      /* We have data for zlib, but we must check that zlib
-       * has someplace to put the results.  It doesn't matter
-       * if we don't expect any results -- it may be the input
-       * data is just the LZ end code.
-       */
-      if (!(png_ptr->zstream.avail_out > 0))
-      {
-         /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
-         png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
-             png_ptr->iwidth) + 1);
-
-         png_ptr->zstream.next_out = png_ptr->row_buf;
-      }
-
-      /* Using Z_SYNC_FLUSH here means that an unterminated
-       * LZ stream (a stream with a missing end code) can still
-       * be handled, otherwise (Z_NO_FLUSH) a future zlib
-       * implementation might defer output and therefore
-       * change the current behavior (see comments in inflate.c
-       * for why this doesn't happen at present with zlib 1.2.5).
-       */
-      ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH);
-
-      /* Check for any failure before proceeding. */
-      if (ret != Z_OK && ret != Z_STREAM_END)
-      {
-         /* Terminate the decompression. */
-         png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
-         png_ptr->zowner = 0;
-
-         /* This may be a truncated stream (missing or
-          * damaged end code).  Treat that as a warning.
-          */
-         if (png_ptr->row_number >= png_ptr->num_rows ||
-             png_ptr->pass > 6)
-            png_warning(png_ptr, "Truncated compressed data in IDAT");
-
-         else
-         {
-            if (ret == Z_DATA_ERROR)
-               png_benign_error(png_ptr, "IDAT: ADLER32 checksum mismatch");
-            else
-               png_error(png_ptr, "Decompression error in IDAT");
-         }
-
-         /* Skip the check on unprocessed input */
-         return;
-      }
-
-      /* Did inflate output any data? */
-      if (png_ptr->zstream.next_out != png_ptr->row_buf)
-      {
-         /* Is this unexpected data after the last row?
-          * If it is, artificially terminate the LZ output
-          * here.
-          */
-         if (png_ptr->row_number >= png_ptr->num_rows ||
-             png_ptr->pass > 6)
-         {
-            /* Extra data. */
-            png_warning(png_ptr, "Extra compressed data in IDAT");
-            png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
-            png_ptr->zowner = 0;
-
-            /* Do no more processing; skip the unprocessed
-             * input check below.
-             */
-            return;
-         }
-
-         /* Do we have a complete row? */
-         if (png_ptr->zstream.avail_out == 0)
-            png_push_process_row(png_ptr);
-      }
-
-      /* And check for the end of the stream. */
-      if (ret == Z_STREAM_END)
-         png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
-   }
-
-   /* All the data should have been processed, if anything
-    * is left at this point we have bytes of IDAT data
-    * after the zlib end code.
-    */
-   if (png_ptr->zstream.avail_in > 0)
-      png_warning(png_ptr, "Extra compression data in IDAT");
-}
-
-void /* PRIVATE */
-png_push_process_row(png_structrp png_ptr)
-{
-   /* 1.5.6: row_info moved out of png_struct to a local here. */
-   png_row_info row_info;
-
-   row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
-   row_info.color_type = png_ptr->color_type;
-   row_info.bit_depth = png_ptr->bit_depth;
-   row_info.channels = png_ptr->channels;
-   row_info.pixel_depth = png_ptr->pixel_depth;
-   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
-
-   if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
-   {
-      if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
-         png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
-            png_ptr->prev_row + 1, png_ptr->row_buf[0]);
-      else
-         png_error(png_ptr, "bad adaptive filter value");
-   }
-
-   /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
-    * 1.5.6, while the buffer really is this big in current versions of libpng
-    * it may not be in the future, so this was changed just to copy the
-    * interlaced row count:
-    */
-   memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
-
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-   if (png_ptr->transformations != 0)
-      png_do_read_transformations(png_ptr, &row_info);
-#endif
-
-   /* The transformed pixel depth should match the depth now in row_info. */
-   if (png_ptr->transformed_pixel_depth == 0)
-   {
-      png_ptr->transformed_pixel_depth = row_info.pixel_depth;
-      if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
-         png_error(png_ptr, "progressive row overflow");
-   }
-
-   else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
-      png_error(png_ptr, "internal progressive row size calculation error");
-
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   /* Expand interlaced rows to full size */
-   if (png_ptr->interlaced != 0 &&
-       (png_ptr->transformations & PNG_INTERLACE) != 0)
-   {
-      if (png_ptr->pass < 6)
-         png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
-             png_ptr->transformations);
-
-      switch (png_ptr->pass)
-      {
-         case 0:
-         {
-            int i;
-            for (i = 0; i < 8 && png_ptr->pass == 0; i++)
-            {
-               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
-               png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
-            }
-
-            if (png_ptr->pass == 2) /* Pass 1 might be empty */
-            {
-               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
-               {
-                  png_push_have_row(png_ptr, NULL);
-                  png_read_push_finish_row(png_ptr);
-               }
-            }
-
-            if (png_ptr->pass == 4 && png_ptr->height <= 4)
-            {
-               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
-               {
-                  png_push_have_row(png_ptr, NULL);
-                  png_read_push_finish_row(png_ptr);
-               }
-            }
-
-            if (png_ptr->pass == 6 && png_ptr->height <= 4)
-            {
-                png_push_have_row(png_ptr, NULL);
-                png_read_push_finish_row(png_ptr);
-            }
-
-            break;
-         }
-
-         case 1:
-         {
-            int i;
-            for (i = 0; i < 8 && png_ptr->pass == 1; i++)
-            {
-               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
-               png_read_push_finish_row(png_ptr);
-            }
-
-            if (png_ptr->pass == 2) /* Skip top 4 generated rows */
-            {
-               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
-               {
-                  png_push_have_row(png_ptr, NULL);
-                  png_read_push_finish_row(png_ptr);
-               }
-            }
-
-            break;
-         }
-
-         case 2:
-         {
-            int i;
-
-            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
-            {
-               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
-               png_read_push_finish_row(png_ptr);
-            }
-
-            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
-            {
-               png_push_have_row(png_ptr, NULL);
-               png_read_push_finish_row(png_ptr);
-            }
-
-            if (png_ptr->pass == 4) /* Pass 3 might be empty */
-            {
-               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
-               {
-                  png_push_have_row(png_ptr, NULL);
-                  png_read_push_finish_row(png_ptr);
-               }
-            }
-
-            break;
-         }
-
-         case 3:
-         {
-            int i;
-
-            for (i = 0; i < 4 && png_ptr->pass == 3; i++)
-            {
-               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
-               png_read_push_finish_row(png_ptr);
-            }
-
-            if (png_ptr->pass == 4) /* Skip top two generated rows */
-            {
-               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
-               {
-                  png_push_have_row(png_ptr, NULL);
-                  png_read_push_finish_row(png_ptr);
-               }
-            }
-
-            break;
-         }
-
-         case 4:
-         {
-            int i;
-
-            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
-            {
-               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
-               png_read_push_finish_row(png_ptr);
-            }
-
-            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
-            {
-               png_push_have_row(png_ptr, NULL);
-               png_read_push_finish_row(png_ptr);
-            }
-
-            if (png_ptr->pass == 6) /* Pass 5 might be empty */
-            {
-               png_push_have_row(png_ptr, NULL);
-               png_read_push_finish_row(png_ptr);
-            }
-
-            break;
-         }
-
-         case 5:
-         {
-            int i;
-
-            for (i = 0; i < 2 && png_ptr->pass == 5; i++)
-            {
-               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
-               png_read_push_finish_row(png_ptr);
-            }
-
-            if (png_ptr->pass == 6) /* Skip top generated row */
-            {
-               png_push_have_row(png_ptr, NULL);
-               png_read_push_finish_row(png_ptr);
-            }
-
-            break;
-         }
-
-         default:
-         case 6:
-         {
-            png_push_have_row(png_ptr, png_ptr->row_buf + 1);
-            png_read_push_finish_row(png_ptr);
-
-            if (png_ptr->pass != 6)
-               break;
-
-            png_push_have_row(png_ptr, NULL);
-            png_read_push_finish_row(png_ptr);
-         }
-      }
-   }
-   else
-#endif
-   {
-      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
-      png_read_push_finish_row(png_ptr);
-   }
-}
-
-void /* PRIVATE */
-png_read_push_finish_row(png_structrp png_ptr)
-{
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-
-   /* Start of interlace block */
-   static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
-
-   /* Offset to next interlace block */
-   static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
-
-   /* Start of interlace block in the y direction */
-   static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
-
-   /* Offset to next interlace block in the y direction */
-   static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
-
-   /* Height of interlace block.  This is not currently used - if you need
-    * it, uncomment it here and in png.h
-   static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
-   */
-#endif
-
-   png_ptr->row_number++;
-   if (png_ptr->row_number < png_ptr->num_rows)
-      return;
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   if (png_ptr->interlaced != 0)
-   {
-      png_ptr->row_number = 0;
-      memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
-
-      do
-      {
-         png_ptr->pass++;
-         if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
-             (png_ptr->pass == 3 && png_ptr->width < 3) ||
-             (png_ptr->pass == 5 && png_ptr->width < 2))
-            png_ptr->pass++;
-
-         if (png_ptr->pass > 7)
-            png_ptr->pass--;
-
-         if (png_ptr->pass >= 7)
-            break;
-
-         png_ptr->iwidth = (png_ptr->width +
-             png_pass_inc[png_ptr->pass] - 1 -
-             png_pass_start[png_ptr->pass]) /
-             png_pass_inc[png_ptr->pass];
-
-         if ((png_ptr->transformations & PNG_INTERLACE) != 0)
-            break;
-
-         png_ptr->num_rows = (png_ptr->height +
-             png_pass_yinc[png_ptr->pass] - 1 -
-             png_pass_ystart[png_ptr->pass]) /
-             png_pass_yinc[png_ptr->pass];
-
-      } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
-   }
-#endif /* READ_INTERLACING */
-}
-
-void /* PRIVATE */
-png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
-{
-   if (png_ptr->info_fn != NULL)
-      (*(png_ptr->info_fn))(png_ptr, info_ptr);
-}
-
-void /* PRIVATE */
-png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
-{
-   if (png_ptr->end_fn != NULL)
-      (*(png_ptr->end_fn))(png_ptr, info_ptr);
-}
-
-void /* PRIVATE */
-png_push_have_row(png_structrp png_ptr, png_bytep row)
-{
-   if (png_ptr->row_fn != NULL)
-      (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
-          (int)png_ptr->pass);
-}
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-void PNGAPI
-png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
-    png_const_bytep new_row)
-{
-   if (png_ptr == NULL)
-      return;
-
-   /* new_row is a flag here - if it is NULL then the app callback was called
-    * from an empty row (see the calls to png_struct::row_fn below), otherwise
-    * it must be png_ptr->row_buf+1
-    */
-   if (new_row != NULL)
-      png_combine_row(png_ptr, old_row, 1/*blocky display*/);
-}
-#endif /* READ_INTERLACING */
-
-void PNGAPI
-png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
-    png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
-    png_progressive_end_ptr end_fn)
-{
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->info_fn = info_fn;
-   png_ptr->row_fn = row_fn;
-   png_ptr->end_fn = end_fn;
-
-   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
-}
-
-png_voidp PNGAPI
-png_get_progressive_ptr(png_const_structrp png_ptr)
-{
-   if (png_ptr == NULL)
-      return (NULL);
-
-   return png_ptr->io_ptr;
-}
-#endif /* PROGRESSIVE_READ */
diff --git a/third_party/libpng16/pngprefix.h b/third_party/libpng16/pngprefix.h
deleted file mode 100644
index ebc6afa..0000000
--- a/third_party/libpng16/pngprefix.h
+++ /dev/null
@@ -1,461 +0,0 @@
-// Copyright 2016 The PDFium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef PNGPREFIX_H
-#define PNGPREFIX_H
-
-// The purpose of this file is to rename conflicting functions
-// when this version of libpng and chromium's version of it are
-// both simultaneously present.
-
-#define png_access_version_number PDFIUM_png_access_version_number
-#define png_app_error PDFIUM_png_app_error
-#define png_app_warning PDFIUM_png_app_warning
-#define png_ascii_from_fixed PDFIUM_png_ascii_from_fixed
-#define png_ascii_from_fp PDFIUM_png_ascii_from_fp
-#define png_benign_error PDFIUM_png_benign_error
-#define png_build_gamma_table PDFIUM_png_build_gamma_table
-#define png_build_grayscale_palette PDFIUM_png_build_grayscale_palette
-#define png_calculate_crc PDFIUM_png_calculate_crc
-#define png_calloc PDFIUM_png_calloc
-#define png_check_IHDR PDFIUM_png_check_IHDR
-#define png_check_chunk_length PDFIUM_png_check_chunk_length
-#define png_check_chunk_name PDFIUM_png_check_chunk_name
-#define png_check_fp_number PDFIUM_png_check_fp_number
-#define png_check_fp_string PDFIUM_png_check_fp_string
-#define png_check_keyword PDFIUM_png_check_keyword
-#define png_chunk_benign_error PDFIUM_png_chunk_benign_error
-#define png_chunk_error PDFIUM_png_chunk_error
-#define png_chunk_report PDFIUM_png_chunk_report
-#define png_chunk_unknown_handling PDFIUM_png_chunk_unknown_handling
-#define png_chunk_warning PDFIUM_png_chunk_warning
-#define png_colorspace_set_ICC PDFIUM_png_colorspace_set_ICC
-#define png_colorspace_set_chromaticities PDFIUM_png_colorspace_set_chromaticities
-#define png_colorspace_set_endpoints PDFIUM_png_colorspace_set_endpoints
-#define png_colorspace_set_gamma PDFIUM_png_colorspace_set_gamma
-#define png_colorspace_set_rgb_coefficients PDFIUM_png_colorspace_set_rgb_coefficients
-#define png_colorspace_set_sRGB PDFIUM_png_colorspace_set_sRGB
-#define png_colorspace_sync PDFIUM_png_colorspace_sync
-#define png_colorspace_sync_info PDFIUM_png_colorspace_sync_info
-#define png_combine_row PDFIUM_png_combine_row
-#define png_compress_IDAT PDFIUM_png_compress_IDAT
-#define png_convert_from_struct_tm PDFIUM_png_convert_from_struct_tm
-#define png_convert_from_time_t PDFIUM_png_convert_from_time_t
-#define png_convert_to_rfc1123 PDFIUM_png_convert_to_rfc1123
-#define png_convert_to_rfc1123_buffer PDFIUM_png_convert_to_rfc1123_buffer
-#define png_crc_error PDFIUM_png_crc_error
-#define png_crc_finish PDFIUM_png_crc_finish
-#define png_crc_read PDFIUM_png_crc_read
-#define png_create_info_struct PDFIUM_png_create_info_struct
-#define png_create_png_struct PDFIUM_png_create_png_struct
-#define png_create_read_struct PDFIUM_png_create_read_struct
-#define png_create_read_struct_2 PDFIUM_png_create_read_struct_2
-#define png_create_write_struct PDFIUM_png_create_write_struct
-#define png_create_write_struct_2 PDFIUM_png_create_write_struct_2
-#define png_data_freer PDFIUM_png_data_freer
-#define png_default_flush PDFIUM_png_default_flush
-#define png_default_read_data PDFIUM_png_default_read_data
-#define png_default_write_data PDFIUM_png_default_write_data
-#define png_destroy_gamma_table PDFIUM_png_destroy_gamma_table
-#define png_destroy_info_struct PDFIUM_png_destroy_info_struct
-#define png_destroy_png_struct PDFIUM_png_destroy_png_struct
-#define png_destroy_read_struct PDFIUM_png_destroy_read_struct
-#define png_destroy_write_struct PDFIUM_png_destroy_write_struct
-#define png_do_bgr PDFIUM_png_do_bgr
-#define png_do_check_palette_indexes PDFIUM_png_do_check_palette_indexes
-#define png_do_chop PDFIUM_png_do_chop
-#define png_do_compose PDFIUM_png_do_compose
-#define png_do_encode_alpha PDFIUM_png_do_encode_alpha
-#define png_do_expand PDFIUM_png_do_expand
-#define png_do_expand_16 PDFIUM_png_do_expand_16
-#define png_do_expand_palette PDFIUM_png_do_expand_palette
-#define png_do_expand_palette_neon_rgb PDFIUM_png_do_expand_palette_neon_rgb
-#define png_do_expand_palette_neon_rgba PDFIUM_png_do_expand_palette_neon_rgba
-#define png_do_gamma PDFIUM_png_do_gamma
-#define png_do_gray_to_rgb PDFIUM_png_do_gray_to_rgb
-#define png_do_invert PDFIUM_png_do_invert
-#define png_do_pack PDFIUM_png_do_pack
-#define png_do_packswap PDFIUM_png_do_packswap
-#define png_do_quantize PDFIUM_png_do_quantize
-#define png_do_read_filler PDFIUM_png_do_read_filler
-#define png_do_read_interlace PDFIUM_png_do_read_interlace
-#define png_do_read_intrapixel PDFIUM_png_do_read_intrapixel
-#define png_do_read_invert_alpha PDFIUM_png_do_read_invert_alpha
-#define png_do_read_swap_alpha PDFIUM_png_do_read_swap_alpha
-#define png_do_read_transformations PDFIUM_png_do_read_transformations
-#define png_do_rgb_to_gray PDFIUM_png_do_rgb_to_gray
-#define png_do_scale_16_to_8 PDFIUM_png_do_scale_16_to_8
-#define png_do_shift PDFIUM_png_do_shift
-#define png_do_strip_channel PDFIUM_png_do_strip_channel
-#define png_do_swap PDFIUM_png_do_swap
-#define png_do_unpack PDFIUM_png_do_unpack
-#define png_do_unshift PDFIUM_png_do_unshift
-#define png_do_write_interlace PDFIUM_png_do_write_interlace
-#define png_do_write_intrapixel PDFIUM_png_do_write_intrapixel
-#define png_do_write_invert_alpha PDFIUM_png_do_write_invert_alpha
-#define png_do_write_swap_alpha PDFIUM_png_do_write_swap_alpha
-#define png_do_write_transformations PDFIUM_png_do_write_transformations
-#define png_error PDFIUM_png_error
-#define png_fixed PDFIUM_png_fixed
-#define png_fixed_error PDFIUM_png_fixed_error
-#define png_flush PDFIUM_png_flush
-#define png_format_number PDFIUM_png_format_number
-#define png_formatted_warning PDFIUM_png_formatted_warning
-#define png_free PDFIUM_png_free
-#define png_free_buffer_list PDFIUM_png_free_buffer_list
-#define png_free_data PDFIUM_png_free_data
-#define png_free_default PDFIUM_png_free_default
-#define png_free_jmpbuf PDFIUM_png_free_jmpbuf
-#define png_gamma_16bit_correct PDFIUM_png_gamma_16bit_correct
-#define png_gamma_8bit_correct PDFIUM_png_gamma_8bit_correct
-#define png_gamma_correct PDFIUM_png_gamma_correct
-#define png_gamma_significant PDFIUM_png_gamma_significant
-#define png_get_IHDR PDFIUM_png_get_IHDR
-#define png_get_PLTE PDFIUM_png_get_PLTE
-#define png_get_bKGD PDFIUM_png_get_bKGD
-#define png_get_bit_depth PDFIUM_png_get_bit_depth
-#define png_get_cHRM PDFIUM_png_get_cHRM
-#define png_get_cHRM_XYZ PDFIUM_png_get_cHRM_XYZ
-#define png_get_cHRM_XYZ_fixed PDFIUM_png_get_cHRM_XYZ_fixed
-#define png_get_cHRM_fixed PDFIUM_png_get_cHRM_fixed
-#define png_get_channels PDFIUM_png_get_channels
-#define png_get_chunk_cache_max PDFIUM_png_get_chunk_cache_max
-#define png_get_chunk_malloc_max PDFIUM_png_get_chunk_malloc_max
-#define png_get_color_type PDFIUM_png_get_color_type
-#define png_get_compression_buffer_size PDFIUM_png_get_compression_buffer_size
-#define png_get_compression_type PDFIUM_png_get_compression_type
-#define png_get_copyright PDFIUM_png_get_copyright
-#define png_get_current_pass_number PDFIUM_png_get_current_pass_number
-#define png_get_current_row_number PDFIUM_png_get_current_row_number
-#define png_get_eXIf PDFIUM_png_get_eXIf
-#define png_get_eXIf_1 PDFIUM_png_get_eXIf_1
-#define png_get_error_ptr PDFIUM_png_get_error_ptr
-#define png_get_filter_type PDFIUM_png_get_filter_type
-#define png_get_gAMA PDFIUM_png_get_gAMA
-#define png_get_gAMA_fixed PDFIUM_png_get_gAMA_fixed
-#define png_get_hIST PDFIUM_png_get_hIST
-#define png_get_header_ver PDFIUM_png_get_header_ver
-#define png_get_header_version PDFIUM_png_get_header_version
-#define png_get_iCCP PDFIUM_png_get_iCCP
-#define png_get_image_height PDFIUM_png_get_image_height
-#define png_get_image_width PDFIUM_png_get_image_width
-#define png_get_int_32 PDFIUM_png_get_int_32
-#define png_get_interlace_type PDFIUM_png_get_interlace_type
-#define png_get_io_chunk_type PDFIUM_png_get_io_chunk_type
-#define png_get_io_ptr PDFIUM_png_get_io_ptr
-#define png_get_io_state PDFIUM_png_get_io_state
-#define png_get_libpng_ver PDFIUM_png_get_libpng_ver
-#define png_get_mem_ptr PDFIUM_png_get_mem_ptr
-#define png_get_oFFs PDFIUM_png_get_oFFs
-#define png_get_pCAL PDFIUM_png_get_pCAL
-#define png_get_pHYs PDFIUM_png_get_pHYs
-#define png_get_pHYs_dpi PDFIUM_png_get_pHYs_dpi
-#define png_get_palette_max PDFIUM_png_get_palette_max
-#define png_get_pixel_aspect_ratio PDFIUM_png_get_pixel_aspect_ratio
-#define png_get_pixel_aspect_ratio_fixed PDFIUM_png_get_pixel_aspect_ratio_fixed
-#define png_get_pixels_per_inch PDFIUM_png_get_pixels_per_inch
-#define png_get_pixels_per_meter PDFIUM_png_get_pixels_per_meter
-#define png_get_progressive_ptr PDFIUM_png_get_progressive_ptr
-#define png_get_rgb_to_gray_status PDFIUM_png_get_rgb_to_gray_status
-#define png_get_rowbytes PDFIUM_png_get_rowbytes
-#define png_get_rows PDFIUM_png_get_rows
-#define png_get_sBIT PDFIUM_png_get_sBIT
-#define png_get_sCAL PDFIUM_png_get_sCAL
-#define png_get_sCAL_fixed PDFIUM_png_get_sCAL_fixed
-#define png_get_sCAL_s PDFIUM_png_get_sCAL_s
-#define png_get_sPLT PDFIUM_png_get_sPLT
-#define png_get_sRGB PDFIUM_png_get_sRGB
-#define png_get_signature PDFIUM_png_get_signature
-#define png_get_tIME PDFIUM_png_get_tIME
-#define png_get_tRNS PDFIUM_png_get_tRNS
-#define png_get_text PDFIUM_png_get_text
-#define png_get_uint_16 PDFIUM_png_get_uint_16
-#define png_get_uint_31 PDFIUM_png_get_uint_31
-#define png_get_uint_32 PDFIUM_png_get_uint_32
-#define png_get_unknown_chunks PDFIUM_png_get_unknown_chunks
-#define png_get_user_chunk_ptr PDFIUM_png_get_user_chunk_ptr
-#define png_get_user_height_max PDFIUM_png_get_user_height_max
-#define png_get_user_transform_ptr PDFIUM_png_get_user_transform_ptr
-#define png_get_user_width_max PDFIUM_png_get_user_width_max
-#define png_get_valid PDFIUM_png_get_valid
-#define png_get_x_offset_inches PDFIUM_png_get_x_offset_inches
-#define png_get_x_offset_inches_fixed PDFIUM_png_get_x_offset_inches_fixed
-#define png_get_x_offset_microns PDFIUM_png_get_x_offset_microns
-#define png_get_x_offset_pixels PDFIUM_png_get_x_offset_pixels
-#define png_get_x_pixels_per_inch PDFIUM_png_get_x_pixels_per_inch
-#define png_get_x_pixels_per_meter PDFIUM_png_get_x_pixels_per_meter
-#define png_get_y_offset_inches PDFIUM_png_get_y_offset_inches
-#define png_get_y_offset_inches_fixed PDFIUM_png_get_y_offset_inches_fixed
-#define png_get_y_offset_microns PDFIUM_png_get_y_offset_microns
-#define png_get_y_offset_pixels PDFIUM_png_get_y_offset_pixels
-#define png_get_y_pixels_per_inch PDFIUM_png_get_y_pixels_per_inch
-#define png_get_y_pixels_per_meter PDFIUM_png_get_y_pixels_per_meter
-#define png_handle_IEND PDFIUM_png_handle_IEND
-#define png_handle_IHDR PDFIUM_png_handle_IHDR
-#define png_handle_PLTE PDFIUM_png_handle_PLTE
-#define png_handle_as_unknown PDFIUM_png_handle_as_unknown
-#define png_handle_bKGD PDFIUM_png_handle_bKGD
-#define png_handle_cHRM PDFIUM_png_handle_cHRM
-#define png_handle_gAMA PDFIUM_png_handle_gAMA
-#define png_handle_hIST PDFIUM_png_handle_hIST
-#define png_handle_iCCP PDFIUM_png_handle_iCCP
-#define png_handle_iTXt PDFIUM_png_handle_iTXt
-#define png_handle_oFFs PDFIUM_png_handle_oFFs
-#define png_handle_pCAL PDFIUM_png_handle_pCAL
-#define png_handle_pHYs PDFIUM_png_handle_pHYs
-#define png_handle_sBIT PDFIUM_png_handle_sBIT
-#define png_handle_sCAL PDFIUM_png_handle_sCAL
-#define png_handle_sPLT PDFIUM_png_handle_sPLT
-#define png_handle_sRGB PDFIUM_png_handle_sRGB
-#define png_handle_tEXt PDFIUM_png_handle_tEXt
-#define png_handle_tIME PDFIUM_png_handle_tIME
-#define png_handle_tRNS PDFIUM_png_handle_tRNS
-#define png_handle_unknown PDFIUM_png_handle_unknown
-#define png_handle_zTXt PDFIUM_png_handle_zTXt
-#define png_icc_check_header PDFIUM_png_icc_check_header
-#define png_icc_check_length PDFIUM_png_icc_check_length
-#define png_icc_check_tag_table PDFIUM_png_icc_check_tag_table
-#define png_icc_set_sRGB PDFIUM_png_icc_set_sRGB
-#define png_image_begin_read_from_file PDFIUM_png_image_begin_read_from_file
-#define png_image_begin_read_from_memory PDFIUM_png_image_begin_read_from_memory
-#define png_image_begin_read_from_stdio PDFIUM_png_image_begin_read_from_stdio
-#define png_image_error PDFIUM_png_image_error
-#define png_image_finish_read PDFIUM_png_image_finish_read
-#define png_image_free PDFIUM_png_image_free
-#define png_image_write_to_file PDFIUM_png_image_write_to_file
-#define png_image_write_to_memory PDFIUM_png_image_write_to_memory
-#define png_image_write_to_stdio PDFIUM_png_image_write_to_stdio
-#define png_info_init_3 PDFIUM_png_info_init_3
-#define png_init_filter_functions_neon PDFIUM_png_init_filter_functions_neon
-#define png_init_filter_functions_sse2 PDFIUM_png_init_filter_functions_sse2
-#define png_init_io PDFIUM_png_init_io
-#define png_init_read_transformations PDFIUM_png_init_read_transformations
-#define png_longjmp PDFIUM_png_longjmp
-#define png_malloc PDFIUM_png_malloc
-#define png_malloc_array PDFIUM_png_malloc_array
-#define png_malloc_base PDFIUM_png_malloc_base
-#define png_malloc_default PDFIUM_png_malloc_default
-#define png_malloc_warn PDFIUM_png_malloc_warn
-#define png_muldiv PDFIUM_png_muldiv
-#define png_muldiv_warn PDFIUM_png_muldiv_warn
-#define png_permit_mng_features PDFIUM_png_permit_mng_features
-#define png_process_IDAT_data PDFIUM_png_process_IDAT_data
-#define png_process_data PDFIUM_png_process_data
-#define png_process_data_pause PDFIUM_png_process_data_pause
-#define png_process_data_skip PDFIUM_png_process_data_skip
-#define png_process_some_data PDFIUM_png_process_some_data
-#define png_progressive_combine_row PDFIUM_png_progressive_combine_row
-#define png_push_check_crc PDFIUM_png_push_check_crc
-#define png_push_crc_finish PDFIUM_png_push_crc_finish
-#define png_push_crc_skip PDFIUM_png_push_crc_skip
-#define png_push_fill_buffer PDFIUM_png_push_fill_buffer
-#define png_push_handle_iTXt PDFIUM_png_push_handle_iTXt
-#define png_push_handle_tEXt PDFIUM_png_push_handle_tEXt
-#define png_push_handle_unknown PDFIUM_png_push_handle_unknown
-#define png_push_handle_zTXt PDFIUM_png_push_handle_zTXt
-#define png_push_have_end PDFIUM_png_push_have_end
-#define png_push_have_info PDFIUM_png_push_have_info
-#define png_push_have_row PDFIUM_png_push_have_row
-#define png_push_process_row PDFIUM_png_push_process_row
-#define png_push_read_IDAT PDFIUM_png_push_read_IDAT
-#define png_push_read_chunk PDFIUM_png_push_read_chunk
-#define png_push_read_end PDFIUM_png_push_read_end
-#define png_push_read_iTXt PDFIUM_png_push_read_iTXt
-#define png_push_read_sig PDFIUM_png_push_read_sig
-#define png_push_read_tEXt PDFIUM_png_push_read_tEXt
-#define png_push_read_zTXt PDFIUM_png_push_read_zTXt
-#define png_push_restore_buffer PDFIUM_png_push_restore_buffer
-#define png_push_save_buffer PDFIUM_png_push_save_buffer
-#define png_read_IDAT_data PDFIUM_png_read_IDAT_data
-#define png_read_chunk_header PDFIUM_png_read_chunk_header
-#define png_read_data PDFIUM_png_read_data
-#define png_read_end PDFIUM_png_read_end
-#define png_read_filter_row PDFIUM_png_read_filter_row
-#define png_read_filter_row_avg3_neon PDFIUM_png_read_filter_row_avg3_neon
-#define png_read_filter_row_avg3_sse2 PDFIUM_png_read_filter_row_avg3_sse2
-#define png_read_filter_row_avg4_neon PDFIUM_png_read_filter_row_avg4_neon
-#define png_read_filter_row_avg4_sse2 PDFIUM_png_read_filter_row_avg4_sse2
-#define png_read_filter_row_paeth3_neon PDFIUM_png_read_filter_row_paeth3_neon
-#define png_read_filter_row_paeth3_sse2 PDFIUM_png_read_filter_row_paeth3_sse2
-#define png_read_filter_row_paeth4_neon PDFIUM_png_read_filter_row_paeth4_neon
-#define png_read_filter_row_paeth4_sse2 PDFIUM_png_read_filter_row_paeth4_sse2
-#define png_read_filter_row_sub3_neon PDFIUM_png_read_filter_row_sub3_neon
-#define png_read_filter_row_sub3_sse2 PDFIUM_png_read_filter_row_sub3_sse2
-#define png_read_filter_row_sub4_neon PDFIUM_png_read_filter_row_sub4_neon
-#define png_read_filter_row_sub4_sse2 PDFIUM_png_read_filter_row_sub4_sse2
-#define png_read_filter_row_up_neon PDFIUM_png_read_filter_row_up_neon
-#define png_read_finish_IDAT PDFIUM_png_read_finish_IDAT
-#define png_read_finish_row PDFIUM_png_read_finish_row
-#define png_read_image PDFIUM_png_read_image
-#define png_read_info PDFIUM_png_read_info
-#define png_read_png PDFIUM_png_read_png
-#define png_read_push_finish_row PDFIUM_png_read_push_finish_row
-#define png_read_row PDFIUM_png_read_row
-#define png_read_rows PDFIUM_png_read_rows
-#define png_read_sig PDFIUM_png_read_sig
-#define png_read_start_row PDFIUM_png_read_start_row
-#define png_read_transform_info PDFIUM_png_read_transform_info
-#define png_read_update_info PDFIUM_png_read_update_info
-#define png_realloc_array PDFIUM_png_realloc_array
-#define png_reciprocal PDFIUM_png_reciprocal
-#define png_reciprocal2 PDFIUM_png_reciprocal2
-#define png_reset_crc PDFIUM_png_reset_crc
-#define png_reset_zstream PDFIUM_png_reset_zstream
-#define png_riffle_palette_rgba PDFIUM_png_riffle_palette_rgba
-#define png_sRGB_base PDFIUM_png_sRGB_base
-#define png_sRGB_delta PDFIUM_png_sRGB_delta
-#define png_sRGB_table PDFIUM_png_sRGB_table
-#define png_safe_error PDFIUM_png_safe_error
-#define png_safe_execute PDFIUM_png_safe_execute
-#define png_safe_warning PDFIUM_png_safe_warning
-#define png_safecat PDFIUM_png_safecat
-#define png_save_int_32 PDFIUM_png_save_int_32
-#define png_save_uint_16 PDFIUM_png_save_uint_16
-#define png_save_uint_32 PDFIUM_png_save_uint_32
-#define png_set_IHDR PDFIUM_png_set_IHDR
-#define png_set_PLTE PDFIUM_png_set_PLTE
-#define png_set_add_alpha PDFIUM_png_set_add_alpha
-#define png_set_alpha_mode PDFIUM_png_set_alpha_mode
-#define png_set_alpha_mode_fixed PDFIUM_png_set_alpha_mode_fixed
-#define png_set_bKGD PDFIUM_png_set_bKGD
-#define png_set_background PDFIUM_png_set_background
-#define png_set_background_fixed PDFIUM_png_set_background_fixed
-#define png_set_benign_errors PDFIUM_png_set_benign_errors
-#define png_set_bgr PDFIUM_png_set_bgr
-#define png_set_cHRM PDFIUM_png_set_cHRM
-#define png_set_cHRM_XYZ PDFIUM_png_set_cHRM_XYZ
-#define png_set_cHRM_XYZ_fixed PDFIUM_png_set_cHRM_XYZ_fixed
-#define png_set_cHRM_fixed PDFIUM_png_set_cHRM_fixed
-#define png_set_check_for_invalid_index PDFIUM_png_set_check_for_invalid_index
-#define png_set_chunk_cache_max PDFIUM_png_set_chunk_cache_max
-#define png_set_chunk_malloc_max PDFIUM_png_set_chunk_malloc_max
-#define png_set_compression_buffer_size PDFIUM_png_set_compression_buffer_size
-#define png_set_compression_level PDFIUM_png_set_compression_level
-#define png_set_compression_mem_level PDFIUM_png_set_compression_mem_level
-#define png_set_compression_method PDFIUM_png_set_compression_method
-#define png_set_compression_strategy PDFIUM_png_set_compression_strategy
-#define png_set_compression_window_bits PDFIUM_png_set_compression_window_bits
-#define png_set_crc_action PDFIUM_png_set_crc_action
-#define png_set_eXIf PDFIUM_png_set_eXIf
-#define png_set_eXIf_1 PDFIUM_png_set_eXIf_1
-#define png_set_error_fn PDFIUM_png_set_error_fn
-#define png_set_expand PDFIUM_png_set_expand
-#define png_set_expand_16 PDFIUM_png_set_expand_16
-#define png_set_expand_gray_1_2_4_to_8 PDFIUM_png_set_expand_gray_1_2_4_to_8
-#define png_set_filler PDFIUM_png_set_filler
-#define png_set_filter PDFIUM_png_set_filter
-#define png_set_filter_heuristics PDFIUM_png_set_filter_heuristics
-#define png_set_filter_heuristics_fixed PDFIUM_png_set_filter_heuristics_fixed
-#define png_set_flush PDFIUM_png_set_flush
-#define png_set_gAMA PDFIUM_png_set_gAMA
-#define png_set_gAMA_fixed PDFIUM_png_set_gAMA_fixed
-#define png_set_gamma PDFIUM_png_set_gamma
-#define png_set_gamma_fixed PDFIUM_png_set_gamma_fixed
-#define png_set_gray_to_rgb PDFIUM_png_set_gray_to_rgb
-#define png_set_hIST PDFIUM_png_set_hIST
-#define png_set_iCCP PDFIUM_png_set_iCCP
-#define png_set_interlace_handling PDFIUM_png_set_interlace_handling
-#define png_set_invalid PDFIUM_png_set_invalid
-#define png_set_invert_alpha PDFIUM_png_set_invert_alpha
-#define png_set_invert_mono PDFIUM_png_set_invert_mono
-#define png_set_keep_unknown_chunks PDFIUM_png_set_keep_unknown_chunks
-#define png_set_longjmp_fn PDFIUM_png_set_longjmp_fn
-#define png_set_mem_fn PDFIUM_png_set_mem_fn
-#define png_set_oFFs PDFIUM_png_set_oFFs
-#define png_set_option PDFIUM_png_set_option
-#define png_set_pCAL PDFIUM_png_set_pCAL
-#define png_set_pHYs PDFIUM_png_set_pHYs
-#define png_set_packing PDFIUM_png_set_packing
-#define png_set_packswap PDFIUM_png_set_packswap
-#define png_set_palette_to_rgb PDFIUM_png_set_palette_to_rgb
-#define png_set_progressive_read_fn PDFIUM_png_set_progressive_read_fn
-#define png_set_quantize PDFIUM_png_set_quantize
-#define png_set_read_fn PDFIUM_png_set_read_fn
-#define png_set_read_status_fn PDFIUM_png_set_read_status_fn
-#define png_set_read_user_chunk_fn PDFIUM_png_set_read_user_chunk_fn
-#define png_set_read_user_transform_fn PDFIUM_png_set_read_user_transform_fn
-#define png_set_rgb_to_gray PDFIUM_png_set_rgb_to_gray
-#define png_set_rgb_to_gray_fixed PDFIUM_png_set_rgb_to_gray_fixed
-#define png_set_rows PDFIUM_png_set_rows
-#define png_set_sBIT PDFIUM_png_set_sBIT
-#define png_set_sCAL PDFIUM_png_set_sCAL
-#define png_set_sCAL_fixed PDFIUM_png_set_sCAL_fixed
-#define png_set_sCAL_s PDFIUM_png_set_sCAL_s
-#define png_set_sPLT PDFIUM_png_set_sPLT
-#define png_set_sRGB PDFIUM_png_set_sRGB
-#define png_set_sRGB_gAMA_and_cHRM PDFIUM_png_set_sRGB_gAMA_and_cHRM
-#define png_set_scale_16 PDFIUM_png_set_scale_16
-#define png_set_shift PDFIUM_png_set_shift
-#define png_set_sig_bytes PDFIUM_png_set_sig_bytes
-#define png_set_strip_16 PDFIUM_png_set_strip_16
-#define png_set_strip_alpha PDFIUM_png_set_strip_alpha
-#define png_set_swap PDFIUM_png_set_swap
-#define png_set_swap_alpha PDFIUM_png_set_swap_alpha
-#define png_set_tIME PDFIUM_png_set_tIME
-#define png_set_tRNS PDFIUM_png_set_tRNS
-#define png_set_tRNS_to_alpha PDFIUM_png_set_tRNS_to_alpha
-#define png_set_text PDFIUM_png_set_text
-#define png_set_text_2 PDFIUM_png_set_text_2
-#define png_set_text_compression_level PDFIUM_png_set_text_compression_level
-#define png_set_text_compression_mem_level PDFIUM_png_set_text_compression_mem_level
-#define png_set_text_compression_method PDFIUM_png_set_text_compression_method
-#define png_set_text_compression_strategy PDFIUM_png_set_text_compression_strategy
-#define png_set_text_compression_window_bits PDFIUM_png_set_text_compression_window_bits
-#define png_set_unknown_chunk_location PDFIUM_png_set_unknown_chunk_location
-#define png_set_unknown_chunks PDFIUM_png_set_unknown_chunks
-#define png_set_user_limits PDFIUM_png_set_user_limits
-#define png_set_user_transform_info PDFIUM_png_set_user_transform_info
-#define png_set_write_fn PDFIUM_png_set_write_fn
-#define png_set_write_status_fn PDFIUM_png_set_write_status_fn
-#define png_set_write_user_transform_fn PDFIUM_png_set_write_user_transform_fn
-#define png_sig_cmp PDFIUM_png_sig_cmp
-#define png_start_read_image PDFIUM_png_start_read_image
-#define png_user_version_check PDFIUM_png_user_version_check
-#define png_warning PDFIUM_png_warning
-#define png_warning_parameter PDFIUM_png_warning_parameter
-#define png_warning_parameter_signed PDFIUM_png_warning_parameter_signed
-#define png_warning_parameter_unsigned PDFIUM_png_warning_parameter_unsigned
-#define png_write_IEND PDFIUM_png_write_IEND
-#define png_write_IHDR PDFIUM_png_write_IHDR
-#define png_write_PLTE PDFIUM_png_write_PLTE
-#define png_write_bKGD PDFIUM_png_write_bKGD
-#define png_write_cHRM_fixed PDFIUM_png_write_cHRM_fixed
-#define png_write_chunk PDFIUM_png_write_chunk
-#define png_write_chunk_data PDFIUM_png_write_chunk_data
-#define png_write_chunk_end PDFIUM_png_write_chunk_end
-#define png_write_chunk_start PDFIUM_png_write_chunk_start
-#define png_write_data PDFIUM_png_write_data
-#define png_write_end PDFIUM_png_write_end
-#define png_write_find_filter PDFIUM_png_write_find_filter
-#define png_write_finish_row PDFIUM_png_write_finish_row
-#define png_write_flush PDFIUM_png_write_flush
-#define png_write_gAMA_fixed PDFIUM_png_write_gAMA_fixed
-#define png_write_hIST PDFIUM_png_write_hIST
-#define png_write_iCCP PDFIUM_png_write_iCCP
-#define png_write_iTXt PDFIUM_png_write_iTXt
-#define png_write_image PDFIUM_png_write_image
-#define png_write_info PDFIUM_png_write_info
-#define png_write_info_before_PLTE PDFIUM_png_write_info_before_PLTE
-#define png_write_oFFs PDFIUM_png_write_oFFs
-#define png_write_pCAL PDFIUM_png_write_pCAL
-#define png_write_pHYs PDFIUM_png_write_pHYs
-#define png_write_png PDFIUM_png_write_png
-#define png_write_row PDFIUM_png_write_row
-#define png_write_rows PDFIUM_png_write_rows
-#define png_write_sBIT PDFIUM_png_write_sBIT
-#define png_write_sCAL_s PDFIUM_png_write_sCAL_s
-#define png_write_sPLT PDFIUM_png_write_sPLT
-#define png_write_sRGB PDFIUM_png_write_sRGB
-#define png_write_sig PDFIUM_png_write_sig
-#define png_write_start_row PDFIUM_png_write_start_row
-#define png_write_tEXt PDFIUM_png_write_tEXt
-#define png_write_tIME PDFIUM_png_write_tIME
-#define png_write_tRNS PDFIUM_png_write_tRNS
-#define png_write_zTXt PDFIUM_png_write_zTXt
-#define png_zalloc PDFIUM_png_zalloc
-#define png_zfree PDFIUM_png_zfree
-#define png_zlib_inflate PDFIUM_png_zlib_inflate
-#define png_zstream_error PDFIUM_png_zstream_error
-
-#endif  // PNGPREFIX_H
diff --git a/third_party/libpng16/pngpriv.h b/third_party/libpng16/pngpriv.h
deleted file mode 100644
index 583c26f..0000000
--- a/third_party/libpng16/pngpriv.h
+++ /dev/null
@@ -1,2152 +0,0 @@
-
-/* pngpriv.h - private declarations for use inside libpng
- *
- * Copyright (c) 2018-2019 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-/* The symbols declared in this file (including the functions declared
- * as extern) are PRIVATE.  They are not part of the libpng public
- * interface, and are not recommended for use by regular applications.
- * Some of them may become public in the future; others may stay private,
- * change in an incompatible way, or even disappear.
- * Although the libpng users are not forbidden to include this header,
- * they should be well aware of the issues that may arise from doing so.
- */
-
-#ifndef PNGPRIV_H
-#define PNGPRIV_H
-
-/* Feature Test Macros.  The following are defined here to ensure that correctly
- * implemented libraries reveal the APIs libpng needs to build and hide those
- * that are not needed and potentially damaging to the compilation.
- *
- * Feature Test Macros must be defined before any system header is included (see
- * POSIX 1003.1 2.8.2 "POSIX Symbols."
- *
- * These macros only have an effect if the operating system supports either
- * POSIX 1003.1 or C99, or both.  On other operating systems (particularly
- * Windows/Visual Studio) there is no effect; the OS specific tests below are
- * still required (as of 2011-05-02.)
- */
-#ifndef _POSIX_SOURCE
-# define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
-#endif
-
-#ifndef PNG_VERSION_INFO_ONLY
-/* Standard library headers not required by png.h: */
-#  include <stdlib.h>
-#  include <string.h>
-#endif
-
-#define PNGLIB_BUILD /*libpng is being built, not used*/
-
-/* If HAVE_CONFIG_H is defined during the build then the build system must
- * provide an appropriate "config.h" file on the include path.  The header file
- * must provide definitions as required below (search for "HAVE_CONFIG_H");
- * see configure.ac for more details of the requirements.  The macro
- * "PNG_NO_CONFIG_H" is provided for maintainers to test for dependencies on
- * 'configure'; define this macro to prevent the configure build including the
- * configure generated config.h.  Libpng is expected to compile without *any*
- * special build system support on a reasonably ANSI-C compliant system.
- */
-#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
-#  include <config.h>
-
-   /* Pick up the definition of 'restrict' from config.h if it was read: */
-#  define PNG_RESTRICT restrict
-#endif
-
-/* To support symbol prefixing it is necessary to know *before* including png.h
- * whether the fixed point (and maybe other) APIs are exported, because if they
- * are not internal definitions may be required.  This is handled below just
- * before png.h is included, but load the configuration now if it is available.
- */
-#ifndef PNGLCONF_H
-#  include "pnglibconf.h"
-#endif
-
-/* Local renames may change non-exported API functions from png.h */
-#if defined(PNG_PREFIX) && !defined(PNGPREFIX_H)
-#  include "pngprefix.h"
-#endif
-
-#ifdef PNG_USER_CONFIG
-#  include "pngusr.h"
-   /* These should have been defined in pngusr.h */
-#  ifndef PNG_USER_PRIVATEBUILD
-#    define PNG_USER_PRIVATEBUILD "Custom libpng build"
-#  endif
-#  ifndef PNG_USER_DLLFNAME_POSTFIX
-#    define PNG_USER_DLLFNAME_POSTFIX "Cb"
-#  endif
-#endif
-
-/* Compile time options.
- * =====================
- * In a multi-arch build the compiler may compile the code several times for the
- * same object module, producing different binaries for different architectures.
- * When this happens configure-time setting of the target host options cannot be
- * done and this interferes with the handling of the ARM NEON optimizations, and
- * possibly other similar optimizations.  Put additional tests here; in general
- * this is needed when the same option can be changed at both compile time and
- * run time depending on the target OS (i.e. iOS vs Android.)
- *
- * NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because
- * this is not possible with certain compilers (Oracle SUN OS CC), as a result
- * it is necessary to ensure that all extern functions that *might* be used
- * regardless of $(CFLAGS) get declared in this file.  The test on __ARM_NEON__
- * below is one example of this behavior because it is controlled by the
- * presence or not of -mfpu=neon on the GCC command line, it is possible to do
- * this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely
- * do this.
- */
-#ifndef PNG_ARM_NEON_OPT
-   /* ARM NEON optimizations are being controlled by the compiler settings,
-    * typically the target FPU.  If the FPU has been set to NEON (-mfpu=neon
-    * with GCC) then the compiler will define __ARM_NEON__ and we can rely
-    * unconditionally on NEON instructions not crashing, otherwise we must
-    * disable use of NEON instructions.
-    *
-    * NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they
-    * can only be turned on automatically if that is supported too.  If
-    * PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail
-    * to compile with an appropriate #error if ALIGNED_MEMORY has been turned
-    * off.
-    *
-    * Note that gcc-4.9 defines __ARM_NEON instead of the deprecated
-    * __ARM_NEON__, so we check both variants.
-    *
-    * To disable ARM_NEON optimizations entirely, and skip compiling the
-    * associated assembler code, pass --enable-arm-neon=no to configure
-    * or put -DPNG_ARM_NEON_OPT=0 in CPPFLAGS.
-    */
-#  if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && \
-   defined(PNG_ALIGNED_MEMORY_SUPPORTED)
-#     define PNG_ARM_NEON_OPT 2
-#  else
-#     define PNG_ARM_NEON_OPT 0
-#  endif
-#endif
-
-#if PNG_ARM_NEON_OPT > 0
-   /* NEON optimizations are to be at least considered by libpng, so enable the
-    * callbacks to do this.
-    */
-#  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon
-
-   /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used
-    * if possible - if __ARM_NEON__ is set and the compiler version is not known
-    * to be broken.  This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can
-    * be:
-    *
-    *    1  The intrinsics code (the default with __ARM_NEON__)
-    *    2  The hand coded assembler (the default without __ARM_NEON__)
-    *
-    * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however
-    * this is *NOT* supported and may cease to work even after a minor revision
-    * to libpng.  It *is* valid to do this for testing purposes, e.g. speed
-    * testing or a new compiler, but the results should be communicated to the
-    * libpng implementation list for incorporation in the next minor release.
-    */
-#  ifndef PNG_ARM_NEON_IMPLEMENTATION
-#     if defined(__ARM_NEON__) || defined(__ARM_NEON)
-#        if defined(__clang__)
-            /* At present it is unknown by the libpng developers which versions
-             * of clang support the intrinsics, however some or perhaps all
-             * versions do not work with the assembler so this may be
-             * irrelevant, so just use the default (do nothing here.)
-             */
-#        elif defined(__GNUC__)
-            /* GCC 4.5.4 NEON support is known to be broken.  4.6.3 is known to
-             * work, so if this *is* GCC, or G++, look for a version >4.5
-             */
-#           if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
-#              define PNG_ARM_NEON_IMPLEMENTATION 2
-#           endif /* no GNUC support */
-#        endif /* __GNUC__ */
-#     else /* !defined __ARM_NEON__ */
-         /* The 'intrinsics' code simply won't compile without this -mfpu=neon:
-          */
-#        if !defined(__aarch64__)
-            /* The assembler code currently does not work on ARM64 */
-#          define PNG_ARM_NEON_IMPLEMENTATION 2
-#        endif /* __aarch64__ */
-#     endif /* __ARM_NEON__ */
-#  endif /* !PNG_ARM_NEON_IMPLEMENTATION */
-
-#  ifndef PNG_ARM_NEON_IMPLEMENTATION
-      /* Use the intrinsics code by default. */
-#     define PNG_ARM_NEON_IMPLEMENTATION 1
-#  endif
-#endif /* PNG_ARM_NEON_OPT > 0 */
-
-#ifndef PNG_MIPS_MSA_OPT
-#  if defined(__mips_msa) && (__mips_isa_rev >= 5) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
-#     define PNG_MIPS_MSA_OPT 2
-#  else
-#     define PNG_MIPS_MSA_OPT 0
-#  endif
-#endif
-
-#ifndef PNG_POWERPC_VSX_OPT
-#  if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__)
-#     define PNG_POWERPC_VSX_OPT 2
-#  else
-#     define PNG_POWERPC_VSX_OPT 0
-#  endif
-#endif
-
-#ifndef PNG_INTEL_SSE_OPT
-#   ifdef PNG_INTEL_SSE
-      /* Only check for SSE if the build configuration has been modified to
-       * enable SSE optimizations.  This means that these optimizations will
-       * be off by default.  See contrib/intel for more details.
-       */
-#     if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
-       defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
-       (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
-#         define PNG_INTEL_SSE_OPT 1
-#      else
-#         define PNG_INTEL_SSE_OPT 0
-#      endif
-#   else
-#      define PNG_INTEL_SSE_OPT 0
-#   endif
-#endif
-
-#if PNG_INTEL_SSE_OPT > 0
-#   ifndef PNG_INTEL_SSE_IMPLEMENTATION
-#      if defined(__SSE4_1__) || defined(__AVX__)
-          /* We are not actually using AVX, but checking for AVX is the best
-             way we can detect SSE4.1 and SSSE3 on MSVC.
-          */
-#         define PNG_INTEL_SSE_IMPLEMENTATION 3
-#      elif defined(__SSSE3__)
-#         define PNG_INTEL_SSE_IMPLEMENTATION 2
-#      elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
-       (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
-#         define PNG_INTEL_SSE_IMPLEMENTATION 1
-#      else
-#         define PNG_INTEL_SSE_IMPLEMENTATION 0
-#      endif
-#   endif
-
-#   if PNG_INTEL_SSE_IMPLEMENTATION > 0
-#      define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2
-#   endif
-#else
-#   define PNG_INTEL_SSE_IMPLEMENTATION 0
-#endif
-
-#if PNG_MIPS_MSA_OPT > 0
-#  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa
-#  ifndef PNG_MIPS_MSA_IMPLEMENTATION
-#     if defined(__mips_msa)
-#        if defined(__clang__)
-#        elif defined(__GNUC__)
-#           if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
-#              define PNG_MIPS_MSA_IMPLEMENTATION 2
-#           endif /* no GNUC support */
-#        endif /* __GNUC__ */
-#     else /* !defined __mips_msa */
-#        define PNG_MIPS_MSA_IMPLEMENTATION 2
-#     endif /* __mips_msa */
-#  endif /* !PNG_MIPS_MSA_IMPLEMENTATION */
-
-#  ifndef PNG_MIPS_MSA_IMPLEMENTATION
-#     define PNG_MIPS_MSA_IMPLEMENTATION 1
-#  endif
-#endif /* PNG_MIPS_MSA_OPT > 0 */
-
-#if PNG_POWERPC_VSX_OPT > 0
-#  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx
-#  define PNG_POWERPC_VSX_IMPLEMENTATION 1
-#endif
-
-
-/* Is this a build of a DLL where compilation of the object modules requires
- * different preprocessor settings to those required for a simple library?  If
- * so PNG_BUILD_DLL must be set.
- *
- * If libpng is used inside a DLL but that DLL does not export the libpng APIs
- * PNG_BUILD_DLL must not be set.  To avoid the code below kicking in build a
- * static library of libpng then link the DLL against that.
- */
-#ifndef PNG_BUILD_DLL
-#  ifdef DLL_EXPORT
-      /* This is set by libtool when files are compiled for a DLL; libtool
-       * always compiles twice, even on systems where it isn't necessary.  Set
-       * PNG_BUILD_DLL in case it is necessary:
-       */
-#     define PNG_BUILD_DLL
-#  else
-#     ifdef _WINDLL
-         /* This is set by the Microsoft Visual Studio IDE in projects that
-          * build a DLL.  It can't easily be removed from those projects (it
-          * isn't visible in the Visual Studio UI) so it is a fairly reliable
-          * indication that PNG_IMPEXP needs to be set to the DLL export
-          * attributes.
-          */
-#        define PNG_BUILD_DLL
-#     else
-#        ifdef __DLL__
-            /* This is set by the Borland C system when compiling for a DLL
-             * (as above.)
-             */
-#           define PNG_BUILD_DLL
-#        else
-            /* Add additional compiler cases here. */
-#        endif
-#     endif
-#  endif
-#endif /* Setting PNG_BUILD_DLL if required */
-
-/* See pngconf.h for more details: the builder of the library may set this on
- * the command line to the right thing for the specific compilation system or it
- * may be automagically set above (at present we know of no system where it does
- * need to be set on the command line.)
- *
- * PNG_IMPEXP must be set here when building the library to prevent pngconf.h
- * setting it to the "import" setting for a DLL build.
- */
-#ifndef PNG_IMPEXP
-#  ifdef PNG_BUILD_DLL
-#     define PNG_IMPEXP PNG_DLL_EXPORT
-#  else
-      /* Not building a DLL, or the DLL doesn't require specific export
-       * definitions.
-       */
-#     define PNG_IMPEXP
-#  endif
-#endif
-
-/* No warnings for private or deprecated functions in the build: */
-#ifndef PNG_DEPRECATED
-#  define PNG_DEPRECATED
-#endif
-#ifndef PNG_PRIVATE
-#  define PNG_PRIVATE
-#endif
-
-/* Symbol preprocessing support.
- *
- * To enable listing global, but internal, symbols the following macros should
- * always be used to declare an extern data or function object in this file.
- */
-#ifndef PNG_INTERNAL_DATA
-#  define PNG_INTERNAL_DATA(type, name, array) PNG_LINKAGE_DATA type name array
-#endif
-
-#ifndef PNG_INTERNAL_FUNCTION
-#  define PNG_INTERNAL_FUNCTION(type, name, args, attributes)\
-      PNG_LINKAGE_FUNCTION PNG_FUNCTION(type, name, args, PNG_EMPTY attributes)
-#endif
-
-#ifndef PNG_INTERNAL_CALLBACK
-#  define PNG_INTERNAL_CALLBACK(type, name, args, attributes)\
-      PNG_LINKAGE_CALLBACK PNG_FUNCTION(type, (PNGCBAPI name), args,\
-         PNG_EMPTY attributes)
-#endif
-
-/* If floating or fixed point APIs are disabled they may still be compiled
- * internally.  To handle this make sure they are declared as the appropriate
- * internal extern function (otherwise the symbol prefixing stuff won't work and
- * the functions will be used without definitions.)
- *
- * NOTE: although all the API functions are declared here they are not all
- * actually built!  Because the declarations are still made it is necessary to
- * fake out types that they depend on.
- */
-#ifndef PNG_FP_EXPORT
-#  ifndef PNG_FLOATING_POINT_SUPPORTED
-#     define PNG_FP_EXPORT(ordinal, type, name, args)\
-         PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY);
-#     ifndef PNG_VERSION_INFO_ONLY
-         typedef struct png_incomplete png_double;
-         typedef png_double*           png_doublep;
-         typedef const png_double*     png_const_doublep;
-         typedef png_double**          png_doublepp;
-#     endif
-#  endif
-#endif
-#ifndef PNG_FIXED_EXPORT
-#  ifndef PNG_FIXED_POINT_SUPPORTED
-#     define PNG_FIXED_EXPORT(ordinal, type, name, args)\
-         PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY);
-#  endif
-#endif
-
-#include "png.h"
-
-/* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */
-#ifndef PNG_DLL_EXPORT
-#  define PNG_DLL_EXPORT
-#endif
-
-/* This is a global switch to set the compilation for an installed system
- * (a release build).  It can be set for testing debug builds to ensure that
- * they will compile when the build type is switched to RC or STABLE, the
- * default is just to use PNG_LIBPNG_BUILD_BASE_TYPE.  Set this in CPPFLAGS
- * with either:
- *
- *   -DPNG_RELEASE_BUILD Turns on the release compile path
- *   -DPNG_RELEASE_BUILD=0 Turns it off
- * or in your pngusr.h with
- *   #define PNG_RELEASE_BUILD=1 Turns on the release compile path
- *   #define PNG_RELEASE_BUILD=0 Turns it off
- */
-#ifndef PNG_RELEASE_BUILD
-#  define PNG_RELEASE_BUILD (PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC)
-#endif
-
-/* SECURITY and SAFETY:
- *
- * libpng is built with support for internal limits on image dimensions and
- * memory usage.  These are documented in scripts/pnglibconf.dfa of the
- * source and recorded in the machine generated header file pnglibconf.h.
- */
-
-/* If you are running on a machine where you cannot allocate more
- * than 64K of memory at once, uncomment this.  While libpng will not
- * normally need that much memory in a chunk (unless you load up a very
- * large file), zlib needs to know how big of a chunk it can use, and
- * libpng thus makes sure to check any memory allocation to verify it
- * will fit into memory.
- *
- * zlib provides 'MAXSEG_64K' which, if defined, indicates the
- * same limit and pngconf.h (already included) sets the limit
- * if certain operating systems are detected.
- */
-#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K)
-#  define PNG_MAX_MALLOC_64K
-#endif
-
-#ifndef PNG_UNUSED
-/* Unused formal parameter warnings are silenced using the following macro
- * which is expected to have no bad effects on performance (optimizing
- * compilers will probably remove it entirely).  Note that if you replace
- * it with something other than whitespace, you must include the terminating
- * semicolon.
- */
-#  define PNG_UNUSED(param) (void)param;
-#endif
-
-/* Just a little check that someone hasn't tried to define something
- * contradictory.
- */
-#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K)
-#  undef PNG_ZBUF_SIZE
-#  define PNG_ZBUF_SIZE 65536L
-#endif
-
-/* If warnings or errors are turned off the code is disabled or redirected here.
- * From 1.5.4 functions have been added to allow very limited formatting of
- * error and warning messages - this code will also be disabled here.
- */
-#ifdef PNG_WARNINGS_SUPPORTED
-#  define PNG_WARNING_PARAMETERS(p) png_warning_parameters p;
-#else
-#  define png_warning_parameter(p,number,string) ((void)0)
-#  define png_warning_parameter_unsigned(p,number,format,value) ((void)0)
-#  define png_warning_parameter_signed(p,number,format,value) ((void)0)
-#  define png_formatted_warning(pp,p,message) ((void)(pp))
-#  define PNG_WARNING_PARAMETERS(p)
-#endif
-#ifndef PNG_ERROR_TEXT_SUPPORTED
-#  define png_fixed_error(s1,s2) png_err(s1)
-#endif
-
-/* Some fixed point APIs are still required even if not exported because
- * they get used by the corresponding floating point APIs.  This magic
- * deals with this:
- */
-#ifdef PNG_FIXED_POINT_SUPPORTED
-#  define PNGFAPI PNGAPI
-#else
-#  define PNGFAPI /* PRIVATE */
-#endif
-
-#ifndef PNG_VERSION_INFO_ONLY
-/* Other defines specific to compilers can go here.  Try to keep
- * them inside an appropriate ifdef/endif pair for portability.
- */
-
-/* C allows up-casts from (void*) to any pointer and (const void*) to any
- * pointer to a const object.  C++ regards this as a type error and requires an
- * explicit, static, cast and provides the static_cast<> rune to ensure that
- * const is not cast away.
- */
-#ifdef __cplusplus
-#  define png_voidcast(type, value) static_cast<type>(value)
-#  define png_constcast(type, value) const_cast<type>(value)
-#  define png_aligncast(type, value) \
-   static_cast<type>(static_cast<void*>(value))
-#  define png_aligncastconst(type, value) \
-   static_cast<type>(static_cast<const void*>(value))
-#else
-#  define png_voidcast(type, value) (value)
-#  ifdef _WIN64
-#     ifdef __GNUC__
-         typedef unsigned long long png_ptruint;
-#     else
-         typedef unsigned __int64 png_ptruint;
-#     endif
-#  else
-      typedef unsigned long png_ptruint;
-#  endif
-#  define png_constcast(type, value) ((type)(png_ptruint)(const void*)(value))
-#  define png_aligncast(type, value) ((void*)(value))
-#  define png_aligncastconst(type, value) ((const void*)(value))
-#endif /* __cplusplus */
-
-#if defined(PNG_FLOATING_POINT_SUPPORTED) ||\
-    defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)
-   /* png.c requires the following ANSI-C constants if the conversion of
-    * floating point to ASCII is implemented therein:
-    *
-    *  DBL_DIG  Maximum number of decimal digits (can be set to any constant)
-    *  DBL_MIN  Smallest normalized fp number (can be set to an arbitrary value)
-    *  DBL_MAX  Maximum floating point number (can be set to an arbitrary value)
-    */
-#  include <float.h>
-
-#  if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \
-    defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC)
-   /* We need to check that <math.h> hasn't already been included earlier
-    * as it seems it doesn't agree with <fp.h>, yet we should really use
-    * <fp.h> if possible.
-    */
-#    if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__)
-#      include <fp.h>
-#    endif
-#  else
-#    include <math.h>
-#  endif
-#  if defined(_AMIGA) && defined(__SASC) && defined(_M68881)
-   /* Amiga SAS/C: We must include builtin FPU functions when compiling using
-    * MATH=68881
-    */
-#    include <m68881.h>
-#  endif
-#endif
-
-/* This provides the non-ANSI (far) memory allocation routines. */
-#if defined(__TURBOC__) && defined(__MSDOS__)
-#  include <mem.h>
-#  include <alloc.h>
-#endif
-
-#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \
-    defined(_WIN32) || defined(__WIN32__)
-#  include <windows.h>  /* defines _WINDOWS_ macro */
-#endif
-#endif /* PNG_VERSION_INFO_ONLY */
-
-/* Moved here around 1.5.0beta36 from pngconf.h */
-/* Users may want to use these so they are not private.  Any library
- * functions that are passed far data must be model-independent.
- */
-
-/* Memory model/platform independent fns */
-#ifndef PNG_ABORT
-#  ifdef _WINDOWS_
-#    define PNG_ABORT() ExitProcess(0)
-#  else
-#    define PNG_ABORT() abort()
-#  endif
-#endif
-
-/* These macros may need to be architecture dependent. */
-#define PNG_ALIGN_NONE   0 /* do not use data alignment */
-#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */
-#ifdef offsetof
-#  define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */
-#else
-#  define PNG_ALIGN_OFFSET -1 /* prevent the use of this */
-#endif
-#define PNG_ALIGN_SIZE   3 /* use sizeof to determine alignment */
-
-#ifndef PNG_ALIGN_TYPE
-   /* Default to using aligned access optimizations and requiring alignment to a
-    * multiple of the data type size.  Override in a compiler specific fashion
-    * if necessary by inserting tests here:
-    */
-#  define PNG_ALIGN_TYPE PNG_ALIGN_SIZE
-#endif
-
-#if PNG_ALIGN_TYPE == PNG_ALIGN_SIZE
-   /* This is used because in some compiler implementations non-aligned
-    * structure members are supported, so the offsetof approach below fails.
-    * Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access
-    * is good for performance.  Do not do this unless you have tested the result
-    * and understand it.
-    */
-#  define png_alignof(type) (sizeof (type))
-#else
-#  if PNG_ALIGN_TYPE == PNG_ALIGN_OFFSET
-#     define png_alignof(type) offsetof(struct{char c; type t;}, t)
-#  else
-#     if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS
-#        define png_alignof(type) (1)
-#     endif
-      /* Else leave png_alignof undefined to prevent use thereof */
-#  endif
-#endif
-
-/* This implicitly assumes alignment is always to a power of 2. */
-#ifdef png_alignof
-#  define png_isaligned(ptr, type)\
-   (((type)((const char*)ptr-(const char*)0) & \
-   (type)(png_alignof(type)-1)) == 0)
-#else
-#  define png_isaligned(ptr, type) 0
-#endif
-
-/* End of memory model/platform independent support */
-/* End of 1.5.0beta36 move from pngconf.h */
-
-/* CONSTANTS and UTILITY MACROS
- * These are used internally by libpng and not exposed in the API
- */
-
-/* Various modes of operation.  Note that after an init, mode is set to
- * zero automatically when the structure is created.  Three of these
- * are defined in png.h because they need to be visible to applications
- * that call png_set_unknown_chunk().
- */
-/* #define PNG_HAVE_IHDR            0x01U (defined in png.h) */
-/* #define PNG_HAVE_PLTE            0x02U (defined in png.h) */
-#define PNG_HAVE_IDAT               0x04U
-/* #define PNG_AFTER_IDAT           0x08U (defined in png.h) */
-#define PNG_HAVE_IEND               0x10U
-                   /*               0x20U (unused) */
-                   /*               0x40U (unused) */
-                   /*               0x80U (unused) */
-#define PNG_HAVE_CHUNK_HEADER      0x100U
-#define PNG_WROTE_tIME             0x200U
-#define PNG_WROTE_INFO_BEFORE_PLTE 0x400U
-#define PNG_BACKGROUND_IS_GRAY     0x800U
-#define PNG_HAVE_PNG_SIGNATURE    0x1000U
-#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */
-                   /*             0x4000U (unused) */
-#define PNG_IS_READ_STRUCT        0x8000U /* Else is a write struct */
-
-/* Flags for the transformations the PNG library does on the image data */
-#define PNG_BGR                 0x0001U
-#define PNG_INTERLACE           0x0002U
-#define PNG_PACK                0x0004U
-#define PNG_SHIFT               0x0008U
-#define PNG_SWAP_BYTES          0x0010U
-#define PNG_INVERT_MONO         0x0020U
-#define PNG_QUANTIZE            0x0040U
-#define PNG_COMPOSE             0x0080U    /* Was PNG_BACKGROUND */
-#define PNG_BACKGROUND_EXPAND   0x0100U
-#define PNG_EXPAND_16           0x0200U    /* Added to libpng 1.5.2 */
-#define PNG_16_TO_8             0x0400U    /* Becomes 'chop' in 1.5.4 */
-#define PNG_RGBA                0x0800U
-#define PNG_EXPAND              0x1000U
-#define PNG_GAMMA               0x2000U
-#define PNG_GRAY_TO_RGB         0x4000U
-#define PNG_FILLER              0x8000U
-#define PNG_PACKSWAP           0x10000U
-#define PNG_SWAP_ALPHA         0x20000U
-#define PNG_STRIP_ALPHA        0x40000U
-#define PNG_INVERT_ALPHA       0x80000U
-#define PNG_USER_TRANSFORM    0x100000U
-#define PNG_RGB_TO_GRAY_ERR   0x200000U
-#define PNG_RGB_TO_GRAY_WARN  0x400000U
-#define PNG_RGB_TO_GRAY       0x600000U /* two bits, RGB_TO_GRAY_ERR|WARN */
-#define PNG_ENCODE_ALPHA      0x800000U /* Added to libpng-1.5.4 */
-#define PNG_ADD_ALPHA        0x1000000U /* Added to libpng-1.2.7 */
-#define PNG_EXPAND_tRNS      0x2000000U /* Added to libpng-1.2.9 */
-#define PNG_SCALE_16_TO_8    0x4000000U /* Added to libpng-1.5.4 */
-                       /*    0x8000000U unused */
-                       /*   0x10000000U unused */
-                       /*   0x20000000U unused */
-                       /*   0x40000000U unused */
-/* Flags for png_create_struct */
-#define PNG_STRUCT_PNG   0x0001U
-#define PNG_STRUCT_INFO  0x0002U
-
-/* Flags for the png_ptr->flags rather than declaring a byte for each one */
-#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY     0x0001U
-#define PNG_FLAG_ZSTREAM_INITIALIZED      0x0002U /* Added to libpng-1.6.0 */
-                                  /*      0x0004U    unused */
-#define PNG_FLAG_ZSTREAM_ENDED            0x0008U /* Added to libpng-1.6.0 */
-                                  /*      0x0010U    unused */
-                                  /*      0x0020U    unused */
-#define PNG_FLAG_ROW_INIT                 0x0040U
-#define PNG_FLAG_FILLER_AFTER             0x0080U
-#define PNG_FLAG_CRC_ANCILLARY_USE        0x0100U
-#define PNG_FLAG_CRC_ANCILLARY_NOWARN     0x0200U
-#define PNG_FLAG_CRC_CRITICAL_USE         0x0400U
-#define PNG_FLAG_CRC_CRITICAL_IGNORE      0x0800U
-#define PNG_FLAG_ASSUME_sRGB              0x1000U /* Added to libpng-1.5.4 */
-#define PNG_FLAG_OPTIMIZE_ALPHA           0x2000U /* Added to libpng-1.5.4 */
-#define PNG_FLAG_DETECT_UNINITIALIZED     0x4000U /* Added to libpng-1.5.4 */
-/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS      0x8000U */
-/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS      0x10000U */
-#define PNG_FLAG_LIBRARY_MISMATCH        0x20000U
-#define PNG_FLAG_STRIP_ERROR_NUMBERS     0x40000U
-#define PNG_FLAG_STRIP_ERROR_TEXT        0x80000U
-#define PNG_FLAG_BENIGN_ERRORS_WARN     0x100000U /* Added to libpng-1.4.0 */
-#define PNG_FLAG_APP_WARNINGS_WARN      0x200000U /* Added to libpng-1.6.0 */
-#define PNG_FLAG_APP_ERRORS_WARN        0x400000U /* Added to libpng-1.6.0 */
-                                  /*    0x800000U    unused */
-                                  /*   0x1000000U    unused */
-                                  /*   0x2000000U    unused */
-                                  /*   0x4000000U    unused */
-                                  /*   0x8000000U    unused */
-                                  /*  0x10000000U    unused */
-                                  /*  0x20000000U    unused */
-                                  /*  0x40000000U    unused */
-
-#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \
-                                     PNG_FLAG_CRC_ANCILLARY_NOWARN)
-
-#define PNG_FLAG_CRC_CRITICAL_MASK  (PNG_FLAG_CRC_CRITICAL_USE | \
-                                     PNG_FLAG_CRC_CRITICAL_IGNORE)
-
-#define PNG_FLAG_CRC_MASK           (PNG_FLAG_CRC_ANCILLARY_MASK | \
-                                     PNG_FLAG_CRC_CRITICAL_MASK)
-
-/* Save typing and make code easier to understand */
-
-#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
-   abs((int)((c1).green) - (int)((c2).green)) + \
-   abs((int)((c1).blue) - (int)((c2).blue)))
-
-/* Added to libpng-1.6.0: scale a 16-bit value in the range 0..65535 to 0..255
- * by dividing by 257 *with rounding*.  This macro is exact for the given range.
- * See the discourse in pngrtran.c png_do_scale_16_to_8.  The values in the
- * macro were established by experiment (modifying the added value).  The macro
- * has a second variant that takes a value already scaled by 255 and divides by
- * 65535 - this has a maximum error of .502.  Over the range 0..65535*65535 it
- * only gives off-by-one errors and only for 0.5% (1 in 200) of the values.
- */
-#define PNG_DIV65535(v24) (((v24) + 32895) >> 16)
-#define PNG_DIV257(v16) PNG_DIV65535((png_uint_32)(v16) * 255)
-
-/* Added to libpng-1.2.6 JB */
-#define PNG_ROWBYTES(pixel_bits, width) \
-    ((pixel_bits) >= 8 ? \
-    ((size_t)(width) * (((size_t)(pixel_bits)) >> 3)) : \
-    (( ((size_t)(width) * ((size_t)(pixel_bits))) + 7) >> 3) )
-
-/* This returns the number of trailing bits in the last byte of a row, 0 if the
- * last byte is completely full of pixels.  It is, in principle, (pixel_bits x
- * width) % 8, but that would overflow for large 'width'.  The second macro is
- * the same except that it returns the number of unused bits in the last byte;
- * (8-TRAILBITS), but 0 when TRAILBITS is 0.
- *
- * NOTE: these macros are intended to be self-evidently correct and never
- * overflow on the assumption that pixel_bits is in the range 0..255.  The
- * arguments are evaluated only once and they can be signed (e.g. as a result of
- * the integral promotions).  The result of the expression always has type
- * (png_uint_32), however the compiler always knows it is in the range 0..7.
- */
-#define PNG_TRAILBITS(pixel_bits, width) \
-    (((pixel_bits) * ((width) % (png_uint_32)8)) % 8)
-
-#define PNG_PADBITS(pixel_bits, width) \
-    ((8 - PNG_TRAILBITS(pixel_bits, width)) % 8)
-
-/* PNG_OUT_OF_RANGE returns true if value is outside the range
- * ideal-delta..ideal+delta.  Each argument is evaluated twice.
- * "ideal" and "delta" should be constants, normally simple
- * integers, "value" a variable. Added to libpng-1.2.6 JB
- */
-#define PNG_OUT_OF_RANGE(value, ideal, delta) \
-   ( (value) < (ideal)-(delta) || (value) > (ideal)+(delta) )
-
-/* Conversions between fixed and floating point, only defined if
- * required (to make sure the code doesn't accidentally use float
- * when it is supposedly disabled.)
- */
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-/* The floating point conversion can't overflow, though it can and
- * does lose accuracy relative to the original fixed point value.
- * In practice this doesn't matter because png_fixed_point only
- * stores numbers with very low precision.  The png_ptr and s
- * arguments are unused by default but are there in case error
- * checking becomes a requirement.
- */
-#define png_float(png_ptr, fixed, s) (.00001 * (fixed))
-
-/* The fixed point conversion performs range checking and evaluates
- * its argument multiple times, so must be used with care.  The
- * range checking uses the PNG specification values for a signed
- * 32-bit fixed point value except that the values are deliberately
- * rounded-to-zero to an integral value - 21474 (21474.83 is roughly
- * (2^31-1) * 100000). 's' is a string that describes the value being
- * converted.
- *
- * NOTE: this macro will raise a png_error if the range check fails,
- * therefore it is normally only appropriate to use this on values
- * that come from API calls or other sources where an out of range
- * error indicates a programming error, not a data error!
- *
- * NOTE: by default this is off - the macro is not used - because the
- * function call saves a lot of code.
- */
-#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED
-#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\
-    ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0))
-#endif
-/* else the corresponding function is defined below, inside the scope of the
- * cplusplus test.
- */
-#endif
-
-/* Constants for known chunk types.  If you need to add a chunk, define the name
- * here.  For historical reasons these constants have the form png_<name>; i.e.
- * the prefix is lower case.  Please use decimal values as the parameters to
- * match the ISO PNG specification and to avoid relying on the C locale
- * interpretation of character values.
- *
- * Prior to 1.5.6 these constants were strings, as of 1.5.6 png_uint_32 values
- * are computed and a new macro (PNG_STRING_FROM_CHUNK) added to allow a string
- * to be generated if required.
- *
- * PNG_32b correctly produces a value shifted by up to 24 bits, even on
- * architectures where (int) is only 16 bits.
- */
-#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.
- *
- * MAINTAINERS: If you need to add a chunk, define the name here.
- * For historical reasons these constants have the form png_<name>; i.e.
- * the prefix is lower case.  Please use decimal values as the parameters to
- * match the ISO PNG specification and to avoid relying on the C locale
- * interpretation of character values.  Please keep the list sorted.
- *
- * Notice that PNG_U32 is used to define a 32-bit value for the 4 byte chunk
- * type.  In fact the specification does not express chunk types this way,
- * however using a 32-bit value means that the chunk type can be read from the
- * stream using exactly the same code as used for a 32-bit unsigned value and
- * can be examined far more efficiently (using one arithmetic compare).
- *
- * Prior to 1.5.6 the chunk type constants were expressed as C strings.  The
- * libpng API still uses strings for 'unknown' chunks and a macro,
- * PNG_STRING_FROM_CHUNK, allows a string to be generated if required.  Notice
- * that for portable code numeric values must still be used; the string "IHDR"
- * is not portable and neither is PNG_U32('I', 'H', 'D', 'R').
- *
- * In 1.7.0 the definitions will be made public in png.h to avoid having to
- * duplicate the same definitions in application code.
- */
-#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_eXIf PNG_U32(101,  88,  73, 102) /* registered July 2017 */
-#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)
-
-/* The following will work on (signed char*) strings, whereas the get_uint_32
- * macro will fail on top-bit-set values because of the sign extension.
- */
-#define PNG_CHUNK_FROM_STRING(s)\
-   PNG_U32(0xff & (s)[0], 0xff & (s)[1], 0xff & (s)[2], 0xff & (s)[3])
-
-/* This uses (char), not (png_byte) to avoid warnings on systems where (char) is
- * signed and the argument is a (char[])  This macro will fail miserably on
- * systems where (char) is more than 8 bits.
- */
-#define PNG_STRING_FROM_CHUNK(s,c)\
-   (void)(((char*)(s))[0]=(char)(((c)>>24) & 0xff), \
-   ((char*)(s))[1]=(char)(((c)>>16) & 0xff),\
-   ((char*)(s))[2]=(char)(((c)>>8) & 0xff), \
-   ((char*)(s))[3]=(char)((c & 0xff)))
-
-/* Do the same but terminate with a null character. */
-#define PNG_CSTRING_FROM_CHUNK(s,c)\
-   (void)(PNG_STRING_FROM_CHUNK(s,c), ((char*)(s))[4] = 0)
-
-/* Test on flag values as defined in the spec (section 5.4): */
-#define PNG_CHUNK_ANCILLARY(c)   (1 & ((c) >> 29))
-#define PNG_CHUNK_CRITICAL(c)     (!PNG_CHUNK_ANCILLARY(c))
-#define PNG_CHUNK_PRIVATE(c)      (1 & ((c) >> 21))
-#define PNG_CHUNK_RESERVED(c)     (1 & ((c) >> 13))
-#define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >>  5))
-
-/* Gamma values (new at libpng-1.5.4): */
-#define PNG_GAMMA_MAC_OLD 151724  /* Assume '1.8' is really 2.2/1.45! */
-#define PNG_GAMMA_MAC_INVERSE 65909
-#define PNG_GAMMA_sRGB_INVERSE 45455
-
-/* Almost everything below is C specific; the #defines above can be used in
- * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot.
- */
-#ifndef PNG_VERSION_INFO_ONLY
-
-#include "pngstruct.h"
-#include "pnginfo.h"
-
-/* Validate the include paths - the include path used to generate pnglibconf.h
- * must match that used in the build, or we must be using pnglibconf.h.prebuilt:
- */
-#if PNG_ZLIB_VERNUM != 0 && PNG_ZLIB_VERNUM != ZLIB_VERNUM
-#  error ZLIB_VERNUM != PNG_ZLIB_VERNUM \
-      "-I (include path) error: see the notes in pngpriv.h"
-   /* This means that when pnglibconf.h was built the copy of zlib.h that it
-    * used is not the same as the one being used here.  Because the build of
-    * libpng makes decisions to use inflateInit2 and inflateReset2 based on the
-    * zlib version number and because this affects handling of certain broken
-    * PNG files the -I directives must match.
-    *
-    * The most likely explanation is that you passed a -I in CFLAGS. This will
-    * not work; all the preprocessor directives and in particular all the -I
-    * directives must be in CPPFLAGS.
-    */
-#endif
-
-/* This is used for 16-bit gamma tables -- only the top level pointers are
- * const; this could be changed:
- */
-typedef const png_uint_16p * png_const_uint_16pp;
-
-/* Added to libpng-1.5.7: sRGB conversion tables */
-#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
-   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
-#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
-PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_table, [256]);
-   /* Convert from an sRGB encoded value 0..255 to a 16-bit linear value,
-    * 0..65535.  This table gives the closest 16-bit answers (no errors).
-    */
-#endif
-
-PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_base, [512]);
-PNG_INTERNAL_DATA(const png_byte, png_sRGB_delta, [512]);
-
-#define PNG_sRGB_FROM_LINEAR(linear) \
-  ((png_byte)(0xff & ((png_sRGB_base[(linear)>>15] \
-   + ((((linear) & 0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8)))
-   /* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB
-    * encoded value with maximum error 0.646365.  Note that the input is not a
-    * 16-bit value; it has been multiplied by 255! */
-#endif /* SIMPLIFIED_READ/WRITE */
-
-
-/* Inhibit C++ name-mangling for libpng functions but not for system calls. */
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-/* Internal functions; these are not exported from a DLL however because they
- * are used within several of the C source files they have to be C extern.
- *
- * All of these functions must be declared with PNG_INTERNAL_FUNCTION.
- */
-
-/* Zlib support */
-#define PNG_UNEXPECTED_ZLIB_RETURN (-7)
-PNG_INTERNAL_FUNCTION(void, png_zstream_error,(png_structrp png_ptr, int ret),
-   PNG_EMPTY);
-   /* Used by the zlib handling functions to ensure that z_stream::msg is always
-    * set before they return.
-    */
-
-#ifdef PNG_WRITE_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr,
-   png_compression_bufferp *list),PNG_EMPTY);
-   /* Free the buffer list used by the compressed write code. */
-#endif
-
-#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
-   !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
-   (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
-   defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
-   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
-   (defined(PNG_sCAL_SUPPORTED) && \
-   defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
-PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr,
-   double fp, png_const_charp text),PNG_EMPTY);
-#endif
-
-/* Check the user version string for compatibility, returns false if the version
- * numbers aren't compatible.
- */
-PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr,
-   png_const_charp user_png_ver),PNG_EMPTY);
-
-/* Internal base allocator - no messages, NULL on failure to allocate.  This
- * does, however, call the application provided allocator and that could call
- * png_error (although that would be a bug in the application implementation.)
- */
-PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_base,(png_const_structrp png_ptr,
-   png_alloc_size_t size),PNG_ALLOCATED);
-
-#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
-   defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
-/* Internal array allocator, outputs no error or warning messages on failure,
- * just returns NULL.
- */
-PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_array,(png_const_structrp png_ptr,
-   int nelements, size_t element_size),PNG_ALLOCATED);
-
-/* The same but an existing array is extended by add_elements.  This function
- * also memsets the new elements to 0 and copies the old elements.  The old
- * array is not freed or altered.
- */
-PNG_INTERNAL_FUNCTION(png_voidp,png_realloc_array,(png_const_structrp png_ptr,
-   png_const_voidp array, int old_elements, int add_elements,
-   size_t element_size),PNG_ALLOCATED);
-#endif /* text, sPLT or unknown chunks */
-
-/* Magic to create a struct when there is no struct to call the user supplied
- * memory allocators.  Because error handling has not been set up the memory
- * handlers can't safely call png_error, but this is an obscure and undocumented
- * restriction so libpng has to assume that the 'free' handler, at least, might
- * call png_error.
- */
-PNG_INTERNAL_FUNCTION(png_structp,png_create_png_struct,
-   (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
-    png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn,
-    png_free_ptr free_fn),PNG_ALLOCATED);
-
-/* Free memory from internal libpng struct */
-PNG_INTERNAL_FUNCTION(void,png_destroy_png_struct,(png_structrp png_ptr),
-   PNG_EMPTY);
-
-/* Free an allocated jmp_buf (always succeeds) */
-PNG_INTERNAL_FUNCTION(void,png_free_jmpbuf,(png_structrp png_ptr),PNG_EMPTY);
-
-/* Function to allocate memory for zlib.  PNGAPI is disallowed. */
-PNG_INTERNAL_FUNCTION(voidpf,png_zalloc,(voidpf png_ptr, uInt items, uInt size),
-   PNG_ALLOCATED);
-
-/* Function to free memory for zlib.  PNGAPI is disallowed. */
-PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY);
-
-/* Next four functions are used internally as callbacks.  PNGCBAPI is required
- * but not PNG_EXPORT.  PNGAPI added at libpng version 1.2.3, changed to
- * PNGCBAPI at 1.5.0
- */
-
-PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr,
-    png_bytep data, size_t length),PNG_EMPTY);
-
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr,
-    png_bytep buffer, size_t length),PNG_EMPTY);
-#endif
-
-PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr,
-    png_bytep data, size_t length),PNG_EMPTY);
-
-#ifdef PNG_WRITE_FLUSH_SUPPORTED
-#  ifdef PNG_STDIO_SUPPORTED
-PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_flush,(png_structp png_ptr),
-   PNG_EMPTY);
-#  endif
-#endif
-
-/* Reset the CRC variable */
-PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY);
-
-/* Write the "data" buffer to whatever output you are using */
-PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr,
-    png_const_bytep data, size_t length),PNG_EMPTY);
-
-/* Read and check the PNG file signature */
-PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr,
-   png_inforp info_ptr),PNG_EMPTY);
-
-/* Read the chunk header (length + type name) */
-PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr),
-   PNG_EMPTY);
-
-/* Read data from whatever input you are using into the "data" buffer */
-PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data,
-    size_t length),PNG_EMPTY);
-
-/* Read bytes into buf, and update png_ptr->crc */
-PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf,
-    png_uint_32 length),PNG_EMPTY);
-
-/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */
-PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr,
-   png_uint_32 skip),PNG_EMPTY);
-
-/* Read the CRC from the file and compare it to the libpng calculated CRC */
-PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY);
-
-/* Calculate the CRC over a section of data.  Note that we are only
- * passing a maximum of 64K on systems that have this as a memory limit,
- * since this is the maximum buffer size we can specify.
- */
-PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr,
-   png_const_bytep ptr, size_t length),PNG_EMPTY);
-
-#ifdef PNG_WRITE_FLUSH_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY);
-#endif
-
-/* Write various chunks */
-
-/* Write the IHDR chunk, and update the png_struct with the necessary
- * information.
- */
-PNG_INTERNAL_FUNCTION(void,png_write_IHDR,(png_structrp png_ptr,
-   png_uint_32 width, png_uint_32 height, int bit_depth, int color_type,
-   int compression_method, int filter_method, int interlace_method),PNG_EMPTY);
-
-PNG_INTERNAL_FUNCTION(void,png_write_PLTE,(png_structrp png_ptr,
-   png_const_colorp palette, png_uint_32 num_pal),PNG_EMPTY);
-
-PNG_INTERNAL_FUNCTION(void,png_compress_IDAT,(png_structrp png_ptr,
-   png_const_bytep row_data, png_alloc_size_t row_data_length, int flush),
-   PNG_EMPTY);
-
-PNG_INTERNAL_FUNCTION(void,png_write_IEND,(png_structrp png_ptr),PNG_EMPTY);
-
-#ifdef PNG_WRITE_gAMA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_gAMA_fixed,(png_structrp png_ptr,
-    png_fixed_point file_gamma),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_sBIT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_sBIT,(png_structrp png_ptr,
-    png_const_color_8p sbit, int color_type),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_cHRM_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr,
-    const png_xy *xy), PNG_EMPTY);
-   /* The xy value must have been previously validated */
-#endif
-
-#ifdef PNG_WRITE_sRGB_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr,
-    int intent),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_eXIf_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_eXIf,(png_structrp png_ptr,
-    png_bytep exif, int num_exif),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_iCCP_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr,
-   png_const_charp name, png_const_bytep profile), PNG_EMPTY);
-   /* The profile must have been previously validated for correctness, the
-    * length comes from the first four bytes.  Only the base, deflate,
-    * compression is supported.
-    */
-#endif
-
-#ifdef PNG_WRITE_sPLT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_sPLT,(png_structrp png_ptr,
-    png_const_sPLT_tp palette),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_tRNS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_tRNS,(png_structrp png_ptr,
-    png_const_bytep trans, png_const_color_16p values, int number,
-    int color_type),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_bKGD_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_bKGD,(png_structrp png_ptr,
-    png_const_color_16p values, int color_type),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_hIST_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr,
-    png_const_uint_16p hist, int num_hist),PNG_EMPTY);
-#endif
-
-/* Chunks that have keywords */
-#ifdef PNG_WRITE_tEXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr,
-   png_const_charp key, png_const_charp text, size_t text_len),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_zTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_zTXt,(png_structrp png_ptr, png_const_charp
-    key, png_const_charp text, int compression),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_iTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_iTXt,(png_structrp png_ptr,
-    int compression, png_const_charp key, png_const_charp lang,
-    png_const_charp lang_key, png_const_charp text),PNG_EMPTY);
-#endif
-
-#ifdef PNG_TEXT_SUPPORTED  /* Added at version 1.0.14 and 1.2.4 */
-PNG_INTERNAL_FUNCTION(int,png_set_text_2,(png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_textp text_ptr, int num_text),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_oFFs_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_oFFs,(png_structrp png_ptr,
-    png_int_32 x_offset, png_int_32 y_offset, int unit_type),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_pCAL_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_pCAL,(png_structrp png_ptr,
-    png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
-    png_const_charp units, png_charpp params),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_pHYs_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_pHYs,(png_structrp png_ptr,
-    png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit,
-    int unit_type),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_tIME_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_tIME,(png_structrp png_ptr,
-    png_const_timep mod_time),PNG_EMPTY);
-#endif
-
-#ifdef PNG_WRITE_sCAL_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_write_sCAL_s,(png_structrp png_ptr,
-    int unit, png_const_charp width, png_const_charp height),PNG_EMPTY);
-#endif
-
-/* Called when finished processing a row of data */
-PNG_INTERNAL_FUNCTION(void,png_write_finish_row,(png_structrp png_ptr),
-    PNG_EMPTY);
-
-/* Internal use only.   Called before first row of data */
-PNG_INTERNAL_FUNCTION(void,png_write_start_row,(png_structrp png_ptr),
-    PNG_EMPTY);
-
-/* Combine a row of data, dealing with alpha, etc. if requested.  'row' is an
- * array of png_ptr->width pixels.  If the image is not interlaced or this
- * is the final pass this just does a memcpy, otherwise the "display" flag
- * is used to determine whether to copy pixels that are not in the current pass.
- *
- * Because 'png_do_read_interlace' (below) replicates pixels this allows this
- * function to achieve the documented 'blocky' appearance during interlaced read
- * if display is 1 and the 'sparkle' appearance, where existing pixels in 'row'
- * are not changed if they are not in the current pass, when display is 0.
- *
- * 'display' must be 0 or 1, otherwise the memcpy will be done regardless.
- *
- * The API always reads from the png_struct row buffer and always assumes that
- * it is full width (png_do_read_interlace has already been called.)
- *
- * This function is only ever used to write to row buffers provided by the
- * caller of the relevant libpng API and the row must have already been
- * transformed by the read transformations.
- *
- * The PNG_USE_COMPILE_TIME_MASKS option causes generation of pre-computed
- * bitmasks for use within the code, otherwise runtime generated masks are used.
- * The default is compile time masks.
- */
-#ifndef PNG_USE_COMPILE_TIME_MASKS
-#  define PNG_USE_COMPILE_TIME_MASKS 1
-#endif
-PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr,
-    png_bytep row, int display),PNG_EMPTY);
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-/* Expand an interlaced row: the 'row_info' describes the pass data that has
- * been read in and must correspond to the pixels in 'row', the pixels are
- * expanded (moved apart) in 'row' to match the final layout, when doing this
- * the pixels are *replicated* to the intervening space.  This is essential for
- * the correct operation of png_combine_row, above.
- */
-PNG_INTERNAL_FUNCTION(void,png_do_read_interlace,(png_row_infop row_info,
-    png_bytep row, int pass, png_uint_32 transformations),PNG_EMPTY);
-#endif
-
-/* GRR TO DO (2.0 or whenever):  simplify other internal calling interfaces */
-
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-/* Grab pixels out of a row for an interlaced pass */
-PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info,
-    png_bytep row, int pass),PNG_EMPTY);
-#endif
-
-/* Unfilter a row: check the filter value before calling this, there is no point
- * calling it for PNG_FILTER_VALUE_NONE.
- */
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY);
-
-#if PNG_ARM_NEON_OPT > 0
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info,
-    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-#endif
-
-#if PNG_MIPS_MSA_OPT > 0
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_msa,(png_row_infop row_info,
-    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_msa,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-#endif
-
-#if PNG_POWERPC_VSX_OPT > 0
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info,
-    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_vsx,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-#endif
-
-#if PNG_INTEL_SSE_IMPLEMENTATION > 0
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
-    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-#endif
-
-/* Choose the best filter to use and filter the row data */
-PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
-    png_row_infop row_info),PNG_EMPTY);
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr,
-   png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY);
-   /* Read 'avail_out' bytes of data from the IDAT stream.  If the output buffer
-    * is NULL the function checks, instead, for the end of the stream.  In this
-    * case a benign error will be issued if the stream end is not found or if
-    * extra data has to be consumed.
-    */
-PNG_INTERNAL_FUNCTION(void,png_read_finish_IDAT,(png_structrp png_ptr),
-   PNG_EMPTY);
-   /* This cleans up when the IDAT LZ stream does not end when the last image
-    * byte is read; there is still some pending input.
-    */
-
-PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr),
-   PNG_EMPTY);
-   /* Finish a row while reading, dealing with interlacing passes, etc. */
-#endif /* SEQUENTIAL_READ */
-
-/* Initialize the row buffers, etc. */
-PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY);
-
-#if ZLIB_VERNUM >= 0x1240
-PNG_INTERNAL_FUNCTION(int,png_zlib_inflate,(png_structrp png_ptr, int flush),
-      PNG_EMPTY);
-#  define PNG_INFLATE(pp, flush) png_zlib_inflate(pp, flush)
-#else /* Zlib < 1.2.4 */
-#  define PNG_INFLATE(pp, flush) inflate(&(pp)->zstream, flush)
-#endif /* Zlib < 1.2.4 */
-
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-/* Optional call to update the users info structure */
-PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-#endif
-
-/* Shared transform functions, defined in pngtran.c */
-#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
-    defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_strip_channel,(png_row_infop row_info,
-    png_bytep row, int at_start),PNG_EMPTY);
-#endif
-
-#ifdef PNG_16BIT_SUPPORTED
-#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_swap,(png_row_infop row_info,
-    png_bytep row),PNG_EMPTY);
-#endif
-#endif
-
-#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \
-    defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_packswap,(png_row_infop row_info,
-    png_bytep row),PNG_EMPTY);
-#endif
-
-#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_invert,(png_row_infop row_info,
-    png_bytep row),PNG_EMPTY);
-#endif
-
-#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info,
-    png_bytep row),PNG_EMPTY);
-#endif
-
-/* The following decodes the appropriate chunks, and does error correction,
- * then calls the appropriate callback for the chunk if it is valid.
- */
-
-/* Decode the IHDR chunk */
-PNG_INTERNAL_FUNCTION(void,png_handle_IHDR,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_handle_PLTE,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_handle_IEND,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-
-#ifdef PNG_READ_bKGD_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_bKGD,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_cHRM_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_eXIf_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_eXIf,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_gAMA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_hIST_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_hIST,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_iCCP_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_iCCP,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif /* READ_iCCP */
-
-#ifdef PNG_READ_iTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_iTXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_oFFs_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_oFFs,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_pCAL_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_pCAL,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_pHYs_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_pHYs,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_sBIT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_sBIT,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_sCAL_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_sCAL,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_sPLT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_sPLT,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif /* READ_sPLT */
-
-#ifdef PNG_READ_sRGB_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_sRGB,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_tEXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_tEXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_tIME_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_tIME,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_tRNS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_tRNS,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_zTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-#endif
-
-PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr,
-    png_uint_32 chunk_name),PNG_EMPTY);
-
-PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr,
-    png_uint_32 chunk_length),PNG_EMPTY);
-
-PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
-   /* This is the function that gets called for unknown chunks.  The 'keep'
-    * argument is either non-zero for a known chunk that has been set to be
-    * handled as unknown or zero for an unknown chunk.  By default the function
-    * just skips the chunk or errors out if it is critical.
-    */
-
-#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
-    defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
-PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling,
-    (png_const_structrp png_ptr, png_uint_32 chunk_name),PNG_EMPTY);
-   /* Exactly as the API png_handle_as_unknown() except that the argument is a
-    * 32-bit chunk name, not a string.
-    */
-#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
-
-/* Handle the transformations for reading and writing */
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_read_transformations,(png_structrp png_ptr,
-   png_row_infop row_info),PNG_EMPTY);
-#endif
-#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_do_write_transformations,(png_structrp png_ptr,
-   png_row_infop row_info),PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_init_read_transformations,(png_structrp png_ptr),
-    PNG_EMPTY);
-#endif
-
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_push_read_chunk,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_sig,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr),
-    PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr,
-    png_bytep buffer, size_t buffer_length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr,
-    png_bytep buffer, size_t buffer_length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr),
-    PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr,
-   png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr,
-   png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr,
-   png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_have_row,(png_structrp png_ptr,
-    png_bytep row),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_end,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_read_push_finish_row,(png_structrp png_ptr),
-    PNG_EMPTY);
-#  ifdef PNG_READ_tEXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_push_handle_tEXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_tEXt,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-#  endif
-#  ifdef PNG_READ_zTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_push_handle_zTXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_zTXt,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-#  endif
-#  ifdef PNG_READ_iTXt_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_push_handle_iTXt,(png_structrp png_ptr,
-    png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_push_read_iTXt,(png_structrp png_ptr,
-    png_inforp info_ptr),PNG_EMPTY);
-#  endif
-
-#endif /* PROGRESSIVE_READ */
-
-/* Added at libpng version 1.6.0 */
-#ifdef PNG_GAMMA_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr,
-    png_colorspacerp colorspace, png_fixed_point gAMA), PNG_EMPTY);
-   /* Set the colorspace gamma with a value provided by the application or by
-    * the gAMA chunk on read.  The value will override anything set by an ICC
-    * profile.
-    */
-
-PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr,
-    png_inforp info_ptr), PNG_EMPTY);
-   /* Synchronize the info 'valid' flags with the colorspace */
-
-PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr,
-    png_inforp info_ptr), PNG_EMPTY);
-   /* Copy the png_struct colorspace to the info_struct and call the above to
-    * synchronize the flags.  Checks for NULL info_ptr and does nothing.
-    */
-#endif
-
-/* Added at libpng version 1.4.0 */
-#ifdef PNG_COLORSPACE_SUPPORTED
-/* These internal functions are for maintaining the colorspace structure within
- * a png_info or png_struct (or, indeed, both).
- */
-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_chromaticities,
-   (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_xy *xy,
-    int preferred), PNG_EMPTY);
-
-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_endpoints,
-   (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_XYZ *XYZ,
-    int preferred), PNG_EMPTY);
-
-#ifdef PNG_sRGB_SUPPORTED
-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_sRGB,(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, int intent), PNG_EMPTY);
-   /* This does set the colorspace gAMA and cHRM values too, but doesn't set the
-    * flags to write them, if it returns false there was a problem and an error
-    * message has already been output (but the colorspace may still need to be
-    * synced to record the invalid flag).
-    */
-#endif /* sRGB */
-
-#ifdef PNG_iCCP_SUPPORTED
-PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_const_charp name,
-   png_uint_32 profile_length, png_const_bytep profile, int color_type),
-   PNG_EMPTY);
-   /* The 'name' is used for information only */
-
-/* Routines for checking parts of an ICC profile. */
-#ifdef PNG_READ_iCCP_SUPPORTED
-PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_const_charp name,
-   png_uint_32 profile_length), PNG_EMPTY);
-#endif /* READ_iCCP */
-PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_const_charp name,
-   png_uint_32 profile_length,
-   png_const_bytep profile /* first 132 bytes only */, int color_type),
-   PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr,
-   png_colorspacerp colorspace, png_const_charp name,
-   png_uint_32 profile_length,
-   png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY);
-#ifdef PNG_sRGB_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_icc_set_sRGB,(
-   png_const_structrp png_ptr, png_colorspacerp colorspace,
-   png_const_bytep profile, uLong adler), PNG_EMPTY);
-   /* 'adler' is the Adler32 checksum of the uncompressed profile data. It may
-    * be zero to indicate that it is not available.  It is used, if provided,
-    * as a fast check on the profile when checking to see if it is sRGB.
-    */
-#endif
-#endif /* iCCP */
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_colorspace_set_rgb_coefficients,
-   (png_structrp png_ptr), PNG_EMPTY);
-   /* Set the rgb_to_gray coefficients from the colorspace Y values */
-#endif /* READ_RGB_TO_GRAY */
-#endif /* COLORSPACE */
-
-/* Added at libpng version 1.4.0 */
-PNG_INTERNAL_FUNCTION(void,png_check_IHDR,(png_const_structrp png_ptr,
-    png_uint_32 width, png_uint_32 height, int bit_depth,
-    int color_type, int interlace_type, int compression_type,
-    int filter_type),PNG_EMPTY);
-
-/* Added at libpng version 1.5.10 */
-#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
-    defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_do_check_palette_indexes,
-   (png_structrp png_ptr, png_row_infop row_info),PNG_EMPTY);
-#endif
-
-#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
-PNG_INTERNAL_FUNCTION(void,png_fixed_error,(png_const_structrp png_ptr,
-   png_const_charp name),PNG_NORETURN);
-#endif
-
-/* Puts 'string' into 'buffer' at buffer[pos], taking care never to overwrite
- * the end.  Always leaves the buffer nul terminated.  Never errors out (and
- * there is no error code.)
- */
-PNG_INTERNAL_FUNCTION(size_t,png_safecat,(png_charp buffer, size_t bufsize,
-   size_t pos, png_const_charp string),PNG_EMPTY);
-
-/* Various internal functions to handle formatted warning messages, currently
- * only implemented for warnings.
- */
-#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED)
-/* Utility to dump an unsigned value into a buffer, given a start pointer and
- * and end pointer (which should point just *beyond* the end of the buffer!)
- * Returns the pointer to the start of the formatted string.  This utility only
- * does unsigned values.
- */
-PNG_INTERNAL_FUNCTION(png_charp,png_format_number,(png_const_charp start,
-   png_charp end, int format, png_alloc_size_t number),PNG_EMPTY);
-
-/* Convenience macro that takes an array: */
-#define PNG_FORMAT_NUMBER(buffer,format,number) \
-   png_format_number(buffer, buffer + (sizeof buffer), format, number)
-
-/* Suggested size for a number buffer (enough for 64 bits and a sign!) */
-#define PNG_NUMBER_BUFFER_SIZE 24
-
-/* These are the integer formats currently supported, the name is formed from
- * the standard printf(3) format string.
- */
-#define PNG_NUMBER_FORMAT_u     1 /* chose unsigned API! */
-#define PNG_NUMBER_FORMAT_02u   2
-#define PNG_NUMBER_FORMAT_d     1 /* chose signed API! */
-#define PNG_NUMBER_FORMAT_02d   2
-#define PNG_NUMBER_FORMAT_x     3
-#define PNG_NUMBER_FORMAT_02x   4
-#define PNG_NUMBER_FORMAT_fixed 5 /* choose the signed API */
-#endif
-
-#ifdef PNG_WARNINGS_SUPPORTED
-/* New defines and members adding in libpng-1.5.4 */
-#  define PNG_WARNING_PARAMETER_SIZE 32
-#  define PNG_WARNING_PARAMETER_COUNT 8 /* Maximum 9; see pngerror.c */
-
-/* An l-value of this type has to be passed to the APIs below to cache the
- * values of the parameters to a formatted warning message.
- */
-typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][
-   PNG_WARNING_PARAMETER_SIZE];
-
-PNG_INTERNAL_FUNCTION(void,png_warning_parameter,(png_warning_parameters p,
-   int number, png_const_charp string),PNG_EMPTY);
-   /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters,
-    * including the trailing '\0'.
-    */
-PNG_INTERNAL_FUNCTION(void,png_warning_parameter_unsigned,
-   (png_warning_parameters p, int number, int format, png_alloc_size_t value),
-   PNG_EMPTY);
-   /* Use png_alloc_size_t because it is an unsigned type as big as any we
-    * need to output.  Use the following for a signed value.
-    */
-PNG_INTERNAL_FUNCTION(void,png_warning_parameter_signed,
-   (png_warning_parameters p, int number, int format, png_int_32 value),
-   PNG_EMPTY);
-
-PNG_INTERNAL_FUNCTION(void,png_formatted_warning,(png_const_structrp png_ptr,
-   png_warning_parameters p, png_const_charp message),PNG_EMPTY);
-   /* 'message' follows the X/Open approach of using @1, @2 to insert
-    * parameters previously supplied using the above functions.  Errors in
-    * specifying the parameters will simply result in garbage substitutions.
-    */
-#endif
-
-#ifdef PNG_BENIGN_ERRORS_SUPPORTED
-/* Application errors (new in 1.6); use these functions (declared below) for
- * errors in the parameters or order of API function calls on read.  The
- * 'warning' should be used for an error that can be handled completely; the
- * 'error' for one which can be handled safely but which may lose application
- * information or settings.
- *
- * By default these both result in a png_error call prior to release, while in a
- * released version the 'warning' is just a warning.  However if the application
- * explicitly disables benign errors (explicitly permitting the code to lose
- * information) they both turn into warnings.
- *
- * If benign errors aren't supported they end up as the corresponding base call
- * (png_warning or png_error.)
- */
-PNG_INTERNAL_FUNCTION(void,png_app_warning,(png_const_structrp png_ptr,
-   png_const_charp message),PNG_EMPTY);
-   /* The application provided invalid parameters to an API function or called
-    * an API function at the wrong time, libpng can completely recover.
-    */
-
-PNG_INTERNAL_FUNCTION(void,png_app_error,(png_const_structrp png_ptr,
-   png_const_charp message),PNG_EMPTY);
-   /* As above but libpng will ignore the call, or attempt some other partial
-    * recovery from the error.
-    */
-#else
-#  define png_app_warning(pp,s) png_warning(pp,s)
-#  define png_app_error(pp,s) png_error(pp,s)
-#endif
-
-PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr,
-   png_const_charp message, int error),PNG_EMPTY);
-   /* Report a recoverable issue in chunk data.  On read this is used to report
-    * a problem found while reading a particular chunk and the
-    * png_chunk_benign_error or png_chunk_warning function is used as
-    * appropriate.  On write this is used to report an error that comes from
-    * data set via an application call to a png_set_ API and png_app_error or
-    * png_app_warning is used as appropriate.
-    *
-    * The 'error' parameter must have one of the following values:
-    */
-#define PNG_CHUNK_WARNING     0 /* never an error */
-#define PNG_CHUNK_WRITE_ERROR 1 /* an error only on write */
-#define PNG_CHUNK_ERROR       2 /* always an error */
-
-/* ASCII to FP interfaces, currently only implemented if sCAL
- * support is required.
- */
-#if defined(PNG_sCAL_SUPPORTED)
-/* MAX_DIGITS is actually the maximum number of characters in an sCAL
- * width or height, derived from the precision (number of significant
- * digits - a build time settable option) and assumptions about the
- * maximum ridiculous exponent.
- */
-#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/)
-
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr,
-   png_charp ascii, size_t size, double fp, unsigned int precision),
-   PNG_EMPTY);
-#endif /* FLOATING_POINT */
-
-#ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr,
-   png_charp ascii, size_t size, png_fixed_point fp),PNG_EMPTY);
-#endif /* FIXED_POINT */
-#endif /* sCAL */
-
-#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
-/* An internal API to validate the format of a floating point number.
- * The result is the index of the next character.  If the number is
- * not valid it will be the index of a character in the supposed number.
- *
- * The format of a number is defined in the PNG extensions specification
- * and this API is strictly conformant to that spec, not anyone elses!
- *
- * The format as a regular expression is:
- *
- * [+-]?[0-9]+.?([Ee][+-]?[0-9]+)?
- *
- * or:
- *
- * [+-]?.[0-9]+(.[0-9]+)?([Ee][+-]?[0-9]+)?
- *
- * The complexity is that either integer or fraction must be present and the
- * fraction is permitted to have no digits only if the integer is present.
- *
- * NOTE: The dangling E problem.
- *   There is a PNG valid floating point number in the following:
- *
- *       PNG floating point numbers are not greedy.
- *
- *   Working this out requires *TWO* character lookahead (because of the
- *   sign), the parser does not do this - it will fail at the 'r' - this
- *   doesn't matter for PNG sCAL chunk values, but it requires more care
- *   if the value were ever to be embedded in something more complex.  Use
- *   ANSI-C strtod if you need the lookahead.
- */
-/* State table for the parser. */
-#define PNG_FP_INTEGER    0  /* before or in integer */
-#define PNG_FP_FRACTION   1  /* before or in fraction */
-#define PNG_FP_EXPONENT   2  /* before or in exponent */
-#define PNG_FP_STATE      3  /* mask for the above */
-#define PNG_FP_SAW_SIGN   4  /* Saw +/- in current state */
-#define PNG_FP_SAW_DIGIT  8  /* Saw a digit in current state */
-#define PNG_FP_SAW_DOT   16  /* Saw a dot in current state */
-#define PNG_FP_SAW_E     32  /* Saw an E (or e) in current state */
-#define PNG_FP_SAW_ANY   60  /* Saw any of the above 4 */
-
-/* These three values don't affect the parser.  They are set but not used.
- */
-#define PNG_FP_WAS_VALID 64  /* Preceding substring is a valid fp number */
-#define PNG_FP_NEGATIVE 128  /* A negative number, including "-0" */
-#define PNG_FP_NONZERO  256  /* A non-zero value */
-#define PNG_FP_STICKY   448  /* The above three flags */
-
-/* This is available for the caller to store in 'state' if required.  Do not
- * call the parser after setting it (the parser sometimes clears it.)
- */
-#define PNG_FP_INVALID  512  /* Available for callers as a distinct value */
-
-/* Result codes for the parser (boolean - true meants ok, false means
- * not ok yet.)
- */
-#define PNG_FP_MAYBE      0  /* The number may be valid in the future */
-#define PNG_FP_OK         1  /* The number is valid */
-
-/* Tests on the sticky non-zero and negative flags.  To pass these checks
- * the state must also indicate that the whole number is valid - this is
- * achieved by testing PNG_FP_SAW_DIGIT (see the implementation for why this
- * is equivalent to PNG_FP_OK above.)
- */
-#define PNG_FP_NZ_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NEGATIVE | PNG_FP_NONZERO)
-   /* NZ_MASK: the string is valid and a non-zero negative value */
-#define PNG_FP_Z_MASK (PNG_FP_SAW_DIGIT | PNG_FP_NONZERO)
-   /* Z MASK: the string is valid and a non-zero value. */
-   /* PNG_FP_SAW_DIGIT: the string is valid. */
-#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT)
-#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK)
-#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK)
-
-/* The actual parser.  This can be called repeatedly. It updates
- * the index into the string and the state variable (which must
- * be initialized to 0).  It returns a result code, as above.  There
- * is no point calling the parser any more if it fails to advance to
- * the end of the string - it is stuck on an invalid character (or
- * terminated by '\0').
- *
- * Note that the pointer will consume an E or even an E+ and then leave
- * a 'maybe' state even though a preceding integer.fraction is valid.
- * The PNG_FP_WAS_VALID flag indicates that a preceding substring was
- * a valid number.  It's possible to recover from this by calling
- * the parser again (from the start, with state 0) but with a string
- * that omits the last character (i.e. set the size to the index of
- * the problem character.)  This has not been tested within libpng.
- */
-PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string,
-   size_t size, int *statep, png_size_tp whereami),PNG_EMPTY);
-
-/* This is the same but it checks a complete string and returns true
- * only if it just contains a floating point number.  As of 1.5.4 this
- * function also returns the state at the end of parsing the number if
- * it was valid (otherwise it returns 0.)  This can be used for testing
- * for negative or zero values using the sticky flag.
- */
-PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
-   size_t size),PNG_EMPTY);
-#endif /* pCAL || sCAL */
-
-#if defined(PNG_GAMMA_SUPPORTED) ||\
-    defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
-/* Added at libpng version 1.5.0 */
-/* This is a utility to provide a*times/div (rounded) and indicate
- * if there is an overflow.  The result is a boolean - false (0)
- * for overflow, true (1) if no overflow, in which case *res
- * holds the result.
- */
-PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a,
-   png_int_32 multiplied_by, png_int_32 divided_by),PNG_EMPTY);
-#endif
-
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
-/* Same deal, but issue a warning on overflow and return 0. */
-PNG_INTERNAL_FUNCTION(png_fixed_point,png_muldiv_warn,
-   (png_const_structrp png_ptr, png_fixed_point a, png_int_32 multiplied_by,
-   png_int_32 divided_by),PNG_EMPTY);
-#endif
-
-#ifdef PNG_GAMMA_SUPPORTED
-/* Calculate a reciprocal - used for gamma values.  This returns
- * 0 if the argument is 0 in order to maintain an undefined value;
- * there are no warnings.
- */
-PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a),
-   PNG_EMPTY);
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-/* The same but gives a reciprocal of the product of two fixed point
- * values.  Accuracy is suitable for gamma calculations but this is
- * not exact - use png_muldiv for that.  Only required at present on read.
- */
-PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a,
-   png_fixed_point b),PNG_EMPTY);
-#endif
-
-/* Return true if the gamma value is significantly different from 1.0 */
-PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value),
-   PNG_EMPTY);
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-/* Internal fixed point gamma correction.  These APIs are called as
- * required to convert single values - they don't need to be fast,
- * they are not used when processing image pixel values.
- *
- * While the input is an 'unsigned' value it must actually be the
- * correct bit value - 0..255 or 0..65535 as required.
- */
-PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_correct,(png_structrp png_ptr,
-   unsigned int value, png_fixed_point gamma_value),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_16bit_correct,(unsigned int value,
-   png_fixed_point gamma_value),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(png_byte,png_gamma_8bit_correct,(unsigned int value,
-   png_fixed_point gamma_value),PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr),
-   PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr,
-   int bit_depth),PNG_EMPTY);
-#endif
-
-/* SIMPLIFIED READ/WRITE SUPPORT */
-#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
-   defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
-/* The internal structure that png_image::opaque points to. */
-typedef struct png_control
-{
-   png_structp png_ptr;
-   png_infop   info_ptr;
-   png_voidp   error_buf;           /* Always a jmp_buf at present. */
-
-   png_const_bytep memory;          /* Memory buffer. */
-   size_t          size;            /* Size of the memory buffer. */
-
-   unsigned int for_write       :1; /* Otherwise it is a read structure */
-   unsigned int owned_file      :1; /* We own the file in io_ptr */
-} png_control;
-
-/* Return the pointer to the jmp_buf from a png_control: necessary because C
- * does not reveal the type of the elements of jmp_buf.
- */
-#ifdef __cplusplus
-#  define png_control_jmp_buf(pc) (((jmp_buf*)((pc)->error_buf))[0])
-#else
-#  define png_control_jmp_buf(pc) ((pc)->error_buf)
-#endif
-
-/* Utility to safely execute a piece of libpng code catching and logging any
- * errors that might occur.  Returns true on success, false on failure (either
- * of the function or as a result of a png_error.)
- */
-PNG_INTERNAL_CALLBACK(void,png_safe_error,(png_structp png_ptr,
-   png_const_charp error_message),PNG_NORETURN);
-
-#ifdef PNG_WARNINGS_SUPPORTED
-PNG_INTERNAL_CALLBACK(void,png_safe_warning,(png_structp png_ptr,
-   png_const_charp warning_message),PNG_EMPTY);
-#else
-#  define png_safe_warning 0/*dummy argument*/
-#endif
-
-PNG_INTERNAL_FUNCTION(int,png_safe_execute,(png_imagep image,
-   int (*function)(png_voidp), png_voidp arg),PNG_EMPTY);
-
-/* Utility to log an error; this also cleans up the png_image; the function
- * always returns 0 (false).
- */
-PNG_INTERNAL_FUNCTION(int,png_image_error,(png_imagep image,
-   png_const_charp error_message),PNG_EMPTY);
-
-#ifndef PNG_SIMPLIFIED_READ_SUPPORTED
-/* png_image_free is used by the write code but not exported */
-PNG_INTERNAL_FUNCTION(void, png_image_free, (png_imagep image), PNG_EMPTY);
-#endif /* !SIMPLIFIED_READ */
-
-#endif /* SIMPLIFIED READ/WRITE */
-
-/* These are initialization functions for hardware specific PNG filter
- * optimizations; list these here then select the appropriate one at compile
- * time using the macro PNG_FILTER_OPTIMIZATIONS.  If the macro is not defined
- * the generic code is used.
- */
-#ifdef PNG_FILTER_OPTIMIZATIONS
-PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr,
-   unsigned int bpp), PNG_EMPTY);
-   /* Just declare the optimization that will be used */
-#else
-   /* List *all* the possible optimizations here - this branch is required if
-    * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in
-    * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing.
-    */
-#  if PNG_ARM_NEON_OPT > 0
-PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
-   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
-#endif
-
-#if PNG_MIPS_MSA_OPT > 0
-PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa,
-   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
-#endif
-
-#  if PNG_INTEL_SSE_IMPLEMENTATION > 0
-PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
-   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
-#  endif
-#endif
-
-PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
-   png_const_charp key, png_bytep new_key), PNG_EMPTY);
-
-#if PNG_ARM_NEON_IMPLEMENTATION == 1
-PNG_INTERNAL_FUNCTION(void,
-                      png_riffle_palette_neon,
-                      (png_structrp),
-                      PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(int,
-                      png_do_expand_palette_rgba8_neon,
-                      (png_structrp,
-                       png_row_infop,
-                       png_const_bytep,
-                       const png_bytepp,
-                       const png_bytepp),
-                      PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(int,
-                      png_do_expand_palette_rgb8_neon,
-                      (png_structrp,
-                       png_row_infop,
-                       png_const_bytep,
-                       const png_bytepp,
-                       const png_bytepp),
-                      PNG_EMPTY);
-#endif
-
-/* Maintainer: Put new private prototypes here ^ */
-
-#include "pngdebug.h"
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* PNG_VERSION_INFO_ONLY */
-#endif /* PNGPRIV_H */
diff --git a/third_party/libpng16/pngread.c b/third_party/libpng16/pngread.c
deleted file mode 100644
index 5ab9224..0000000
--- a/third_party/libpng16/pngread.c
+++ /dev/null
@@ -1,4222 +0,0 @@
-
-/* pngread.c - read a PNG file
- *
- * Copyright (c) 2018-2019 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- *
- * This file contains routines that an application calls directly to
- * read a PNG file or stream.
- */
-
-#include "pngpriv.h"
-#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
-#  include <errno.h>
-#endif
-
-#ifdef PNG_READ_SUPPORTED
-
-/* Create a PNG structure for reading, and allocate any memory needed. */
-PNG_FUNCTION(png_structp,PNGAPI
-png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
-{
-#ifndef PNG_USER_MEM_SUPPORTED
-   png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
-        error_fn, warn_fn, NULL, NULL, NULL);
-#else
-   return png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
-        warn_fn, NULL, NULL, NULL);
-}
-
-/* Alternate create PNG structure for reading, and allocate any memory
- * needed.
- */
-PNG_FUNCTION(png_structp,PNGAPI
-png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
-    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
-{
-   png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
-       error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
-#endif /* USER_MEM */
-
-   if (png_ptr != NULL)
-   {
-      png_ptr->mode = PNG_IS_READ_STRUCT;
-
-      /* Added in libpng-1.6.0; this can be used to detect a read structure if
-       * required (it will be zero in a write structure.)
-       */
-#     ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-         png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE;
-#     endif
-
-#     ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED
-         png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
-
-         /* In stable builds only warn if an application error can be completely
-          * handled.
-          */
-#        if PNG_RELEASE_BUILD
-            png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
-#        endif
-#     endif
-
-      /* TODO: delay this, it can be done in png_init_io (if the app doesn't
-       * do it itself) avoiding setting the default function if it is not
-       * required.
-       */
-      png_set_read_fn(png_ptr, NULL, NULL);
-   }
-
-   return png_ptr;
-}
-
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-/* Read the information before the actual image data.  This has been
- * changed in v0.90 to allow reading a file that already has the magic
- * bytes read from the stream.  You can tell libpng how many bytes have
- * been read from the beginning of the stream (up to the maximum of 8)
- * via png_set_sig_bytes(), and we will only check the remaining bytes
- * here.  The application can then have access to the signature bytes we
- * read if it is determined that this isn't a valid PNG file.
- */
-void PNGAPI
-png_read_info(png_structrp png_ptr, png_inforp info_ptr)
-{
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-   int keep;
-#endif
-
-   png_debug(1, "in png_read_info");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   /* Read and check the PNG file signature. */
-   png_read_sig(png_ptr, info_ptr);
-
-   for (;;)
-   {
-      png_uint_32 length = png_read_chunk_header(png_ptr);
-      png_uint_32 chunk_name = png_ptr->chunk_name;
-
-      /* IDAT logic needs to happen here to simplify getting the two flags
-       * right.
-       */
-      if (chunk_name == png_IDAT)
-      {
-         if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-            png_chunk_error(png_ptr, "Missing IHDR before IDAT");
-
-         else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
-             (png_ptr->mode & PNG_HAVE_PLTE) == 0)
-            png_chunk_error(png_ptr, "Missing PLTE before IDAT");
-
-         else if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
-            png_chunk_benign_error(png_ptr, "Too many IDATs found");
-
-         png_ptr->mode |= PNG_HAVE_IDAT;
-      }
-
-      else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-      {
-         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
-         png_ptr->mode |= PNG_AFTER_IDAT;
-      }
-
-      /* This should be a binary subdivision search or a hash for
-       * matching the chunk name rather than a linear search.
-       */
-      if (chunk_name == png_IHDR)
-         png_handle_IHDR(png_ptr, info_ptr, length);
-
-      else if (chunk_name == png_IEND)
-         png_handle_IEND(png_ptr, info_ptr, length);
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-      else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
-      {
-         png_handle_unknown(png_ptr, info_ptr, length, keep);
-
-         if (chunk_name == png_PLTE)
-            png_ptr->mode |= PNG_HAVE_PLTE;
-
-         else if (chunk_name == png_IDAT)
-         {
-            png_ptr->idat_size = 0; /* It has been consumed */
-            break;
-         }
-      }
-#endif
-      else if (chunk_name == png_PLTE)
-         png_handle_PLTE(png_ptr, info_ptr, length);
-
-      else if (chunk_name == png_IDAT)
-      {
-         png_ptr->idat_size = length;
-         break;
-      }
-
-#ifdef PNG_READ_bKGD_SUPPORTED
-      else if (chunk_name == png_bKGD)
-         png_handle_bKGD(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_cHRM_SUPPORTED
-      else if (chunk_name == png_cHRM)
-         png_handle_cHRM(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_eXIf_SUPPORTED
-      else if (chunk_name == png_eXIf)
-         png_handle_eXIf(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_gAMA_SUPPORTED
-      else if (chunk_name == png_gAMA)
-         png_handle_gAMA(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_hIST_SUPPORTED
-      else if (chunk_name == png_hIST)
-         png_handle_hIST(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_oFFs_SUPPORTED
-      else if (chunk_name == png_oFFs)
-         png_handle_oFFs(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_pCAL_SUPPORTED
-      else if (chunk_name == png_pCAL)
-         png_handle_pCAL(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sCAL_SUPPORTED
-      else if (chunk_name == png_sCAL)
-         png_handle_sCAL(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_pHYs_SUPPORTED
-      else if (chunk_name == png_pHYs)
-         png_handle_pHYs(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sBIT_SUPPORTED
-      else if (chunk_name == png_sBIT)
-         png_handle_sBIT(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sRGB_SUPPORTED
-      else if (chunk_name == png_sRGB)
-         png_handle_sRGB(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_iCCP_SUPPORTED
-      else if (chunk_name == png_iCCP)
-         png_handle_iCCP(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sPLT_SUPPORTED
-      else if (chunk_name == png_sPLT)
-         png_handle_sPLT(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tEXt_SUPPORTED
-      else if (chunk_name == png_tEXt)
-         png_handle_tEXt(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tIME_SUPPORTED
-      else if (chunk_name == png_tIME)
-         png_handle_tIME(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tRNS_SUPPORTED
-      else if (chunk_name == png_tRNS)
-         png_handle_tRNS(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_zTXt_SUPPORTED
-      else if (chunk_name == png_zTXt)
-         png_handle_zTXt(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_iTXt_SUPPORTED
-      else if (chunk_name == png_iTXt)
-         png_handle_iTXt(png_ptr, info_ptr, length);
-#endif
-
-      else
-         png_handle_unknown(png_ptr, info_ptr, length,
-             PNG_HANDLE_CHUNK_AS_DEFAULT);
-   }
-}
-#endif /* SEQUENTIAL_READ */
-
-/* Optional call to update the users info_ptr structure */
-void PNGAPI
-png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
-{
-   png_debug(1, "in png_read_update_info");
-
-   if (png_ptr != NULL)
-   {
-      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
-      {
-         png_read_start_row(png_ptr);
-
-#        ifdef PNG_READ_TRANSFORMS_SUPPORTED
-            png_read_transform_info(png_ptr, info_ptr);
-#        else
-            PNG_UNUSED(info_ptr)
-#        endif
-      }
-
-      /* New in 1.6.0 this avoids the bug of doing the initializations twice */
-      else
-         png_app_error(png_ptr,
-             "png_read_update_info/png_start_read_image: duplicate call");
-   }
-}
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-/* Initialize palette, background, etc, after transformations
- * are set, but before any reading takes place.  This allows
- * the user to obtain a gamma-corrected palette, for example.
- * If the user doesn't call this, we will do it ourselves.
- */
-void PNGAPI
-png_start_read_image(png_structrp png_ptr)
-{
-   png_debug(1, "in png_start_read_image");
-
-   if (png_ptr != NULL)
-   {
-      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
-         png_read_start_row(png_ptr);
-
-      /* New in 1.6.0 this avoids the bug of doing the initializations twice */
-      else
-         png_app_error(png_ptr,
-             "png_start_read_image/png_read_update_info: duplicate call");
-   }
-}
-#endif /* SEQUENTIAL_READ */
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-/* Undoes intrapixel differencing,
- * NOTE: this is apparently only supported in the 'sequential' reader.
- */
-static void
-png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_read_intrapixel");
-
-   if (
-       (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
-   {
-      int bytes_per_pixel;
-      png_uint_32 row_width = row_info->width;
-
-      if (row_info->bit_depth == 8)
-      {
-         png_bytep rp;
-         png_uint_32 i;
-
-         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
-            bytes_per_pixel = 3;
-
-         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-            bytes_per_pixel = 4;
-
-         else
-            return;
-
-         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
-         {
-            *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
-            *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
-         }
-      }
-      else if (row_info->bit_depth == 16)
-      {
-         png_bytep rp;
-         png_uint_32 i;
-
-         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
-            bytes_per_pixel = 6;
-
-         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-            bytes_per_pixel = 8;
-
-         else
-            return;
-
-         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
-         {
-            png_uint_32 s0   = (png_uint_32)(*(rp    ) << 8) | *(rp + 1);
-            png_uint_32 s1   = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3);
-            png_uint_32 s2   = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5);
-            png_uint_32 red  = (s0 + s1 + 65536) & 0xffff;
-            png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
-            *(rp    ) = (png_byte)((red >> 8) & 0xff);
-            *(rp + 1) = (png_byte)(red & 0xff);
-            *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
-            *(rp + 5) = (png_byte)(blue & 0xff);
-         }
-      }
-   }
-}
-#endif /* MNG_FEATURES */
-
-void PNGAPI
-png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
-{
-   png_row_info row_info;
-
-   if (png_ptr == NULL)
-      return;
-
-   png_debug2(1, "in png_read_row (row %lu, pass %d)",
-       (unsigned long)png_ptr->row_number, png_ptr->pass);
-
-   /* png_read_start_row sets the information (in particular iwidth) for this
-    * interlace pass.
-    */
-   if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
-      png_read_start_row(png_ptr);
-
-   /* 1.5.6: row_info moved out of png_struct to a local here. */
-   row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
-   row_info.color_type = png_ptr->color_type;
-   row_info.bit_depth = png_ptr->bit_depth;
-   row_info.channels = png_ptr->channels;
-   row_info.pixel_depth = png_ptr->pixel_depth;
-   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
-
-#ifdef PNG_WARNINGS_SUPPORTED
-   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
-   {
-   /* Check for transforms that have been set but were defined out */
-#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
-   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
-      png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined");
-#endif
-
-#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
-   if ((png_ptr->transformations & PNG_FILLER) != 0)
-      png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined");
-#endif
-
-#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
-    !defined(PNG_READ_PACKSWAP_SUPPORTED)
-   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
-      png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined");
-#endif
-
-#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
-   if ((png_ptr->transformations & PNG_PACK) != 0)
-      png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined");
-#endif
-
-#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
-   if ((png_ptr->transformations & PNG_SHIFT) != 0)
-      png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined");
-#endif
-
-#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
-   if ((png_ptr->transformations & PNG_BGR) != 0)
-      png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined");
-#endif
-
-#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
-   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
-      png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined");
-#endif
-   }
-#endif /* WARNINGS */
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   /* If interlaced and we do not need a new row, combine row and return.
-    * Notice that the pixels we have from previous rows have been transformed
-    * already; we can only combine like with like (transformed or
-    * untransformed) and, because of the libpng API for interlaced images, this
-    * means we must transform before de-interlacing.
-    */
-   if (png_ptr->interlaced != 0 &&
-       (png_ptr->transformations & PNG_INTERLACE) != 0)
-   {
-      switch (png_ptr->pass)
-      {
-         case 0:
-            if (png_ptr->row_number & 0x07)
-            {
-               if (dsp_row != NULL)
-                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
-               png_read_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 1:
-            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
-            {
-               if (dsp_row != NULL)
-                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
-
-               png_read_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 2:
-            if ((png_ptr->row_number & 0x07) != 4)
-            {
-               if (dsp_row != NULL && (png_ptr->row_number & 4))
-                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
-
-               png_read_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 3:
-            if ((png_ptr->row_number & 3) || png_ptr->width < 3)
-            {
-               if (dsp_row != NULL)
-                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
-
-               png_read_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 4:
-            if ((png_ptr->row_number & 3) != 2)
-            {
-               if (dsp_row != NULL && (png_ptr->row_number & 2))
-                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
-
-               png_read_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 5:
-            if ((png_ptr->row_number & 1) || png_ptr->width < 2)
-            {
-               if (dsp_row != NULL)
-                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
-
-               png_read_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         default:
-         case 6:
-            if ((png_ptr->row_number & 1) == 0)
-            {
-               png_read_finish_row(png_ptr);
-               return;
-            }
-            break;
-      }
-   }
-#endif
-
-   if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
-      png_error(png_ptr, "Invalid attempt to read row data");
-
-   /* Fill the row with IDAT data: */
-   png_ptr->row_buf[0]=255; /* to force error if no data was found */
-   png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1);
-
-   if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
-   {
-      if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
-         png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
-             png_ptr->prev_row + 1, png_ptr->row_buf[0]);
-      else
-         png_error(png_ptr, "bad adaptive filter value");
-   }
-
-   /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
-    * 1.5.6, while the buffer really is this big in current versions of libpng
-    * it may not be in the future, so this was changed just to copy the
-    * interlaced count:
-    */
-   memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
-
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
-       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
-   {
-      /* Intrapixel differencing */
-      png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1);
-   }
-#endif
-
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-   if (png_ptr->transformations)
-      png_do_read_transformations(png_ptr, &row_info);
-#endif
-
-   /* The transformed pixel depth should match the depth now in row_info. */
-   if (png_ptr->transformed_pixel_depth == 0)
-   {
-      png_ptr->transformed_pixel_depth = row_info.pixel_depth;
-      if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
-         png_error(png_ptr, "sequential row overflow");
-   }
-
-   else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
-      png_error(png_ptr, "internal sequential row size calculation error");
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   /* Expand interlaced rows to full size */
-   if (png_ptr->interlaced != 0 &&
-      (png_ptr->transformations & PNG_INTERLACE) != 0)
-   {
-      if (png_ptr->pass < 6)
-         png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
-             png_ptr->transformations);
-
-      if (dsp_row != NULL)
-         png_combine_row(png_ptr, dsp_row, 1/*display*/);
-
-      if (row != NULL)
-         png_combine_row(png_ptr, row, 0/*row*/);
-   }
-
-   else
-#endif
-   {
-      if (row != NULL)
-         png_combine_row(png_ptr, row, -1/*ignored*/);
-
-      if (dsp_row != NULL)
-         png_combine_row(png_ptr, dsp_row, -1/*ignored*/);
-   }
-   png_read_finish_row(png_ptr);
-
-   if (png_ptr->read_row_fn != NULL)
-      (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
-
-}
-#endif /* SEQUENTIAL_READ */
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-/* Read one or more rows of image data.  If the image is interlaced,
- * and png_set_interlace_handling() has been called, the rows need to
- * contain the contents of the rows from the previous pass.  If the
- * image has alpha or transparency, and png_handle_alpha()[*] has been
- * called, the rows contents must be initialized to the contents of the
- * screen.
- *
- * "row" holds the actual image, and pixels are placed in it
- * as they arrive.  If the image is displayed after each pass, it will
- * appear to "sparkle" in.  "display_row" can be used to display a
- * "chunky" progressive image, with finer detail added as it becomes
- * available.  If you do not want this "chunky" display, you may pass
- * NULL for display_row.  If you do not want the sparkle display, and
- * you have not called png_handle_alpha(), you may pass NULL for rows.
- * If you have called png_handle_alpha(), and the image has either an
- * alpha channel or a transparency chunk, you must provide a buffer for
- * rows.  In this case, you do not have to provide a display_row buffer
- * also, but you may.  If the image is not interlaced, or if you have
- * not called png_set_interlace_handling(), the display_row buffer will
- * be ignored, so pass NULL to it.
- *
- * [*] png_handle_alpha() does not exist yet, as of this version of libpng
- */
-
-void PNGAPI
-png_read_rows(png_structrp png_ptr, png_bytepp row,
-    png_bytepp display_row, png_uint_32 num_rows)
-{
-   png_uint_32 i;
-   png_bytepp rp;
-   png_bytepp dp;
-
-   png_debug(1, "in png_read_rows");
-
-   if (png_ptr == NULL)
-      return;
-
-   rp = row;
-   dp = display_row;
-   if (rp != NULL && dp != NULL)
-      for (i = 0; i < num_rows; i++)
-      {
-         png_bytep rptr = *rp++;
-         png_bytep dptr = *dp++;
-
-         png_read_row(png_ptr, rptr, dptr);
-      }
-
-   else if (rp != NULL)
-      for (i = 0; i < num_rows; i++)
-      {
-         png_bytep rptr = *rp;
-         png_read_row(png_ptr, rptr, NULL);
-         rp++;
-      }
-
-   else if (dp != NULL)
-      for (i = 0; i < num_rows; i++)
-      {
-         png_bytep dptr = *dp;
-         png_read_row(png_ptr, NULL, dptr);
-         dp++;
-      }
-}
-#endif /* SEQUENTIAL_READ */
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-/* Read the entire image.  If the image has an alpha channel or a tRNS
- * chunk, and you have called png_handle_alpha()[*], you will need to
- * initialize the image to the current image that PNG will be overlaying.
- * We set the num_rows again here, in case it was incorrectly set in
- * png_read_start_row() by a call to png_read_update_info() or
- * png_start_read_image() if png_set_interlace_handling() wasn't called
- * prior to either of these functions like it should have been.  You can
- * only call this function once.  If you desire to have an image for
- * each pass of a interlaced image, use png_read_rows() instead.
- *
- * [*] png_handle_alpha() does not exist yet, as of this version of libpng
- */
-void PNGAPI
-png_read_image(png_structrp png_ptr, png_bytepp image)
-{
-   png_uint_32 i, image_height;
-   int pass, j;
-   png_bytepp rp;
-
-   png_debug(1, "in png_read_image");
-
-   if (png_ptr == NULL)
-      return;
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
-   {
-      pass = png_set_interlace_handling(png_ptr);
-      /* And make sure transforms are initialized. */
-      png_start_read_image(png_ptr);
-   }
-   else
-   {
-      if (png_ptr->interlaced != 0 &&
-          (png_ptr->transformations & PNG_INTERLACE) == 0)
-      {
-         /* Caller called png_start_read_image or png_read_update_info without
-          * first turning on the PNG_INTERLACE transform.  We can fix this here,
-          * but the caller should do it!
-          */
-         png_warning(png_ptr, "Interlace handling should be turned on when "
-             "using png_read_image");
-         /* Make sure this is set correctly */
-         png_ptr->num_rows = png_ptr->height;
-      }
-
-      /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in
-       * the above error case.
-       */
-      pass = png_set_interlace_handling(png_ptr);
-   }
-#else
-   if (png_ptr->interlaced)
-      png_error(png_ptr,
-          "Cannot read interlaced image -- interlace handler disabled");
-
-   pass = 1;
-#endif
-
-   image_height=png_ptr->height;
-
-   for (j = 0; j < pass; j++)
-   {
-      rp = image;
-      for (i = 0; i < image_height; i++)
-      {
-         png_read_row(png_ptr, *rp, NULL);
-         rp++;
-      }
-   }
-}
-#endif /* SEQUENTIAL_READ */
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-/* Read the end of the PNG file.  Will not read past the end of the
- * file, will verify the end is accurate, and will read any comments
- * or time information at the end of the file, if info is not NULL.
- */
-void PNGAPI
-png_read_end(png_structrp png_ptr, png_inforp info_ptr)
-{
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-   int keep;
-#endif
-
-   png_debug(1, "in png_read_end");
-
-   if (png_ptr == NULL)
-      return;
-
-   /* If png_read_end is called in the middle of reading the rows there may
-    * still be pending IDAT data and an owned zstream.  Deal with this here.
-    */
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-   if (png_chunk_unknown_handling(png_ptr, png_IDAT) == 0)
-#endif
-      png_read_finish_IDAT(png_ptr);
-
-#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
-   /* Report invalid palette index; added at libng-1.5.10 */
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
-       png_ptr->num_palette_max > png_ptr->num_palette)
-      png_benign_error(png_ptr, "Read palette index exceeding num_palette");
-#endif
-
-   do
-   {
-      png_uint_32 length = png_read_chunk_header(png_ptr);
-      png_uint_32 chunk_name = png_ptr->chunk_name;
-
-      if (chunk_name != png_IDAT)
-         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
-
-      if (chunk_name == png_IEND)
-         png_handle_IEND(png_ptr, info_ptr, length);
-
-      else if (chunk_name == png_IHDR)
-         png_handle_IHDR(png_ptr, info_ptr, length);
-
-      else if (info_ptr == NULL)
-         png_crc_finish(png_ptr, length);
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-      else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
-      {
-         if (chunk_name == png_IDAT)
-         {
-            if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
-                || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
-               png_benign_error(png_ptr, ".Too many IDATs found");
-         }
-         png_handle_unknown(png_ptr, info_ptr, length, keep);
-         if (chunk_name == png_PLTE)
-            png_ptr->mode |= PNG_HAVE_PLTE;
-      }
-#endif
-
-      else if (chunk_name == png_IDAT)
-      {
-         /* Zero length IDATs are legal after the last IDAT has been
-          * read, but not after other chunks have been read.  1.6 does not
-          * always read all the deflate data; specifically it cannot be relied
-          * upon to read the Adler32 at the end.  If it doesn't ignore IDAT
-          * chunks which are longer than zero as well:
-          */
-         if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
-             || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
-            png_benign_error(png_ptr, "..Too many IDATs found");
-
-         png_crc_finish(png_ptr, length);
-      }
-      else if (chunk_name == png_PLTE)
-         png_handle_PLTE(png_ptr, info_ptr, length);
-
-#ifdef PNG_READ_bKGD_SUPPORTED
-      else if (chunk_name == png_bKGD)
-         png_handle_bKGD(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_cHRM_SUPPORTED
-      else if (chunk_name == png_cHRM)
-         png_handle_cHRM(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_eXIf_SUPPORTED
-      else if (chunk_name == png_eXIf)
-         png_handle_eXIf(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_gAMA_SUPPORTED
-      else if (chunk_name == png_gAMA)
-         png_handle_gAMA(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_hIST_SUPPORTED
-      else if (chunk_name == png_hIST)
-         png_handle_hIST(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_oFFs_SUPPORTED
-      else if (chunk_name == png_oFFs)
-         png_handle_oFFs(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_pCAL_SUPPORTED
-      else if (chunk_name == png_pCAL)
-         png_handle_pCAL(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sCAL_SUPPORTED
-      else if (chunk_name == png_sCAL)
-         png_handle_sCAL(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_pHYs_SUPPORTED
-      else if (chunk_name == png_pHYs)
-         png_handle_pHYs(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sBIT_SUPPORTED
-      else if (chunk_name == png_sBIT)
-         png_handle_sBIT(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sRGB_SUPPORTED
-      else if (chunk_name == png_sRGB)
-         png_handle_sRGB(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_iCCP_SUPPORTED
-      else if (chunk_name == png_iCCP)
-         png_handle_iCCP(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_sPLT_SUPPORTED
-      else if (chunk_name == png_sPLT)
-         png_handle_sPLT(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tEXt_SUPPORTED
-      else if (chunk_name == png_tEXt)
-         png_handle_tEXt(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tIME_SUPPORTED
-      else if (chunk_name == png_tIME)
-         png_handle_tIME(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_tRNS_SUPPORTED
-      else if (chunk_name == png_tRNS)
-         png_handle_tRNS(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_zTXt_SUPPORTED
-      else if (chunk_name == png_zTXt)
-         png_handle_zTXt(png_ptr, info_ptr, length);
-#endif
-
-#ifdef PNG_READ_iTXt_SUPPORTED
-      else if (chunk_name == png_iTXt)
-         png_handle_iTXt(png_ptr, info_ptr, length);
-#endif
-
-      else
-         png_handle_unknown(png_ptr, info_ptr, length,
-             PNG_HANDLE_CHUNK_AS_DEFAULT);
-   } while ((png_ptr->mode & PNG_HAVE_IEND) == 0);
-}
-#endif /* SEQUENTIAL_READ */
-
-/* Free all memory used in the read struct */
-static void
-png_read_destroy(png_structrp png_ptr)
-{
-   png_debug(1, "in png_read_destroy");
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-   png_destroy_gamma_table(png_ptr);
-#endif
-
-   png_free(png_ptr, png_ptr->big_row_buf);
-   png_ptr->big_row_buf = NULL;
-   png_free(png_ptr, png_ptr->big_prev_row);
-   png_ptr->big_prev_row = NULL;
-   png_free(png_ptr, png_ptr->read_buffer);
-   png_ptr->read_buffer = NULL;
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-   png_free(png_ptr, png_ptr->palette_lookup);
-   png_ptr->palette_lookup = NULL;
-   png_free(png_ptr, png_ptr->quantize_index);
-   png_ptr->quantize_index = NULL;
-#endif
-
-   if ((png_ptr->free_me & PNG_FREE_PLTE) != 0)
-   {
-      png_zfree(png_ptr, png_ptr->palette);
-      png_ptr->palette = NULL;
-   }
-   png_ptr->free_me &= ~PNG_FREE_PLTE;
-
-#if defined(PNG_tRNS_SUPPORTED) || \
-    defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
-   if ((png_ptr->free_me & PNG_FREE_TRNS) != 0)
-   {
-      png_free(png_ptr, png_ptr->trans_alpha);
-      png_ptr->trans_alpha = NULL;
-   }
-   png_ptr->free_me &= ~PNG_FREE_TRNS;
-#endif
-
-   inflateEnd(&png_ptr->zstream);
-
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-   png_free(png_ptr, png_ptr->save_buffer);
-   png_ptr->save_buffer = NULL;
-#endif
-
-#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) && \
-   defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
-   png_free(png_ptr, png_ptr->unknown_chunk.data);
-   png_ptr->unknown_chunk.data = NULL;
-#endif
-
-#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-   png_free(png_ptr, png_ptr->chunk_list);
-   png_ptr->chunk_list = NULL;
-#endif
-
-#if defined(PNG_READ_EXPAND_SUPPORTED) && \
-    defined(PNG_ARM_NEON_IMPLEMENTATION)
-   png_free(png_ptr, png_ptr->riffled_palette);
-   png_ptr->riffled_palette = NULL;
-#endif
-
-   /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
-    * callbacks are still set at this point.  They are required to complete the
-    * destruction of the png_struct itself.
-    */
-}
-
-/* Free all memory used by the read */
-void PNGAPI
-png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
-    png_infopp end_info_ptr_ptr)
-{
-   png_structrp png_ptr = NULL;
-
-   png_debug(1, "in png_destroy_read_struct");
-
-   if (png_ptr_ptr != NULL)
-      png_ptr = *png_ptr_ptr;
-
-   if (png_ptr == NULL)
-      return;
-
-   /* libpng 1.6.0: use the API to destroy info structs to ensure consistent
-    * behavior.  Prior to 1.6.0 libpng did extra 'info' destruction in this API.
-    * The extra was, apparently, unnecessary yet this hides memory leak bugs.
-    */
-   png_destroy_info_struct(png_ptr, end_info_ptr_ptr);
-   png_destroy_info_struct(png_ptr, info_ptr_ptr);
-
-   *png_ptr_ptr = NULL;
-   png_read_destroy(png_ptr);
-   png_destroy_png_struct(png_ptr);
-}
-
-void PNGAPI
-png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)
-{
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->read_row_fn = read_row_fn;
-}
-
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-#ifdef PNG_INFO_IMAGE_SUPPORTED
-void PNGAPI
-png_read_png(png_structrp png_ptr, png_inforp info_ptr,
-    int transforms, voidp params)
-{
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   /* png_read_info() gives us all of the information from the
-    * PNG file before the first IDAT (image data chunk).
-    */
-   png_read_info(png_ptr, info_ptr);
-   if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep)))
-      png_error(png_ptr, "Image is too high to process with png_read_png()");
-
-   /* -------------- image transformations start here ------------------- */
-   /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM
-    * is not implemented.  This will only happen in de-configured (non-default)
-    * libpng builds.  The results can be unexpected - png_read_png may return
-    * short or mal-formed rows because the transform is skipped.
-    */
-
-   /* Tell libpng to strip 16-bit/color files down to 8 bits per color.
-    */
-   if ((transforms & PNG_TRANSFORM_SCALE_16) != 0)
-      /* Added at libpng-1.5.4. "strip_16" produces the same result that it
-       * did in earlier versions, while "scale_16" is now more accurate.
-       */
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
-      png_set_scale_16(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported");
-#endif
-
-   /* If both SCALE and STRIP are required pngrtran will effectively cancel the
-    * latter by doing SCALE first.  This is ok and allows apps not to check for
-    * which is supported to get the right answer.
-    */
-   if ((transforms & PNG_TRANSFORM_STRIP_16) != 0)
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-      png_set_strip_16(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported");
-#endif
-
-   /* Strip alpha bytes from the input data without combining with
-    * the background (not recommended).
-    */
-   if ((transforms & PNG_TRANSFORM_STRIP_ALPHA) != 0)
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-      png_set_strip_alpha(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported");
-#endif
-
-   /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
-    * byte into separate bytes (useful for paletted and grayscale images).
-    */
-   if ((transforms & PNG_TRANSFORM_PACKING) != 0)
-#ifdef PNG_READ_PACK_SUPPORTED
-      png_set_packing(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
-#endif
-
-   /* Change the order of packed pixels to least significant bit first
-    * (not useful if you are using png_set_packing).
-    */
-   if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
-      png_set_packswap(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
-#endif
-
-   /* Expand paletted colors into true RGB triplets
-    * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
-    * Expand paletted or RGB images with transparency to full alpha
-    * channels so the data will be available as RGBA quartets.
-    */
-   if ((transforms & PNG_TRANSFORM_EXPAND) != 0)
-#ifdef PNG_READ_EXPAND_SUPPORTED
-      png_set_expand(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported");
-#endif
-
-   /* We don't handle background color or gamma transformation or quantizing.
-    */
-
-   /* Invert monochrome files to have 0 as white and 1 as black
-    */
-   if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
-#ifdef PNG_READ_INVERT_SUPPORTED
-      png_set_invert_mono(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
-#endif
-
-   /* If you want to shift the pixel values from the range [0,255] or
-    * [0,65535] to the original [0,7] or [0,31], or whatever range the
-    * colors were originally in:
-    */
-   if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
-#ifdef PNG_READ_SHIFT_SUPPORTED
-      if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
-         png_set_shift(png_ptr, &info_ptr->sig_bit);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
-#endif
-
-   /* Flip the RGB pixels to BGR (or RGBA to BGRA) */
-   if ((transforms & PNG_TRANSFORM_BGR) != 0)
-#ifdef PNG_READ_BGR_SUPPORTED
-      png_set_bgr(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
-#endif
-
-   /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
-   if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
-      png_set_swap_alpha(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
-#endif
-
-   /* Swap bytes of 16-bit files to least significant byte first */
-   if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
-#ifdef PNG_READ_SWAP_SUPPORTED
-      png_set_swap(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
-#endif
-
-/* Added at libpng-1.2.41 */
-   /* Invert the alpha channel from opacity to transparency */
-   if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-      png_set_invert_alpha(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
-#endif
-
-/* Added at libpng-1.2.41 */
-   /* Expand grayscale image to RGB */
-   if ((transforms & PNG_TRANSFORM_GRAY_TO_RGB) != 0)
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-      png_set_gray_to_rgb(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported");
-#endif
-
-/* Added at libpng-1.5.4 */
-   if ((transforms & PNG_TRANSFORM_EXPAND_16) != 0)
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
-      png_set_expand_16(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported");
-#endif
-
-   /* We don't handle adding filler bytes */
-
-   /* We use png_read_image and rely on that for interlace handling, but we also
-    * call png_read_update_info therefore must turn on interlace handling now:
-    */
-   (void)png_set_interlace_handling(png_ptr);
-
-   /* Optional call to gamma correct and add the background to the palette
-    * and update info structure.  REQUIRED if you are expecting libpng to
-    * update the palette for you (i.e., you selected such a transform above).
-    */
-   png_read_update_info(png_ptr, info_ptr);
-
-   /* -------------- image transformations end here ------------------- */
-
-   png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
-   if (info_ptr->row_pointers == NULL)
-   {
-      png_uint_32 iptr;
-
-      info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr,
-          info_ptr->height * (sizeof (png_bytep))));
-
-      for (iptr=0; iptr<info_ptr->height; iptr++)
-         info_ptr->row_pointers[iptr] = NULL;
-
-      info_ptr->free_me |= PNG_FREE_ROWS;
-
-      for (iptr = 0; iptr < info_ptr->height; iptr++)
-         info_ptr->row_pointers[iptr] = png_voidcast(png_bytep,
-             png_malloc(png_ptr, info_ptr->rowbytes));
-   }
-
-   png_read_image(png_ptr, info_ptr->row_pointers);
-   info_ptr->valid |= PNG_INFO_IDAT;
-
-   /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
-   png_read_end(png_ptr, info_ptr);
-
-   PNG_UNUSED(params)
-}
-#endif /* INFO_IMAGE */
-#endif /* SEQUENTIAL_READ */
-
-#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
-/* SIMPLIFIED READ
- *
- * This code currently relies on the sequential reader, though it could easily
- * be made to work with the progressive one.
- */
-/* Arguments to png_image_finish_read: */
-
-/* Encoding of PNG data (used by the color-map code) */
-#  define P_NOTSET  0 /* File encoding not yet known */
-#  define P_sRGB    1 /* 8-bit encoded to sRGB gamma */
-#  define P_LINEAR  2 /* 16-bit linear: not encoded, NOT pre-multiplied! */
-#  define P_FILE    3 /* 8-bit encoded to file gamma, not sRGB or linear */
-#  define P_LINEAR8 4 /* 8-bit linear: only from a file value */
-
-/* Color-map processing: after libpng has run on the PNG image further
- * processing may be needed to convert the data to color-map indices.
- */
-#define PNG_CMAP_NONE      0
-#define PNG_CMAP_GA        1 /* Process GA data to a color-map with alpha */
-#define PNG_CMAP_TRANS     2 /* Process GA data to a background index */
-#define PNG_CMAP_RGB       3 /* Process RGB data */
-#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */
-
-/* The following document where the background is for each processing case. */
-#define PNG_CMAP_NONE_BACKGROUND      256
-#define PNG_CMAP_GA_BACKGROUND        231
-#define PNG_CMAP_TRANS_BACKGROUND     254
-#define PNG_CMAP_RGB_BACKGROUND       256
-#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216
-
-typedef struct
-{
-   /* Arguments: */
-   png_imagep image;
-   png_voidp  buffer;
-   png_int_32 row_stride;
-   png_voidp  colormap;
-   png_const_colorp background;
-   /* Local variables: */
-   png_voidp       local_row;
-   png_voidp       first_row;
-   ptrdiff_t       row_bytes;           /* step between rows */
-   int             file_encoding;       /* E_ values above */
-   png_fixed_point gamma_to_linear;     /* For P_FILE, reciprocal of gamma */
-   int             colormap_processing; /* PNG_CMAP_ values above */
-} png_image_read_control;
-
-/* Do all the *safe* initialization - 'safe' means that png_error won't be
- * called, so setting up the jmp_buf is not required.  This means that anything
- * called from here must *not* call png_malloc - it has to call png_malloc_warn
- * instead so that control is returned safely back to this routine.
- */
-static int
-png_image_read_init(png_imagep image)
-{
-   if (image->opaque == NULL)
-   {
-      png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,
-          png_safe_error, png_safe_warning);
-
-      /* And set the rest of the structure to NULL to ensure that the various
-       * fields are consistent.
-       */
-      memset(image, 0, (sizeof *image));
-      image->version = PNG_IMAGE_VERSION;
-
-      if (png_ptr != NULL)
-      {
-         png_infop info_ptr = png_create_info_struct(png_ptr);
-
-         if (info_ptr != NULL)
-         {
-            png_controlp control = png_voidcast(png_controlp,
-                png_malloc_warn(png_ptr, (sizeof *control)));
-
-            if (control != NULL)
-            {
-               memset(control, 0, (sizeof *control));
-
-               control->png_ptr = png_ptr;
-               control->info_ptr = info_ptr;
-               control->for_write = 0;
-
-               image->opaque = control;
-               return 1;
-            }
-
-            /* Error clean up */
-            png_destroy_info_struct(png_ptr, &info_ptr);
-         }
-
-         png_destroy_read_struct(&png_ptr, NULL, NULL);
-      }
-
-      return png_image_error(image, "png_image_read: out of memory");
-   }
-
-   return png_image_error(image, "png_image_read: opaque pointer not NULL");
-}
-
-/* Utility to find the base format of a PNG file from a png_struct. */
-static png_uint_32
-png_image_format(png_structrp png_ptr)
-{
-   png_uint_32 format = 0;
-
-   if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
-      format |= PNG_FORMAT_FLAG_COLOR;
-
-   if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
-      format |= PNG_FORMAT_FLAG_ALPHA;
-
-   /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS
-    * sets the png_struct fields; that's all we are interested in here.  The
-    * precise interaction with an app call to png_set_tRNS and PNG file reading
-    * is unclear.
-    */
-   else if (png_ptr->num_trans > 0)
-      format |= PNG_FORMAT_FLAG_ALPHA;
-
-   if (png_ptr->bit_depth == 16)
-      format |= PNG_FORMAT_FLAG_LINEAR;
-
-   if ((png_ptr->color_type & PNG_COLOR_MASK_PALETTE) != 0)
-      format |= PNG_FORMAT_FLAG_COLORMAP;
-
-   return format;
-}
-
-/* Is the given gamma significantly different from sRGB?  The test is the same
- * one used in pngrtran.c when deciding whether to do gamma correction.  The
- * arithmetic optimizes the division by using the fact that the inverse of the
- * file sRGB gamma is 2.2
- */
-static int
-png_gamma_not_sRGB(png_fixed_point g)
-{
-   if (g < PNG_FP_1)
-   {
-      /* An uninitialized gamma is assumed to be sRGB for the simplified API. */
-      if (g == 0)
-         return 0;
-
-      return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);
-   }
-
-   return 1;
-}
-
-/* Do the main body of a 'png_image_begin_read' function; read the PNG file
- * header and fill in all the information.  This is executed in a safe context,
- * unlike the init routine above.
- */
-static int
-png_image_read_header(png_voidp argument)
-{
-   png_imagep image = png_voidcast(png_imagep, argument);
-   png_structrp png_ptr = image->opaque->png_ptr;
-   png_inforp info_ptr = image->opaque->info_ptr;
-
-#ifdef PNG_BENIGN_ERRORS_SUPPORTED
-   png_set_benign_errors(png_ptr, 1/*warn*/);
-#endif
-   png_read_info(png_ptr, info_ptr);
-
-   /* Do this the fast way; just read directly out of png_struct. */
-   image->width = png_ptr->width;
-   image->height = png_ptr->height;
-
-   {
-      png_uint_32 format = png_image_format(png_ptr);
-
-      image->format = format;
-
-#ifdef PNG_COLORSPACE_SUPPORTED
-      /* Does the colorspace match sRGB?  If there is no color endpoint
-       * (colorant) information assume yes, otherwise require the
-       * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set.  If the
-       * colorspace has been determined to be invalid ignore it.
-       */
-      if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags
-         & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB|
-            PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS))
-         image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
-#endif
-   }
-
-   /* We need the maximum number of entries regardless of the format the
-    * application sets here.
-    */
-   {
-      png_uint_32 cmap_entries;
-
-      switch (png_ptr->color_type)
-      {
-         case PNG_COLOR_TYPE_GRAY:
-            cmap_entries = 1U << png_ptr->bit_depth;
-            break;
-
-         case PNG_COLOR_TYPE_PALETTE:
-            cmap_entries = (png_uint_32)png_ptr->num_palette;
-            break;
-
-         default:
-            cmap_entries = 256;
-            break;
-      }
-
-      if (cmap_entries > 256)
-         cmap_entries = 256;
-
-      image->colormap_entries = cmap_entries;
-   }
-
-   return 1;
-}
-
-#ifdef PNG_STDIO_SUPPORTED
-int PNGAPI
-png_image_begin_read_from_stdio(png_imagep image, FILE* file)
-{
-   if (image != NULL && image->version == PNG_IMAGE_VERSION)
-   {
-      if (file != NULL)
-      {
-         if (png_image_read_init(image) != 0)
-         {
-            /* This is slightly evil, but png_init_io doesn't do anything other
-             * than this and we haven't changed the standard IO functions so
-             * this saves a 'safe' function.
-             */
-            image->opaque->png_ptr->io_ptr = file;
-            return png_safe_execute(image, png_image_read_header, image);
-         }
-      }
-
-      else
-         return png_image_error(image,
-             "png_image_begin_read_from_stdio: invalid argument");
-   }
-
-   else if (image != NULL)
-      return png_image_error(image,
-          "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION");
-
-   return 0;
-}
-
-int PNGAPI
-png_image_begin_read_from_file(png_imagep image, const char *file_name)
-{
-   if (image != NULL && image->version == PNG_IMAGE_VERSION)
-   {
-      if (file_name != NULL)
-      {
-         FILE *fp = fopen(file_name, "rb");
-
-         if (fp != NULL)
-         {
-            if (png_image_read_init(image) != 0)
-            {
-               image->opaque->png_ptr->io_ptr = fp;
-               image->opaque->owned_file = 1;
-               return png_safe_execute(image, png_image_read_header, image);
-            }
-
-            /* Clean up: just the opened file. */
-            (void)fclose(fp);
-         }
-
-         else
-            return png_image_error(image, strerror(errno));
-      }
-
-      else
-         return png_image_error(image,
-             "png_image_begin_read_from_file: invalid argument");
-   }
-
-   else if (image != NULL)
-      return png_image_error(image,
-          "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION");
-
-   return 0;
-}
-#endif /* STDIO */
-
-static void PNGCBAPI
-png_image_memory_read(png_structp png_ptr, png_bytep out, size_t need)
-{
-   if (png_ptr != NULL)
-   {
-      png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr);
-      if (image != NULL)
-      {
-         png_controlp cp = image->opaque;
-         if (cp != NULL)
-         {
-            png_const_bytep memory = cp->memory;
-            size_t size = cp->size;
-
-            if (memory != NULL && size >= need)
-            {
-               memcpy(out, memory, need);
-               cp->memory = memory + need;
-               cp->size = size - need;
-               return;
-            }
-
-            png_error(png_ptr, "read beyond end of data");
-         }
-      }
-
-      png_error(png_ptr, "invalid memory read");
-   }
-}
-
-int PNGAPI png_image_begin_read_from_memory(png_imagep image,
-    png_const_voidp memory, size_t size)
-{
-   if (image != NULL && image->version == PNG_IMAGE_VERSION)
-   {
-      if (memory != NULL && size > 0)
-      {
-         if (png_image_read_init(image) != 0)
-         {
-            /* Now set the IO functions to read from the memory buffer and
-             * store it into io_ptr.  Again do this in-place to avoid calling a
-             * libpng function that requires error handling.
-             */
-            image->opaque->memory = png_voidcast(png_const_bytep, memory);
-            image->opaque->size = size;
-            image->opaque->png_ptr->io_ptr = image;
-            image->opaque->png_ptr->read_data_fn = png_image_memory_read;
-
-            return png_safe_execute(image, png_image_read_header, image);
-         }
-      }
-
-      else
-         return png_image_error(image,
-             "png_image_begin_read_from_memory: invalid argument");
-   }
-
-   else if (image != NULL)
-      return png_image_error(image,
-          "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION");
-
-   return 0;
-}
-
-/* Utility function to skip chunks that are not used by the simplified image
- * read functions and an appropriate macro to call it.
- */
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-static void
-png_image_skip_unused_chunks(png_structrp png_ptr)
-{
-   /* Prepare the reader to ignore all recognized chunks whose data will not
-    * be used, i.e., all chunks recognized by libpng except for those
-    * involved in basic image reading:
-    *
-    *    IHDR, PLTE, IDAT, IEND
-    *
-    * Or image data handling:
-    *
-    *    tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT.
-    *
-    * This provides a small performance improvement and eliminates any
-    * potential vulnerability to security problems in the unused chunks.
-    *
-    * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored
-    * too.  This allows the simplified API to be compiled without iCCP support,
-    * however if the support is there the chunk is still checked to detect
-    * errors (which are unfortunately quite common.)
-    */
-   {
-         static const png_byte chunks_to_process[] = {
-            98,  75,  71,  68, '\0',  /* bKGD */
-            99,  72,  82,  77, '\0',  /* cHRM */
-           103,  65,  77,  65, '\0',  /* gAMA */
-#        ifdef PNG_READ_iCCP_SUPPORTED
-           105,  67,  67,  80, '\0',  /* iCCP */
-#        endif
-           115,  66,  73,  84, '\0',  /* sBIT */
-           115,  82,  71,  66, '\0',  /* sRGB */
-           };
-
-       /* Ignore unknown chunks and all other chunks except for the
-        * IHDR, PLTE, tRNS, IDAT, and IEND chunks.
-        */
-       png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER,
-           NULL, -1);
-
-       /* But do not ignore image data handling chunks */
-       png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT,
-           chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5);
-   }
-}
-
-#  define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p)
-#else
-#  define PNG_SKIP_CHUNKS(p) ((void)0)
-#endif /* HANDLE_AS_UNKNOWN */
-
-/* The following macro gives the exact rounded answer for all values in the
- * range 0..255 (it actually divides by 51.2, but the rounding still generates
- * the correct numbers 0..5
- */
-#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8)
-
-/* Utility functions to make particular color-maps */
-static void
-set_file_encoding(png_image_read_control *display)
-{
-   png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma;
-   if (png_gamma_significant(g) != 0)
-   {
-      if (png_gamma_not_sRGB(g) != 0)
-      {
-         display->file_encoding = P_FILE;
-         display->gamma_to_linear = png_reciprocal(g);
-      }
-
-      else
-         display->file_encoding = P_sRGB;
-   }
-
-   else
-      display->file_encoding = P_LINEAR8;
-}
-
-static unsigned int
-decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding)
-{
-   if (encoding == P_FILE) /* double check */
-      encoding = display->file_encoding;
-
-   if (encoding == P_NOTSET) /* must be the file encoding */
-   {
-      set_file_encoding(display);
-      encoding = display->file_encoding;
-   }
-
-   switch (encoding)
-   {
-      case P_FILE:
-         value = png_gamma_16bit_correct(value*257, display->gamma_to_linear);
-         break;
-
-      case P_sRGB:
-         value = png_sRGB_table[value];
-         break;
-
-      case P_LINEAR:
-         break;
-
-      case P_LINEAR8:
-         value *= 257;
-         break;
-
-#ifdef __GNUC__
-      default:
-         png_error(display->image->opaque->png_ptr,
-             "unexpected encoding (internal error)");
-#endif
-   }
-
-   return value;
-}
-
-static png_uint_32
-png_colormap_compose(png_image_read_control *display,
-    png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha,
-    png_uint_32 background, int encoding)
-{
-   /* The file value is composed on the background, the background has the given
-    * encoding and so does the result, the file is encoded with P_FILE and the
-    * file and alpha are 8-bit values.  The (output) encoding will always be
-    * P_LINEAR or P_sRGB.
-    */
-   png_uint_32 f = decode_gamma(display, foreground, foreground_encoding);
-   png_uint_32 b = decode_gamma(display, background, encoding);
-
-   /* The alpha is always an 8-bit value (it comes from the palette), the value
-    * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires.
-    */
-   f = f * alpha + b * (255-alpha);
-
-   if (encoding == P_LINEAR)
-   {
-      /* Scale to 65535; divide by 255, approximately (in fact this is extremely
-       * accurate, it divides by 255.00000005937181414556, with no overflow.)
-       */
-      f *= 257; /* Now scaled by 65535 */
-      f += f >> 16;
-      f = (f+32768) >> 16;
-   }
-
-   else /* P_sRGB */
-      f = PNG_sRGB_FROM_LINEAR(f);
-
-   return f;
-}
-
-/* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must
- * be 8-bit.
- */
-static void
-png_create_colormap_entry(png_image_read_control *display,
-    png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue,
-    png_uint_32 alpha, int encoding)
-{
-   png_imagep image = display->image;
-   int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
-       P_LINEAR : P_sRGB;
-   int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
-       (red != green || green != blue);
-
-   if (ip > 255)
-      png_error(image->opaque->png_ptr, "color-map index out of range");
-
-   /* Update the cache with whether the file gamma is significantly different
-    * from sRGB.
-    */
-   if (encoding == P_FILE)
-   {
-      if (display->file_encoding == P_NOTSET)
-         set_file_encoding(display);
-
-      /* Note that the cached value may be P_FILE too, but if it is then the
-       * gamma_to_linear member has been set.
-       */
-      encoding = display->file_encoding;
-   }
-
-   if (encoding == P_FILE)
-   {
-      png_fixed_point g = display->gamma_to_linear;
-
-      red = png_gamma_16bit_correct(red*257, g);
-      green = png_gamma_16bit_correct(green*257, g);
-      blue = png_gamma_16bit_correct(blue*257, g);
-
-      if (convert_to_Y != 0 || output_encoding == P_LINEAR)
-      {
-         alpha *= 257;
-         encoding = P_LINEAR;
-      }
-
-      else
-      {
-         red = PNG_sRGB_FROM_LINEAR(red * 255);
-         green = PNG_sRGB_FROM_LINEAR(green * 255);
-         blue = PNG_sRGB_FROM_LINEAR(blue * 255);
-         encoding = P_sRGB;
-      }
-   }
-
-   else if (encoding == P_LINEAR8)
-   {
-      /* This encoding occurs quite frequently in test cases because PngSuite
-       * includes a gAMA 1.0 chunk with most images.
-       */
-      red *= 257;
-      green *= 257;
-      blue *= 257;
-      alpha *= 257;
-      encoding = P_LINEAR;
-   }
-
-   else if (encoding == P_sRGB &&
-       (convert_to_Y  != 0 || output_encoding == P_LINEAR))
-   {
-      /* The values are 8-bit sRGB values, but must be converted to 16-bit
-       * linear.
-       */
-      red = png_sRGB_table[red];
-      green = png_sRGB_table[green];
-      blue = png_sRGB_table[blue];
-      alpha *= 257;
-      encoding = P_LINEAR;
-   }
-
-   /* This is set if the color isn't gray but the output is. */
-   if (encoding == P_LINEAR)
-   {
-      if (convert_to_Y != 0)
-      {
-         /* NOTE: these values are copied from png_do_rgb_to_gray */
-         png_uint_32 y = (png_uint_32)6968 * red  + (png_uint_32)23434 * green +
-            (png_uint_32)2366 * blue;
-
-         if (output_encoding == P_LINEAR)
-            y = (y + 16384) >> 15;
-
-         else
-         {
-            /* y is scaled by 32768, we need it scaled by 255: */
-            y = (y + 128) >> 8;
-            y *= 255;
-            y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7);
-            alpha = PNG_DIV257(alpha);
-            encoding = P_sRGB;
-         }
-
-         blue = red = green = y;
-      }
-
-      else if (output_encoding == P_sRGB)
-      {
-         red = PNG_sRGB_FROM_LINEAR(red * 255);
-         green = PNG_sRGB_FROM_LINEAR(green * 255);
-         blue = PNG_sRGB_FROM_LINEAR(blue * 255);
-         alpha = PNG_DIV257(alpha);
-         encoding = P_sRGB;
-      }
-   }
-
-   if (encoding != output_encoding)
-      png_error(image->opaque->png_ptr, "bad encoding (internal error)");
-
-   /* Store the value. */
-   {
-#     ifdef PNG_FORMAT_AFIRST_SUPPORTED
-         int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
-            (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
-#     else
-#        define afirst 0
-#     endif
-#     ifdef PNG_FORMAT_BGR_SUPPORTED
-         int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
-#     else
-#        define bgr 0
-#     endif
-
-      if (output_encoding == P_LINEAR)
-      {
-         png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap);
-
-         entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
-
-         /* The linear 16-bit values must be pre-multiplied by the alpha channel
-          * value, if less than 65535 (this is, effectively, composite on black
-          * if the alpha channel is removed.)
-          */
-         switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
-         {
-            case 4:
-               entry[afirst ? 0 : 3] = (png_uint_16)alpha;
-               /* FALLTHROUGH */
-
-            case 3:
-               if (alpha < 65535)
-               {
-                  if (alpha > 0)
-                  {
-                     blue = (blue * alpha + 32767U)/65535U;
-                     green = (green * alpha + 32767U)/65535U;
-                     red = (red * alpha + 32767U)/65535U;
-                  }
-
-                  else
-                     red = green = blue = 0;
-               }
-               entry[afirst + (2 ^ bgr)] = (png_uint_16)blue;
-               entry[afirst + 1] = (png_uint_16)green;
-               entry[afirst + bgr] = (png_uint_16)red;
-               break;
-
-            case 2:
-               entry[1 ^ afirst] = (png_uint_16)alpha;
-               /* FALLTHROUGH */
-
-            case 1:
-               if (alpha < 65535)
-               {
-                  if (alpha > 0)
-                     green = (green * alpha + 32767U)/65535U;
-
-                  else
-                     green = 0;
-               }
-               entry[afirst] = (png_uint_16)green;
-               break;
-
-            default:
-               break;
-         }
-      }
-
-      else /* output encoding is P_sRGB */
-      {
-         png_bytep entry = png_voidcast(png_bytep, display->colormap);
-
-         entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
-
-         switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
-         {
-            case 4:
-               entry[afirst ? 0 : 3] = (png_byte)alpha;
-               /* FALLTHROUGH */
-            case 3:
-               entry[afirst + (2 ^ bgr)] = (png_byte)blue;
-               entry[afirst + 1] = (png_byte)green;
-               entry[afirst + bgr] = (png_byte)red;
-               break;
-
-            case 2:
-               entry[1 ^ afirst] = (png_byte)alpha;
-               /* FALLTHROUGH */
-            case 1:
-               entry[afirst] = (png_byte)green;
-               break;
-
-            default:
-               break;
-         }
-      }
-
-#     ifdef afirst
-#        undef afirst
-#     endif
-#     ifdef bgr
-#        undef bgr
-#     endif
-   }
-}
-
-static int
-make_gray_file_colormap(png_image_read_control *display)
-{
-   unsigned int i;
-
-   for (i=0; i<256; ++i)
-      png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);
-
-   return (int)i;
-}
-
-static int
-make_gray_colormap(png_image_read_control *display)
-{
-   unsigned int i;
-
-   for (i=0; i<256; ++i)
-      png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);
-
-   return (int)i;
-}
-#define PNG_GRAY_COLORMAP_ENTRIES 256
-
-static int
-make_ga_colormap(png_image_read_control *display)
-{
-   unsigned int i, a;
-
-   /* Alpha is retained, the output will be a color-map with entries
-    * selected by six levels of alpha.  One transparent entry, 6 gray
-    * levels for all the intermediate alpha values, leaving 230 entries
-    * for the opaque grays.  The color-map entries are the six values
-    * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the
-    * relevant entry.
-    *
-    * if (alpha > 229) // opaque
-    * {
-    *    // The 231 entries are selected to make the math below work:
-    *    base = 0;
-    *    entry = (231 * gray + 128) >> 8;
-    * }
-    * else if (alpha < 26) // transparent
-    * {
-    *    base = 231;
-    *    entry = 0;
-    * }
-    * else // partially opaque
-    * {
-    *    base = 226 + 6 * PNG_DIV51(alpha);
-    *    entry = PNG_DIV51(gray);
-    * }
-    */
-   i = 0;
-   while (i < 231)
-   {
-      unsigned int gray = (i * 256 + 115) / 231;
-      png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB);
-   }
-
-   /* 255 is used here for the component values for consistency with the code
-    * that undoes premultiplication in pngwrite.c.
-    */
-   png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB);
-
-   for (a=1; a<5; ++a)
-   {
-      unsigned int g;
-
-      for (g=0; g<6; ++g)
-         png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51,
-             P_sRGB);
-   }
-
-   return (int)i;
-}
-
-#define PNG_GA_COLORMAP_ENTRIES 256
-
-static int
-make_rgb_colormap(png_image_read_control *display)
-{
-   unsigned int i, r;
-
-   /* Build a 6x6x6 opaque RGB cube */
-   for (i=r=0; r<6; ++r)
-   {
-      unsigned int g;
-
-      for (g=0; g<6; ++g)
-      {
-         unsigned int b;
-
-         for (b=0; b<6; ++b)
-            png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255,
-                P_sRGB);
-      }
-   }
-
-   return (int)i;
-}
-
-#define PNG_RGB_COLORMAP_ENTRIES 216
-
-/* Return a palette index to the above palette given three 8-bit sRGB values. */
-#define PNG_RGB_INDEX(r,g,b) \
-   ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b)))
-
-static int
-png_image_read_colormap(png_voidp argument)
-{
-   png_image_read_control *display =
-      png_voidcast(png_image_read_control*, argument);
-   png_imagep image = display->image;
-
-   png_structrp png_ptr = image->opaque->png_ptr;
-   png_uint_32 output_format = image->format;
-   int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
-      P_LINEAR : P_sRGB;
-
-   unsigned int cmap_entries;
-   unsigned int output_processing;        /* Output processing option */
-   unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */
-
-   /* Background information; the background color and the index of this color
-    * in the color-map if it exists (else 256).
-    */
-   unsigned int background_index = 256;
-   png_uint_32 back_r, back_g, back_b;
-
-   /* Flags to accumulate things that need to be done to the input. */
-   int expand_tRNS = 0;
-
-   /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is
-    * very difficult to do, the results look awful, and it is difficult to see
-    * what possible use it is because the application can't control the
-    * color-map.
-    */
-   if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 ||
-         png_ptr->num_trans > 0) /* alpha in input */ &&
-      ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */)
-   {
-      if (output_encoding == P_LINEAR) /* compose on black */
-         back_b = back_g = back_r = 0;
-
-      else if (display->background == NULL /* no way to remove it */)
-         png_error(png_ptr,
-             "background color must be supplied to remove alpha/transparency");
-
-      /* Get a copy of the background color (this avoids repeating the checks
-       * below.)  The encoding is 8-bit sRGB or 16-bit linear, depending on the
-       * output format.
-       */
-      else
-      {
-         back_g = display->background->green;
-         if ((output_format & PNG_FORMAT_FLAG_COLOR) != 0)
-         {
-            back_r = display->background->red;
-            back_b = display->background->blue;
-         }
-         else
-            back_b = back_r = back_g;
-      }
-   }
-
-   else if (output_encoding == P_LINEAR)
-      back_b = back_r = back_g = 65535;
-
-   else
-      back_b = back_r = back_g = 255;
-
-   /* Default the input file gamma if required - this is necessary because
-    * libpng assumes that if no gamma information is present the data is in the
-    * output format, but the simplified API deduces the gamma from the input
-    * format.
-    */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)
-   {
-      /* Do this directly, not using the png_colorspace functions, to ensure
-       * that it happens even if the colorspace is invalid (though probably if
-       * it is the setting will be ignored)  Note that the same thing can be
-       * achieved at the application interface with png_set_gAMA.
-       */
-      if (png_ptr->bit_depth == 16 &&
-         (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
-         png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;
-
-      else
-         png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;
-
-      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
-   }
-
-   /* Decide what to do based on the PNG color type of the input data.  The
-    * utility function png_create_colormap_entry deals with most aspects of the
-    * output transformations; this code works out how to produce bytes of
-    * color-map entries from the original format.
-    */
-   switch (png_ptr->color_type)
-   {
-      case PNG_COLOR_TYPE_GRAY:
-         if (png_ptr->bit_depth <= 8)
-         {
-            /* There at most 256 colors in the output, regardless of
-             * transparency.
-             */
-            unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0;
-
-            cmap_entries = 1U << png_ptr->bit_depth;
-            if (cmap_entries > image->colormap_entries)
-               png_error(png_ptr, "gray[8] color-map: too few entries");
-
-            step = 255 / (cmap_entries - 1);
-            output_processing = PNG_CMAP_NONE;
-
-            /* If there is a tRNS chunk then this either selects a transparent
-             * value or, if the output has no alpha, the background color.
-             */
-            if (png_ptr->num_trans > 0)
-            {
-               trans = png_ptr->trans_color.gray;
-
-               if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0)
-                  back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
-            }
-
-            /* png_create_colormap_entry just takes an RGBA and writes the
-             * corresponding color-map entry using the format from 'image',
-             * including the required conversion to sRGB or linear as
-             * appropriate.  The input values are always either sRGB (if the
-             * gamma correction flag is 0) or 0..255 scaled file encoded values
-             * (if the function must gamma correct them).
-             */
-            for (i=val=0; i<cmap_entries; ++i, val += step)
-            {
-               /* 'i' is a file value.  While this will result in duplicated
-                * entries for 8-bit non-sRGB encoded files it is necessary to
-                * have non-gamma corrected values to do tRNS handling.
-                */
-               if (i != trans)
-                  png_create_colormap_entry(display, i, val, val, val, 255,
-                      P_FILE/*8-bit with file gamma*/);
-
-               /* Else this entry is transparent.  The colors don't matter if
-                * there is an alpha channel (back_alpha == 0), but it does no
-                * harm to pass them in; the values are not set above so this
-                * passes in white.
-                *
-                * NOTE: this preserves the full precision of the application
-                * supplied background color when it is used.
-                */
-               else
-                  png_create_colormap_entry(display, i, back_r, back_g, back_b,
-                      back_alpha, output_encoding);
-            }
-
-            /* We need libpng to preserve the original encoding. */
-            data_encoding = P_FILE;
-
-            /* The rows from libpng, while technically gray values, are now also
-             * color-map indices; however, they may need to be expanded to 1
-             * byte per pixel.  This is what png_set_packing does (i.e., it
-             * unpacks the bit values into bytes.)
-             */
-            if (png_ptr->bit_depth < 8)
-               png_set_packing(png_ptr);
-         }
-
-         else /* bit depth is 16 */
-         {
-            /* The 16-bit input values can be converted directly to 8-bit gamma
-             * encoded values; however, if a tRNS chunk is present 257 color-map
-             * entries are required.  This means that the extra entry requires
-             * special processing; add an alpha channel, sacrifice gray level
-             * 254 and convert transparent (alpha==0) entries to that.
-             *
-             * Use libpng to chop the data to 8 bits.  Convert it to sRGB at the
-             * same time to minimize quality loss.  If a tRNS chunk is present
-             * this means libpng must handle it too; otherwise it is impossible
-             * to do the exact match on the 16-bit value.
-             *
-             * If the output has no alpha channel *and* the background color is
-             * gray then it is possible to let libpng handle the substitution by
-             * ensuring that the corresponding gray level matches the background
-             * color exactly.
-             */
-            data_encoding = P_sRGB;
-
-            if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
-               png_error(png_ptr, "gray[16] color-map: too few entries");
-
-            cmap_entries = (unsigned int)make_gray_colormap(display);
-
-            if (png_ptr->num_trans > 0)
-            {
-               unsigned int back_alpha;
-
-               if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
-                  back_alpha = 0;
-
-               else
-               {
-                  if (back_r == back_g && back_g == back_b)
-                  {
-                     /* Background is gray; no special processing will be
-                      * required.
-                      */
-                     png_color_16 c;
-                     png_uint_32 gray = back_g;
-
-                     if (output_encoding == P_LINEAR)
-                     {
-                        gray = PNG_sRGB_FROM_LINEAR(gray * 255);
-
-                        /* And make sure the corresponding palette entry
-                         * matches.
-                         */
-                        png_create_colormap_entry(display, gray, back_g, back_g,
-                            back_g, 65535, P_LINEAR);
-                     }
-
-                     /* The background passed to libpng, however, must be the
-                      * sRGB value.
-                      */
-                     c.index = 0; /*unused*/
-                     c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
-
-                     /* NOTE: does this work without expanding tRNS to alpha?
-                      * It should be the color->gray case below apparently
-                      * doesn't.
-                      */
-                     png_set_background_fixed(png_ptr, &c,
-                         PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
-                         0/*gamma: not used*/);
-
-                     output_processing = PNG_CMAP_NONE;
-                     break;
-                  }
-#ifdef __COVERITY__
-                 /* Coverity claims that output_encoding cannot be 2 (P_LINEAR)
-                  * here.
-                  */
-                  back_alpha = 255;
-#else
-                  back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
-#endif
-               }
-
-               /* output_processing means that the libpng-processed row will be
-                * 8-bit GA and it has to be processing to single byte color-map
-                * values.  Entry 254 is replaced by either a completely
-                * transparent entry or by the background color at full
-                * precision (and the background color is not a simple gray
-                * level in this case.)
-                */
-               expand_tRNS = 1;
-               output_processing = PNG_CMAP_TRANS;
-               background_index = 254;
-
-               /* And set (overwrite) color-map entry 254 to the actual
-                * background color at full precision.
-                */
-               png_create_colormap_entry(display, 254, back_r, back_g, back_b,
-                   back_alpha, output_encoding);
-            }
-
-            else
-               output_processing = PNG_CMAP_NONE;
-         }
-         break;
-
-      case PNG_COLOR_TYPE_GRAY_ALPHA:
-         /* 8-bit or 16-bit PNG with two channels - gray and alpha.  A minimum
-          * of 65536 combinations.  If, however, the alpha channel is to be
-          * removed there are only 256 possibilities if the background is gray.
-          * (Otherwise there is a subset of the 65536 possibilities defined by
-          * the triangle between black, white and the background color.)
-          *
-          * Reduce 16-bit files to 8-bit and sRGB encode the result.  No need to
-          * worry about tRNS matching - tRNS is ignored if there is an alpha
-          * channel.
-          */
-         data_encoding = P_sRGB;
-
-         if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
-         {
-            if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
-               png_error(png_ptr, "gray+alpha color-map: too few entries");
-
-            cmap_entries = (unsigned int)make_ga_colormap(display);
-
-            background_index = PNG_CMAP_GA_BACKGROUND;
-            output_processing = PNG_CMAP_GA;
-         }
-
-         else /* alpha is removed */
-         {
-            /* Alpha must be removed as the PNG data is processed when the
-             * background is a color because the G and A channels are
-             * independent and the vector addition (non-parallel vectors) is a
-             * 2-D problem.
-             *
-             * This can be reduced to the same algorithm as above by making a
-             * colormap containing gray levels (for the opaque grays), a
-             * background entry (for a transparent pixel) and a set of four six
-             * level color values, one set for each intermediate alpha value.
-             * See the comments in make_ga_colormap for how this works in the
-             * per-pixel processing.
-             *
-             * If the background is gray, however, we only need a 256 entry gray
-             * level color map.  It is sufficient to make the entry generated
-             * for the background color be exactly the color specified.
-             */
-            if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 ||
-               (back_r == back_g && back_g == back_b))
-            {
-               /* Background is gray; no special processing will be required. */
-               png_color_16 c;
-               png_uint_32 gray = back_g;
-
-               if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
-                  png_error(png_ptr, "gray-alpha color-map: too few entries");
-
-               cmap_entries = (unsigned int)make_gray_colormap(display);
-
-               if (output_encoding == P_LINEAR)
-               {
-                  gray = PNG_sRGB_FROM_LINEAR(gray * 255);
-
-                  /* And make sure the corresponding palette entry matches. */
-                  png_create_colormap_entry(display, gray, back_g, back_g,
-                      back_g, 65535, P_LINEAR);
-               }
-
-               /* The background passed to libpng, however, must be the sRGB
-                * value.
-                */
-               c.index = 0; /*unused*/
-               c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
-
-               png_set_background_fixed(png_ptr, &c,
-                   PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
-                   0/*gamma: not used*/);
-
-               output_processing = PNG_CMAP_NONE;
-            }
-
-            else
-            {
-               png_uint_32 i, a;
-
-               /* This is the same as png_make_ga_colormap, above, except that
-                * the entries are all opaque.
-                */
-               if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
-                  png_error(png_ptr, "ga-alpha color-map: too few entries");
-
-               i = 0;
-               while (i < 231)
-               {
-                  png_uint_32 gray = (i * 256 + 115) / 231;
-                  png_create_colormap_entry(display, i++, gray, gray, gray,
-                      255, P_sRGB);
-               }
-
-               /* NOTE: this preserves the full precision of the application
-                * background color.
-                */
-               background_index = i;
-               png_create_colormap_entry(display, i++, back_r, back_g, back_b,
-#ifdef __COVERITY__
-                   /* Coverity claims that output_encoding
-                    * cannot be 2 (P_LINEAR) here.
-                    */ 255U,
-#else
-                    output_encoding == P_LINEAR ? 65535U : 255U,
-#endif
-                    output_encoding);
-
-               /* For non-opaque input composite on the sRGB background - this
-                * requires inverting the encoding for each component.  The input
-                * is still converted to the sRGB encoding because this is a
-                * reasonable approximate to the logarithmic curve of human
-                * visual sensitivity, at least over the narrow range which PNG
-                * represents.  Consequently 'G' is always sRGB encoded, while
-                * 'A' is linear.  We need the linear background colors.
-                */
-               if (output_encoding == P_sRGB) /* else already linear */
-               {
-                  /* This may produce a value not exactly matching the
-                   * background, but that's ok because these numbers are only
-                   * used when alpha != 0
-                   */
-                  back_r = png_sRGB_table[back_r];
-                  back_g = png_sRGB_table[back_g];
-                  back_b = png_sRGB_table[back_b];
-               }
-
-               for (a=1; a<5; ++a)
-               {
-                  unsigned int g;
-
-                  /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled
-                   * by an 8-bit alpha value (0..255).
-                   */
-                  png_uint_32 alpha = 51 * a;
-                  png_uint_32 back_rx = (255-alpha) * back_r;
-                  png_uint_32 back_gx = (255-alpha) * back_g;
-                  png_uint_32 back_bx = (255-alpha) * back_b;
-
-                  for (g=0; g<6; ++g)
-                  {
-                     png_uint_32 gray = png_sRGB_table[g*51] * alpha;
-
-                     png_create_colormap_entry(display, i++,
-                         PNG_sRGB_FROM_LINEAR(gray + back_rx),
-                         PNG_sRGB_FROM_LINEAR(gray + back_gx),
-                         PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);
-                  }
-               }
-
-               cmap_entries = i;
-               output_processing = PNG_CMAP_GA;
-            }
-         }
-         break;
-
-      case PNG_COLOR_TYPE_RGB:
-      case PNG_COLOR_TYPE_RGB_ALPHA:
-         /* Exclude the case where the output is gray; we can always handle this
-          * with the cases above.
-          */
-         if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0)
-         {
-            /* The color-map will be grayscale, so we may as well convert the
-             * input RGB values to a simple grayscale and use the grayscale
-             * code above.
-             *
-             * NOTE: calling this apparently damages the recognition of the
-             * transparent color in background color handling; call
-             * png_set_tRNS_to_alpha before png_set_background_fixed.
-             */
-            png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1,
-                -1);
-            data_encoding = P_sRGB;
-
-            /* The output will now be one or two 8-bit gray or gray+alpha
-             * channels.  The more complex case arises when the input has alpha.
-             */
-            if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
-               png_ptr->num_trans > 0) &&
-               (output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
-            {
-               /* Both input and output have an alpha channel, so no background
-                * processing is required; just map the GA bytes to the right
-                * color-map entry.
-                */
-               expand_tRNS = 1;
-
-               if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
-                  png_error(png_ptr, "rgb[ga] color-map: too few entries");
-
-               cmap_entries = (unsigned int)make_ga_colormap(display);
-               background_index = PNG_CMAP_GA_BACKGROUND;
-               output_processing = PNG_CMAP_GA;
-            }
-
-            else
-            {
-               /* Either the input or the output has no alpha channel, so there
-                * will be no non-opaque pixels in the color-map; it will just be
-                * grayscale.
-                */
-               if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
-                  png_error(png_ptr, "rgb[gray] color-map: too few entries");
-
-               /* Ideally this code would use libpng to do the gamma correction,
-                * but if an input alpha channel is to be removed we will hit the
-                * libpng bug in gamma+compose+rgb-to-gray (the double gamma
-                * correction bug).  Fix this by dropping the gamma correction in
-                * this case and doing it in the palette; this will result in
-                * duplicate palette entries, but that's better than the
-                * alternative of double gamma correction.
-                */
-               if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
-                  png_ptr->num_trans > 0) &&
-                  png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0)
-               {
-                  cmap_entries = (unsigned int)make_gray_file_colormap(display);
-                  data_encoding = P_FILE;
-               }
-
-               else
-                  cmap_entries = (unsigned int)make_gray_colormap(display);
-
-               /* But if the input has alpha or transparency it must be removed
-                */
-               if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
-                  png_ptr->num_trans > 0)
-               {
-                  png_color_16 c;
-                  png_uint_32 gray = back_g;
-
-                  /* We need to ensure that the application background exists in
-                   * the colormap and that completely transparent pixels map to
-                   * it.  Achieve this simply by ensuring that the entry
-                   * selected for the background really is the background color.
-                   */
-                  if (data_encoding == P_FILE) /* from the fixup above */
-                  {
-                     /* The app supplied a gray which is in output_encoding, we
-                      * need to convert it to a value of the input (P_FILE)
-                      * encoding then set this palette entry to the required
-                      * output encoding.
-                      */
-                     if (output_encoding == P_sRGB)
-                        gray = png_sRGB_table[gray]; /* now P_LINEAR */
-
-                     gray = PNG_DIV257(png_gamma_16bit_correct(gray,
-                         png_ptr->colorspace.gamma)); /* now P_FILE */
-
-                     /* And make sure the corresponding palette entry contains
-                      * exactly the required sRGB value.
-                      */
-                     png_create_colormap_entry(display, gray, back_g, back_g,
-                         back_g, 0/*unused*/, output_encoding);
-                  }
-
-                  else if (output_encoding == P_LINEAR)
-                  {
-                     gray = PNG_sRGB_FROM_LINEAR(gray * 255);
-
-                     /* And make sure the corresponding palette entry matches.
-                      */
-                     png_create_colormap_entry(display, gray, back_g, back_g,
-                        back_g, 0/*unused*/, P_LINEAR);
-                  }
-
-                  /* The background passed to libpng, however, must be the
-                   * output (normally sRGB) value.
-                   */
-                  c.index = 0; /*unused*/
-                  c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
-
-                  /* NOTE: the following is apparently a bug in libpng. Without
-                   * it the transparent color recognition in
-                   * png_set_background_fixed seems to go wrong.
-                   */
-                  expand_tRNS = 1;
-                  png_set_background_fixed(png_ptr, &c,
-                      PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
-                      0/*gamma: not used*/);
-               }
-
-               output_processing = PNG_CMAP_NONE;
-            }
-         }
-
-         else /* output is color */
-         {
-            /* We could use png_quantize here so long as there is no transparent
-             * color or alpha; png_quantize ignores alpha.  Easier overall just
-             * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube.
-             * Consequently we always want libpng to produce sRGB data.
-             */
-            data_encoding = P_sRGB;
-
-            /* Is there any transparency or alpha? */
-            if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
-               png_ptr->num_trans > 0)
-            {
-               /* Is there alpha in the output too?  If so all four channels are
-                * processed into a special RGB cube with alpha support.
-                */
-               if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
-               {
-                  png_uint_32 r;
-
-                  if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
-                     png_error(png_ptr, "rgb+alpha color-map: too few entries");
-
-                  cmap_entries = (unsigned int)make_rgb_colormap(display);
-
-                  /* Add a transparent entry. */
-                  png_create_colormap_entry(display, cmap_entries, 255, 255,
-                      255, 0, P_sRGB);
-
-                  /* This is stored as the background index for the processing
-                   * algorithm.
-                   */
-                  background_index = cmap_entries++;
-
-                  /* Add 27 r,g,b entries each with alpha 0.5. */
-                  for (r=0; r<256; r = (r << 1) | 0x7f)
-                  {
-                     png_uint_32 g;
-
-                     for (g=0; g<256; g = (g << 1) | 0x7f)
-                     {
-                        png_uint_32 b;
-
-                        /* This generates components with the values 0, 127 and
-                         * 255
-                         */
-                        for (b=0; b<256; b = (b << 1) | 0x7f)
-                           png_create_colormap_entry(display, cmap_entries++,
-                               r, g, b, 128, P_sRGB);
-                     }
-                  }
-
-                  expand_tRNS = 1;
-                  output_processing = PNG_CMAP_RGB_ALPHA;
-               }
-
-               else
-               {
-                  /* Alpha/transparency must be removed.  The background must
-                   * exist in the color map (achieved by setting adding it after
-                   * the 666 color-map).  If the standard processing code will
-                   * pick up this entry automatically that's all that is
-                   * required; libpng can be called to do the background
-                   * processing.
-                   */
-                  unsigned int sample_size =
-                     PNG_IMAGE_SAMPLE_SIZE(output_format);
-                  png_uint_32 r, g, b; /* sRGB background */
-
-                  if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
-                     png_error(png_ptr, "rgb-alpha color-map: too few entries");
-
-                  cmap_entries = (unsigned int)make_rgb_colormap(display);
-
-                  png_create_colormap_entry(display, cmap_entries, back_r,
-                      back_g, back_b, 0/*unused*/, output_encoding);
-
-                  if (output_encoding == P_LINEAR)
-                  {
-                     r = PNG_sRGB_FROM_LINEAR(back_r * 255);
-                     g = PNG_sRGB_FROM_LINEAR(back_g * 255);
-                     b = PNG_sRGB_FROM_LINEAR(back_b * 255);
-                  }
-
-                  else
-                  {
-                     r = back_r;
-                     g = back_g;
-                     b = back_g;
-                  }
-
-                  /* Compare the newly-created color-map entry with the one the
-                   * PNG_CMAP_RGB algorithm will use.  If the two entries don't
-                   * match, add the new one and set this as the background
-                   * index.
-                   */
-                  if (memcmp((png_const_bytep)display->colormap +
-                      sample_size * cmap_entries,
-                      (png_const_bytep)display->colormap +
-                          sample_size * PNG_RGB_INDEX(r,g,b),
-                     sample_size) != 0)
-                  {
-                     /* The background color must be added. */
-                     background_index = cmap_entries++;
-
-                     /* Add 27 r,g,b entries each with created by composing with
-                      * the background at alpha 0.5.
-                      */
-                     for (r=0; r<256; r = (r << 1) | 0x7f)
-                     {
-                        for (g=0; g<256; g = (g << 1) | 0x7f)
-                        {
-                           /* This generates components with the values 0, 127
-                            * and 255
-                            */
-                           for (b=0; b<256; b = (b << 1) | 0x7f)
-                              png_create_colormap_entry(display, cmap_entries++,
-                                  png_colormap_compose(display, r, P_sRGB, 128,
-                                      back_r, output_encoding),
-                                  png_colormap_compose(display, g, P_sRGB, 128,
-                                      back_g, output_encoding),
-                                  png_colormap_compose(display, b, P_sRGB, 128,
-                                      back_b, output_encoding),
-                                  0/*unused*/, output_encoding);
-                        }
-                     }
-
-                     expand_tRNS = 1;
-                     output_processing = PNG_CMAP_RGB_ALPHA;
-                  }
-
-                  else /* background color is in the standard color-map */
-                  {
-                     png_color_16 c;
-
-                     c.index = 0; /*unused*/
-                     c.red = (png_uint_16)back_r;
-                     c.gray = c.green = (png_uint_16)back_g;
-                     c.blue = (png_uint_16)back_b;
-
-                     png_set_background_fixed(png_ptr, &c,
-                         PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
-                         0/*gamma: not used*/);
-
-                     output_processing = PNG_CMAP_RGB;
-                  }
-               }
-            }
-
-            else /* no alpha or transparency in the input */
-            {
-               /* Alpha in the output is irrelevant, simply map the opaque input
-                * pixels to the 6x6x6 color-map.
-                */
-               if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries)
-                  png_error(png_ptr, "rgb color-map: too few entries");
-
-               cmap_entries = (unsigned int)make_rgb_colormap(display);
-               output_processing = PNG_CMAP_RGB;
-            }
-         }
-         break;
-
-      case PNG_COLOR_TYPE_PALETTE:
-         /* It's already got a color-map.  It may be necessary to eliminate the
-          * tRNS entries though.
-          */
-         {
-            unsigned int num_trans = png_ptr->num_trans;
-            png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
-            png_const_colorp colormap = png_ptr->palette;
-            int do_background = trans != NULL &&
-               (output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
-            unsigned int i;
-
-            /* Just in case: */
-            if (trans == NULL)
-               num_trans = 0;
-
-            output_processing = PNG_CMAP_NONE;
-            data_encoding = P_FILE; /* Don't change from color-map indices */
-            cmap_entries = (unsigned int)png_ptr->num_palette;
-            if (cmap_entries > 256)
-               cmap_entries = 256;
-
-            if (cmap_entries > (unsigned int)image->colormap_entries)
-               png_error(png_ptr, "palette color-map: too few entries");
-
-            for (i=0; i < cmap_entries; ++i)
-            {
-               if (do_background != 0 && i < num_trans && trans[i] < 255)
-               {
-                  if (trans[i] == 0)
-                     png_create_colormap_entry(display, i, back_r, back_g,
-                         back_b, 0, output_encoding);
-
-                  else
-                  {
-                     /* Must compose the PNG file color in the color-map entry
-                      * on the sRGB color in 'back'.
-                      */
-                     png_create_colormap_entry(display, i,
-                         png_colormap_compose(display, colormap[i].red,
-                             P_FILE, trans[i], back_r, output_encoding),
-                         png_colormap_compose(display, colormap[i].green,
-                             P_FILE, trans[i], back_g, output_encoding),
-                         png_colormap_compose(display, colormap[i].blue,
-                             P_FILE, trans[i], back_b, output_encoding),
-                         output_encoding == P_LINEAR ? trans[i] * 257U :
-                             trans[i],
-                         output_encoding);
-                  }
-               }
-
-               else
-                  png_create_colormap_entry(display, i, colormap[i].red,
-                      colormap[i].green, colormap[i].blue,
-                      i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/);
-            }
-
-            /* The PNG data may have indices packed in fewer than 8 bits, it
-             * must be expanded if so.
-             */
-            if (png_ptr->bit_depth < 8)
-               png_set_packing(png_ptr);
-         }
-         break;
-
-      default:
-         png_error(png_ptr, "invalid PNG color type");
-         /*NOT REACHED*/
-   }
-
-   /* Now deal with the output processing */
-   if (expand_tRNS != 0 && png_ptr->num_trans > 0 &&
-       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0)
-      png_set_tRNS_to_alpha(png_ptr);
-
-   switch (data_encoding)
-   {
-      case P_sRGB:
-         /* Change to 8-bit sRGB */
-         png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
-         /* FALLTHROUGH */
-
-      case P_FILE:
-         if (png_ptr->bit_depth > 8)
-            png_set_scale_16(png_ptr);
-         break;
-
-#ifdef __GNUC__
-      default:
-         png_error(png_ptr, "bad data option (internal error)");
-#endif
-   }
-
-   if (cmap_entries > 256 || cmap_entries > image->colormap_entries)
-      png_error(png_ptr, "color map overflow (BAD internal error)");
-
-   image->colormap_entries = cmap_entries;
-
-   /* Double check using the recorded background index */
-   switch (output_processing)
-   {
-      case PNG_CMAP_NONE:
-         if (background_index != PNG_CMAP_NONE_BACKGROUND)
-            goto bad_background;
-         break;
-
-      case PNG_CMAP_GA:
-         if (background_index != PNG_CMAP_GA_BACKGROUND)
-            goto bad_background;
-         break;
-
-      case PNG_CMAP_TRANS:
-         if (background_index >= cmap_entries ||
-            background_index != PNG_CMAP_TRANS_BACKGROUND)
-            goto bad_background;
-         break;
-
-      case PNG_CMAP_RGB:
-         if (background_index != PNG_CMAP_RGB_BACKGROUND)
-            goto bad_background;
-         break;
-
-      case PNG_CMAP_RGB_ALPHA:
-         if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND)
-            goto bad_background;
-         break;
-
-      default:
-         png_error(png_ptr, "bad processing option (internal error)");
-
-      bad_background:
-         png_error(png_ptr, "bad background index (internal error)");
-   }
-
-   display->colormap_processing = (int)output_processing;
-
-   return 1/*ok*/;
-}
-
-/* The final part of the color-map read called from png_image_finish_read. */
-static int
-png_image_read_and_map(png_voidp argument)
-{
-   png_image_read_control *display = png_voidcast(png_image_read_control*,
-       argument);
-   png_imagep image = display->image;
-   png_structrp png_ptr = image->opaque->png_ptr;
-   int passes;
-
-   /* Called when the libpng data must be transformed into the color-mapped
-    * form.  There is a local row buffer in display->local and this routine must
-    * do the interlace handling.
-    */
-   switch (png_ptr->interlaced)
-   {
-      case PNG_INTERLACE_NONE:
-         passes = 1;
-         break;
-
-      case PNG_INTERLACE_ADAM7:
-         passes = PNG_INTERLACE_ADAM7_PASSES;
-         break;
-
-      default:
-         png_error(png_ptr, "unknown interlace type");
-   }
-
-   {
-      png_uint_32  height = image->height;
-      png_uint_32  width = image->width;
-      int          proc = display->colormap_processing;
-      png_bytep    first_row = png_voidcast(png_bytep, display->first_row);
-      ptrdiff_t    step_row = display->row_bytes;
-      int pass;
-
-      for (pass = 0; pass < passes; ++pass)
-      {
-         unsigned int     startx, stepx, stepy;
-         png_uint_32      y;
-
-         if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
-         {
-            /* The row may be empty for a short image: */
-            if (PNG_PASS_COLS(width, pass) == 0)
-               continue;
-
-            startx = PNG_PASS_START_COL(pass);
-            stepx = PNG_PASS_COL_OFFSET(pass);
-            y = PNG_PASS_START_ROW(pass);
-            stepy = PNG_PASS_ROW_OFFSET(pass);
-         }
-
-         else
-         {
-            y = 0;
-            startx = 0;
-            stepx = stepy = 1;
-         }
-
-         for (; y<height; y += stepy)
-         {
-            png_bytep inrow = png_voidcast(png_bytep, display->local_row);
-            png_bytep outrow = first_row + y * step_row;
-            png_const_bytep end_row = outrow + width;
-
-            /* Read read the libpng data into the temporary buffer. */
-            png_read_row(png_ptr, inrow, NULL);
-
-            /* Now process the row according to the processing option, note
-             * that the caller verifies that the format of the libpng output
-             * data is as required.
-             */
-            outrow += startx;
-            switch (proc)
-            {
-               case PNG_CMAP_GA:
-                  for (; outrow < end_row; outrow += stepx)
-                  {
-                     /* The data is always in the PNG order */
-                     unsigned int gray = *inrow++;
-                     unsigned int alpha = *inrow++;
-                     unsigned int entry;
-
-                     /* NOTE: this code is copied as a comment in
-                      * make_ga_colormap above.  Please update the
-                      * comment if you change this code!
-                      */
-                     if (alpha > 229) /* opaque */
-                     {
-                        entry = (231 * gray + 128) >> 8;
-                     }
-                     else if (alpha < 26) /* transparent */
-                     {
-                        entry = 231;
-                     }
-                     else /* partially opaque */
-                     {
-                        entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray);
-                     }
-
-                     *outrow = (png_byte)entry;
-                  }
-                  break;
-
-               case PNG_CMAP_TRANS:
-                  for (; outrow < end_row; outrow += stepx)
-                  {
-                     png_byte gray = *inrow++;
-                     png_byte alpha = *inrow++;
-
-                     if (alpha == 0)
-                        *outrow = PNG_CMAP_TRANS_BACKGROUND;
-
-                     else if (gray != PNG_CMAP_TRANS_BACKGROUND)
-                        *outrow = gray;
-
-                     else
-                        *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1);
-                  }
-                  break;
-
-               case PNG_CMAP_RGB:
-                  for (; outrow < end_row; outrow += stepx)
-                  {
-                     *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]);
-                     inrow += 3;
-                  }
-                  break;
-
-               case PNG_CMAP_RGB_ALPHA:
-                  for (; outrow < end_row; outrow += stepx)
-                  {
-                     unsigned int alpha = inrow[3];
-
-                     /* Because the alpha entries only hold alpha==0.5 values
-                      * split the processing at alpha==0.25 (64) and 0.75
-                      * (196).
-                      */
-
-                     if (alpha >= 196)
-                        *outrow = PNG_RGB_INDEX(inrow[0], inrow[1],
-                            inrow[2]);
-
-                     else if (alpha < 64)
-                        *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND;
-
-                     else
-                     {
-                        /* Likewise there are three entries for each of r, g
-                         * and b.  We could select the entry by popcount on
-                         * the top two bits on those architectures that
-                         * support it, this is what the code below does,
-                         * crudely.
-                         */
-                        unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1;
-
-                        /* Here are how the values map:
-                         *
-                         * 0x00 .. 0x3f -> 0
-                         * 0x40 .. 0xbf -> 1
-                         * 0xc0 .. 0xff -> 2
-                         *
-                         * So, as above with the explicit alpha checks, the
-                         * breakpoints are at 64 and 196.
-                         */
-                        if (inrow[0] & 0x80) back_i += 9; /* red */
-                        if (inrow[0] & 0x40) back_i += 9;
-                        if (inrow[0] & 0x80) back_i += 3; /* green */
-                        if (inrow[0] & 0x40) back_i += 3;
-                        if (inrow[0] & 0x80) back_i += 1; /* blue */
-                        if (inrow[0] & 0x40) back_i += 1;
-
-                        *outrow = (png_byte)back_i;
-                     }
-
-                     inrow += 4;
-                  }
-                  break;
-
-               default:
-                  break;
-            }
-         }
-      }
-   }
-
-   return 1;
-}
-
-static int
-png_image_read_colormapped(png_voidp argument)
-{
-   png_image_read_control *display = png_voidcast(png_image_read_control*,
-       argument);
-   png_imagep image = display->image;
-   png_controlp control = image->opaque;
-   png_structrp png_ptr = control->png_ptr;
-   png_inforp info_ptr = control->info_ptr;
-
-   int passes = 0; /* As a flag */
-
-   PNG_SKIP_CHUNKS(png_ptr);
-
-   /* Update the 'info' structure and make sure the result is as required; first
-    * make sure to turn on the interlace handling if it will be required
-    * (because it can't be turned on *after* the call to png_read_update_info!)
-    */
-   if (display->colormap_processing == PNG_CMAP_NONE)
-      passes = png_set_interlace_handling(png_ptr);
-
-   png_read_update_info(png_ptr, info_ptr);
-
-   /* The expected output can be deduced from the colormap_processing option. */
-   switch (display->colormap_processing)
-   {
-      case PNG_CMAP_NONE:
-         /* Output must be one channel and one byte per pixel, the output
-          * encoding can be anything.
-          */
-         if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
-            info_ptr->color_type == PNG_COLOR_TYPE_GRAY) &&
-            info_ptr->bit_depth == 8)
-            break;
-
-         goto bad_output;
-
-      case PNG_CMAP_TRANS:
-      case PNG_CMAP_GA:
-         /* Output must be two channels and the 'G' one must be sRGB, the latter
-          * can be checked with an exact number because it should have been set
-          * to this number above!
-          */
-         if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
-            info_ptr->bit_depth == 8 &&
-            png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
-            image->colormap_entries == 256)
-            break;
-
-         goto bad_output;
-
-      case PNG_CMAP_RGB:
-         /* Output must be 8-bit sRGB encoded RGB */
-         if (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
-            info_ptr->bit_depth == 8 &&
-            png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
-            image->colormap_entries == 216)
-            break;
-
-         goto bad_output;
-
-      case PNG_CMAP_RGB_ALPHA:
-         /* Output must be 8-bit sRGB encoded RGBA */
-         if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
-            info_ptr->bit_depth == 8 &&
-            png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
-            image->colormap_entries == 244 /* 216 + 1 + 27 */)
-            break;
-
-         goto bad_output;
-
-      default:
-      bad_output:
-         png_error(png_ptr, "bad color-map processing (internal error)");
-   }
-
-   /* Now read the rows.  Do this here if it is possible to read directly into
-    * the output buffer, otherwise allocate a local row buffer of the maximum
-    * size libpng requires and call the relevant processing routine safely.
-    */
-   {
-      png_voidp first_row = display->buffer;
-      ptrdiff_t row_bytes = display->row_stride;
-
-      /* The following expression is designed to work correctly whether it gives
-       * a signed or an unsigned result.
-       */
-      if (row_bytes < 0)
-      {
-         char *ptr = png_voidcast(char*, first_row);
-         ptr += (image->height-1) * (-row_bytes);
-         first_row = png_voidcast(png_voidp, ptr);
-      }
-
-      display->first_row = first_row;
-      display->row_bytes = row_bytes;
-   }
-
-   if (passes == 0)
-   {
-      int result;
-      png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
-
-      display->local_row = row;
-      result = png_safe_execute(image, png_image_read_and_map, display);
-      display->local_row = NULL;
-      png_free(png_ptr, row);
-
-      return result;
-   }
-
-   else
-   {
-      png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
-
-      while (--passes >= 0)
-      {
-         png_uint_32      y = image->height;
-         png_bytep        row = png_voidcast(png_bytep, display->first_row);
-
-         for (; y > 0; --y)
-         {
-            png_read_row(png_ptr, row, NULL);
-            row += row_bytes;
-         }
-      }
-
-      return 1;
-   }
-}
-
-/* Just the row reading part of png_image_read. */
-static int
-png_image_read_composite(png_voidp argument)
-{
-   png_image_read_control *display = png_voidcast(png_image_read_control*,
-       argument);
-   png_imagep image = display->image;
-   png_structrp png_ptr = image->opaque->png_ptr;
-   int passes;
-
-   switch (png_ptr->interlaced)
-   {
-      case PNG_INTERLACE_NONE:
-         passes = 1;
-         break;
-
-      case PNG_INTERLACE_ADAM7:
-         passes = PNG_INTERLACE_ADAM7_PASSES;
-         break;
-
-      default:
-         png_error(png_ptr, "unknown interlace type");
-   }
-
-   {
-      png_uint_32  height = image->height;
-      png_uint_32  width = image->width;
-      ptrdiff_t    step_row = display->row_bytes;
-      unsigned int channels =
-          (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
-      int pass;
-
-      for (pass = 0; pass < passes; ++pass)
-      {
-         unsigned int     startx, stepx, stepy;
-         png_uint_32      y;
-
-         if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
-         {
-            /* The row may be empty for a short image: */
-            if (PNG_PASS_COLS(width, pass) == 0)
-               continue;
-
-            startx = PNG_PASS_START_COL(pass) * channels;
-            stepx = PNG_PASS_COL_OFFSET(pass) * channels;
-            y = PNG_PASS_START_ROW(pass);
-            stepy = PNG_PASS_ROW_OFFSET(pass);
-         }
-
-         else
-         {
-            y = 0;
-            startx = 0;
-            stepx = channels;
-            stepy = 1;
-         }
-
-         for (; y<height; y += stepy)
-         {
-            png_bytep inrow = png_voidcast(png_bytep, display->local_row);
-            png_bytep outrow;
-            png_const_bytep end_row;
-
-            /* Read the row, which is packed: */
-            png_read_row(png_ptr, inrow, NULL);
-
-            outrow = png_voidcast(png_bytep, display->first_row);
-            outrow += y * step_row;
-            end_row = outrow + width * channels;
-
-            /* Now do the composition on each pixel in this row. */
-            outrow += startx;
-            for (; outrow < end_row; outrow += stepx)
-            {
-               png_byte alpha = inrow[channels];
-
-               if (alpha > 0) /* else no change to the output */
-               {
-                  unsigned int c;
-
-                  for (c=0; c<channels; ++c)
-                  {
-                     png_uint_32 component = inrow[c];
-
-                     if (alpha < 255) /* else just use component */
-                     {
-                        /* This is PNG_OPTIMIZED_ALPHA, the component value
-                         * is a linear 8-bit value.  Combine this with the
-                         * current outrow[c] value which is sRGB encoded.
-                         * Arithmetic here is 16-bits to preserve the output
-                         * values correctly.
-                         */
-                        component *= 257*255; /* =65535 */
-                        component += (255-alpha)*png_sRGB_table[outrow[c]];
-
-                        /* So 'component' is scaled by 255*65535 and is
-                         * therefore appropriate for the sRGB to linear
-                         * conversion table.
-                         */
-                        component = PNG_sRGB_FROM_LINEAR(component);
-                     }
-
-                     outrow[c] = (png_byte)component;
-                  }
-               }
-
-               inrow += channels+1; /* components and alpha channel */
-            }
-         }
-      }
-   }
-
-   return 1;
-}
-
-/* The do_local_background case; called when all the following transforms are to
- * be done:
- *
- * PNG_RGB_TO_GRAY
- * PNG_COMPOSITE
- * PNG_GAMMA
- *
- * This is a work-around for the fact that both the PNG_RGB_TO_GRAY and
- * PNG_COMPOSITE code performs gamma correction, so we get double gamma
- * correction.  The fix-up is to prevent the PNG_COMPOSITE operation from
- * happening inside libpng, so this routine sees an 8 or 16-bit gray+alpha
- * row and handles the removal or pre-multiplication of the alpha channel.
- */
-static int
-png_image_read_background(png_voidp argument)
-{
-   png_image_read_control *display = png_voidcast(png_image_read_control*,
-       argument);
-   png_imagep image = display->image;
-   png_structrp png_ptr = image->opaque->png_ptr;
-   png_inforp info_ptr = image->opaque->info_ptr;
-   png_uint_32 height = image->height;
-   png_uint_32 width = image->width;
-   int pass, passes;
-
-   /* Double check the convoluted logic below.  We expect to get here with
-    * libpng doing rgb to gray and gamma correction but background processing
-    * left to the png_image_read_background function.  The rows libpng produce
-    * might be 8 or 16-bit but should always have two channels; gray plus alpha.
-    */
-   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
-      png_error(png_ptr, "lost rgb to gray");
-
-   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
-      png_error(png_ptr, "unexpected compose");
-
-   if (png_get_channels(png_ptr, info_ptr) != 2)
-      png_error(png_ptr, "lost/gained channels");
-
-   /* Expect the 8-bit case to always remove the alpha channel */
-   if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 &&
-      (image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
-      png_error(png_ptr, "unexpected 8-bit transformation");
-
-   switch (png_ptr->interlaced)
-   {
-      case PNG_INTERLACE_NONE:
-         passes = 1;
-         break;
-
-      case PNG_INTERLACE_ADAM7:
-         passes = PNG_INTERLACE_ADAM7_PASSES;
-         break;
-
-      default:
-         png_error(png_ptr, "unknown interlace type");
-   }
-
-   /* Use direct access to info_ptr here because otherwise the simplified API
-    * would require PNG_EASY_ACCESS_SUPPORTED (just for this.)  Note this is
-    * checking the value after libpng expansions, not the original value in the
-    * PNG.
-    */
-   switch (info_ptr->bit_depth)
-   {
-      case 8:
-         /* 8-bit sRGB gray values with an alpha channel; the alpha channel is
-          * to be removed by composing on a background: either the row if
-          * display->background is NULL or display->background->green if not.
-          * Unlike the code above ALPHA_OPTIMIZED has *not* been done.
-          */
-         {
-            png_bytep first_row = png_voidcast(png_bytep, display->first_row);
-            ptrdiff_t step_row = display->row_bytes;
-
-            for (pass = 0; pass < passes; ++pass)
-            {
-               unsigned int     startx, stepx, stepy;
-               png_uint_32      y;
-
-               if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
-               {
-                  /* The row may be empty for a short image: */
-                  if (PNG_PASS_COLS(width, pass) == 0)
-                     continue;
-
-                  startx = PNG_PASS_START_COL(pass);
-                  stepx = PNG_PASS_COL_OFFSET(pass);
-                  y = PNG_PASS_START_ROW(pass);
-                  stepy = PNG_PASS_ROW_OFFSET(pass);
-               }
-
-               else
-               {
-                  y = 0;
-                  startx = 0;
-                  stepx = stepy = 1;
-               }
-
-               if (display->background == NULL)
-               {
-                  for (; y<height; y += stepy)
-                  {
-                     png_bytep inrow = png_voidcast(png_bytep,
-                         display->local_row);
-                     png_bytep outrow = first_row + y * step_row;
-                     png_const_bytep end_row = outrow + width;
-
-                     /* Read the row, which is packed: */
-                     png_read_row(png_ptr, inrow, NULL);
-
-                     /* Now do the composition on each pixel in this row. */
-                     outrow += startx;
-                     for (; outrow < end_row; outrow += stepx)
-                     {
-                        png_byte alpha = inrow[1];
-
-                        if (alpha > 0) /* else no change to the output */
-                        {
-                           png_uint_32 component = inrow[0];
-
-                           if (alpha < 255) /* else just use component */
-                           {
-                              /* Since PNG_OPTIMIZED_ALPHA was not set it is
-                               * necessary to invert the sRGB transfer
-                               * function and multiply the alpha out.
-                               */
-                              component = png_sRGB_table[component] * alpha;
-                              component += png_sRGB_table[outrow[0]] *
-                                 (255-alpha);
-                              component = PNG_sRGB_FROM_LINEAR(component);
-                           }
-
-                           outrow[0] = (png_byte)component;
-                        }
-
-                        inrow += 2; /* gray and alpha channel */
-                     }
-                  }
-               }
-
-               else /* constant background value */
-               {
-                  png_byte background8 = display->background->green;
-                  png_uint_16 background = png_sRGB_table[background8];
-
-                  for (; y<height; y += stepy)
-                  {
-                     png_bytep inrow = png_voidcast(png_bytep,
-                         display->local_row);
-                     png_bytep outrow = first_row + y * step_row;
-                     png_const_bytep end_row = outrow + width;
-
-                     /* Read the row, which is packed: */
-                     png_read_row(png_ptr, inrow, NULL);
-
-                     /* Now do the composition on each pixel in this row. */
-                     outrow += startx;
-                     for (; outrow < end_row; outrow += stepx)
-                     {
-                        png_byte alpha = inrow[1];
-
-                        if (alpha > 0) /* else use background */
-                        {
-                           png_uint_32 component = inrow[0];
-
-                           if (alpha < 255) /* else just use component */
-                           {
-                              component = png_sRGB_table[component] * alpha;
-                              component += background * (255-alpha);
-                              component = PNG_sRGB_FROM_LINEAR(component);
-                           }
-
-                           outrow[0] = (png_byte)component;
-                        }
-
-                        else
-                           outrow[0] = background8;
-
-                        inrow += 2; /* gray and alpha channel */
-                     }
-                  }
-               }
-            }
-         }
-         break;
-
-      case 16:
-         /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must
-          * still be done and, maybe, the alpha channel removed.  This code also
-          * handles the alpha-first option.
-          */
-         {
-            png_uint_16p first_row = png_voidcast(png_uint_16p,
-                display->first_row);
-            /* The division by two is safe because the caller passed in a
-             * stride which was multiplied by 2 (below) to get row_bytes.
-             */
-            ptrdiff_t    step_row = display->row_bytes / 2;
-            unsigned int preserve_alpha = (image->format &
-                PNG_FORMAT_FLAG_ALPHA) != 0;
-            unsigned int outchannels = 1U+preserve_alpha;
-            int swap_alpha = 0;
-
-#           ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
-               if (preserve_alpha != 0 &&
-                   (image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
-                  swap_alpha = 1;
-#           endif
-
-            for (pass = 0; pass < passes; ++pass)
-            {
-               unsigned int     startx, stepx, stepy;
-               png_uint_32      y;
-
-               /* The 'x' start and step are adjusted to output components here.
-                */
-               if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
-               {
-                  /* The row may be empty for a short image: */
-                  if (PNG_PASS_COLS(width, pass) == 0)
-                     continue;
-
-                  startx = PNG_PASS_START_COL(pass) * outchannels;
-                  stepx = PNG_PASS_COL_OFFSET(pass) * outchannels;
-                  y = PNG_PASS_START_ROW(pass);
-                  stepy = PNG_PASS_ROW_OFFSET(pass);
-               }
-
-               else
-               {
-                  y = 0;
-                  startx = 0;
-                  stepx = outchannels;
-                  stepy = 1;
-               }
-
-               for (; y<height; y += stepy)
-               {
-                  png_const_uint_16p inrow;
-                  png_uint_16p outrow = first_row + y*step_row;
-                  png_uint_16p end_row = outrow + width * outchannels;
-
-                  /* Read the row, which is packed: */
-                  png_read_row(png_ptr, png_voidcast(png_bytep,
-                      display->local_row), NULL);
-                  inrow = png_voidcast(png_const_uint_16p, display->local_row);
-
-                  /* Now do the pre-multiplication on each pixel in this row.
-                   */
-                  outrow += startx;
-                  for (; outrow < end_row; outrow += stepx)
-                  {
-                     png_uint_32 component = inrow[0];
-                     png_uint_16 alpha = inrow[1];
-
-                     if (alpha > 0) /* else 0 */
-                     {
-                        if (alpha < 65535) /* else just use component */
-                        {
-                           component *= alpha;
-                           component += 32767;
-                           component /= 65535;
-                        }
-                     }
-
-                     else
-                        component = 0;
-
-                     outrow[swap_alpha] = (png_uint_16)component;
-                     if (preserve_alpha != 0)
-                        outrow[1 ^ swap_alpha] = alpha;
-
-                     inrow += 2; /* components and alpha channel */
-                  }
-               }
-            }
-         }
-         break;
-
-#ifdef __GNUC__
-      default:
-         png_error(png_ptr, "unexpected bit depth");
-#endif
-   }
-
-   return 1;
-}
-
-/* The guts of png_image_finish_read as a png_safe_execute callback. */
-static int
-png_image_read_direct(png_voidp argument)
-{
-   png_image_read_control *display = png_voidcast(png_image_read_control*,
-       argument);
-   png_imagep image = display->image;
-   png_structrp png_ptr = image->opaque->png_ptr;
-   png_inforp info_ptr = image->opaque->info_ptr;
-
-   png_uint_32 format = image->format;
-   int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
-   int do_local_compose = 0;
-   int do_local_background = 0; /* to avoid double gamma correction bug */
-   int passes = 0;
-
-   /* Add transforms to ensure the correct output format is produced then check
-    * that the required implementation support is there.  Always expand; always
-    * need 8 bits minimum, no palette and expanded tRNS.
-    */
-   png_set_expand(png_ptr);
-
-   /* Now check the format to see if it was modified. */
-   {
-      png_uint_32 base_format = png_image_format(png_ptr) &
-         ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */;
-      png_uint_32 change = format ^ base_format;
-      png_fixed_point output_gamma;
-      int mode; /* alpha mode */
-
-      /* Do this first so that we have a record if rgb to gray is happening. */
-      if ((change & PNG_FORMAT_FLAG_COLOR) != 0)
-      {
-         /* gray<->color transformation required. */
-         if ((format & PNG_FORMAT_FLAG_COLOR) != 0)
-            png_set_gray_to_rgb(png_ptr);
-
-         else
-         {
-            /* libpng can't do both rgb to gray and
-             * background/pre-multiplication if there is also significant gamma
-             * correction, because both operations require linear colors and
-             * the code only supports one transform doing the gamma correction.
-             * Handle this by doing the pre-multiplication or background
-             * operation in this code, if necessary.
-             *
-             * TODO: fix this by rewriting pngrtran.c (!)
-             *
-             * For the moment (given that fixing this in pngrtran.c is an
-             * enormous change) 'do_local_background' is used to indicate that
-             * the problem exists.
-             */
-            if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
-               do_local_background = 1/*maybe*/;
-
-            png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
-                PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
-         }
-
-         change &= ~PNG_FORMAT_FLAG_COLOR;
-      }
-
-      /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
-       */
-      {
-         png_fixed_point input_gamma_default;
-
-         if ((base_format & PNG_FORMAT_FLAG_LINEAR) != 0 &&
-             (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
-            input_gamma_default = PNG_GAMMA_LINEAR;
-         else
-            input_gamma_default = PNG_DEFAULT_sRGB;
-
-         /* Call png_set_alpha_mode to set the default for the input gamma; the
-          * output gamma is set by a second call below.
-          */
-         png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default);
-      }
-
-      if (linear != 0)
-      {
-         /* If there *is* an alpha channel in the input it must be multiplied
-          * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG.
-          */
-         if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
-            mode = PNG_ALPHA_STANDARD; /* associated alpha */
-
-         else
-            mode = PNG_ALPHA_PNG;
-
-         output_gamma = PNG_GAMMA_LINEAR;
-      }
-
-      else
-      {
-         mode = PNG_ALPHA_PNG;
-         output_gamma = PNG_DEFAULT_sRGB;
-      }
-      
-      if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0)
-      {
-         mode = PNG_ALPHA_OPTIMIZED;
-         change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
-      }
-      
-      /* If 'do_local_background' is set check for the presence of gamma
-       * correction; this is part of the work-round for the libpng bug
-       * described above.
-       *
-       * TODO: fix libpng and remove this.
-       */
-      if (do_local_background != 0)
-      {
-         png_fixed_point gtest;
-
-         /* This is 'png_gamma_threshold' from pngrtran.c; the test used for
-          * gamma correction, the screen gamma hasn't been set on png_struct
-          * yet; it's set below.  png_struct::gamma, however, is set to the
-          * final value.
-          */
-         if (png_muldiv(&gtest, output_gamma, png_ptr->colorspace.gamma,
-             PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0)
-            do_local_background = 0;
-
-         else if (mode == PNG_ALPHA_STANDARD)
-         {
-            do_local_background = 2/*required*/;
-            mode = PNG_ALPHA_PNG; /* prevent libpng doing it */
-         }
-
-         /* else leave as 1 for the checks below */
-      }
-
-      /* If the bit-depth changes then handle that here. */
-      if ((change & PNG_FORMAT_FLAG_LINEAR) != 0)
-      {
-         if (linear != 0 /*16-bit output*/)
-            png_set_expand_16(png_ptr);
-
-         else /* 8-bit output */
-            png_set_scale_16(png_ptr);
-
-         change &= ~PNG_FORMAT_FLAG_LINEAR;
-      }
-
-      /* Now the background/alpha channel changes. */
-      if ((change & PNG_FORMAT_FLAG_ALPHA) != 0)
-      {
-         /* Removing an alpha channel requires composition for the 8-bit
-          * formats; for the 16-bit it is already done, above, by the
-          * pre-multiplication and the channel just needs to be stripped.
-          */
-         if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
-         {
-            /* If RGB->gray is happening the alpha channel must be left and the
-             * operation completed locally.
-             *
-             * TODO: fix libpng and remove this.
-             */
-            if (do_local_background != 0)
-               do_local_background = 2/*required*/;
-
-            /* 16-bit output: just remove the channel */
-            else if (linear != 0) /* compose on black (well, pre-multiply) */
-               png_set_strip_alpha(png_ptr);
-
-            /* 8-bit output: do an appropriate compose */
-            else if (display->background != NULL)
-            {
-               png_color_16 c;
-
-               c.index = 0; /*unused*/
-               c.red = display->background->red;
-               c.green = display->background->green;
-               c.blue = display->background->blue;
-               c.gray = display->background->green;
-
-               /* This is always an 8-bit sRGB value, using the 'green' channel
-                * for gray is much better than calculating the luminance here;
-                * we can get off-by-one errors in that calculation relative to
-                * the app expectations and that will show up in transparent
-                * pixels.
-                */
-               png_set_background_fixed(png_ptr, &c,
-                   PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
-                   0/*gamma: not used*/);
-            }
-
-            else /* compose on row: implemented below. */
-            {
-               do_local_compose = 1;
-               /* This leaves the alpha channel in the output, so it has to be
-                * removed by the code below.  Set the encoding to the 'OPTIMIZE'
-                * one so the code only has to hack on the pixels that require
-                * composition.
-                */
-               mode = PNG_ALPHA_OPTIMIZED;
-            }
-         }
-
-         else /* output needs an alpha channel */
-         {
-            /* This is tricky because it happens before the swap operation has
-             * been accomplished; however, the swap does *not* swap the added
-             * alpha channel (weird API), so it must be added in the correct
-             * place.
-             */
-            png_uint_32 filler; /* opaque filler */
-            int where;
-
-            if (linear != 0)
-               filler = 65535;
-
-            else
-               filler = 255;
-
-#ifdef PNG_FORMAT_AFIRST_SUPPORTED
-            if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
-            {
-               where = PNG_FILLER_BEFORE;
-               change &= ~PNG_FORMAT_FLAG_AFIRST;
-            }
-
-            else
-#endif
-            where = PNG_FILLER_AFTER;
-
-            png_set_add_alpha(png_ptr, filler, where);
-         }
-
-         /* This stops the (irrelevant) call to swap_alpha below. */
-         change &= ~PNG_FORMAT_FLAG_ALPHA;
-      }
-
-      /* Now set the alpha mode correctly; this is always done, even if there is
-       * no alpha channel in either the input or the output because it correctly
-       * sets the output gamma.
-       */
-      png_set_alpha_mode_fixed(png_ptr, mode, output_gamma);
-
-#     ifdef PNG_FORMAT_BGR_SUPPORTED
-         if ((change & PNG_FORMAT_FLAG_BGR) != 0)
-         {
-            /* Check only the output format; PNG is never BGR; don't do this if
-             * the output is gray, but fix up the 'format' value in that case.
-             */
-            if ((format & PNG_FORMAT_FLAG_COLOR) != 0)
-               png_set_bgr(png_ptr);
-
-            else
-               format &= ~PNG_FORMAT_FLAG_BGR;
-
-            change &= ~PNG_FORMAT_FLAG_BGR;
-         }
-#     endif
-
-#     ifdef PNG_FORMAT_AFIRST_SUPPORTED
-         if ((change & PNG_FORMAT_FLAG_AFIRST) != 0)
-         {
-            /* Only relevant if there is an alpha channel - it's particularly
-             * important to handle this correctly because do_local_compose may
-             * be set above and then libpng will keep the alpha channel for this
-             * code to remove.
-             */
-            if ((format & PNG_FORMAT_FLAG_ALPHA) != 0)
-            {
-               /* Disable this if doing a local background,
-                * TODO: remove this when local background is no longer required.
-                */
-               if (do_local_background != 2)
-                  png_set_swap_alpha(png_ptr);
-            }
-
-            else
-               format &= ~PNG_FORMAT_FLAG_AFIRST;
-
-            change &= ~PNG_FORMAT_FLAG_AFIRST;
-         }
-#     endif
-
-      /* If the *output* is 16-bit then we need to check for a byte-swap on this
-       * architecture.
-       */
-      if (linear != 0)
-      {
-         png_uint_16 le = 0x0001;
-
-         if ((*(png_const_bytep) & le) != 0)
-            png_set_swap(png_ptr);
-      }
-
-      /* If change is not now 0 some transformation is missing - error out. */
-      if (change != 0)
-         png_error(png_ptr, "png_read_image: unsupported transformation");
-   }
-
-   PNG_SKIP_CHUNKS(png_ptr);
-
-   /* Update the 'info' structure and make sure the result is as required; first
-    * make sure to turn on the interlace handling if it will be required
-    * (because it can't be turned on *after* the call to png_read_update_info!)
-    *
-    * TODO: remove the do_local_background fixup below.
-    */
-   if (do_local_compose == 0 && do_local_background != 2)
-      passes = png_set_interlace_handling(png_ptr);
-
-   png_read_update_info(png_ptr, info_ptr);
-
-   {
-      png_uint_32 info_format = 0;
-
-      if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
-         info_format |= PNG_FORMAT_FLAG_COLOR;
-
-      if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
-      {
-         /* do_local_compose removes this channel below. */
-         if (do_local_compose == 0)
-         {
-            /* do_local_background does the same if required. */
-            if (do_local_background != 2 ||
-               (format & PNG_FORMAT_FLAG_ALPHA) != 0)
-               info_format |= PNG_FORMAT_FLAG_ALPHA;
-         }
-      }
-
-      else if (do_local_compose != 0) /* internal error */
-         png_error(png_ptr, "png_image_read: alpha channel lost");
-
-      if ((format & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) {
-         info_format |= PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
-      }
-
-      if (info_ptr->bit_depth == 16)
-         info_format |= PNG_FORMAT_FLAG_LINEAR;
-
-#ifdef PNG_FORMAT_BGR_SUPPORTED
-      if ((png_ptr->transformations & PNG_BGR) != 0)
-         info_format |= PNG_FORMAT_FLAG_BGR;
-#endif
-
-#ifdef PNG_FORMAT_AFIRST_SUPPORTED
-         if (do_local_background == 2)
-         {
-            if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
-               info_format |= PNG_FORMAT_FLAG_AFIRST;
-         }
-
-         if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 ||
-            ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
-            (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))
-         {
-            if (do_local_background == 2)
-               png_error(png_ptr, "unexpected alpha swap transformation");
-
-            info_format |= PNG_FORMAT_FLAG_AFIRST;
-         }
-#     endif
-
-      /* This is actually an internal error. */
-      if (info_format != format)
-         png_error(png_ptr, "png_read_image: invalid transformations");
-   }
-
-   /* Now read the rows.  If do_local_compose is set then it is necessary to use
-    * a local row buffer.  The output will be GA, RGBA or BGRA and must be
-    * converted to G, RGB or BGR as appropriate.  The 'local_row' member of the
-    * display acts as a flag.
-    */
-   {
-      png_voidp first_row = display->buffer;
-      ptrdiff_t row_bytes = display->row_stride;
-
-      if (linear != 0)
-         row_bytes *= 2;
-
-      /* The following expression is designed to work correctly whether it gives
-       * a signed or an unsigned result.
-       */
-      if (row_bytes < 0)
-      {
-         char *ptr = png_voidcast(char*, first_row);
-         ptr += (image->height-1) * (-row_bytes);
-         first_row = png_voidcast(png_voidp, ptr);
-      }
-
-      display->first_row = first_row;
-      display->row_bytes = row_bytes;
-   }
-
-   if (do_local_compose != 0)
-   {
-      int result;
-      png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
-
-      display->local_row = row;
-      result = png_safe_execute(image, png_image_read_composite, display);
-      display->local_row = NULL;
-      png_free(png_ptr, row);
-
-      return result;
-   }
-
-   else if (do_local_background == 2)
-   {
-      int result;
-      png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
-
-      display->local_row = row;
-      result = png_safe_execute(image, png_image_read_background, display);
-      display->local_row = NULL;
-      png_free(png_ptr, row);
-
-      return result;
-   }
-
-   else
-   {
-      png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
-
-      while (--passes >= 0)
-      {
-         png_uint_32      y = image->height;
-         png_bytep        row = png_voidcast(png_bytep, display->first_row);
-
-         for (; y > 0; --y)
-         {
-            png_read_row(png_ptr, row, NULL);
-            row += row_bytes;
-         }
-      }
-
-      return 1;
-   }
-}
-
-int PNGAPI
-png_image_finish_read(png_imagep image, png_const_colorp background,
-    void *buffer, png_int_32 row_stride, void *colormap)
-{
-   if (image != NULL && image->version == PNG_IMAGE_VERSION)
-   {
-      /* Check for row_stride overflow.  This check is not performed on the
-       * original PNG format because it may not occur in the output PNG format
-       * and libpng deals with the issues of reading the original.
-       */
-      unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
-
-      /* The following checks just the 'row_stride' calculation to ensure it
-       * fits in a signed 32-bit value.  Because channels/components can be
-       * either 1 or 2 bytes in size the length of a row can still overflow 32
-       * bits; this is just to verify that the 'row_stride' argument can be
-       * represented.
-       */
-      if (image->width <= 0x7fffffffU/channels) /* no overflow */
-      {
-         png_uint_32 check;
-         png_uint_32 png_row_stride = image->width * channels;
-
-         if (row_stride == 0)
-            row_stride = (png_int_32)/*SAFE*/png_row_stride;
-
-         if (row_stride < 0)
-            check = (png_uint_32)(-row_stride);
-
-         else
-            check = (png_uint_32)row_stride;
-
-         /* This verifies 'check', the absolute value of the actual stride
-          * passed in and detects overflow in the application calculation (i.e.
-          * if the app did actually pass in a non-zero 'row_stride'.
-          */
-         if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
-         {
-            /* Now check for overflow of the image buffer calculation; this
-             * limits the whole image size to 32 bits for API compatibility with
-             * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
-             *
-             * The PNG_IMAGE_BUFFER_SIZE macro is:
-             *
-             *    (PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)*height*(row_stride))
-             *
-             * And the component size is always 1 or 2, so make sure that the
-             * number of *bytes* that the application is saying are available
-             * does actually fit into a 32-bit number.
-             *
-             * NOTE: this will be changed in 1.7 because PNG_IMAGE_BUFFER_SIZE
-             * will be changed to use png_alloc_size_t; bigger images can be
-             * accommodated on 64-bit systems.
-             */
-            if (image->height <=
-                0xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check)
-            {
-               if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
-                  (image->colormap_entries > 0 && colormap != NULL))
-               {
-                  int result;
-                  png_image_read_control display;
-
-                  memset(&display, 0, (sizeof display));
-                  display.image = image;
-                  display.buffer = buffer;
-                  display.row_stride = row_stride;
-                  display.colormap = colormap;
-                  display.background = background;
-                  display.local_row = NULL;
-
-                  /* Choose the correct 'end' routine; for the color-map case
-                   * all the setup has already been done.
-                   */
-                  if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
-                     result =
-                         png_safe_execute(image,
-                             png_image_read_colormap, &display) &&
-                             png_safe_execute(image,
-                             png_image_read_colormapped, &display);
-
-                  else
-                     result =
-                        png_safe_execute(image,
-                            png_image_read_direct, &display);
-
-                  png_image_free(image);
-                  return result;
-               }
-
-               else
-                  return png_image_error(image,
-                      "png_image_finish_read[color-map]: no color-map");
-            }
-
-            else
-               return png_image_error(image,
-                   "png_image_finish_read: image too large");
-         }
-
-         else
-            return png_image_error(image,
-                "png_image_finish_read: invalid argument");
-      }
-
-      else
-         return png_image_error(image,
-             "png_image_finish_read: row_stride too large");
-   }
-
-   else if (image != NULL)
-      return png_image_error(image,
-          "png_image_finish_read: damaged PNG_IMAGE_VERSION");
-
-   return 0;
-}
-
-#endif /* SIMPLIFIED_READ */
-#endif /* READ */
diff --git a/third_party/libpng16/pngrio.c b/third_party/libpng16/pngrio.c
deleted file mode 100644
index 7946358..0000000
--- a/third_party/libpng16/pngrio.c
+++ /dev/null
@@ -1,120 +0,0 @@
-
-/* pngrio.c - functions for data input
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- *
- * This file provides a location for all input.  Users who need
- * special handling are expected to write a function that has the same
- * arguments as this and performs a similar function, but that possibly
- * has a different input method.  Note that you shouldn't change this
- * function, but rather write a replacement function and then make
- * libpng use it at run time with png_set_read_fn(...).
- */
-
-#include "pngpriv.h"
-
-#ifdef PNG_READ_SUPPORTED
-
-/* Read the data from whatever input you are using.  The default routine
- * reads from a file pointer.  Note that this routine sometimes gets called
- * with very small lengths, so you should implement some kind of simple
- * buffering if you are using unbuffered reads.  This should never be asked
- * to read more than 64K on a 16-bit machine.
- */
-void /* PRIVATE */
-png_read_data(png_structrp png_ptr, png_bytep data, size_t length)
-{
-   png_debug1(4, "reading %d bytes", (int)length);
-
-   if (png_ptr->read_data_fn != NULL)
-      (*(png_ptr->read_data_fn))(png_ptr, data, length);
-
-   else
-      png_error(png_ptr, "Call to NULL read function");
-}
-
-#ifdef PNG_STDIO_SUPPORTED
-/* This is the function that does the actual reading of data.  If you are
- * not reading from a standard C stream, you should create a replacement
- * read_data function and use it at run time with png_set_read_fn(), rather
- * than changing the library.
- */
-void PNGCBAPI
-png_default_read_data(png_structp png_ptr, png_bytep data, size_t length)
-{
-   size_t check;
-
-   if (png_ptr == NULL)
-      return;
-
-   /* fread() returns 0 on error, so it is OK to store this in a size_t
-    * instead of an int, which is what fread() actually returns.
-    */
-   check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));
-
-   if (check != length)
-      png_error(png_ptr, "Read Error");
-}
-#endif
-
-/* This function allows the application to supply a new input function
- * for libpng if standard C streams aren't being used.
- *
- * This function takes as its arguments:
- *
- * png_ptr      - pointer to a png input data structure
- *
- * io_ptr       - pointer to user supplied structure containing info about
- *                the input functions.  May be NULL.
- *
- * read_data_fn - pointer to a new input function that takes as its
- *                arguments a pointer to a png_struct, a pointer to
- *                a location where input data can be stored, and a 32-bit
- *                unsigned int that is the number of bytes to be read.
- *                To exit and output any fatal error messages the new write
- *                function should call png_error(png_ptr, "Error msg").
- *                May be NULL, in which case libpng's default function will
- *                be used.
- */
-void PNGAPI
-png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr,
-    png_rw_ptr read_data_fn)
-{
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->io_ptr = io_ptr;
-
-#ifdef PNG_STDIO_SUPPORTED
-   if (read_data_fn != NULL)
-      png_ptr->read_data_fn = read_data_fn;
-
-   else
-      png_ptr->read_data_fn = png_default_read_data;
-#else
-   png_ptr->read_data_fn = read_data_fn;
-#endif
-
-#ifdef PNG_WRITE_SUPPORTED
-   /* It is an error to write to a read device */
-   if (png_ptr->write_data_fn != NULL)
-   {
-      png_ptr->write_data_fn = NULL;
-      png_warning(png_ptr,
-          "Can't set both read_data_fn and write_data_fn in the"
-          " same structure");
-   }
-#endif
-
-#ifdef PNG_WRITE_FLUSH_SUPPORTED
-   png_ptr->output_flush_fn = NULL;
-#endif
-}
-#endif /* READ */
diff --git a/third_party/libpng16/pngrtran.c b/third_party/libpng16/pngrtran.c
deleted file mode 100644
index 786e0de..0000000
--- a/third_party/libpng16/pngrtran.c
+++ /dev/null
@@ -1,5044 +0,0 @@
-
-/* pngrtran.c - transforms the data in a row for PNG readers
- *
- * Copyright (c) 2018-2019 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- *
- * This file contains functions optionally called by an application
- * in order to tell libpng how to handle data when reading a PNG.
- * Transformations that are used in both reading and writing are
- * in pngtrans.c.
- */
-
-#include "pngpriv.h"
-
-#ifdef PNG_ARM_NEON_IMPLEMENTATION
-#  if PNG_ARM_NEON_IMPLEMENTATION == 1
-#    define PNG_ARM_NEON_INTRINSICS_AVAILABLE
-#    if defined(_MSC_VER) && defined(_M_ARM64) && !defined(__clang__)
-#      include <arm64_neon.h>
-#    else
-#      include <arm_neon.h>
-#    endif
-#  endif
-#endif
-
-#ifdef PNG_READ_SUPPORTED
-
-/* Set the action on getting a CRC error for an ancillary or critical chunk. */
-void PNGAPI
-png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
-{
-   png_debug(1, "in png_set_crc_action");
-
-   if (png_ptr == NULL)
-      return;
-
-   /* Tell libpng how we react to CRC errors in critical chunks */
-   switch (crit_action)
-   {
-      case PNG_CRC_NO_CHANGE:                        /* Leave setting as is */
-         break;
-
-      case PNG_CRC_WARN_USE:                               /* Warn/use data */
-         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
-         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE;
-         break;
-
-      case PNG_CRC_QUIET_USE:                             /* Quiet/use data */
-         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
-         png_ptr->flags |= PNG_FLAG_CRC_CRITICAL_USE |
-                           PNG_FLAG_CRC_CRITICAL_IGNORE;
-         break;
-
-      case PNG_CRC_WARN_DISCARD:    /* Not a valid action for critical data */
-         png_warning(png_ptr,
-             "Can't discard critical data on CRC error");
-         /* FALLTHROUGH */
-      case PNG_CRC_ERROR_QUIT:                                /* Error/quit */
-
-      case PNG_CRC_DEFAULT:
-      default:
-         png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
-         break;
-   }
-
-   /* Tell libpng how we react to CRC errors in ancillary chunks */
-   switch (ancil_action)
-   {
-      case PNG_CRC_NO_CHANGE:                       /* Leave setting as is */
-         break;
-
-      case PNG_CRC_WARN_USE:                              /* Warn/use data */
-         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
-         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE;
-         break;
-
-      case PNG_CRC_QUIET_USE:                            /* Quiet/use data */
-         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
-         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_USE |
-                           PNG_FLAG_CRC_ANCILLARY_NOWARN;
-         break;
-
-      case PNG_CRC_ERROR_QUIT:                               /* Error/quit */
-         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
-         png_ptr->flags |= PNG_FLAG_CRC_ANCILLARY_NOWARN;
-         break;
-
-      case PNG_CRC_WARN_DISCARD:                      /* Warn/discard data */
-
-      case PNG_CRC_DEFAULT:
-      default:
-         png_ptr->flags &= ~PNG_FLAG_CRC_ANCILLARY_MASK;
-         break;
-   }
-}
-
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-/* Is it OK to set a transformation now?  Only if png_start_read_image or
- * png_read_update_info have not been called.  It is not necessary for the IHDR
- * to have been read in all cases; the need_IHDR parameter allows for this
- * check too.
- */
-static int
-png_rtran_ok(png_structrp png_ptr, int need_IHDR)
-{
-   if (png_ptr != NULL)
-   {
-      if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
-         png_app_error(png_ptr,
-             "invalid after png_start_read_image or png_read_update_info");
-
-      else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
-         png_app_error(png_ptr, "invalid before the PNG header has been read");
-
-      else
-      {
-         /* Turn on failure to initialize correctly for all transforms. */
-         png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
-
-         return 1; /* Ok */
-      }
-   }
-
-   return 0; /* no png_error possible! */
-}
-#endif
-
-#ifdef PNG_READ_BACKGROUND_SUPPORTED
-/* Handle alpha and tRNS via a background color */
-void PNGFAPI
-png_set_background_fixed(png_structrp png_ptr,
-    png_const_color_16p background_color, int background_gamma_code,
-    int need_expand, png_fixed_point background_gamma)
-{
-   png_debug(1, "in png_set_background_fixed");
-
-   if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL)
-      return;
-
-   if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
-   {
-      png_warning(png_ptr, "Application must supply a known background gamma");
-      return;
-   }
-
-   png_ptr->transformations |= PNG_COMPOSE | PNG_STRIP_ALPHA;
-   png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
-   png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
-
-   png_ptr->background = *background_color;
-   png_ptr->background_gamma = background_gamma;
-   png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
-   if (need_expand != 0)
-      png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
-   else
-      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
-}
-
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-void PNGAPI
-png_set_background(png_structrp png_ptr,
-    png_const_color_16p background_color, int background_gamma_code,
-    int need_expand, double background_gamma)
-{
-   png_set_background_fixed(png_ptr, background_color, background_gamma_code,
-      need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
-}
-#  endif /* FLOATING_POINT */
-#endif /* READ_BACKGROUND */
-
-/* Scale 16-bit depth files to 8-bit depth.  If both of these are set then the
- * one that pngrtran does first (scale) happens.  This is necessary to allow the
- * TRANSFORM and API behavior to be somewhat consistent, and it's simpler.
- */
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
-void PNGAPI
-png_set_scale_16(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_scale_16");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   png_ptr->transformations |= PNG_SCALE_16_TO_8;
-}
-#endif
-
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-/* Chop 16-bit depth files to 8-bit depth */
-void PNGAPI
-png_set_strip_16(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_strip_16");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   png_ptr->transformations |= PNG_16_TO_8;
-}
-#endif
-
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-void PNGAPI
-png_set_strip_alpha(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_strip_alpha");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   png_ptr->transformations |= PNG_STRIP_ALPHA;
-}
-#endif
-
-#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
-static png_fixed_point
-translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
-    int is_screen)
-{
-   /* Check for flag values.  The main reason for having the old Mac value as a
-    * flag is that it is pretty near impossible to work out what the correct
-    * value is from Apple documentation - a working Mac system is needed to
-    * discover the value!
-    */
-   if (output_gamma == PNG_DEFAULT_sRGB ||
-      output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB)
-   {
-      /* If there is no sRGB support this just sets the gamma to the standard
-       * sRGB value.  (This is a side effect of using this function!)
-       */
-#     ifdef PNG_READ_sRGB_SUPPORTED
-         png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
-#     else
-         PNG_UNUSED(png_ptr)
-#     endif
-      if (is_screen != 0)
-         output_gamma = PNG_GAMMA_sRGB;
-      else
-         output_gamma = PNG_GAMMA_sRGB_INVERSE;
-   }
-
-   else if (output_gamma == PNG_GAMMA_MAC_18 ||
-      output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
-   {
-      if (is_screen != 0)
-         output_gamma = PNG_GAMMA_MAC_OLD;
-      else
-         output_gamma = PNG_GAMMA_MAC_INVERSE;
-   }
-
-   return output_gamma;
-}
-
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-static png_fixed_point
-convert_gamma_value(png_structrp png_ptr, double output_gamma)
-{
-   /* The following silently ignores cases where fixed point (times 100,000)
-    * gamma values are passed to the floating point API.  This is safe and it
-    * means the fixed point constants work just fine with the floating point
-    * API.  The alternative would just lead to undetected errors and spurious
-    * bug reports.  Negative values fail inside the _fixed API unless they
-    * correspond to the flag values.
-    */
-   if (output_gamma > 0 && output_gamma < 128)
-      output_gamma *= PNG_FP_1;
-
-   /* This preserves -1 and -2 exactly: */
-   output_gamma = floor(output_gamma + .5);
-
-   if (output_gamma > PNG_FP_MAX || output_gamma < PNG_FP_MIN)
-      png_fixed_error(png_ptr, "gamma value");
-
-   return (png_fixed_point)output_gamma;
-}
-#  endif
-#endif /* READ_ALPHA_MODE || READ_GAMMA */
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-void PNGFAPI
-png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
-    png_fixed_point output_gamma)
-{
-   int compose = 0;
-   png_fixed_point file_gamma;
-
-   png_debug(1, "in png_set_alpha_mode");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
-
-   /* Validate the value to ensure it is in a reasonable range. The value
-    * is expected to be 1 or greater, but this range test allows for some
-    * viewing correction values.  The intent is to weed out users of this API
-    * who use the inverse of the gamma value accidentally!  Since some of these
-    * values are reasonable this may have to be changed:
-    *
-    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit
-    * gamma of 36, and its reciprocal.)
-    */
-   if (output_gamma < 1000 || output_gamma > 10000000)
-      png_error(png_ptr, "output gamma out of expected range");
-
-   /* The default file gamma is the inverse of the output gamma; the output
-    * gamma may be changed below so get the file value first:
-    */
-   file_gamma = png_reciprocal(output_gamma);
-
-   /* There are really 8 possibilities here, composed of any combination
-    * of:
-    *
-    *    premultiply the color channels
-    *    do not encode non-opaque pixels
-    *    encode the alpha as well as the color channels
-    *
-    * The differences disappear if the input/output ('screen') gamma is 1.0,
-    * because then the encoding is a no-op and there is only the choice of
-    * premultiplying the color channels or not.
-    *
-    * png_set_alpha_mode and png_set_background interact because both use
-    * png_compose to do the work.  Calling both is only useful when
-    * png_set_alpha_mode is used to set the default mode - PNG_ALPHA_PNG - along
-    * with a default gamma value.  Otherwise PNG_COMPOSE must not be set.
-    */
-   switch (mode)
-   {
-      case PNG_ALPHA_PNG:        /* default: png standard */
-         /* No compose, but it may be set by png_set_background! */
-         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
-         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
-         break;
-
-      case PNG_ALPHA_ASSOCIATED: /* color channels premultiplied */
-         compose = 1;
-         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
-         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
-         /* The output is linear: */
-         output_gamma = PNG_FP_1;
-         break;
-
-      case PNG_ALPHA_OPTIMIZED:  /* associated, non-opaque pixels linear */
-         compose = 1;
-         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
-         png_ptr->flags |= PNG_FLAG_OPTIMIZE_ALPHA;
-         /* output_gamma records the encoding of opaque pixels! */
-         break;
-
-      case PNG_ALPHA_BROKEN:     /* associated, non-linear, alpha encoded */
-         compose = 1;
-         png_ptr->transformations |= PNG_ENCODE_ALPHA;
-         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
-         break;
-
-      default:
-         png_error(png_ptr, "invalid alpha mode");
-   }
-
-   /* Only set the default gamma if the file gamma has not been set (this has
-    * the side effect that the gamma in a second call to png_set_alpha_mode will
-    * be ignored.)
-    */
-   if (png_ptr->colorspace.gamma == 0)
-   {
-      png_ptr->colorspace.gamma = file_gamma;
-      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
-   }
-
-   /* But always set the output gamma: */
-   png_ptr->screen_gamma = output_gamma;
-
-   /* Finally, if pre-multiplying, set the background fields to achieve the
-    * desired result.
-    */
-   if (compose != 0)
-   {
-      /* And obtain alpha pre-multiplication by composing on black: */
-      memset(&png_ptr->background, 0, (sizeof png_ptr->background));
-      png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
-      png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
-      png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
-
-      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
-         png_error(png_ptr,
-             "conflicting calls to set alpha mode and background");
-
-      png_ptr->transformations |= PNG_COMPOSE;
-   }
-}
-
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-void PNGAPI
-png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
-{
-   png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
-       output_gamma));
-}
-#  endif
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-/* Dither file to 8-bit.  Supply a palette, the current number
- * of elements in the palette, the maximum number of elements
- * allowed, and a histogram if possible.  If the current number
- * of colors is greater than the maximum number, the palette will be
- * modified to fit in the maximum number.  "full_quantize" indicates
- * whether we need a quantizing cube set up for RGB images, or if we
- * simply are reducing the number of colors in a paletted image.
- */
-
-typedef struct png_dsort_struct
-{
-   struct png_dsort_struct * next;
-   png_byte left;
-   png_byte right;
-} png_dsort;
-typedef png_dsort *   png_dsortp;
-typedef png_dsort * * png_dsortpp;
-
-void PNGAPI
-png_set_quantize(png_structrp png_ptr, png_colorp palette,
-    int num_palette, int maximum_colors, png_const_uint_16p histogram,
-    int full_quantize)
-{
-   png_debug(1, "in png_set_quantize");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   png_ptr->transformations |= PNG_QUANTIZE;
-
-   if (full_quantize == 0)
-   {
-      int i;
-
-      png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
-          (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
-      for (i = 0; i < num_palette; i++)
-         png_ptr->quantize_index[i] = (png_byte)i;
-   }
-
-   if (num_palette > maximum_colors)
-   {
-      if (histogram != NULL)
-      {
-         /* This is easy enough, just throw out the least used colors.
-          * Perhaps not the best solution, but good enough.
-          */
-
-         int i;
-
-         /* Initialize an array to sort colors */
-         png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
-             (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
-
-         /* Initialize the quantize_sort array */
-         for (i = 0; i < num_palette; i++)
-            png_ptr->quantize_sort[i] = (png_byte)i;
-
-         /* Find the least used palette entries by starting a
-          * bubble sort, and running it until we have sorted
-          * out enough colors.  Note that we don't care about
-          * sorting all the colors, just finding which are
-          * least used.
-          */
-
-         for (i = num_palette - 1; i >= maximum_colors; i--)
-         {
-            int done; /* To stop early if the list is pre-sorted */
-            int j;
-
-            done = 1;
-            for (j = 0; j < i; j++)
-            {
-               if (histogram[png_ptr->quantize_sort[j]]
-                   < histogram[png_ptr->quantize_sort[j + 1]])
-               {
-                  png_byte t;
-
-                  t = png_ptr->quantize_sort[j];
-                  png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1];
-                  png_ptr->quantize_sort[j + 1] = t;
-                  done = 0;
-               }
-            }
-
-            if (done != 0)
-               break;
-         }
-
-         /* Swap the palette around, and set up a table, if necessary */
-         if (full_quantize != 0)
-         {
-            int j = num_palette;
-
-            /* Put all the useful colors within the max, but don't
-             * move the others.
-             */
-            for (i = 0; i < maximum_colors; i++)
-            {
-               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
-               {
-                  do
-                     j--;
-                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
-
-                  palette[i] = palette[j];
-               }
-            }
-         }
-         else
-         {
-            int j = num_palette;
-
-            /* Move all the used colors inside the max limit, and
-             * develop a translation table.
-             */
-            for (i = 0; i < maximum_colors; i++)
-            {
-               /* Only move the colors we need to */
-               if ((int)png_ptr->quantize_sort[i] >= maximum_colors)
-               {
-                  png_color tmp_color;
-
-                  do
-                     j--;
-                  while ((int)png_ptr->quantize_sort[j] >= maximum_colors);
-
-                  tmp_color = palette[j];
-                  palette[j] = palette[i];
-                  palette[i] = tmp_color;
-                  /* Indicate where the color went */
-                  png_ptr->quantize_index[j] = (png_byte)i;
-                  png_ptr->quantize_index[i] = (png_byte)j;
-               }
-            }
-
-            /* Find closest color for those colors we are not using */
-            for (i = 0; i < num_palette; i++)
-            {
-               if ((int)png_ptr->quantize_index[i] >= maximum_colors)
-               {
-                  int min_d, k, min_k, d_index;
-
-                  /* Find the closest color to one we threw out */
-                  d_index = png_ptr->quantize_index[i];
-                  min_d = PNG_COLOR_DIST(palette[d_index], palette[0]);
-                  for (k = 1, min_k = 0; k < maximum_colors; k++)
-                  {
-                     int d;
-
-                     d = PNG_COLOR_DIST(palette[d_index], palette[k]);
-
-                     if (d < min_d)
-                     {
-                        min_d = d;
-                        min_k = k;
-                     }
-                  }
-                  /* Point to closest color */
-                  png_ptr->quantize_index[i] = (png_byte)min_k;
-               }
-            }
-         }
-         png_free(png_ptr, png_ptr->quantize_sort);
-         png_ptr->quantize_sort = NULL;
-      }
-      else
-      {
-         /* This is much harder to do simply (and quickly).  Perhaps
-          * we need to go through a median cut routine, but those
-          * don't always behave themselves with only a few colors
-          * as input.  So we will just find the closest two colors,
-          * and throw out one of them (chosen somewhat randomly).
-          * [We don't understand this at all, so if someone wants to
-          *  work on improving it, be our guest - AED, GRP]
-          */
-         int i;
-         int max_d;
-         int num_new_palette;
-         png_dsortp t;
-         png_dsortpp hash;
-
-         t = NULL;
-
-         /* Initialize palette index arrays */
-         png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
-             (png_alloc_size_t)((png_uint_32)num_palette *
-             (sizeof (png_byte))));
-         png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
-             (png_alloc_size_t)((png_uint_32)num_palette *
-             (sizeof (png_byte))));
-
-         /* Initialize the sort array */
-         for (i = 0; i < num_palette; i++)
-         {
-            png_ptr->index_to_palette[i] = (png_byte)i;
-            png_ptr->palette_to_index[i] = (png_byte)i;
-         }
-
-         hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 *
-             (sizeof (png_dsortp))));
-
-         num_new_palette = num_palette;
-
-         /* Initial wild guess at how far apart the farthest pixel
-          * pair we will be eliminating will be.  Larger
-          * numbers mean more areas will be allocated, Smaller
-          * numbers run the risk of not saving enough data, and
-          * having to do this all over again.
-          *
-          * I have not done extensive checking on this number.
-          */
-         max_d = 96;
-
-         while (num_new_palette > maximum_colors)
-         {
-            for (i = 0; i < num_new_palette - 1; i++)
-            {
-               int j;
-
-               for (j = i + 1; j < num_new_palette; j++)
-               {
-                  int d;
-
-                  d = PNG_COLOR_DIST(palette[i], palette[j]);
-
-                  if (d <= max_d)
-                  {
-
-                     t = (png_dsortp)png_malloc_warn(png_ptr,
-                         (png_alloc_size_t)(sizeof (png_dsort)));
-
-                     if (t == NULL)
-                         break;
-
-                     t->next = hash[d];
-                     t->left = (png_byte)i;
-                     t->right = (png_byte)j;
-                     hash[d] = t;
-                  }
-               }
-               if (t == NULL)
-                  break;
-            }
-
-            if (t != NULL)
-            for (i = 0; i <= max_d; i++)
-            {
-               if (hash[i] != NULL)
-               {
-                  png_dsortp p;
-
-                  for (p = hash[i]; p; p = p->next)
-                  {
-                     if ((int)png_ptr->index_to_palette[p->left]
-                         < num_new_palette &&
-                         (int)png_ptr->index_to_palette[p->right]
-                         < num_new_palette)
-                     {
-                        int j, next_j;
-
-                        if (num_new_palette & 0x01)
-                        {
-                           j = p->left;
-                           next_j = p->right;
-                        }
-                        else
-                        {
-                           j = p->right;
-                           next_j = p->left;
-                        }
-
-                        num_new_palette--;
-                        palette[png_ptr->index_to_palette[j]]
-                            = palette[num_new_palette];
-                        if (full_quantize == 0)
-                        {
-                           int k;
-
-                           for (k = 0; k < num_palette; k++)
-                           {
-                              if (png_ptr->quantize_index[k] ==
-                                  png_ptr->index_to_palette[j])
-                                 png_ptr->quantize_index[k] =
-                                     png_ptr->index_to_palette[next_j];
-
-                              if ((int)png_ptr->quantize_index[k] ==
-                                  num_new_palette)
-                                 png_ptr->quantize_index[k] =
-                                     png_ptr->index_to_palette[j];
-                           }
-                        }
-
-                        png_ptr->index_to_palette[png_ptr->palette_to_index
-                            [num_new_palette]] = png_ptr->index_to_palette[j];
-
-                        png_ptr->palette_to_index[png_ptr->index_to_palette[j]]
-                            = png_ptr->palette_to_index[num_new_palette];
-
-                        png_ptr->index_to_palette[j] =
-                            (png_byte)num_new_palette;
-
-                        png_ptr->palette_to_index[num_new_palette] =
-                            (png_byte)j;
-                     }
-                     if (num_new_palette <= maximum_colors)
-                        break;
-                  }
-                  if (num_new_palette <= maximum_colors)
-                     break;
-               }
-            }
-
-            for (i = 0; i < 769; i++)
-            {
-               if (hash[i] != NULL)
-               {
-                  png_dsortp p = hash[i];
-                  while (p)
-                  {
-                     t = p->next;
-                     png_free(png_ptr, p);
-                     p = t;
-                  }
-               }
-               hash[i] = 0;
-            }
-            max_d += 96;
-         }
-         png_free(png_ptr, hash);
-         png_free(png_ptr, png_ptr->palette_to_index);
-         png_free(png_ptr, png_ptr->index_to_palette);
-         png_ptr->palette_to_index = NULL;
-         png_ptr->index_to_palette = NULL;
-      }
-      num_palette = maximum_colors;
-   }
-   if (png_ptr->palette == NULL)
-   {
-      png_ptr->palette = palette;
-   }
-   png_ptr->num_palette = (png_uint_16)num_palette;
-
-   if (full_quantize != 0)
-   {
-      int i;
-      png_bytep distance;
-      int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS +
-          PNG_QUANTIZE_BLUE_BITS;
-      int num_red = (1 << PNG_QUANTIZE_RED_BITS);
-      int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
-      int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
-      size_t num_entries = ((size_t)1 << total_bits);
-
-      png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
-          (png_alloc_size_t)(num_entries * (sizeof (png_byte))));
-
-      distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries *
-          (sizeof (png_byte))));
-
-      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
-
-      for (i = 0; i < num_palette; i++)
-      {
-         int ir, ig, ib;
-         int r = (palette[i].red >> (8 - PNG_QUANTIZE_RED_BITS));
-         int g = (palette[i].green >> (8 - PNG_QUANTIZE_GREEN_BITS));
-         int b = (palette[i].blue >> (8 - PNG_QUANTIZE_BLUE_BITS));
-
-         for (ir = 0; ir < num_red; ir++)
-         {
-            /* int dr = abs(ir - r); */
-            int dr = ((ir > r) ? ir - r : r - ir);
-            int index_r = (ir << (PNG_QUANTIZE_BLUE_BITS +
-                PNG_QUANTIZE_GREEN_BITS));
-
-            for (ig = 0; ig < num_green; ig++)
-            {
-               /* int dg = abs(ig - g); */
-               int dg = ((ig > g) ? ig - g : g - ig);
-               int dt = dr + dg;
-               int dm = ((dr > dg) ? dr : dg);
-               int index_g = index_r | (ig << PNG_QUANTIZE_BLUE_BITS);
-
-               for (ib = 0; ib < num_blue; ib++)
-               {
-                  int d_index = index_g | ib;
-                  /* int db = abs(ib - b); */
-                  int db = ((ib > b) ? ib - b : b - ib);
-                  int dmax = ((dm > db) ? dm : db);
-                  int d = dmax + dt + db;
-
-                  if (d < (int)distance[d_index])
-                  {
-                     distance[d_index] = (png_byte)d;
-                     png_ptr->palette_lookup[d_index] = (png_byte)i;
-                  }
-               }
-            }
-         }
-      }
-
-      png_free(png_ptr, distance);
-   }
-}
-#endif /* READ_QUANTIZE */
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-void PNGFAPI
-png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
-    png_fixed_point file_gamma)
-{
-   png_debug(1, "in png_set_gamma_fixed");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   /* New in libpng-1.5.4 - reserve particular negative values as flags. */
-   scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
-   file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
-
-   /* Checking the gamma values for being >0 was added in 1.5.4 along with the
-    * premultiplied alpha support; this actually hides an undocumented feature
-    * of the previous implementation which allowed gamma processing to be
-    * disabled in background handling.  There is no evidence (so far) that this
-    * was being used; however, png_set_background itself accepted and must still
-    * accept '0' for the gamma value it takes, because it isn't always used.
-    *
-    * Since this is an API change (albeit a very minor one that removes an
-    * undocumented API feature) the following checks were only enabled in
-    * libpng-1.6.0.
-    */
-   if (file_gamma <= 0)
-      png_error(png_ptr, "invalid file gamma in png_set_gamma");
-
-   if (scrn_gamma <= 0)
-      png_error(png_ptr, "invalid screen gamma in png_set_gamma");
-
-   /* Set the gamma values unconditionally - this overrides the value in the PNG
-    * file if a gAMA chunk was present.  png_set_alpha_mode provides a
-    * different, easier, way to default the file gamma.
-    */
-   png_ptr->colorspace.gamma = file_gamma;
-   png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
-   png_ptr->screen_gamma = scrn_gamma;
-}
-
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-void PNGAPI
-png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
-{
-   png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
-       convert_gamma_value(png_ptr, file_gamma));
-}
-#  endif /* FLOATING_POINT */
-#endif /* READ_GAMMA */
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
-/* Expand paletted images to RGB, expand grayscale images of
- * less than 8-bit depth to 8-bit depth, and expand tRNS chunks
- * to alpha channels.
- */
-void PNGAPI
-png_set_expand(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_expand");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
-}
-
-/* GRR 19990627:  the following three functions currently are identical
- *  to png_set_expand().  However, it is entirely reasonable that someone
- *  might wish to expand an indexed image to RGB but *not* expand a single,
- *  fully transparent palette entry to a full alpha channel--perhaps instead
- *  convert tRNS to the grayscale/RGB format (16-bit RGB value), or replace
- *  the transparent color with a particular RGB value, or drop tRNS entirely.
- *  IOW, a future version of the library may make the transformations flag
- *  a bit more fine-grained, with separate bits for each of these three
- *  functions.
- *
- *  More to the point, these functions make it obvious what libpng will be
- *  doing, whereas "expand" can (and does) mean any number of things.
- *
- *  GRP 20060307: In libpng-1.2.9, png_set_gray_1_2_4_to_8() was modified
- *  to expand only the sample depth but not to expand the tRNS to alpha
- *  and its name was changed to png_set_expand_gray_1_2_4_to_8().
- */
-
-/* Expand paletted images to RGB. */
-void PNGAPI
-png_set_palette_to_rgb(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_palette_to_rgb");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
-}
-
-/* Expand grayscale images of less than 8-bit depth to 8 bits. */
-void PNGAPI
-png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   png_ptr->transformations |= PNG_EXPAND;
-}
-
-/* Expand tRNS chunks to alpha channels. */
-void PNGAPI
-png_set_tRNS_to_alpha(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_tRNS_to_alpha");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
-}
-#endif /* READ_EXPAND */
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
-/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
- * it may not work correctly.)
- */
-void PNGAPI
-png_set_expand_16(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_expand_16");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
-}
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-void PNGAPI
-png_set_gray_to_rgb(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_gray_to_rgb");
-
-   if (png_rtran_ok(png_ptr, 0) == 0)
-      return;
-
-   /* Because rgb must be 8 bits or more: */
-   png_set_expand_gray_1_2_4_to_8(png_ptr);
-   png_ptr->transformations |= PNG_GRAY_TO_RGB;
-}
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-void PNGFAPI
-png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
-    png_fixed_point red, png_fixed_point green)
-{
-   png_debug(1, "in png_set_rgb_to_gray");
-
-   /* Need the IHDR here because of the check on color_type below. */
-   /* TODO: fix this */
-   if (png_rtran_ok(png_ptr, 1) == 0)
-      return;
-
-   switch (error_action)
-   {
-      case PNG_ERROR_ACTION_NONE:
-         png_ptr->transformations |= PNG_RGB_TO_GRAY;
-         break;
-
-      case PNG_ERROR_ACTION_WARN:
-         png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN;
-         break;
-
-      case PNG_ERROR_ACTION_ERROR:
-         png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR;
-         break;
-
-      default:
-         png_error(png_ptr, "invalid error action to rgb_to_gray");
-   }
-
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-#ifdef PNG_READ_EXPAND_SUPPORTED
-      png_ptr->transformations |= PNG_EXPAND;
-#else
-   {
-      /* Make this an error in 1.6 because otherwise the application may assume
-       * that it just worked and get a memory overwrite.
-       */
-      png_error(png_ptr,
-          "Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
-
-      /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
-   }
-#endif
-   {
-      if (red >= 0 && green >= 0 && red + green <= PNG_FP_1)
-      {
-         png_uint_16 red_int, green_int;
-
-         /* NOTE: this calculation does not round, but this behavior is retained
-          * for consistency; the inaccuracy is very small.  The code here always
-          * overwrites the coefficients, regardless of whether they have been
-          * defaulted or set already.
-          */
-         red_int = (png_uint_16)(((png_uint_32)red*32768)/100000);
-         green_int = (png_uint_16)(((png_uint_32)green*32768)/100000);
-
-         png_ptr->rgb_to_gray_red_coeff   = red_int;
-         png_ptr->rgb_to_gray_green_coeff = green_int;
-         png_ptr->rgb_to_gray_coefficients_set = 1;
-      }
-
-      else
-      {
-         if (red >= 0 && green >= 0)
-            png_app_warning(png_ptr,
-                "ignoring out of range rgb_to_gray coefficients");
-
-         /* Use the defaults, from the cHRM chunk if set, else the historical
-          * values which are close to the sRGB/HDTV/ITU-Rec 709 values.  See
-          * png_do_rgb_to_gray for more discussion of the values.  In this case
-          * the coefficients are not marked as 'set' and are not overwritten if
-          * something has already provided a default.
-          */
-         if (png_ptr->rgb_to_gray_red_coeff == 0 &&
-             png_ptr->rgb_to_gray_green_coeff == 0)
-         {
-            png_ptr->rgb_to_gray_red_coeff   = 6968;
-            png_ptr->rgb_to_gray_green_coeff = 23434;
-            /* png_ptr->rgb_to_gray_blue_coeff  = 2366; */
-         }
-      }
-   }
-}
-
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-/* Convert a RGB image to a grayscale of the same width.  This allows us,
- * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image.
- */
-
-void PNGAPI
-png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
-    double green)
-{
-   png_set_rgb_to_gray_fixed(png_ptr, error_action,
-       png_fixed(png_ptr, red, "rgb to gray red coefficient"),
-      png_fixed(png_ptr, green, "rgb to gray green coefficient"));
-}
-#endif /* FLOATING POINT */
-
-#endif /* RGB_TO_GRAY */
-
-#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
-    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
-void PNGAPI
-png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
-    read_user_transform_fn)
-{
-   png_debug(1, "in png_set_read_user_transform_fn");
-
-#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
-   png_ptr->transformations |= PNG_USER_TRANSFORM;
-   png_ptr->read_user_transform_fn = read_user_transform_fn;
-#endif
-}
-#endif
-
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-#ifdef PNG_READ_GAMMA_SUPPORTED
-/* In the case of gamma transformations only do transformations on images where
- * the [file] gamma and screen_gamma are not close reciprocals, otherwise it
- * slows things down slightly, and also needlessly introduces small errors.
- */
-static int /* PRIVATE */
-png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
-{
-   /* PNG_GAMMA_THRESHOLD is the threshold for performing gamma
-    * correction as a difference of the overall transform from 1.0
-    *
-    * We want to compare the threshold with s*f - 1, if we get
-    * overflow here it is because of wacky gamma values so we
-    * turn on processing anyway.
-    */
-   png_fixed_point gtest;
-   return !png_muldiv(&gtest, screen_gamma, file_gamma, PNG_FP_1) ||
-       png_gamma_significant(gtest);
-}
-#endif
-
-/* Initialize everything needed for the read.  This includes modifying
- * the palette.
- */
-
-/* For the moment 'png_init_palette_transformations' and
- * 'png_init_rgb_transformations' only do some flag canceling optimizations.
- * The intent is that these two routines should have palette or rgb operations
- * extracted from 'png_init_read_transformations'.
- */
-static void /* PRIVATE */
-png_init_palette_transformations(png_structrp png_ptr)
-{
-   /* Called to handle the (input) palette case.  In png_do_read_transformations
-    * the first step is to expand the palette if requested, so this code must
-    * take care to only make changes that are invariant with respect to the
-    * palette expansion, or only do them if there is no expansion.
-    *
-    * STRIP_ALPHA has already been handled in the caller (by setting num_trans
-    * to 0.)
-    */
-   int input_has_alpha = 0;
-   int input_has_transparency = 0;
-
-   if (png_ptr->num_trans > 0)
-   {
-      int i;
-
-      /* Ignore if all the entries are opaque (unlikely!) */
-      for (i=0; i<png_ptr->num_trans; ++i)
-      {
-         if (png_ptr->trans_alpha[i] == 255)
-            continue;
-         else if (png_ptr->trans_alpha[i] == 0)
-            input_has_transparency = 1;
-         else
-         {
-            input_has_transparency = 1;
-            input_has_alpha = 1;
-            break;
-         }
-      }
-   }
-
-   /* If no alpha we can optimize. */
-   if (input_has_alpha == 0)
-   {
-      /* Any alpha means background and associative alpha processing is
-       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
-       * and ENCODE_ALPHA are irrelevant.
-       */
-      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
-      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
-
-      if (input_has_transparency == 0)
-         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
-   }
-
-#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
-   /* png_set_background handling - deals with the complexity of whether the
-    * background color is in the file format or the screen format in the case
-    * where an 'expand' will happen.
-    */
-
-   /* The following code cannot be entered in the alpha pre-multiplication case
-    * because PNG_BACKGROUND_EXPAND is cancelled below.
-    */
-   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
-       (png_ptr->transformations & PNG_EXPAND) != 0)
-   {
-      {
-         png_ptr->background.red   =
-             png_ptr->palette[png_ptr->background.index].red;
-         png_ptr->background.green =
-             png_ptr->palette[png_ptr->background.index].green;
-         png_ptr->background.blue  =
-             png_ptr->palette[png_ptr->background.index].blue;
-
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-         if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
-         {
-            if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
-            {
-               /* Invert the alpha channel (in tRNS) unless the pixels are
-                * going to be expanded, in which case leave it for later
-                */
-               int i, istop = png_ptr->num_trans;
-
-               for (i = 0; i < istop; i++)
-                  png_ptr->trans_alpha[i] =
-                      (png_byte)(255 - png_ptr->trans_alpha[i]);
-            }
-         }
-#endif /* READ_INVERT_ALPHA */
-      }
-   } /* background expand and (therefore) no alpha association. */
-#endif /* READ_EXPAND && READ_BACKGROUND */
-}
-
-static void /* PRIVATE */
-png_init_rgb_transformations(png_structrp png_ptr)
-{
-   /* Added to libpng-1.5.4: check the color type to determine whether there
-    * is any alpha or transparency in the image and simply cancel the
-    * background and alpha mode stuff if there isn't.
-    */
-   int input_has_alpha = (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0;
-   int input_has_transparency = png_ptr->num_trans > 0;
-
-   /* If no alpha we can optimize. */
-   if (input_has_alpha == 0)
-   {
-      /* Any alpha means background and associative alpha processing is
-       * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
-       * and ENCODE_ALPHA are irrelevant.
-       */
-#     ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-         png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
-         png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
-#     endif
-
-      if (input_has_transparency == 0)
-         png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
-   }
-
-#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
-   /* png_set_background handling - deals with the complexity of whether the
-    * background color is in the file format or the screen format in the case
-    * where an 'expand' will happen.
-    */
-
-   /* The following code cannot be entered in the alpha pre-multiplication case
-    * because PNG_BACKGROUND_EXPAND is cancelled below.
-    */
-   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
-       (png_ptr->transformations & PNG_EXPAND) != 0 &&
-       (png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
-       /* i.e., GRAY or GRAY_ALPHA */
-   {
-      {
-         /* Expand background and tRNS chunks */
-         int gray = png_ptr->background.gray;
-         int trans_gray = png_ptr->trans_color.gray;
-
-         switch (png_ptr->bit_depth)
-         {
-            case 1:
-               gray *= 0xff;
-               trans_gray *= 0xff;
-               break;
-
-            case 2:
-               gray *= 0x55;
-               trans_gray *= 0x55;
-               break;
-
-            case 4:
-               gray *= 0x11;
-               trans_gray *= 0x11;
-               break;
-
-            default:
-
-            case 8:
-               /* FALLTHROUGH */ /*  (Already 8 bits) */
-
-            case 16:
-               /* Already a full 16 bits */
-               break;
-         }
-
-         png_ptr->background.red = png_ptr->background.green =
-            png_ptr->background.blue = (png_uint_16)gray;
-
-         if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
-         {
-            png_ptr->trans_color.red = png_ptr->trans_color.green =
-               png_ptr->trans_color.blue = (png_uint_16)trans_gray;
-         }
-      }
-   } /* background expand and (therefore) no alpha association. */
-#endif /* READ_EXPAND && READ_BACKGROUND */
-}
-
-void /* PRIVATE */
-png_init_read_transformations(png_structrp png_ptr)
-{
-   png_debug(1, "in png_init_read_transformations");
-
-   /* This internal function is called from png_read_start_row in pngrutil.c
-    * and it is called before the 'rowbytes' calculation is done, so the code
-    * in here can change or update the transformations flags.
-    *
-    * First do updates that do not depend on the details of the PNG image data
-    * being processed.
-    */
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-   /* Prior to 1.5.4 these tests were performed from png_set_gamma, 1.5.4 adds
-    * png_set_alpha_mode and this is another source for a default file gamma so
-    * the test needs to be performed later - here.  In addition prior to 1.5.4
-    * the tests were repeated for the PALETTE color type here - this is no
-    * longer necessary (and doesn't seem to have been necessary before.)
-    */
-   {
-      /* The following temporary indicates if overall gamma correction is
-       * required.
-       */
-      int gamma_correction = 0;
-
-      if (png_ptr->colorspace.gamma != 0) /* has been set */
-      {
-         if (png_ptr->screen_gamma != 0) /* screen set too */
-            gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
-                png_ptr->screen_gamma);
-
-         else
-            /* Assume the output matches the input; a long time default behavior
-             * of libpng, although the standard has nothing to say about this.
-             */
-            png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
-      }
-
-      else if (png_ptr->screen_gamma != 0)
-         /* The converse - assume the file matches the screen, note that this
-          * perhaps undesirable default can (from 1.5.4) be changed by calling
-          * png_set_alpha_mode (even if the alpha handling mode isn't required
-          * or isn't changed from the default.)
-          */
-         png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
-
-      else /* neither are set */
-         /* Just in case the following prevents any processing - file and screen
-          * are both assumed to be linear and there is no way to introduce a
-          * third gamma value other than png_set_background with 'UNIQUE', and,
-          * prior to 1.5.4
-          */
-         png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
-
-      /* We have a gamma value now. */
-      png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
-
-      /* Now turn the gamma transformation on or off as appropriate.  Notice
-       * that PNG_GAMMA just refers to the file->screen correction.  Alpha
-       * composition may independently cause gamma correction because it needs
-       * linear data (e.g. if the file has a gAMA chunk but the screen gamma
-       * hasn't been specified.)  In any case this flag may get turned off in
-       * the code immediately below if the transform can be handled outside the
-       * row loop.
-       */
-      if (gamma_correction != 0)
-         png_ptr->transformations |= PNG_GAMMA;
-
-      else
-         png_ptr->transformations &= ~PNG_GAMMA;
-   }
-#endif
-
-   /* Certain transformations have the effect of preventing other
-    * transformations that happen afterward in png_do_read_transformations;
-    * resolve the interdependencies here.  From the code of
-    * png_do_read_transformations the order is:
-    *
-    *  1) PNG_EXPAND (including PNG_EXPAND_tRNS)
-    *  2) PNG_STRIP_ALPHA (if no compose)
-    *  3) PNG_RGB_TO_GRAY
-    *  4) PNG_GRAY_TO_RGB iff !PNG_BACKGROUND_IS_GRAY
-    *  5) PNG_COMPOSE
-    *  6) PNG_GAMMA
-    *  7) PNG_STRIP_ALPHA (if compose)
-    *  8) PNG_ENCODE_ALPHA
-    *  9) PNG_SCALE_16_TO_8
-    * 10) PNG_16_TO_8
-    * 11) PNG_QUANTIZE (converts to palette)
-    * 12) PNG_EXPAND_16
-    * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
-    * 14) PNG_INVERT_MONO
-    * 15) PNG_INVERT_ALPHA
-    * 16) PNG_SHIFT
-    * 17) PNG_PACK
-    * 18) PNG_BGR
-    * 19) PNG_PACKSWAP
-    * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
-    * 21) PNG_SWAP_ALPHA
-    * 22) PNG_SWAP_BYTES
-    * 23) PNG_USER_TRANSFORM [must be last]
-    */
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
-       (png_ptr->transformations & PNG_COMPOSE) == 0)
-   {
-      /* Stripping the alpha channel happens immediately after the 'expand'
-       * transformations, before all other transformation, so it cancels out
-       * the alpha handling.  It has the side effect negating the effect of
-       * PNG_EXPAND_tRNS too:
-       */
-      png_ptr->transformations &= ~(PNG_BACKGROUND_EXPAND | PNG_ENCODE_ALPHA |
-         PNG_EXPAND_tRNS);
-      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
-
-      /* Kill the tRNS chunk itself too.  Prior to 1.5.4 this did not happen
-       * so transparency information would remain just so long as it wasn't
-       * expanded.  This produces unexpected API changes if the set of things
-       * that do PNG_EXPAND_tRNS changes (perfectly possible given the
-       * documentation - which says ask for what you want, accept what you
-       * get.)  This makes the behavior consistent from 1.5.4:
-       */
-      png_ptr->num_trans = 0;
-   }
-#endif /* STRIP_ALPHA supported, no COMPOSE */
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-   /* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
-    * settings will have no effect.
-    */
-   if (png_gamma_significant(png_ptr->screen_gamma) == 0)
-   {
-      png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
-      png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
-   }
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-   /* Make sure the coefficients for the rgb to gray conversion are set
-    * appropriately.
-    */
-   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
-      png_colorspace_set_rgb_coefficients(png_ptr);
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
-   /* Detect gray background and attempt to enable optimization for
-    * gray --> RGB case.
-    *
-    * Note:  if PNG_BACKGROUND_EXPAND is set and color_type is either RGB or
-    * RGB_ALPHA (in which case need_expand is superfluous anyway), the
-    * background color might actually be gray yet not be flagged as such.
-    * This is not a problem for the current code, which uses
-    * PNG_BACKGROUND_IS_GRAY only to decide when to do the
-    * png_do_gray_to_rgb() transformation.
-    *
-    * TODO: this code needs to be revised to avoid the complexity and
-    * interdependencies.  The color type of the background should be recorded in
-    * png_set_background, along with the bit depth, then the code has a record
-    * of exactly what color space the background is currently in.
-    */
-   if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
-   {
-      /* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
-       * the file was grayscale the background value is gray.
-       */
-      if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
-         png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
-   }
-
-   else if ((png_ptr->transformations & PNG_COMPOSE) != 0)
-   {
-      /* PNG_COMPOSE: png_set_background was called with need_expand false,
-       * so the color is in the color space of the output or png_set_alpha_mode
-       * was called and the color is black.  Ignore RGB_TO_GRAY because that
-       * happens before GRAY_TO_RGB.
-       */
-      if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
-      {
-         if (png_ptr->background.red == png_ptr->background.green &&
-             png_ptr->background.red == png_ptr->background.blue)
-         {
-            png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
-            png_ptr->background.gray = png_ptr->background.red;
-         }
-      }
-   }
-#endif /* READ_EXPAND && READ_BACKGROUND */
-#endif /* READ_GRAY_TO_RGB */
-
-   /* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
-    * can be performed directly on the palette, and some (such as rgb to gray)
-    * can be optimized inside the palette.  This is particularly true of the
-    * composite (background and alpha) stuff, which can be pretty much all done
-    * in the palette even if the result is expanded to RGB or gray afterward.
-    *
-    * NOTE: this is Not Yet Implemented, the code behaves as in 1.5.1 and
-    * earlier and the palette stuff is actually handled on the first row.  This
-    * leads to the reported bug that the palette returned by png_get_PLTE is not
-    * updated.
-    */
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      png_init_palette_transformations(png_ptr);
-
-   else
-      png_init_rgb_transformations(png_ptr);
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
-   defined(PNG_READ_EXPAND_16_SUPPORTED)
-   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
-       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
-       (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
-       png_ptr->bit_depth != 16)
-   {
-      /* TODO: fix this.  Because the expand_16 operation is after the compose
-       * handling the background color must be 8, not 16, bits deep, but the
-       * application will supply a 16-bit value so reduce it here.
-       *
-       * The PNG_BACKGROUND_EXPAND code above does not expand to 16 bits at
-       * present, so that case is ok (until do_expand_16 is moved.)
-       *
-       * NOTE: this discards the low 16 bits of the user supplied background
-       * color, but until expand_16 works properly there is no choice!
-       */
-#     define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
-      CHOP(png_ptr->background.red);
-      CHOP(png_ptr->background.green);
-      CHOP(png_ptr->background.blue);
-      CHOP(png_ptr->background.gray);
-#     undef CHOP
-   }
-#endif /* READ_BACKGROUND && READ_EXPAND_16 */
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
-   (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
-   defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
-   if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&
-       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
-       (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
-       png_ptr->bit_depth == 16)
-   {
-      /* On the other hand, if a 16-bit file is to be reduced to 8-bits per
-       * component this will also happen after PNG_COMPOSE and so the background
-       * color must be pre-expanded here.
-       *
-       * TODO: fix this too.
-       */
-      png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257);
-      png_ptr->background.green =
-         (png_uint_16)(png_ptr->background.green * 257);
-      png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257);
-      png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257);
-   }
-#endif
-
-   /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the
-    * background support (see the comments in scripts/pnglibconf.dfa), this
-    * allows pre-multiplication of the alpha channel to be implemented as
-    * compositing on black.  This is probably sub-optimal and has been done in
-    * 1.5.4 betas simply to enable external critique and testing (i.e. to
-    * implement the new API quickly, without lots of internal changes.)
-    */
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-#  ifdef PNG_READ_BACKGROUND_SUPPORTED
-      /* Includes ALPHA_MODE */
-      png_ptr->background_1 = png_ptr->background;
-#  endif
-
-   /* This needs to change - in the palette image case a whole set of tables are
-    * built when it would be quicker to just calculate the correct value for
-    * each palette entry directly.  Also, the test is too tricky - why check
-    * PNG_RGB_TO_GRAY if PNG_GAMMA is not set?  The answer seems to be that
-    * PNG_GAMMA is cancelled even if the gamma is known?  The test excludes the
-    * PNG_COMPOSE case, so apparently if there is no *overall* gamma correction
-    * the gamma tables will not be built even if composition is required on a
-    * gamma encoded value.
-    *
-    * In 1.5.4 this is addressed below by an additional check on the individual
-    * file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
-    * tables.
-    */
-   if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
-       ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
-        (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
-         png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
-        ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
-         (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
-          png_gamma_significant(png_ptr->screen_gamma) != 0
-#  ifdef PNG_READ_BACKGROUND_SUPPORTED
-         || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
-           png_gamma_significant(png_ptr->background_gamma) != 0)
-#  endif
-        )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
-       png_gamma_significant(png_ptr->screen_gamma) != 0))
-   {
-      png_build_gamma_table(png_ptr, png_ptr->bit_depth);
-
-#ifdef PNG_READ_BACKGROUND_SUPPORTED
-      if ((png_ptr->transformations & PNG_COMPOSE) != 0)
-      {
-         /* Issue a warning about this combination: because RGB_TO_GRAY is
-          * optimized to do the gamma transform if present yet do_background has
-          * to do the same thing if both options are set a
-          * double-gamma-correction happens.  This is true in all versions of
-          * libpng to date.
-          */
-         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
-            png_warning(png_ptr,
-                "libpng does not support gamma+background+rgb_to_gray");
-
-         if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
-         {
-            /* We don't get to here unless there is a tRNS chunk with non-opaque
-             * entries - see the checking code at the start of this function.
-             */
-            png_color back, back_1;
-            png_colorp palette = png_ptr->palette;
-            int num_palette = png_ptr->num_palette;
-            int i;
-            if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE)
-            {
-
-               back.red = png_ptr->gamma_table[png_ptr->background.red];
-               back.green = png_ptr->gamma_table[png_ptr->background.green];
-               back.blue = png_ptr->gamma_table[png_ptr->background.blue];
-
-               back_1.red = png_ptr->gamma_to_1[png_ptr->background.red];
-               back_1.green = png_ptr->gamma_to_1[png_ptr->background.green];
-               back_1.blue = png_ptr->gamma_to_1[png_ptr->background.blue];
-            }
-            else
-            {
-               png_fixed_point g, gs;
-
-               switch (png_ptr->background_gamma_type)
-               {
-                  case PNG_BACKGROUND_GAMMA_SCREEN:
-                     g = (png_ptr->screen_gamma);
-                     gs = PNG_FP_1;
-                     break;
-
-                  case PNG_BACKGROUND_GAMMA_FILE:
-                     g = png_reciprocal(png_ptr->colorspace.gamma);
-                     gs = png_reciprocal2(png_ptr->colorspace.gamma,
-                         png_ptr->screen_gamma);
-                     break;
-
-                  case PNG_BACKGROUND_GAMMA_UNIQUE:
-                     g = png_reciprocal(png_ptr->background_gamma);
-                     gs = png_reciprocal2(png_ptr->background_gamma,
-                         png_ptr->screen_gamma);
-                     break;
-                  default:
-                     g = PNG_FP_1;    /* back_1 */
-                     gs = PNG_FP_1;   /* back */
-                     break;
-               }
-
-               if (png_gamma_significant(gs) != 0)
-               {
-                  back.red = png_gamma_8bit_correct(png_ptr->background.red,
-                      gs);
-                  back.green = png_gamma_8bit_correct(png_ptr->background.green,
-                      gs);
-                  back.blue = png_gamma_8bit_correct(png_ptr->background.blue,
-                      gs);
-               }
-
-               else
-               {
-                  back.red   = (png_byte)png_ptr->background.red;
-                  back.green = (png_byte)png_ptr->background.green;
-                  back.blue  = (png_byte)png_ptr->background.blue;
-               }
-
-               if (png_gamma_significant(g) != 0)
-               {
-                  back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
-                      g);
-                  back_1.green = png_gamma_8bit_correct(
-                      png_ptr->background.green, g);
-                  back_1.blue = png_gamma_8bit_correct(png_ptr->background.blue,
-                      g);
-               }
-
-               else
-               {
-                  back_1.red   = (png_byte)png_ptr->background.red;
-                  back_1.green = (png_byte)png_ptr->background.green;
-                  back_1.blue  = (png_byte)png_ptr->background.blue;
-               }
-            }
-
-            for (i = 0; i < num_palette; i++)
-            {
-               if (i < (int)png_ptr->num_trans &&
-                   png_ptr->trans_alpha[i] != 0xff)
-               {
-                  if (png_ptr->trans_alpha[i] == 0)
-                  {
-                     palette[i] = back;
-                  }
-                  else /* if (png_ptr->trans_alpha[i] != 0xff) */
-                  {
-                     png_byte v, w;
-
-                     v = png_ptr->gamma_to_1[palette[i].red];
-                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.red);
-                     palette[i].red = png_ptr->gamma_from_1[w];
-
-                     v = png_ptr->gamma_to_1[palette[i].green];
-                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.green);
-                     palette[i].green = png_ptr->gamma_from_1[w];
-
-                     v = png_ptr->gamma_to_1[palette[i].blue];
-                     png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue);
-                     palette[i].blue = png_ptr->gamma_from_1[w];
-                  }
-               }
-               else
-               {
-                  palette[i].red = png_ptr->gamma_table[palette[i].red];
-                  palette[i].green = png_ptr->gamma_table[palette[i].green];
-                  palette[i].blue = png_ptr->gamma_table[palette[i].blue];
-               }
-            }
-
-            /* Prevent the transformations being done again.
-             *
-             * NOTE: this is highly dubious; it removes the transformations in
-             * place.  This seems inconsistent with the general treatment of the
-             * transformations elsewhere.
-             */
-            png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA);
-         } /* color_type == PNG_COLOR_TYPE_PALETTE */
-
-         /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */
-         else /* color_type != PNG_COLOR_TYPE_PALETTE */
-         {
-            int gs_sig, g_sig;
-            png_fixed_point g = PNG_FP_1;  /* Correction to linear */
-            png_fixed_point gs = PNG_FP_1; /* Correction to screen */
-
-            switch (png_ptr->background_gamma_type)
-            {
-               case PNG_BACKGROUND_GAMMA_SCREEN:
-                  g = png_ptr->screen_gamma;
-                  /* gs = PNG_FP_1; */
-                  break;
-
-               case PNG_BACKGROUND_GAMMA_FILE:
-                  g = png_reciprocal(png_ptr->colorspace.gamma);
-                  gs = png_reciprocal2(png_ptr->colorspace.gamma,
-                      png_ptr->screen_gamma);
-                  break;
-
-               case PNG_BACKGROUND_GAMMA_UNIQUE:
-                  g = png_reciprocal(png_ptr->background_gamma);
-                  gs = png_reciprocal2(png_ptr->background_gamma,
-                      png_ptr->screen_gamma);
-                  break;
-
-               default:
-                  png_error(png_ptr, "invalid background gamma type");
-            }
-
-            g_sig = png_gamma_significant(g);
-            gs_sig = png_gamma_significant(gs);
-
-            if (g_sig != 0)
-               png_ptr->background_1.gray = png_gamma_correct(png_ptr,
-                   png_ptr->background.gray, g);
-
-            if (gs_sig != 0)
-               png_ptr->background.gray = png_gamma_correct(png_ptr,
-                   png_ptr->background.gray, gs);
-
-            if ((png_ptr->background.red != png_ptr->background.green) ||
-                (png_ptr->background.red != png_ptr->background.blue) ||
-                (png_ptr->background.red != png_ptr->background.gray))
-            {
-               /* RGB or RGBA with color background */
-               if (g_sig != 0)
-               {
-                  png_ptr->background_1.red = png_gamma_correct(png_ptr,
-                      png_ptr->background.red, g);
-
-                  png_ptr->background_1.green = png_gamma_correct(png_ptr,
-                      png_ptr->background.green, g);
-
-                  png_ptr->background_1.blue = png_gamma_correct(png_ptr,
-                      png_ptr->background.blue, g);
-               }
-
-               if (gs_sig != 0)
-               {
-                  png_ptr->background.red = png_gamma_correct(png_ptr,
-                      png_ptr->background.red, gs);
-
-                  png_ptr->background.green = png_gamma_correct(png_ptr,
-                      png_ptr->background.green, gs);
-
-                  png_ptr->background.blue = png_gamma_correct(png_ptr,
-                      png_ptr->background.blue, gs);
-               }
-            }
-
-            else
-            {
-               /* GRAY, GRAY ALPHA, RGB, or RGBA with gray background */
-               png_ptr->background_1.red = png_ptr->background_1.green
-                   = png_ptr->background_1.blue = png_ptr->background_1.gray;
-
-               png_ptr->background.red = png_ptr->background.green
-                   = png_ptr->background.blue = png_ptr->background.gray;
-            }
-
-            /* The background is now in screen gamma: */
-            png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_SCREEN;
-         } /* color_type != PNG_COLOR_TYPE_PALETTE */
-      }/* png_ptr->transformations & PNG_BACKGROUND */
-
-      else
-      /* Transformation does not include PNG_BACKGROUND */
-#endif /* READ_BACKGROUND */
-      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-         /* RGB_TO_GRAY needs to have non-gamma-corrected values! */
-         && ((png_ptr->transformations & PNG_EXPAND) == 0 ||
-         (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
-#endif
-         )
-      {
-         png_colorp palette = png_ptr->palette;
-         int num_palette = png_ptr->num_palette;
-         int i;
-
-         /* NOTE: there are other transformations that should probably be in
-          * here too.
-          */
-         for (i = 0; i < num_palette; i++)
-         {
-            palette[i].red = png_ptr->gamma_table[palette[i].red];
-            palette[i].green = png_ptr->gamma_table[palette[i].green];
-            palette[i].blue = png_ptr->gamma_table[palette[i].blue];
-         }
-
-         /* Done the gamma correction. */
-         png_ptr->transformations &= ~PNG_GAMMA;
-      } /* color_type == PALETTE && !PNG_BACKGROUND transformation */
-   }
-#ifdef PNG_READ_BACKGROUND_SUPPORTED
-   else
-#endif
-#endif /* READ_GAMMA */
-
-#ifdef PNG_READ_BACKGROUND_SUPPORTED
-   /* No GAMMA transformation (see the hanging else 4 lines above) */
-   if ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
-       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
-   {
-      int i;
-      int istop = (int)png_ptr->num_trans;
-      png_color back;
-      png_colorp palette = png_ptr->palette;
-
-      back.red   = (png_byte)png_ptr->background.red;
-      back.green = (png_byte)png_ptr->background.green;
-      back.blue  = (png_byte)png_ptr->background.blue;
-
-      for (i = 0; i < istop; i++)
-      {
-         if (png_ptr->trans_alpha[i] == 0)
-         {
-            palette[i] = back;
-         }
-
-         else if (png_ptr->trans_alpha[i] != 0xff)
-         {
-            /* The png_composite() macro is defined in png.h */
-            png_composite(palette[i].red, palette[i].red,
-                png_ptr->trans_alpha[i], back.red);
-
-            png_composite(palette[i].green, palette[i].green,
-                png_ptr->trans_alpha[i], back.green);
-
-            png_composite(palette[i].blue, palette[i].blue,
-                png_ptr->trans_alpha[i], back.blue);
-         }
-      }
-
-      png_ptr->transformations &= ~PNG_COMPOSE;
-   }
-#endif /* READ_BACKGROUND */
-
-#ifdef PNG_READ_SHIFT_SUPPORTED
-   if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
-       (png_ptr->transformations & PNG_EXPAND) == 0 &&
-       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
-   {
-      int i;
-      int istop = png_ptr->num_palette;
-      int shift = 8 - png_ptr->sig_bit.red;
-
-      png_ptr->transformations &= ~PNG_SHIFT;
-
-      /* significant bits can be in the range 1 to 7 for a meaningful result, if
-       * the number of significant bits is 0 then no shift is done (this is an
-       * error condition which is silently ignored.)
-       */
-      if (shift > 0 && shift < 8)
-         for (i=0; i<istop; ++i)
-         {
-            int component = png_ptr->palette[i].red;
-
-            component >>= shift;
-            png_ptr->palette[i].red = (png_byte)component;
-         }
-
-      shift = 8 - png_ptr->sig_bit.green;
-      if (shift > 0 && shift < 8)
-         for (i=0; i<istop; ++i)
-         {
-            int component = png_ptr->palette[i].green;
-
-            component >>= shift;
-            png_ptr->palette[i].green = (png_byte)component;
-         }
-
-      shift = 8 - png_ptr->sig_bit.blue;
-      if (shift > 0 && shift < 8)
-         for (i=0; i<istop; ++i)
-         {
-            int component = png_ptr->palette[i].blue;
-
-            component >>= shift;
-            png_ptr->palette[i].blue = (png_byte)component;
-         }
-   }
-#endif /* READ_SHIFT */
-}
-
-/* Modify the info structure to reflect the transformations.  The
- * info should be updated so a PNG file could be written with it,
- * assuming the transformations result in valid PNG data.
- */
-void /* PRIVATE */
-png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
-{
-   png_debug(1, "in png_read_transform_info");
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
-   if ((png_ptr->transformations & PNG_EXPAND) != 0)
-   {
-      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      {
-         /* This check must match what actually happens in
-          * png_do_expand_palette; if it ever checks the tRNS chunk to see if
-          * it is all opaque we must do the same (at present it does not.)
-          */
-         if (png_ptr->num_trans > 0)
-            info_ptr->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
-
-         else
-            info_ptr->color_type = PNG_COLOR_TYPE_RGB;
-
-         info_ptr->bit_depth = 8;
-         info_ptr->num_trans = 0;
-
-         if (png_ptr->palette == NULL)
-            png_error (png_ptr, "Palette is NULL in indexed image");
-      }
-      else
-      {
-         if (png_ptr->num_trans != 0)
-         {
-            if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
-               info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
-         }
-         if (info_ptr->bit_depth < 8)
-            info_ptr->bit_depth = 8;
-
-         info_ptr->num_trans = 0;
-      }
-   }
-#endif
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
-   /* The following is almost certainly wrong unless the background value is in
-    * the screen space!
-    */
-   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
-      info_ptr->background = png_ptr->background;
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-   /* The following used to be conditional on PNG_GAMMA (prior to 1.5.4),
-    * however it seems that the code in png_init_read_transformations, which has
-    * been called before this from png_read_update_info->png_read_start_row
-    * sometimes does the gamma transform and cancels the flag.
-    *
-    * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
-    * the screen_gamma value.  The following probably results in weirdness if
-    * the info_ptr is used by the app after the rows have been read.
-    */
-   info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
-#endif
-
-   if (info_ptr->bit_depth == 16)
-   {
-#  ifdef PNG_READ_16BIT_SUPPORTED
-#     ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
-         if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
-            info_ptr->bit_depth = 8;
-#     endif
-
-#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-         if ((png_ptr->transformations & PNG_16_TO_8) != 0)
-            info_ptr->bit_depth = 8;
-#     endif
-
-#  else
-      /* No 16-bit support: force chopping 16-bit input down to 8, in this case
-       * the app program can chose if both APIs are available by setting the
-       * correct scaling to use.
-       */
-#     ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-         /* For compatibility with previous versions use the strip method by
-          * default.  This code works because if PNG_SCALE_16_TO_8 is already
-          * set the code below will do that in preference to the chop.
-          */
-         png_ptr->transformations |= PNG_16_TO_8;
-         info_ptr->bit_depth = 8;
-#     else
-
-#        ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
-            png_ptr->transformations |= PNG_SCALE_16_TO_8;
-            info_ptr->bit_depth = 8;
-#        else
-
-            CONFIGURATION ERROR: you must enable at least one 16 to 8 method
-#        endif
-#    endif
-#endif /* !READ_16BIT */
-   }
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
-      info_ptr->color_type = (png_byte)(info_ptr->color_type |
-         PNG_COLOR_MASK_COLOR);
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
-      info_ptr->color_type = (png_byte)(info_ptr->color_type &
-         ~PNG_COLOR_MASK_COLOR);
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
-   {
-      if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
-          (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
-          png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)
-      {
-         info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
-      }
-   }
-#endif
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
-   if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
-       info_ptr->bit_depth == 8 &&
-       info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
-   {
-      info_ptr->bit_depth = 16;
-   }
-#endif
-
-#ifdef PNG_READ_PACK_SUPPORTED
-   if ((png_ptr->transformations & PNG_PACK) != 0 &&
-       (info_ptr->bit_depth < 8))
-      info_ptr->bit_depth = 8;
-#endif
-
-   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      info_ptr->channels = 1;
-
-   else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
-      info_ptr->channels = 3;
-
-   else
-      info_ptr->channels = 1;
-
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)
-   {
-      info_ptr->color_type = (png_byte)(info_ptr->color_type &
-         ~PNG_COLOR_MASK_ALPHA);
-      info_ptr->num_trans = 0;
-   }
-#endif
-
-   if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
-      info_ptr->channels++;
-
-#ifdef PNG_READ_FILLER_SUPPORTED
-   /* STRIP_ALPHA and FILLER allowed:  MASK_ALPHA bit stripped above */
-   if ((png_ptr->transformations & PNG_FILLER) != 0 &&
-       (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
-       info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
-   {
-      info_ptr->channels++;
-      /* If adding a true alpha channel not just filler */
-      if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0)
-         info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
-   }
-#endif
-
-#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
-defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
-   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
-   {
-      if (png_ptr->user_transform_depth != 0)
-         info_ptr->bit_depth = png_ptr->user_transform_depth;
-
-      if (png_ptr->user_transform_channels != 0)
-         info_ptr->channels = png_ptr->user_transform_channels;
-   }
-#endif
-
-   info_ptr->pixel_depth = (png_byte)(info_ptr->channels *
-       info_ptr->bit_depth);
-
-   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, info_ptr->width);
-
-   /* Adding in 1.5.4: cache the above value in png_struct so that we can later
-    * check in png_rowbytes that the user buffer won't get overwritten.  Note
-    * that the field is not always set - if png_read_update_info isn't called
-    * the application has to either not do any transforms or get the calculation
-    * right itself.
-    */
-   png_ptr->info_rowbytes = info_ptr->rowbytes;
-
-#ifndef PNG_READ_EXPAND_SUPPORTED
-   if (png_ptr != NULL)
-      return;
-#endif
-}
-
-#ifdef PNG_READ_PACK_SUPPORTED
-/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
- * without changing the actual values.  Thus, if you had a row with
- * a bit depth of 1, you would end up with bytes that only contained
- * the numbers 0 or 1.  If you would rather they contain 0 and 255, use
- * png_do_shift() after this.
- */
-static void
-png_do_unpack(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_unpack");
-
-   if (row_info->bit_depth < 8)
-   {
-      png_uint_32 i;
-      png_uint_32 row_width=row_info->width;
-
-      switch (row_info->bit_depth)
-      {
-         case 1:
-         {
-            png_bytep sp = row + (size_t)((row_width - 1) >> 3);
-            png_bytep dp = row + (size_t)row_width - 1;
-            png_uint_32 shift = 7U - ((row_width + 7U) & 0x07);
-            for (i = 0; i < row_width; i++)
-            {
-               *dp = (png_byte)((*sp >> shift) & 0x01);
-
-               if (shift == 7)
-               {
-                  shift = 0;
-                  sp--;
-               }
-
-               else
-                  shift++;
-
-               dp--;
-            }
-            break;
-         }
-
-         case 2:
-         {
-
-            png_bytep sp = row + (size_t)((row_width - 1) >> 2);
-            png_bytep dp = row + (size_t)row_width - 1;
-            png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1);
-            for (i = 0; i < row_width; i++)
-            {
-               *dp = (png_byte)((*sp >> shift) & 0x03);
-
-               if (shift == 6)
-               {
-                  shift = 0;
-                  sp--;
-               }
-
-               else
-                  shift += 2;
-
-               dp--;
-            }
-            break;
-         }
-
-         case 4:
-         {
-            png_bytep sp = row + (size_t)((row_width - 1) >> 1);
-            png_bytep dp = row + (size_t)row_width - 1;
-            png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2);
-            for (i = 0; i < row_width; i++)
-            {
-               *dp = (png_byte)((*sp >> shift) & 0x0f);
-
-               if (shift == 4)
-               {
-                  shift = 0;
-                  sp--;
-               }
-
-               else
-                  shift = 4;
-
-               dp--;
-            }
-            break;
-         }
-
-         default:
-            break;
-      }
-      row_info->bit_depth = 8;
-      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
-      row_info->rowbytes = row_width * row_info->channels;
-   }
-}
-#endif
-
-#ifdef PNG_READ_SHIFT_SUPPORTED
-/* Reverse the effects of png_do_shift.  This routine merely shifts the
- * pixels back to their significant bits values.  Thus, if you have
- * a row of bit depth 8, but only 5 are significant, this will shift
- * the values back to 0 through 31.
- */
-static void
-png_do_unshift(png_row_infop row_info, png_bytep row,
-    png_const_color_8p sig_bits)
-{
-   int color_type;
-
-   png_debug(1, "in png_do_unshift");
-
-   /* The palette case has already been handled in the _init routine. */
-   color_type = row_info->color_type;
-
-   if (color_type != PNG_COLOR_TYPE_PALETTE)
-   {
-      int shift[4];
-      int channels = 0;
-      int bit_depth = row_info->bit_depth;
-
-      if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
-      {
-         shift[channels++] = bit_depth - sig_bits->red;
-         shift[channels++] = bit_depth - sig_bits->green;
-         shift[channels++] = bit_depth - sig_bits->blue;
-      }
-
-      else
-      {
-         shift[channels++] = bit_depth - sig_bits->gray;
-      }
-
-      if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
-      {
-         shift[channels++] = bit_depth - sig_bits->alpha;
-      }
-
-      {
-         int c, have_shift;
-
-         for (c = have_shift = 0; c < channels; ++c)
-         {
-            /* A shift of more than the bit depth is an error condition but it
-             * gets ignored here.
-             */
-            if (shift[c] <= 0 || shift[c] >= bit_depth)
-               shift[c] = 0;
-
-            else
-               have_shift = 1;
-         }
-
-         if (have_shift == 0)
-            return;
-      }
-
-      switch (bit_depth)
-      {
-         default:
-         /* Must be 1bpp gray: should not be here! */
-            /* NOTREACHED */
-            break;
-
-         case 2:
-         /* Must be 2bpp gray */
-         /* assert(channels == 1 && shift[0] == 1) */
-         {
-            png_bytep bp = row;
-            png_bytep bp_end = bp + row_info->rowbytes;
-
-            while (bp < bp_end)
-            {
-               int b = (*bp >> 1) & 0x55;
-               *bp++ = (png_byte)b;
-            }
-            break;
-         }
-
-         case 4:
-         /* Must be 4bpp gray */
-         /* assert(channels == 1) */
-         {
-            png_bytep bp = row;
-            png_bytep bp_end = bp + row_info->rowbytes;
-            int gray_shift = shift[0];
-            int mask =  0xf >> gray_shift;
-
-            mask |= mask << 4;
-
-            while (bp < bp_end)
-            {
-               int b = (*bp >> gray_shift) & mask;
-               *bp++ = (png_byte)b;
-            }
-            break;
-         }
-
-         case 8:
-         /* Single byte components, G, GA, RGB, RGBA */
-         {
-            png_bytep bp = row;
-            png_bytep bp_end = bp + row_info->rowbytes;
-            int channel = 0;
-
-            while (bp < bp_end)
-            {
-               int b = *bp >> shift[channel];
-               if (++channel >= channels)
-                  channel = 0;
-               *bp++ = (png_byte)b;
-            }
-            break;
-         }
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-         case 16:
-         /* Double byte components, G, GA, RGB, RGBA */
-         {
-            png_bytep bp = row;
-            png_bytep bp_end = bp + row_info->rowbytes;
-            int channel = 0;
-
-            while (bp < bp_end)
-            {
-               int value = (bp[0] << 8) + bp[1];
-
-               value >>= shift[channel];
-               if (++channel >= channels)
-                  channel = 0;
-               *bp++ = (png_byte)(value >> 8);
-               *bp++ = (png_byte)value;
-            }
-            break;
-         }
-#endif
-      }
-   }
-}
-#endif
-
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
-/* Scale rows of bit depth 16 down to 8 accurately */
-static void
-png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_scale_16_to_8");
-
-   if (row_info->bit_depth == 16)
-   {
-      png_bytep sp = row; /* source */
-      png_bytep dp = row; /* destination */
-      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
-
-      while (sp < ep)
-      {
-         /* The input is an array of 16-bit components, these must be scaled to
-          * 8 bits each.  For a 16-bit value V the required value (from the PNG
-          * specification) is:
-          *
-          *    (V * 255) / 65535
-          *
-          * This reduces to round(V / 257), or floor((V + 128.5)/257)
-          *
-          * Represent V as the two byte value vhi.vlo.  Make a guess that the
-          * result is the top byte of V, vhi, then the correction to this value
-          * is:
-          *
-          *    error = floor(((V-vhi.vhi) + 128.5) / 257)
-          *          = floor(((vlo-vhi) + 128.5) / 257)
-          *
-          * This can be approximated using integer arithmetic (and a signed
-          * shift):
-          *
-          *    error = (vlo-vhi+128) >> 8;
-          *
-          * The approximate differs from the exact answer only when (vlo-vhi) is
-          * 128; it then gives a correction of +1 when the exact correction is
-          * 0.  This gives 128 errors.  The exact answer (correct for all 16-bit
-          * input values) is:
-          *
-          *    error = (vlo-vhi+128)*65535 >> 24;
-          *
-          * An alternative arithmetic calculation which also gives no errors is:
-          *
-          *    (V * 255 + 32895) >> 16
-          */
-
-         png_int_32 tmp = *sp++; /* must be signed! */
-         tmp += (((int)*sp++ - tmp + 128) * 65535) >> 24;
-         *dp++ = (png_byte)tmp;
-      }
-
-      row_info->bit_depth = 8;
-      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
-      row_info->rowbytes = row_info->width * row_info->channels;
-   }
-}
-#endif
-
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-static void
-/* Simply discard the low byte.  This was the default behavior prior
- * to libpng-1.5.4.
- */
-png_do_chop(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_chop");
-
-   if (row_info->bit_depth == 16)
-   {
-      png_bytep sp = row; /* source */
-      png_bytep dp = row; /* destination */
-      png_bytep ep = sp + row_info->rowbytes; /* end+1 */
-
-      while (sp < ep)
-      {
-         *dp++ = *sp;
-         sp += 2; /* skip low byte */
-      }
-
-      row_info->bit_depth = 8;
-      row_info->pixel_depth = (png_byte)(8 * row_info->channels);
-      row_info->rowbytes = row_info->width * row_info->channels;
-   }
-}
-#endif
-
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
-static void
-png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
-{
-   png_uint_32 row_width = row_info->width;
-
-   png_debug(1, "in png_do_read_swap_alpha");
-
-   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-   {
-      /* This converts from RGBA to ARGB */
-      if (row_info->bit_depth == 8)
-      {
-         png_bytep sp = row + row_info->rowbytes;
-         png_bytep dp = sp;
-         png_byte save;
-         png_uint_32 i;
-
-         for (i = 0; i < row_width; i++)
-         {
-            save = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = save;
-         }
-      }
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-      /* This converts from RRGGBBAA to AARRGGBB */
-      else
-      {
-         png_bytep sp = row + row_info->rowbytes;
-         png_bytep dp = sp;
-         png_byte save[2];
-         png_uint_32 i;
-
-         for (i = 0; i < row_width; i++)
-         {
-            save[0] = *(--sp);
-            save[1] = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = save[0];
-            *(--dp) = save[1];
-         }
-      }
-#endif
-   }
-
-   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-   {
-      /* This converts from GA to AG */
-      if (row_info->bit_depth == 8)
-      {
-         png_bytep sp = row + row_info->rowbytes;
-         png_bytep dp = sp;
-         png_byte save;
-         png_uint_32 i;
-
-         for (i = 0; i < row_width; i++)
-         {
-            save = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = save;
-         }
-      }
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-      /* This converts from GGAA to AAGG */
-      else
-      {
-         png_bytep sp = row + row_info->rowbytes;
-         png_bytep dp = sp;
-         png_byte save[2];
-         png_uint_32 i;
-
-         for (i = 0; i < row_width; i++)
-         {
-            save[0] = *(--sp);
-            save[1] = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = save[0];
-            *(--dp) = save[1];
-         }
-      }
-#endif
-   }
-}
-#endif
-
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-static void
-png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
-{
-   png_uint_32 row_width;
-   png_debug(1, "in png_do_read_invert_alpha");
-
-   row_width = row_info->width;
-   if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-   {
-      if (row_info->bit_depth == 8)
-      {
-         /* This inverts the alpha channel in RGBA */
-         png_bytep sp = row + row_info->rowbytes;
-         png_bytep dp = sp;
-         png_uint_32 i;
-
-         for (i = 0; i < row_width; i++)
-         {
-            *(--dp) = (png_byte)(255 - *(--sp));
-
-/*          This does nothing:
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            We can replace it with:
-*/
-            sp-=3;
-            dp=sp;
-         }
-      }
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-      /* This inverts the alpha channel in RRGGBBAA */
-      else
-      {
-         png_bytep sp = row + row_info->rowbytes;
-         png_bytep dp = sp;
-         png_uint_32 i;
-
-         for (i = 0; i < row_width; i++)
-         {
-            *(--dp) = (png_byte)(255 - *(--sp));
-            *(--dp) = (png_byte)(255 - *(--sp));
-
-/*          This does nothing:
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-            We can replace it with:
-*/
-            sp-=6;
-            dp=sp;
-         }
-      }
-#endif
-   }
-   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-   {
-      if (row_info->bit_depth == 8)
-      {
-         /* This inverts the alpha channel in GA */
-         png_bytep sp = row + row_info->rowbytes;
-         png_bytep dp = sp;
-         png_uint_32 i;
-
-         for (i = 0; i < row_width; i++)
-         {
-            *(--dp) = (png_byte)(255 - *(--sp));
-            *(--dp) = *(--sp);
-         }
-      }
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-      else
-      {
-         /* This inverts the alpha channel in GGAA */
-         png_bytep sp  = row + row_info->rowbytes;
-         png_bytep dp = sp;
-         png_uint_32 i;
-
-         for (i = 0; i < row_width; i++)
-         {
-            *(--dp) = (png_byte)(255 - *(--sp));
-            *(--dp) = (png_byte)(255 - *(--sp));
-/*
-            *(--dp) = *(--sp);
-            *(--dp) = *(--sp);
-*/
-            sp-=2;
-            dp=sp;
-         }
-      }
-#endif
-   }
-}
-#endif
-
-#ifdef PNG_READ_FILLER_SUPPORTED
-/* Add filler channel if we have RGB color */
-static void
-png_do_read_filler(png_row_infop row_info, png_bytep row,
-    png_uint_32 filler, png_uint_32 flags)
-{
-   png_uint_32 i;
-   png_uint_32 row_width = row_info->width;
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-   png_byte hi_filler = (png_byte)(filler>>8);
-#endif
-   png_byte lo_filler = (png_byte)filler;
-
-   png_debug(1, "in png_do_read_filler");
-
-   if (
-       row_info->color_type == PNG_COLOR_TYPE_GRAY)
-   {
-      if (row_info->bit_depth == 8)
-      {
-         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
-         {
-            /* This changes the data from G to GX */
-            png_bytep sp = row + (size_t)row_width;
-            png_bytep dp =  sp + (size_t)row_width;
-            for (i = 1; i < row_width; i++)
-            {
-               *(--dp) = lo_filler;
-               *(--dp) = *(--sp);
-            }
-            *(--dp) = lo_filler;
-            row_info->channels = 2;
-            row_info->pixel_depth = 16;
-            row_info->rowbytes = row_width * 2;
-         }
-
-         else
-         {
-            /* This changes the data from G to XG */
-            png_bytep sp = row + (size_t)row_width;
-            png_bytep dp = sp  + (size_t)row_width;
-            for (i = 0; i < row_width; i++)
-            {
-               *(--dp) = *(--sp);
-               *(--dp) = lo_filler;
-            }
-            row_info->channels = 2;
-            row_info->pixel_depth = 16;
-            row_info->rowbytes = row_width * 2;
-         }
-      }
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-      else if (row_info->bit_depth == 16)
-      {
-         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
-         {
-            /* This changes the data from GG to GGXX */
-            png_bytep sp = row + (size_t)row_width * 2;
-            png_bytep dp = sp  + (size_t)row_width * 2;
-            for (i = 1; i < row_width; i++)
-            {
-               *(--dp) = lo_filler;
-               *(--dp) = hi_filler;
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-            }
-            *(--dp) = lo_filler;
-            *(--dp) = hi_filler;
-            row_info->channels = 2;
-            row_info->pixel_depth = 32;
-            row_info->rowbytes = row_width * 4;
-         }
-
-         else
-         {
-            /* This changes the data from GG to XXGG */
-            png_bytep sp = row + (size_t)row_width * 2;
-            png_bytep dp = sp  + (size_t)row_width * 2;
-            for (i = 0; i < row_width; i++)
-            {
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = lo_filler;
-               *(--dp) = hi_filler;
-            }
-            row_info->channels = 2;
-            row_info->pixel_depth = 32;
-            row_info->rowbytes = row_width * 4;
-         }
-      }
-#endif
-   } /* COLOR_TYPE == GRAY */
-   else if (row_info->color_type == PNG_COLOR_TYPE_RGB)
-   {
-      if (row_info->bit_depth == 8)
-      {
-         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
-         {
-            /* This changes the data from RGB to RGBX */
-            png_bytep sp = row + (size_t)row_width * 3;
-            png_bytep dp = sp  + (size_t)row_width;
-            for (i = 1; i < row_width; i++)
-            {
-               *(--dp) = lo_filler;
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-            }
-            *(--dp) = lo_filler;
-            row_info->channels = 4;
-            row_info->pixel_depth = 32;
-            row_info->rowbytes = row_width * 4;
-         }
-
-         else
-         {
-            /* This changes the data from RGB to XRGB */
-            png_bytep sp = row + (size_t)row_width * 3;
-            png_bytep dp = sp + (size_t)row_width;
-            for (i = 0; i < row_width; i++)
-            {
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = lo_filler;
-            }
-            row_info->channels = 4;
-            row_info->pixel_depth = 32;
-            row_info->rowbytes = row_width * 4;
-         }
-      }
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-      else if (row_info->bit_depth == 16)
-      {
-         if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
-         {
-            /* This changes the data from RRGGBB to RRGGBBXX */
-            png_bytep sp = row + (size_t)row_width * 6;
-            png_bytep dp = sp  + (size_t)row_width * 2;
-            for (i = 1; i < row_width; i++)
-            {
-               *(--dp) = lo_filler;
-               *(--dp) = hi_filler;
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-            }
-            *(--dp) = lo_filler;
-            *(--dp) = hi_filler;
-            row_info->channels = 4;
-            row_info->pixel_depth = 64;
-            row_info->rowbytes = row_width * 8;
-         }
-
-         else
-         {
-            /* This changes the data from RRGGBB to XXRRGGBB */
-            png_bytep sp = row + (size_t)row_width * 6;
-            png_bytep dp = sp  + (size_t)row_width * 2;
-            for (i = 0; i < row_width; i++)
-            {
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = *(--sp);
-               *(--dp) = lo_filler;
-               *(--dp) = hi_filler;
-            }
-
-            row_info->channels = 4;
-            row_info->pixel_depth = 64;
-            row_info->rowbytes = row_width * 8;
-         }
-      }
-#endif
-   } /* COLOR_TYPE == RGB */
-}
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-/* Expand grayscale files to RGB, with or without alpha */
-static void
-png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
-{
-   png_uint_32 i;
-   png_uint_32 row_width = row_info->width;
-
-   png_debug(1, "in png_do_gray_to_rgb");
-
-   if (row_info->bit_depth >= 8 &&
-       (row_info->color_type & PNG_COLOR_MASK_COLOR) == 0)
-   {
-      if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
-      {
-         if (row_info->bit_depth == 8)
-         {
-            /* This changes G to RGB */
-            png_bytep sp = row + (size_t)row_width - 1;
-            png_bytep dp = sp  + (size_t)row_width * 2;
-            for (i = 0; i < row_width; i++)
-            {
-               *(dp--) = *sp;
-               *(dp--) = *sp;
-               *(dp--) = *(sp--);
-            }
-         }
-
-         else
-         {
-            /* This changes GG to RRGGBB */
-            png_bytep sp = row + (size_t)row_width * 2 - 1;
-            png_bytep dp = sp  + (size_t)row_width * 4;
-            for (i = 0; i < row_width; i++)
-            {
-               *(dp--) = *sp;
-               *(dp--) = *(sp - 1);
-               *(dp--) = *sp;
-               *(dp--) = *(sp - 1);
-               *(dp--) = *(sp--);
-               *(dp--) = *(sp--);
-            }
-         }
-      }
-
-      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-      {
-         if (row_info->bit_depth == 8)
-         {
-            /* This changes GA to RGBA */
-            png_bytep sp = row + (size_t)row_width * 2 - 1;
-            png_bytep dp = sp  + (size_t)row_width * 2;
-            for (i = 0; i < row_width; i++)
-            {
-               *(dp--) = *(sp--);
-               *(dp--) = *sp;
-               *(dp--) = *sp;
-               *(dp--) = *(sp--);
-            }
-         }
-
-         else
-         {
-            /* This changes GGAA to RRGGBBAA */
-            png_bytep sp = row + (size_t)row_width * 4 - 1;
-            png_bytep dp = sp  + (size_t)row_width * 4;
-            for (i = 0; i < row_width; i++)
-            {
-               *(dp--) = *(sp--);
-               *(dp--) = *(sp--);
-               *(dp--) = *sp;
-               *(dp--) = *(sp - 1);
-               *(dp--) = *sp;
-               *(dp--) = *(sp - 1);
-               *(dp--) = *(sp--);
-               *(dp--) = *(sp--);
-            }
-         }
-      }
-      row_info->channels = (png_byte)(row_info->channels + 2);
-      row_info->color_type |= PNG_COLOR_MASK_COLOR;
-      row_info->pixel_depth = (png_byte)(row_info->channels *
-          row_info->bit_depth);
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
-   }
-}
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-/* Reduce RGB files to grayscale, with or without alpha
- * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
- * <http://www.inforamp.net/~poynton/>  (THIS LINK IS DEAD June 2008 but
- * versions dated 1998 through November 2002 have been archived at
- * https://web.archive.org/web/20000816232553/www.inforamp.net/
- * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
- * Charles Poynton poynton at poynton.com
- *
- *     Y = 0.212671 * R + 0.715160 * G + 0.072169 * B
- *
- *  which can be expressed with integers as
- *
- *     Y = (6969 * R + 23434 * G + 2365 * B)/32768
- *
- * Poynton's current link (as of January 2003 through July 2011):
- * <http://www.poynton.com/notes/colour_and_gamma/>
- * has changed the numbers slightly:
- *
- *     Y = 0.2126*R + 0.7152*G + 0.0722*B
- *
- *  which can be expressed with integers as
- *
- *     Y = (6966 * R + 23436 * G + 2366 * B)/32768
- *
- *  Historically, however, libpng uses numbers derived from the ITU-R Rec 709
- *  end point chromaticities and the D65 white point.  Depending on the
- *  precision used for the D65 white point this produces a variety of different
- *  numbers, however if the four decimal place value used in ITU-R Rec 709 is
- *  used (0.3127,0.3290) the Y calculation would be:
- *
- *     Y = (6968 * R + 23435 * G + 2366 * B)/32768
- *
- *  While this is correct the rounding results in an overflow for white, because
- *  the sum of the rounded coefficients is 32769, not 32768.  Consequently
- *  libpng uses, instead, the closest non-overflowing approximation:
- *
- *     Y = (6968 * R + 23434 * G + 2366 * B)/32768
- *
- *  Starting with libpng-1.5.5, if the image being converted has a cHRM chunk
- *  (including an sRGB chunk) then the chromaticities are used to calculate the
- *  coefficients.  See the chunk handling in pngrutil.c for more information.
- *
- *  In all cases the calculation is to be done in a linear colorspace.  If no
- *  gamma information is available to correct the encoding of the original RGB
- *  values this results in an implicit assumption that the original PNG RGB
- *  values were linear.
- *
- *  Other integer coefficients can be used via png_set_rgb_to_gray().  Because
- *  the API takes just red and green coefficients the blue coefficient is
- *  calculated to make the sum 32768.  This will result in different rounding
- *  to that used above.
- */
-static int
-png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
-{
-   int rgb_error = 0;
-
-   png_debug(1, "in png_do_rgb_to_gray");
-
-   if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
-       (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
-   {
-      png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
-      png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
-      png_uint_32 bc = 32768 - rc - gc;
-      png_uint_32 row_width = row_info->width;
-      int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
-
-      if (row_info->bit_depth == 8)
-      {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-         /* Notice that gamma to/from 1 are not necessarily inverses (if
-          * there is an overall gamma correction).  Prior to 1.5.5 this code
-          * checked the linearized values for equality; this doesn't match
-          * the documentation, the original values must be checked.
-          */
-         if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL)
-         {
-            png_bytep sp = row;
-            png_bytep dp = row;
-            png_uint_32 i;
-
-            for (i = 0; i < row_width; i++)
-            {
-               png_byte red   = *(sp++);
-               png_byte green = *(sp++);
-               png_byte blue  = *(sp++);
-
-               if (red != green || red != blue)
-               {
-                  red = png_ptr->gamma_to_1[red];
-                  green = png_ptr->gamma_to_1[green];
-                  blue = png_ptr->gamma_to_1[blue];
-
-                  rgb_error |= 1;
-                  *(dp++) = png_ptr->gamma_from_1[
-                      (rc*red + gc*green + bc*blue + 16384)>>15];
-               }
-
-               else
-               {
-                  /* If there is no overall correction the table will not be
-                   * set.
-                   */
-                  if (png_ptr->gamma_table != NULL)
-                     red = png_ptr->gamma_table[red];
-
-                  *(dp++) = red;
-               }
-
-               if (have_alpha != 0)
-                  *(dp++) = *(sp++);
-            }
-         }
-         else
-#endif
-         {
-            png_bytep sp = row;
-            png_bytep dp = row;
-            png_uint_32 i;
-
-            for (i = 0; i < row_width; i++)
-            {
-               png_byte red   = *(sp++);
-               png_byte green = *(sp++);
-               png_byte blue  = *(sp++);
-
-               if (red != green || red != blue)
-               {
-                  rgb_error |= 1;
-                  /* NOTE: this is the historical approach which simply
-                   * truncates the results.
-                   */
-                  *(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
-               }
-
-               else
-                  *(dp++) = red;
-
-               if (have_alpha != 0)
-                  *(dp++) = *(sp++);
-            }
-         }
-      }
-
-      else /* RGB bit_depth == 16 */
-      {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-         if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
-         {
-            png_bytep sp = row;
-            png_bytep dp = row;
-            png_uint_32 i;
-
-            for (i = 0; i < row_width; i++)
-            {
-               png_uint_16 red, green, blue, w;
-               png_byte hi,lo;
-
-               hi=*(sp)++; lo=*(sp)++; red   = (png_uint_16)((hi << 8) | (lo));
-               hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
-               hi=*(sp)++; lo=*(sp)++; blue  = (png_uint_16)((hi << 8) | (lo));
-
-               if (red == green && red == blue)
-               {
-                  if (png_ptr->gamma_16_table != NULL)
-                     w = png_ptr->gamma_16_table[(red & 0xff)
-                         >> png_ptr->gamma_shift][red >> 8];
-
-                  else
-                     w = red;
-               }
-
-               else
-               {
-                  png_uint_16 red_1   = png_ptr->gamma_16_to_1[(red & 0xff)
-                      >> png_ptr->gamma_shift][red>>8];
-                  png_uint_16 green_1 =
-                      png_ptr->gamma_16_to_1[(green & 0xff) >>
-                      png_ptr->gamma_shift][green>>8];
-                  png_uint_16 blue_1  = png_ptr->gamma_16_to_1[(blue & 0xff)
-                      >> png_ptr->gamma_shift][blue>>8];
-                  png_uint_16 gray16  = (png_uint_16)((rc*red_1 + gc*green_1
-                      + bc*blue_1 + 16384)>>15);
-                  w = png_ptr->gamma_16_from_1[(gray16 & 0xff) >>
-                      png_ptr->gamma_shift][gray16 >> 8];
-                  rgb_error |= 1;
-               }
-
-               *(dp++) = (png_byte)((w>>8) & 0xff);
-               *(dp++) = (png_byte)(w & 0xff);
-
-               if (have_alpha != 0)
-               {
-                  *(dp++) = *(sp++);
-                  *(dp++) = *(sp++);
-               }
-            }
-         }
-         else
-#endif
-         {
-            png_bytep sp = row;
-            png_bytep dp = row;
-            png_uint_32 i;
-
-            for (i = 0; i < row_width; i++)
-            {
-               png_uint_16 red, green, blue, gray16;
-               png_byte hi,lo;
-
-               hi=*(sp)++; lo=*(sp)++; red   = (png_uint_16)((hi << 8) | (lo));
-               hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
-               hi=*(sp)++; lo=*(sp)++; blue  = (png_uint_16)((hi << 8) | (lo));
-
-               if (red != green || red != blue)
-                  rgb_error |= 1;
-
-               /* From 1.5.5 in the 16-bit case do the accurate conversion even
-                * in the 'fast' case - this is because this is where the code
-                * ends up when handling linear 16-bit data.
-                */
-               gray16  = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
-                  15);
-               *(dp++) = (png_byte)((gray16 >> 8) & 0xff);
-               *(dp++) = (png_byte)(gray16 & 0xff);
-
-               if (have_alpha != 0)
-               {
-                  *(dp++) = *(sp++);
-                  *(dp++) = *(sp++);
-               }
-            }
-         }
-      }
-
-      row_info->channels = (png_byte)(row_info->channels - 2);
-      row_info->color_type = (png_byte)(row_info->color_type &
-          ~PNG_COLOR_MASK_COLOR);
-      row_info->pixel_depth = (png_byte)(row_info->channels *
-          row_info->bit_depth);
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
-   }
-   return rgb_error;
-}
-#endif
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
-/* Replace any alpha or transparency with the supplied background color.
- * "background" is already in the screen gamma, while "background_1" is
- * at a gamma of 1.0.  Paletted files have already been taken care of.
- */
-static void
-png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
-{
-#ifdef PNG_READ_GAMMA_SUPPORTED
-   png_const_bytep gamma_table = png_ptr->gamma_table;
-   png_const_bytep gamma_from_1 = png_ptr->gamma_from_1;
-   png_const_bytep gamma_to_1 = png_ptr->gamma_to_1;
-   png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table;
-   png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
-   png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
-   int gamma_shift = png_ptr->gamma_shift;
-   int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
-#endif
-
-   png_bytep sp;
-   png_uint_32 i;
-   png_uint_32 row_width = row_info->width;
-   int shift;
-
-   png_debug(1, "in png_do_compose");
-
-   switch (row_info->color_type)
-   {
-      case PNG_COLOR_TYPE_GRAY:
-      {
-         switch (row_info->bit_depth)
-         {
-            case 1:
-            {
-               sp = row;
-               shift = 7;
-               for (i = 0; i < row_width; i++)
-               {
-                  if ((png_uint_16)((*sp >> shift) & 0x01)
-                     == png_ptr->trans_color.gray)
-                  {
-                     unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
-                     tmp |=
-                         (unsigned int)(png_ptr->background.gray << shift);
-                     *sp = (png_byte)(tmp & 0xff);
-                  }
-
-                  if (shift == 0)
-                  {
-                     shift = 7;
-                     sp++;
-                  }
-
-                  else
-                     shift--;
-               }
-               break;
-            }
-
-            case 2:
-            {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-               if (gamma_table != NULL)
-               {
-                  sp = row;
-                  shift = 6;
-                  for (i = 0; i < row_width; i++)
-                  {
-                     if ((png_uint_16)((*sp >> shift) & 0x03)
-                         == png_ptr->trans_color.gray)
-                     {
-                        unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
-                        tmp |=
-                           (unsigned int)png_ptr->background.gray << shift;
-                        *sp = (png_byte)(tmp & 0xff);
-                     }
-
-                     else
-                     {
-                        unsigned int p = (*sp >> shift) & 0x03;
-                        unsigned int g = (gamma_table [p | (p << 2) |
-                            (p << 4) | (p << 6)] >> 6) & 0x03;
-                        unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
-                        tmp |= (unsigned int)(g << shift);
-                        *sp = (png_byte)(tmp & 0xff);
-                     }
-
-                     if (shift == 0)
-                     {
-                        shift = 6;
-                        sp++;
-                     }
-
-                     else
-                        shift -= 2;
-                  }
-               }
-
-               else
-#endif
-               {
-                  sp = row;
-                  shift = 6;
-                  for (i = 0; i < row_width; i++)
-                  {
-                     if ((png_uint_16)((*sp >> shift) & 0x03)
-                         == png_ptr->trans_color.gray)
-                     {
-                        unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
-                        tmp |=
-                            (unsigned int)png_ptr->background.gray << shift;
-                        *sp = (png_byte)(tmp & 0xff);
-                     }
-
-                     if (shift == 0)
-                     {
-                        shift = 6;
-                        sp++;
-                     }
-
-                     else
-                        shift -= 2;
-                  }
-               }
-               break;
-            }
-
-            case 4:
-            {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-               if (gamma_table != NULL)
-               {
-                  sp = row;
-                  shift = 4;
-                  for (i = 0; i < row_width; i++)
-                  {
-                     if ((png_uint_16)((*sp >> shift) & 0x0f)
-                         == png_ptr->trans_color.gray)
-                     {
-                        unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
-                        tmp |=
-                           (unsigned int)(png_ptr->background.gray << shift);
-                        *sp = (png_byte)(tmp & 0xff);
-                     }
-
-                     else
-                     {
-                        unsigned int p = (*sp >> shift) & 0x0f;
-                        unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
-                           0x0f;
-                        unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
-                        tmp |= (unsigned int)(g << shift);
-                        *sp = (png_byte)(tmp & 0xff);
-                     }
-
-                     if (shift == 0)
-                     {
-                        shift = 4;
-                        sp++;
-                     }
-
-                     else
-                        shift -= 4;
-                  }
-               }
-
-               else
-#endif
-               {
-                  sp = row;
-                  shift = 4;
-                  for (i = 0; i < row_width; i++)
-                  {
-                     if ((png_uint_16)((*sp >> shift) & 0x0f)
-                         == png_ptr->trans_color.gray)
-                     {
-                        unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
-                        tmp |=
-                           (unsigned int)(png_ptr->background.gray << shift);
-                        *sp = (png_byte)(tmp & 0xff);
-                     }
-
-                     if (shift == 0)
-                     {
-                        shift = 4;
-                        sp++;
-                     }
-
-                     else
-                        shift -= 4;
-                  }
-               }
-               break;
-            }
-
-            case 8:
-            {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-               if (gamma_table != NULL)
-               {
-                  sp = row;
-                  for (i = 0; i < row_width; i++, sp++)
-                  {
-                     if (*sp == png_ptr->trans_color.gray)
-                        *sp = (png_byte)png_ptr->background.gray;
-
-                     else
-                        *sp = gamma_table[*sp];
-                  }
-               }
-               else
-#endif
-               {
-                  sp = row;
-                  for (i = 0; i < row_width; i++, sp++)
-                  {
-                     if (*sp == png_ptr->trans_color.gray)
-                        *sp = (png_byte)png_ptr->background.gray;
-                  }
-               }
-               break;
-            }
-
-            case 16:
-            {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-               if (gamma_16 != NULL)
-               {
-                  sp = row;
-                  for (i = 0; i < row_width; i++, sp += 2)
-                  {
-                     png_uint_16 v;
-
-                     v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
-
-                     if (v == png_ptr->trans_color.gray)
-                     {
-                        /* Background is already in screen gamma */
-                        *sp = (png_byte)((png_ptr->background.gray >> 8)
-                             & 0xff);
-                        *(sp + 1) = (png_byte)(png_ptr->background.gray
-                             & 0xff);
-                     }
-
-                     else
-                     {
-                        v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
-                        *sp = (png_byte)((v >> 8) & 0xff);
-                        *(sp + 1) = (png_byte)(v & 0xff);
-                     }
-                  }
-               }
-               else
-#endif
-               {
-                  sp = row;
-                  for (i = 0; i < row_width; i++, sp += 2)
-                  {
-                     png_uint_16 v;
-
-                     v = (png_uint_16)(((*sp) << 8) + *(sp + 1));
-
-                     if (v == png_ptr->trans_color.gray)
-                     {
-                        *sp = (png_byte)((png_ptr->background.gray >> 8)
-                             & 0xff);
-                        *(sp + 1) = (png_byte)(png_ptr->background.gray
-                             & 0xff);
-                     }
-                  }
-               }
-               break;
-            }
-
-            default:
-               break;
-         }
-         break;
-      }
-
-      case PNG_COLOR_TYPE_RGB:
-      {
-         if (row_info->bit_depth == 8)
-         {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-            if (gamma_table != NULL)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 3)
-               {
-                  if (*sp == png_ptr->trans_color.red &&
-                      *(sp + 1) == png_ptr->trans_color.green &&
-                      *(sp + 2) == png_ptr->trans_color.blue)
-                  {
-                     *sp = (png_byte)png_ptr->background.red;
-                     *(sp + 1) = (png_byte)png_ptr->background.green;
-                     *(sp + 2) = (png_byte)png_ptr->background.blue;
-                  }
-
-                  else
-                  {
-                     *sp = gamma_table[*sp];
-                     *(sp + 1) = gamma_table[*(sp + 1)];
-                     *(sp + 2) = gamma_table[*(sp + 2)];
-                  }
-               }
-            }
-            else
-#endif
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 3)
-               {
-                  if (*sp == png_ptr->trans_color.red &&
-                      *(sp + 1) == png_ptr->trans_color.green &&
-                      *(sp + 2) == png_ptr->trans_color.blue)
-                  {
-                     *sp = (png_byte)png_ptr->background.red;
-                     *(sp + 1) = (png_byte)png_ptr->background.green;
-                     *(sp + 2) = (png_byte)png_ptr->background.blue;
-                  }
-               }
-            }
-         }
-         else /* if (row_info->bit_depth == 16) */
-         {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-            if (gamma_16 != NULL)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 6)
-               {
-                  png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
-
-                  png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
-                      + *(sp + 3));
-
-                  png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
-                      + *(sp + 5));
-
-                  if (r == png_ptr->trans_color.red &&
-                      g == png_ptr->trans_color.green &&
-                      b == png_ptr->trans_color.blue)
-                  {
-                     /* Background is already in screen gamma */
-                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
-                             & 0xff);
-                     *(sp + 3) = (png_byte)(png_ptr->background.green
-                             & 0xff);
-                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
-                             & 0xff);
-                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
-                  }
-
-                  else
-                  {
-                     png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
-                     *sp = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(v & 0xff);
-
-                     v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
-                     *(sp + 2) = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 3) = (png_byte)(v & 0xff);
-
-                     v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
-                     *(sp + 4) = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 5) = (png_byte)(v & 0xff);
-                  }
-               }
-            }
-
-            else
-#endif
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 6)
-               {
-                  png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
-
-                  png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
-                      + *(sp + 3));
-
-                  png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
-                      + *(sp + 5));
-
-                  if (r == png_ptr->trans_color.red &&
-                      g == png_ptr->trans_color.green &&
-                      b == png_ptr->trans_color.blue)
-                  {
-                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
-                             & 0xff);
-                     *(sp + 3) = (png_byte)(png_ptr->background.green
-                             & 0xff);
-                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
-                             & 0xff);
-                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
-                  }
-               }
-            }
-         }
-         break;
-      }
-
-      case PNG_COLOR_TYPE_GRAY_ALPHA:
-      {
-         if (row_info->bit_depth == 8)
-         {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-            if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
-                gamma_table != NULL)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 2)
-               {
-                  png_uint_16 a = *(sp + 1);
-
-                  if (a == 0xff)
-                     *sp = gamma_table[*sp];
-
-                  else if (a == 0)
-                  {
-                     /* Background is already in screen gamma */
-                     *sp = (png_byte)png_ptr->background.gray;
-                  }
-
-                  else
-                  {
-                     png_byte v, w;
-
-                     v = gamma_to_1[*sp];
-                     png_composite(w, v, a, png_ptr->background_1.gray);
-                     if (optimize == 0)
-                        w = gamma_from_1[w];
-                     *sp = w;
-                  }
-               }
-            }
-            else
-#endif
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 2)
-               {
-                  png_byte a = *(sp + 1);
-
-                  if (a == 0)
-                     *sp = (png_byte)png_ptr->background.gray;
-
-                  else if (a < 0xff)
-                     png_composite(*sp, *sp, a, png_ptr->background.gray);
-               }
-            }
-         }
-         else /* if (png_ptr->bit_depth == 16) */
-         {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-            if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
-                gamma_16_to_1 != NULL)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 4)
-               {
-                  png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
-                      + *(sp + 3));
-
-                  if (a == (png_uint_16)0xffff)
-                  {
-                     png_uint_16 v;
-
-                     v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
-                     *sp = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(v & 0xff);
-                  }
-
-                  else if (a == 0)
-                  {
-                     /* Background is already in screen gamma */
-                     *sp = (png_byte)((png_ptr->background.gray >> 8)
-                             & 0xff);
-                     *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
-                  }
-
-                  else
-                  {
-                     png_uint_16 g, v, w;
-
-                     g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
-                     png_composite_16(v, g, a, png_ptr->background_1.gray);
-                     if (optimize != 0)
-                        w = v;
-                     else
-                        w = gamma_16_from_1[(v & 0xff) >>
-                            gamma_shift][v >> 8];
-                     *sp = (png_byte)((w >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(w & 0xff);
-                  }
-               }
-            }
-            else
-#endif
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 4)
-               {
-                  png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8)
-                      + *(sp + 3));
-
-                  if (a == 0)
-                  {
-                     *sp = (png_byte)((png_ptr->background.gray >> 8)
-                             & 0xff);
-                     *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
-                  }
-
-                  else if (a < 0xffff)
-                  {
-                     png_uint_16 g, v;
-
-                     g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
-                     png_composite_16(v, g, a, png_ptr->background.gray);
-                     *sp = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(v & 0xff);
-                  }
-               }
-            }
-         }
-         break;
-      }
-
-      case PNG_COLOR_TYPE_RGB_ALPHA:
-      {
-         if (row_info->bit_depth == 8)
-         {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-            if (gamma_to_1 != NULL && gamma_from_1 != NULL &&
-                gamma_table != NULL)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 4)
-               {
-                  png_byte a = *(sp + 3);
-
-                  if (a == 0xff)
-                  {
-                     *sp = gamma_table[*sp];
-                     *(sp + 1) = gamma_table[*(sp + 1)];
-                     *(sp + 2) = gamma_table[*(sp + 2)];
-                  }
-
-                  else if (a == 0)
-                  {
-                     /* Background is already in screen gamma */
-                     *sp = (png_byte)png_ptr->background.red;
-                     *(sp + 1) = (png_byte)png_ptr->background.green;
-                     *(sp + 2) = (png_byte)png_ptr->background.blue;
-                  }
-
-                  else
-                  {
-                     png_byte v, w;
-
-                     v = gamma_to_1[*sp];
-                     png_composite(w, v, a, png_ptr->background_1.red);
-                     if (optimize == 0) w = gamma_from_1[w];
-                     *sp = w;
-
-                     v = gamma_to_1[*(sp + 1)];
-                     png_composite(w, v, a, png_ptr->background_1.green);
-                     if (optimize == 0) w = gamma_from_1[w];
-                     *(sp + 1) = w;
-
-                     v = gamma_to_1[*(sp + 2)];
-                     png_composite(w, v, a, png_ptr->background_1.blue);
-                     if (optimize == 0) w = gamma_from_1[w];
-                     *(sp + 2) = w;
-                  }
-               }
-            }
-            else
-#endif
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 4)
-               {
-                  png_byte a = *(sp + 3);
-
-                  if (a == 0)
-                  {
-                     *sp = (png_byte)png_ptr->background.red;
-                     *(sp + 1) = (png_byte)png_ptr->background.green;
-                     *(sp + 2) = (png_byte)png_ptr->background.blue;
-                  }
-
-                  else if (a < 0xff)
-                  {
-                     png_composite(*sp, *sp, a, png_ptr->background.red);
-
-                     png_composite(*(sp + 1), *(sp + 1), a,
-                         png_ptr->background.green);
-
-                     png_composite(*(sp + 2), *(sp + 2), a,
-                         png_ptr->background.blue);
-                  }
-               }
-            }
-         }
-         else /* if (row_info->bit_depth == 16) */
-         {
-#ifdef PNG_READ_GAMMA_SUPPORTED
-            if (gamma_16 != NULL && gamma_16_from_1 != NULL &&
-                gamma_16_to_1 != NULL)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 8)
-               {
-                  png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
-                      << 8) + (png_uint_16)(*(sp + 7)));
-
-                  if (a == (png_uint_16)0xffff)
-                  {
-                     png_uint_16 v;
-
-                     v = gamma_16[*(sp + 1) >> gamma_shift][*sp];
-                     *sp = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(v & 0xff);
-
-                     v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)];
-                     *(sp + 2) = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 3) = (png_byte)(v & 0xff);
-
-                     v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)];
-                     *(sp + 4) = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 5) = (png_byte)(v & 0xff);
-                  }
-
-                  else if (a == 0)
-                  {
-                     /* Background is already in screen gamma */
-                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
-                             & 0xff);
-                     *(sp + 3) = (png_byte)(png_ptr->background.green
-                             & 0xff);
-                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
-                             & 0xff);
-                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
-                  }
-
-                  else
-                  {
-                     png_uint_16 v, w;
-
-                     v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
-                     png_composite_16(w, v, a, png_ptr->background_1.red);
-                     if (optimize == 0)
-                        w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
-                             8];
-                     *sp = (png_byte)((w >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(w & 0xff);
-
-                     v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
-                     png_composite_16(w, v, a, png_ptr->background_1.green);
-                     if (optimize == 0)
-                        w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
-                             8];
-
-                     *(sp + 2) = (png_byte)((w >> 8) & 0xff);
-                     *(sp + 3) = (png_byte)(w & 0xff);
-
-                     v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
-                     png_composite_16(w, v, a, png_ptr->background_1.blue);
-                     if (optimize == 0)
-                        w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
-                             8];
-
-                     *(sp + 4) = (png_byte)((w >> 8) & 0xff);
-                     *(sp + 5) = (png_byte)(w & 0xff);
-                  }
-               }
-            }
-
-            else
-#endif
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++, sp += 8)
-               {
-                  png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6))
-                      << 8) + (png_uint_16)(*(sp + 7)));
-
-                  if (a == 0)
-                  {
-                     *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
-                     *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
-                             & 0xff);
-                     *(sp + 3) = (png_byte)(png_ptr->background.green
-                             & 0xff);
-                     *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
-                             & 0xff);
-                     *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
-                  }
-
-                  else if (a < 0xffff)
-                  {
-                     png_uint_16 v;
-
-                     png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1));
-                     png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8)
-                         + *(sp + 3));
-                     png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8)
-                         + *(sp + 5));
-
-                     png_composite_16(v, r, a, png_ptr->background.red);
-                     *sp = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 1) = (png_byte)(v & 0xff);
-
-                     png_composite_16(v, g, a, png_ptr->background.green);
-                     *(sp + 2) = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 3) = (png_byte)(v & 0xff);
-
-                     png_composite_16(v, b, a, png_ptr->background.blue);
-                     *(sp + 4) = (png_byte)((v >> 8) & 0xff);
-                     *(sp + 5) = (png_byte)(v & 0xff);
-                  }
-               }
-            }
-         }
-         break;
-      }
-
-      default:
-         break;
-   }
-}
-#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-/* Gamma correct the image, avoiding the alpha channel.  Make sure
- * you do this after you deal with the transparency issue on grayscale
- * or RGB images. If your bit depth is 8, use gamma_table, if it
- * is 16, use gamma_16_table and gamma_shift.  Build these with
- * build_gamma_table().
- */
-static void
-png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
-{
-   png_const_bytep gamma_table = png_ptr->gamma_table;
-   png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
-   int gamma_shift = png_ptr->gamma_shift;
-
-   png_bytep sp;
-   png_uint_32 i;
-   png_uint_32 row_width=row_info->width;
-
-   png_debug(1, "in png_do_gamma");
-
-   if (((row_info->bit_depth <= 8 && gamma_table != NULL) ||
-       (row_info->bit_depth == 16 && gamma_16_table != NULL)))
-   {
-      switch (row_info->color_type)
-      {
-         case PNG_COLOR_TYPE_RGB:
-         {
-            if (row_info->bit_depth == 8)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++)
-               {
-                  *sp = gamma_table[*sp];
-                  sp++;
-                  *sp = gamma_table[*sp];
-                  sp++;
-                  *sp = gamma_table[*sp];
-                  sp++;
-               }
-            }
-
-            else /* if (row_info->bit_depth == 16) */
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++)
-               {
-                  png_uint_16 v;
-
-                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
-                  *sp = (png_byte)((v >> 8) & 0xff);
-                  *(sp + 1) = (png_byte)(v & 0xff);
-                  sp += 2;
-
-                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
-                  *sp = (png_byte)((v >> 8) & 0xff);
-                  *(sp + 1) = (png_byte)(v & 0xff);
-                  sp += 2;
-
-                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
-                  *sp = (png_byte)((v >> 8) & 0xff);
-                  *(sp + 1) = (png_byte)(v & 0xff);
-                  sp += 2;
-               }
-            }
-            break;
-         }
-
-         case PNG_COLOR_TYPE_RGB_ALPHA:
-         {
-            if (row_info->bit_depth == 8)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++)
-               {
-                  *sp = gamma_table[*sp];
-                  sp++;
-
-                  *sp = gamma_table[*sp];
-                  sp++;
-
-                  *sp = gamma_table[*sp];
-                  sp++;
-
-                  sp++;
-               }
-            }
-
-            else /* if (row_info->bit_depth == 16) */
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++)
-               {
-                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
-                  *sp = (png_byte)((v >> 8) & 0xff);
-                  *(sp + 1) = (png_byte)(v & 0xff);
-                  sp += 2;
-
-                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
-                  *sp = (png_byte)((v >> 8) & 0xff);
-                  *(sp + 1) = (png_byte)(v & 0xff);
-                  sp += 2;
-
-                  v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
-                  *sp = (png_byte)((v >> 8) & 0xff);
-                  *(sp + 1) = (png_byte)(v & 0xff);
-                  sp += 4;
-               }
-            }
-            break;
-         }
-
-         case PNG_COLOR_TYPE_GRAY_ALPHA:
-         {
-            if (row_info->bit_depth == 8)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++)
-               {
-                  *sp = gamma_table[*sp];
-                  sp += 2;
-               }
-            }
-
-            else /* if (row_info->bit_depth == 16) */
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++)
-               {
-                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
-                  *sp = (png_byte)((v >> 8) & 0xff);
-                  *(sp + 1) = (png_byte)(v & 0xff);
-                  sp += 4;
-               }
-            }
-            break;
-         }
-
-         case PNG_COLOR_TYPE_GRAY:
-         {
-            if (row_info->bit_depth == 2)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i += 4)
-               {
-                  int a = *sp & 0xc0;
-                  int b = *sp & 0x30;
-                  int c = *sp & 0x0c;
-                  int d = *sp & 0x03;
-
-                  *sp = (png_byte)(
-                      ((((int)gamma_table[a|(a>>2)|(a>>4)|(a>>6)])   ) & 0xc0)|
-                      ((((int)gamma_table[(b<<2)|b|(b>>2)|(b>>4)])>>2) & 0x30)|
-                      ((((int)gamma_table[(c<<4)|(c<<2)|c|(c>>2)])>>4) & 0x0c)|
-                      ((((int)gamma_table[(d<<6)|(d<<4)|(d<<2)|d])>>6) ));
-                  sp++;
-               }
-            }
-
-            if (row_info->bit_depth == 4)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i += 2)
-               {
-                  int msb = *sp & 0xf0;
-                  int lsb = *sp & 0x0f;
-
-                  *sp = (png_byte)((((int)gamma_table[msb | (msb >> 4)]) & 0xf0)
-                      | (((int)gamma_table[(lsb << 4) | lsb]) >> 4));
-                  sp++;
-               }
-            }
-
-            else if (row_info->bit_depth == 8)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++)
-               {
-                  *sp = gamma_table[*sp];
-                  sp++;
-               }
-            }
-
-            else if (row_info->bit_depth == 16)
-            {
-               sp = row;
-               for (i = 0; i < row_width; i++)
-               {
-                  png_uint_16 v = gamma_16_table[*(sp + 1) >> gamma_shift][*sp];
-                  *sp = (png_byte)((v >> 8) & 0xff);
-                  *(sp + 1) = (png_byte)(v & 0xff);
-                  sp += 2;
-               }
-            }
-            break;
-         }
-
-         default:
-            break;
-      }
-   }
-}
-#endif
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-/* Encode the alpha channel to the output gamma (the input channel is always
- * linear.)  Called only with color types that have an alpha channel.  Needs the
- * from_1 tables.
- */
-static void
-png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
-{
-   png_uint_32 row_width = row_info->width;
-
-   png_debug(1, "in png_do_encode_alpha");
-
-   if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
-   {
-      if (row_info->bit_depth == 8)
-      {
-         png_bytep table = png_ptr->gamma_from_1;
-
-         if (table != NULL)
-         {
-            int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
-
-            /* The alpha channel is the last component: */
-            row += step - 1;
-
-            for (; row_width > 0; --row_width, row += step)
-               *row = table[*row];
-
-            return;
-         }
-      }
-
-      else if (row_info->bit_depth == 16)
-      {
-         png_uint_16pp table = png_ptr->gamma_16_from_1;
-         int gamma_shift = png_ptr->gamma_shift;
-
-         if (table != NULL)
-         {
-            int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
-
-            /* The alpha channel is the last component: */
-            row += step - 2;
-
-            for (; row_width > 0; --row_width, row += step)
-            {
-               png_uint_16 v;
-
-               v = table[*(row + 1) >> gamma_shift][*row];
-               *row = (png_byte)((v >> 8) & 0xff);
-               *(row + 1) = (png_byte)(v & 0xff);
-            }
-
-            return;
-         }
-      }
-   }
-
-   /* Only get to here if called with a weird row_info; no harm has been done,
-    * so just issue a warning.
-    */
-   png_warning(png_ptr, "png_do_encode_alpha: unexpected call");
-}
-#endif
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
-/* Expands a palette row to an RGB or RGBA row depending
- * upon whether you supply trans and num_trans.
- */
-static void
-png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,
-    png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha,
-    int num_trans)
-{
-   int shift, value;
-   png_bytep sp, dp;
-   png_uint_32 i;
-   png_uint_32 row_width=row_info->width;
-
-   png_debug(1, "in png_do_expand_palette");
-
-   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
-   {
-      if (row_info->bit_depth < 8)
-      {
-         switch (row_info->bit_depth)
-         {
-            case 1:
-            {
-               sp = row + (size_t)((row_width - 1) >> 3);
-               dp = row + (size_t)row_width - 1;
-               shift = 7 - (int)((row_width + 7) & 0x07);
-               for (i = 0; i < row_width; i++)
-               {
-                  if ((*sp >> shift) & 0x01)
-                     *dp = 1;
-
-                  else
-                     *dp = 0;
-
-                  if (shift == 7)
-                  {
-                     shift = 0;
-                     sp--;
-                  }
-
-                  else
-                     shift++;
-
-                  dp--;
-               }
-               break;
-            }
-
-            case 2:
-            {
-               sp = row + (size_t)((row_width - 1) >> 2);
-               dp = row + (size_t)row_width - 1;
-               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
-               for (i = 0; i < row_width; i++)
-               {
-                  value = (*sp >> shift) & 0x03;
-                  *dp = (png_byte)value;
-                  if (shift == 6)
-                  {
-                     shift = 0;
-                     sp--;
-                  }
-
-                  else
-                     shift += 2;
-
-                  dp--;
-               }
-               break;
-            }
-
-            case 4:
-            {
-               sp = row + (size_t)((row_width - 1) >> 1);
-               dp = row + (size_t)row_width - 1;
-               shift = (int)((row_width & 0x01) << 2);
-               for (i = 0; i < row_width; i++)
-               {
-                  value = (*sp >> shift) & 0x0f;
-                  *dp = (png_byte)value;
-                  if (shift == 4)
-                  {
-                     shift = 0;
-                     sp--;
-                  }
-
-                  else
-                     shift += 4;
-
-                  dp--;
-               }
-               break;
-            }
-
-            default:
-               break;
-         }
-         row_info->bit_depth = 8;
-         row_info->pixel_depth = 8;
-         row_info->rowbytes = row_width;
-      }
-
-      if (row_info->bit_depth == 8)
-      {
-         {
-            if (num_trans > 0)
-            {
-               sp = row + (size_t)row_width - 1;
-               dp = row + ((size_t)row_width << 2) - 1;
-
-               i = 0;
-#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
-               if (png_ptr->riffled_palette != NULL)
-               {
-                  /* The RGBA optimization works with png_ptr->bit_depth == 8
-                   * but sometimes row_info->bit_depth has been changed to 8.
-                   * In these cases, the palette hasn't been riffled.
-                   */
-                  i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row,
-                      &sp, &dp);
-               }
-#else
-               PNG_UNUSED(png_ptr)
-#endif
-
-               for (; i < row_width; i++)
-               {
-                  if ((int)(*sp) >= num_trans)
-                     *dp-- = 0xff;
-                  else
-                     *dp-- = trans_alpha[*sp];
-                  *dp-- = palette[*sp].blue;
-                  *dp-- = palette[*sp].green;
-                  *dp-- = palette[*sp].red;
-                  sp--;
-               }
-               row_info->bit_depth = 8;
-               row_info->pixel_depth = 32;
-               row_info->rowbytes = row_width * 4;
-               row_info->color_type = 6;
-               row_info->channels = 4;
-            }
-
-            else
-            {
-               sp = row + (size_t)row_width - 1;
-               dp = row + (size_t)(row_width * 3) - 1;
-               i = 0;
-#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
-               i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row,
-                   &sp, &dp);
-#else
-               PNG_UNUSED(png_ptr)
-#endif
-
-               for (; i < row_width; i++)
-               {
-                  *dp-- = palette[*sp].blue;
-                  *dp-- = palette[*sp].green;
-                  *dp-- = palette[*sp].red;
-                  sp--;
-               }
-
-               row_info->bit_depth = 8;
-               row_info->pixel_depth = 24;
-               row_info->rowbytes = row_width * 3;
-               row_info->color_type = 2;
-               row_info->channels = 3;
-            }
-         }
-      }
-   }
-}
-
-/* If the bit depth < 8, it is expanded to 8.  Also, if the already
- * expanded transparency value is supplied, an alpha channel is built.
- */
-static void
-png_do_expand(png_row_infop row_info, png_bytep row,
-    png_const_color_16p trans_color)
-{
-   int shift, value;
-   png_bytep sp, dp;
-   png_uint_32 i;
-   png_uint_32 row_width=row_info->width;
-
-   png_debug(1, "in png_do_expand");
-
-   if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
-   {
-      unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
-
-      if (row_info->bit_depth < 8)
-      {
-         switch (row_info->bit_depth)
-         {
-            case 1:
-            {
-               gray = (gray & 0x01) * 0xff;
-               sp = row + (size_t)((row_width - 1) >> 3);
-               dp = row + (size_t)row_width - 1;
-               shift = 7 - (int)((row_width + 7) & 0x07);
-               for (i = 0; i < row_width; i++)
-               {
-                  if ((*sp >> shift) & 0x01)
-                     *dp = 0xff;
-
-                  else
-                     *dp = 0;
-
-                  if (shift == 7)
-                  {
-                     shift = 0;
-                     sp--;
-                  }
-
-                  else
-                     shift++;
-
-                  dp--;
-               }
-               break;
-            }
-
-            case 2:
-            {
-               gray = (gray & 0x03) * 0x55;
-               sp = row + (size_t)((row_width - 1) >> 2);
-               dp = row + (size_t)row_width - 1;
-               shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
-               for (i = 0; i < row_width; i++)
-               {
-                  value = (*sp >> shift) & 0x03;
-                  *dp = (png_byte)(value | (value << 2) | (value << 4) |
-                     (value << 6));
-                  if (shift == 6)
-                  {
-                     shift = 0;
-                     sp--;
-                  }
-
-                  else
-                     shift += 2;
-
-                  dp--;
-               }
-               break;
-            }
-
-            case 4:
-            {
-               gray = (gray & 0x0f) * 0x11;
-               sp = row + (size_t)((row_width - 1) >> 1);
-               dp = row + (size_t)row_width - 1;
-               shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
-               for (i = 0; i < row_width; i++)
-               {
-                  value = (*sp >> shift) & 0x0f;
-                  *dp = (png_byte)(value | (value << 4));
-                  if (shift == 4)
-                  {
-                     shift = 0;
-                     sp--;
-                  }
-
-                  else
-                     shift = 4;
-
-                  dp--;
-               }
-               break;
-            }
-
-            default:
-               break;
-         }
-
-         row_info->bit_depth = 8;
-         row_info->pixel_depth = 8;
-         row_info->rowbytes = row_width;
-      }
-
-      if (trans_color != NULL)
-      {
-         if (row_info->bit_depth == 8)
-         {
-            gray = gray & 0xff;
-            sp = row + (size_t)row_width - 1;
-            dp = row + ((size_t)row_width << 1) - 1;
-
-            for (i = 0; i < row_width; i++)
-            {
-               if ((*sp & 0xffU) == gray)
-                  *dp-- = 0;
-
-               else
-                  *dp-- = 0xff;
-
-               *dp-- = *sp--;
-            }
-         }
-
-         else if (row_info->bit_depth == 16)
-         {
-            unsigned int gray_high = (gray >> 8) & 0xff;
-            unsigned int gray_low = gray & 0xff;
-            sp = row + row_info->rowbytes - 1;
-            dp = row + (row_info->rowbytes << 1) - 1;
-            for (i = 0; i < row_width; i++)
-            {
-               if ((*(sp - 1) & 0xffU) == gray_high &&
-                   (*(sp) & 0xffU) == gray_low)
-               {
-                  *dp-- = 0;
-                  *dp-- = 0;
-               }
-
-               else
-               {
-                  *dp-- = 0xff;
-                  *dp-- = 0xff;
-               }
-
-               *dp-- = *sp--;
-               *dp-- = *sp--;
-            }
-         }
-
-         row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA;
-         row_info->channels = 2;
-         row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1);
-         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
-             row_width);
-      }
-   }
-   else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
-       trans_color != NULL)
-   {
-      if (row_info->bit_depth == 8)
-      {
-         png_byte red = (png_byte)(trans_color->red & 0xff);
-         png_byte green = (png_byte)(trans_color->green & 0xff);
-         png_byte blue = (png_byte)(trans_color->blue & 0xff);
-         sp = row + (size_t)row_info->rowbytes - 1;
-         dp = row + ((size_t)row_width << 2) - 1;
-         for (i = 0; i < row_width; i++)
-         {
-            if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
-               *dp-- = 0;
-
-            else
-               *dp-- = 0xff;
-
-            *dp-- = *sp--;
-            *dp-- = *sp--;
-            *dp-- = *sp--;
-         }
-      }
-      else if (row_info->bit_depth == 16)
-      {
-         png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff);
-         png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff);
-         png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff);
-         png_byte red_low = (png_byte)(trans_color->red & 0xff);
-         png_byte green_low = (png_byte)(trans_color->green & 0xff);
-         png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
-         sp = row + row_info->rowbytes - 1;
-         dp = row + ((size_t)row_width << 3) - 1;
-         for (i = 0; i < row_width; i++)
-         {
-            if (*(sp - 5) == red_high &&
-                *(sp - 4) == red_low &&
-                *(sp - 3) == green_high &&
-                *(sp - 2) == green_low &&
-                *(sp - 1) == blue_high &&
-                *(sp    ) == blue_low)
-            {
-               *dp-- = 0;
-               *dp-- = 0;
-            }
-
-            else
-            {
-               *dp-- = 0xff;
-               *dp-- = 0xff;
-            }
-
-            *dp-- = *sp--;
-            *dp-- = *sp--;
-            *dp-- = *sp--;
-            *dp-- = *sp--;
-            *dp-- = *sp--;
-            *dp-- = *sp--;
-         }
-      }
-      row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA;
-      row_info->channels = 4;
-      row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
-   }
-}
-#endif
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
-/* If the bit depth is 8 and the color type is not a palette type expand the
- * whole row to 16 bits.  Has no effect otherwise.
- */
-static void
-png_do_expand_16(png_row_infop row_info, png_bytep row)
-{
-   if (row_info->bit_depth == 8 &&
-      row_info->color_type != PNG_COLOR_TYPE_PALETTE)
-   {
-      /* The row have a sequence of bytes containing [0..255] and we need
-       * to turn it into another row containing [0..65535], to do this we
-       * calculate:
-       *
-       *  (input / 255) * 65535
-       *
-       *  Which happens to be exactly input * 257 and this can be achieved
-       *  simply by byte replication in place (copying backwards).
-       */
-      png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
-      png_byte *dp = sp + row_info->rowbytes;  /* destination, end + 1 */
-      while (dp > sp)
-      {
-         dp[-2] = dp[-1] = *--sp; dp -= 2;
-      }
-
-      row_info->rowbytes *= 2;
-      row_info->bit_depth = 16;
-      row_info->pixel_depth = (png_byte)(row_info->channels * 16);
-   }
-}
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-static void
-png_do_quantize(png_row_infop row_info, png_bytep row,
-    png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
-{
-   png_bytep sp, dp;
-   png_uint_32 i;
-   png_uint_32 row_width=row_info->width;
-
-   png_debug(1, "in png_do_quantize");
-
-   if (row_info->bit_depth == 8)
-   {
-      if (row_info->color_type == PNG_COLOR_TYPE_RGB && palette_lookup)
-      {
-         int r, g, b, p;
-         sp = row;
-         dp = row;
-         for (i = 0; i < row_width; i++)
-         {
-            r = *sp++;
-            g = *sp++;
-            b = *sp++;
-
-            /* This looks real messy, but the compiler will reduce
-             * it down to a reasonable formula.  For example, with
-             * 5 bits per color, we get:
-             * p = (((r >> 3) & 0x1f) << 10) |
-             *    (((g >> 3) & 0x1f) << 5) |
-             *    ((b >> 3) & 0x1f);
-             */
-            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
-                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
-                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
-                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
-                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
-                (PNG_QUANTIZE_BLUE_BITS)) |
-                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
-                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
-
-            *dp++ = palette_lookup[p];
-         }
-
-         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
-         row_info->channels = 1;
-         row_info->pixel_depth = row_info->bit_depth;
-         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
-      }
-
-      else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
-         palette_lookup != NULL)
-      {
-         int r, g, b, p;
-         sp = row;
-         dp = row;
-         for (i = 0; i < row_width; i++)
-         {
-            r = *sp++;
-            g = *sp++;
-            b = *sp++;
-            sp++;
-
-            p = (((r >> (8 - PNG_QUANTIZE_RED_BITS)) &
-                ((1 << PNG_QUANTIZE_RED_BITS) - 1)) <<
-                (PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS)) |
-                (((g >> (8 - PNG_QUANTIZE_GREEN_BITS)) &
-                ((1 << PNG_QUANTIZE_GREEN_BITS) - 1)) <<
-                (PNG_QUANTIZE_BLUE_BITS)) |
-                ((b >> (8 - PNG_QUANTIZE_BLUE_BITS)) &
-                ((1 << PNG_QUANTIZE_BLUE_BITS) - 1));
-
-            *dp++ = palette_lookup[p];
-         }
-
-         row_info->color_type = PNG_COLOR_TYPE_PALETTE;
-         row_info->channels = 1;
-         row_info->pixel_depth = row_info->bit_depth;
-         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
-      }
-
-      else if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
-         quantize_lookup)
-      {
-         sp = row;
-
-         for (i = 0; i < row_width; i++, sp++)
-         {
-            *sp = quantize_lookup[*sp];
-         }
-      }
-   }
-}
-#endif /* READ_QUANTIZE */
-
-/* Transform the row.  The order of transformations is significant,
- * and is very touchy.  If you add a transformation, take care to
- * decide how it fits in with the other transformations here.
- */
-void /* PRIVATE */
-png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
-{
-   png_debug(1, "in png_do_read_transformations");
-
-   if (png_ptr->row_buf == NULL)
-   {
-      /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
-       * error is incredibly rare and incredibly easy to debug without this
-       * information.
-       */
-      png_error(png_ptr, "NULL row buffer");
-   }
-
-   /* The following is debugging; prior to 1.5.4 the code was never compiled in;
-    * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
-    * PNG_WARN_UNINITIALIZED_ROW removed.  In 1.6 the new flag is set only for
-    * all transformations, however in practice the ROW_INIT always gets done on
-    * demand, if necessary.
-    */
-   if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
-       (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
-   {
-      /* Application has failed to call either png_read_start_image() or
-       * png_read_update_info() after setting transforms that expand pixels.
-       * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
-       */
-      png_error(png_ptr, "Uninitialized row");
-   }
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
-   if ((png_ptr->transformations & PNG_EXPAND) != 0)
-   {
-      if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
-      {
-#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
-         if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))
-         {
-            if (png_ptr->riffled_palette == NULL)
-            {
-               /* Initialize the accelerated palette expansion. */
-               png_ptr->riffled_palette =
-                   (png_bytep)png_malloc(png_ptr, 256 * 4);
-               png_riffle_palette_neon(png_ptr);
-            }
-         }
-#endif
-         png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,
-             png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
-      }
-
-      else
-      {
-         if (png_ptr->num_trans != 0 &&
-             (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
-            png_do_expand(row_info, png_ptr->row_buf + 1,
-                &(png_ptr->trans_color));
-
-         else
-            png_do_expand(row_info, png_ptr->row_buf + 1, NULL);
-      }
-   }
-#endif
-
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
-       (png_ptr->transformations & PNG_COMPOSE) == 0 &&
-       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
-       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
-      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
-          0 /* at_start == false, because SWAP_ALPHA happens later */);
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
-   {
-      int rgb_error =
-          png_do_rgb_to_gray(png_ptr, row_info,
-              png_ptr->row_buf + 1);
-
-      if (rgb_error != 0)
-      {
-         png_ptr->rgb_to_gray_status=1;
-         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
-             PNG_RGB_TO_GRAY_WARN)
-            png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
-
-         if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
-             PNG_RGB_TO_GRAY_ERR)
-            png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
-      }
-   }
-#endif
-
-/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
- *
- *   In most cases, the "simple transparency" should be done prior to doing
- *   gray-to-RGB, or you will have to test 3x as many bytes to check if a
- *   pixel is transparent.  You would also need to make sure that the
- *   transparency information is upgraded to RGB.
- *
- *   To summarize, the current flow is:
- *   - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
- *                                   with background "in place" if transparent,
- *                                   convert to RGB if necessary
- *   - Gray + alpha -> composite with gray background and remove alpha bytes,
- *                                   convert to RGB if necessary
- *
- *   To support RGB backgrounds for gray images we need:
- *   - Gray + simple transparency -> convert to RGB + simple transparency,
- *                                   compare 3 or 6 bytes and composite with
- *                                   background "in place" if transparent
- *                                   (3x compare/pixel compared to doing
- *                                   composite with gray bkgrnd)
- *   - Gray + alpha -> convert to RGB + alpha, composite with background and
- *                                   remove alpha bytes (3x float
- *                                   operations/pixel compared with composite
- *                                   on gray background)
- *
- *  Greg's change will do this.  The reason it wasn't done before is for
- *  performance, as this increases the per-pixel operations.  If we would check
- *  in advance if the background was gray or RGB, and position the gray-to-RGB
- *  transform appropriately, then it would save a lot of work/time.
- */
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-   /* If gray -> RGB, do so now only if background is non-gray; else do later
-    * for performance reasons
-    */
-   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
-       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
-      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
-#endif
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
-   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
-      png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-   if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-      /* Because RGB_TO_GRAY does the gamma transform. */
-      (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
-#endif
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
-      /* Because PNG_COMPOSE does the gamma transform if there is something to
-       * do (if there is an alpha channel or transparency.)
-       */
-       !((png_ptr->transformations & PNG_COMPOSE) != 0 &&
-       ((png_ptr->num_trans != 0) ||
-       (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
-#endif
-      /* Because png_init_read_transformations transforms the palette, unless
-       * RGB_TO_GRAY will do the transform.
-       */
-       (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
-      png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-   if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
-       (png_ptr->transformations & PNG_COMPOSE) != 0 &&
-       (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
-       row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
-      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
-          0 /* at_start == false, because SWAP_ALPHA happens later */);
-#endif
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-   if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
-       (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
-      png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
-   if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
-      png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-   /* There is no harm in doing both of these because only one has any effect,
-    * by putting the 'scale' option first if the app asks for scale (either by
-    * calling the API or in a TRANSFORM flag) this is what happens.
-    */
-   if ((png_ptr->transformations & PNG_16_TO_8) != 0)
-      png_do_chop(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-   if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
-   {
-      png_do_quantize(row_info, png_ptr->row_buf + 1,
-          png_ptr->palette_lookup, png_ptr->quantize_index);
-
-      if (row_info->rowbytes == 0)
-         png_error(png_ptr, "png_do_quantize returned rowbytes=0");
-   }
-#endif /* READ_QUANTIZE */
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
-   /* Do the expansion now, after all the arithmetic has been done.  Notice
-    * that previous transformations can handle the PNG_EXPAND_16 flag if this
-    * is efficient (particularly true in the case of gamma correction, where
-    * better accuracy results faster!)
-    */
-   if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
-      png_do_expand_16(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-   /* NOTE: moved here in 1.5.4 (from much later in this list.) */
-   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
-       (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
-      png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_INVERT_SUPPORTED
-   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
-      png_do_invert(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-   if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
-      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_SHIFT_SUPPORTED
-   if ((png_ptr->transformations & PNG_SHIFT) != 0)
-      png_do_unshift(row_info, png_ptr->row_buf + 1,
-          &(png_ptr->shift));
-#endif
-
-#ifdef PNG_READ_PACK_SUPPORTED
-   if ((png_ptr->transformations & PNG_PACK) != 0)
-      png_do_unpack(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
-   /* Added at libpng-1.5.10 */
-   if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
-       png_ptr->num_palette_max >= 0)
-      png_do_check_palette_indexes(png_ptr, row_info);
-#endif
-
-#ifdef PNG_READ_BGR_SUPPORTED
-   if ((png_ptr->transformations & PNG_BGR) != 0)
-      png_do_bgr(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
-   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
-      png_do_packswap(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_FILLER_SUPPORTED
-   if ((png_ptr->transformations & PNG_FILLER) != 0)
-      png_do_read_filler(row_info, png_ptr->row_buf + 1,
-          (png_uint_32)png_ptr->filler, png_ptr->flags);
-#endif
-
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
-   if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
-      png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-#ifdef PNG_READ_SWAP_SUPPORTED
-   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
-      png_do_swap(row_info, png_ptr->row_buf + 1);
-#endif
-#endif
-
-#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
-   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
-   {
-      if (png_ptr->read_user_transform_fn != NULL)
-         (*(png_ptr->read_user_transform_fn)) /* User read transform function */
-             (png_ptr,     /* png_ptr */
-             row_info,     /* row_info: */
-                /*  png_uint_32 width;       width of row */
-                /*  size_t rowbytes;         number of bytes in row */
-                /*  png_byte color_type;     color type of pixels */
-                /*  png_byte bit_depth;      bit depth of samples */
-                /*  png_byte channels;       number of channels (1-4) */
-                /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
-             png_ptr->row_buf + 1);    /* start of pixel data for row */
-#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
-      if (png_ptr->user_transform_depth != 0)
-         row_info->bit_depth = png_ptr->user_transform_depth;
-
-      if (png_ptr->user_transform_channels != 0)
-         row_info->channels = png_ptr->user_transform_channels;
-#endif
-      row_info->pixel_depth = (png_byte)(row_info->bit_depth *
-          row_info->channels);
-
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
-   }
-#endif
-}
-
-#endif /* READ_TRANSFORMS */
-#endif /* READ */
diff --git a/third_party/libpng16/pngrutil.c b/third_party/libpng16/pngrutil.c
deleted file mode 100644
index 3007414..0000000
--- a/third_party/libpng16/pngrutil.c
+++ /dev/null
@@ -1,4681 +0,0 @@
-
-/* pngrutil.c - utilities to read a PNG file
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- *
- * This file contains routines that are only called from within
- * libpng itself during the course of reading an image.
- */
-
-#include "pngpriv.h"
-
-#ifdef PNG_READ_SUPPORTED
-
-png_uint_32 PNGAPI
-png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
-{
-   png_uint_32 uval = png_get_uint_32(buf);
-
-   if (uval > PNG_UINT_31_MAX)
-      png_error(png_ptr, "PNG unsigned integer out of range");
-
-   return (uval);
-}
-
-#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)
-/* The following is a variation on the above for use with the fixed
- * point values used for gAMA and cHRM.  Instead of png_error it
- * issues a warning and returns (-1) - an invalid value because both
- * gAMA and cHRM use *unsigned* integers for fixed point values.
- */
-#define PNG_FIXED_ERROR (-1)
-
-static png_fixed_point /* PRIVATE */
-png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf)
-{
-   png_uint_32 uval = png_get_uint_32(buf);
-
-   if (uval <= PNG_UINT_31_MAX)
-      return (png_fixed_point)uval; /* known to be in range */
-
-   /* The caller can turn off the warning by passing NULL. */
-   if (png_ptr != NULL)
-      png_warning(png_ptr, "PNG fixed point integer out of range");
-
-   return PNG_FIXED_ERROR;
-}
-#endif
-
-#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
-/* NOTE: the read macros will obscure these definitions, so that if
- * PNG_USE_READ_MACROS is set the library will not use them internally,
- * but the APIs will still be available externally.
- *
- * The parentheses around "PNGAPI function_name" in the following three
- * functions are necessary because they allow the macros to co-exist with
- * these (unused but exported) functions.
- */
-
-/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
-png_uint_32 (PNGAPI
-png_get_uint_32)(png_const_bytep buf)
-{
-   png_uint_32 uval =
-       ((png_uint_32)(*(buf    )) << 24) +
-       ((png_uint_32)(*(buf + 1)) << 16) +
-       ((png_uint_32)(*(buf + 2)) <<  8) +
-       ((png_uint_32)(*(buf + 3))      ) ;
-
-   return uval;
-}
-
-/* Grab a signed 32-bit integer from a buffer in big-endian format.  The
- * data is stored in the PNG file in two's complement format and there
- * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore
- * the following code does a two's complement to native conversion.
- */
-png_int_32 (PNGAPI
-png_get_int_32)(png_const_bytep buf)
-{
-   png_uint_32 uval = png_get_uint_32(buf);
-   if ((uval & 0x80000000) == 0) /* non-negative */
-      return (png_int_32)uval;
-
-   uval = (uval ^ 0xffffffff) + 1;  /* 2's complement: -x = ~x+1 */
-   if ((uval & 0x80000000) == 0) /* no overflow */
-      return -(png_int_32)uval;
-   /* The following has to be safe; this function only gets called on PNG data
-    * and if we get here that data is invalid.  0 is the most safe value and
-    * if not then an attacker would surely just generate a PNG with 0 instead.
-    */
-   return 0;
-}
-
-/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
-png_uint_16 (PNGAPI
-png_get_uint_16)(png_const_bytep buf)
-{
-   /* ANSI-C requires an int value to accommodate at least 16 bits so this
-    * works and allows the compiler not to worry about possible narrowing
-    * on 32-bit systems.  (Pre-ANSI systems did not make integers smaller
-    * than 16 bits either.)
-    */
-   unsigned int val =
-       ((unsigned int)(*buf) << 8) +
-       ((unsigned int)(*(buf + 1)));
-
-   return (png_uint_16)val;
-}
-
-#endif /* READ_INT_FUNCTIONS */
-
-/* Read and check the PNG file signature */
-void /* PRIVATE */
-png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
-{
-   size_t num_checked, num_to_check;
-
-   /* Exit if the user application does not expect a signature. */
-   if (png_ptr->sig_bytes >= 8)
-      return;
-
-   num_checked = png_ptr->sig_bytes;
-   num_to_check = 8 - num_checked;
-
-#ifdef PNG_IO_STATE_SUPPORTED
-   png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE;
-#endif
-
-   /* The signature must be serialized in a single I/O call. */
-   png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
-   png_ptr->sig_bytes = 8;
-
-   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
-   {
-      if (num_checked < 4 &&
-          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
-         png_error(png_ptr, "Not a PNG file");
-      else
-         png_error(png_ptr, "PNG file corrupted by ASCII conversion");
-   }
-   if (num_checked < 3)
-      png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
-}
-
-/* Read the chunk header (length + type name).
- * Put the type name into png_ptr->chunk_name, and return the length.
- */
-png_uint_32 /* PRIVATE */
-png_read_chunk_header(png_structrp png_ptr)
-{
-   png_byte buf[8];
-   png_uint_32 length;
-
-#ifdef PNG_IO_STATE_SUPPORTED
-   png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;
-#endif
-
-   /* Read the length and the chunk name.
-    * This must be performed in a single I/O call.
-    */
-   png_read_data(png_ptr, buf, 8);
-   length = png_get_uint_31(png_ptr, buf);
-
-   /* Put the chunk name into png_ptr->chunk_name. */
-   png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
-
-   png_debug2(0, "Reading %lx chunk, length = %lu",
-       (unsigned long)png_ptr->chunk_name, (unsigned long)length);
-
-   /* Reset the crc and run it over the chunk name. */
-   png_reset_crc(png_ptr);
-   png_calculate_crc(png_ptr, buf + 4, 4);
-
-   /* Check to see if chunk name is valid. */
-   png_check_chunk_name(png_ptr, png_ptr->chunk_name);
-
-   /* Check for too-large chunk length */
-   png_check_chunk_length(png_ptr, length);
-
-#ifdef PNG_IO_STATE_SUPPORTED
-   png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
-#endif
-
-   return length;
-}
-
-/* Read data, and (optionally) run it through the CRC. */
-void /* PRIVATE */
-png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length)
-{
-   if (png_ptr == NULL)
-      return;
-
-   png_read_data(png_ptr, buf, length);
-   png_calculate_crc(png_ptr, buf, length);
-}
-
-/* Optionally skip data and then check the CRC.  Depending on whether we
- * are reading an ancillary or critical chunk, and how the program has set
- * things up, we may calculate the CRC on the data and print a message.
- * Returns '1' if there was a CRC error, '0' otherwise.
- */
-int /* PRIVATE */
-png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
-{
-   /* The size of the local buffer for inflate is a good guess as to a
-    * reasonable size to use for buffering reads from the application.
-    */
-   while (skip > 0)
-   {
-      png_uint_32 len;
-      png_byte tmpbuf[PNG_INFLATE_BUF_SIZE];
-
-      len = (sizeof tmpbuf);
-      if (len > skip)
-         len = skip;
-      skip -= len;
-
-      png_crc_read(png_ptr, tmpbuf, len);
-   }
-
-   if (png_crc_error(png_ptr) != 0)
-   {
-      if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0 ?
-          (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0 :
-          (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE) != 0)
-      {
-         png_chunk_warning(png_ptr, "CRC error");
-      }
-
-      else
-         png_chunk_error(png_ptr, "CRC error");
-
-      return (1);
-   }
-
-   return (0);
-}
-
-/* Compare the CRC stored in the PNG file with that calculated by libpng from
- * the data it has read thus far.
- */
-int /* PRIVATE */
-png_crc_error(png_structrp png_ptr)
-{
-   png_byte crc_bytes[4];
-   png_uint_32 crc;
-   int need_crc = 1;
-
-   if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
-   {
-      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
-          (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
-         need_crc = 0;
-   }
-
-   else /* critical */
-   {
-      if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
-         need_crc = 0;
-   }
-
-#ifdef PNG_IO_STATE_SUPPORTED
-   png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
-#endif
-
-   /* The chunk CRC must be serialized in a single I/O call. */
-   png_read_data(png_ptr, crc_bytes, 4);
-
-   if (need_crc != 0)
-   {
-      crc = png_get_uint_32(crc_bytes);
-      return ((int)(crc != png_ptr->crc));
-   }
-
-   else
-      return (0);
-}
-
-#if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
-    defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_sCAL_SUPPORTED) ||\
-    defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) ||\
-    defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_SEQUENTIAL_READ_SUPPORTED)
-/* Manage the read buffer; this simply reallocates the buffer if it is not small
- * enough (or if it is not allocated).  The routine returns a pointer to the
- * buffer; if an error occurs and 'warn' is set the routine returns NULL, else
- * it will call png_error (via png_malloc) on failure.  (warn == 2 means
- * 'silent').
- */
-static png_bytep
-png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
-{
-   png_bytep buffer = png_ptr->read_buffer;
-
-   if (buffer != NULL && new_size > png_ptr->read_buffer_size)
-   {
-      png_ptr->read_buffer = NULL;
-      png_ptr->read_buffer = NULL;
-      png_ptr->read_buffer_size = 0;
-      png_free(png_ptr, buffer);
-      buffer = NULL;
-   }
-
-   if (buffer == NULL)
-   {
-      buffer = png_voidcast(png_bytep, png_malloc_base(png_ptr, new_size));
-
-      if (buffer != NULL)
-      {
-         memset(buffer, 0, new_size); /* just in case */
-         png_ptr->read_buffer = buffer;
-         png_ptr->read_buffer_size = new_size;
-      }
-
-      else if (warn < 2) /* else silent */
-      {
-         if (warn != 0)
-             png_chunk_warning(png_ptr, "insufficient memory to read chunk");
-
-         else
-             png_chunk_error(png_ptr, "insufficient memory to read chunk");
-      }
-   }
-
-   return buffer;
-}
-#endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|SEQUENTIAL_READ */
-
-/* png_inflate_claim: claim the zstream for some nefarious purpose that involves
- * decompression.  Returns Z_OK on success, else a zlib error code.  It checks
- * the owner but, in final release builds, just issues a warning if some other
- * chunk apparently owns the stream.  Prior to release it does a png_error.
- */
-static int
-png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
-{
-   if (png_ptr->zowner != 0)
-   {
-      char msg[64];
-
-      PNG_STRING_FROM_CHUNK(msg, png_ptr->zowner);
-      /* So the message that results is "<chunk> using zstream"; this is an
-       * internal error, but is very useful for debugging.  i18n requirements
-       * are minimal.
-       */
-      (void)png_safecat(msg, (sizeof msg), 4, " using zstream");
-#if PNG_RELEASE_BUILD
-      png_chunk_warning(png_ptr, msg);
-      png_ptr->zowner = 0;
-#else
-      png_chunk_error(png_ptr, msg);
-#endif
-   }
-
-   /* Implementation note: unlike 'png_deflate_claim' this internal function
-    * does not take the size of the data as an argument.  Some efficiency could
-    * be gained by using this when it is known *if* the zlib stream itself does
-    * not record the number; however, this is an illusion: the original writer
-    * of the PNG may have selected a lower window size, and we really must
-    * follow that because, for systems with with limited capabilities, we
-    * would otherwise reject the application's attempts to use a smaller window
-    * size (zlib doesn't have an interface to say "this or lower"!).
-    *
-    * inflateReset2 was added to zlib 1.2.4; before this the window could not be
-    * reset, therefore it is necessary to always allocate the maximum window
-    * size with earlier zlibs just in case later compressed chunks need it.
-    */
-   {
-      int ret; /* zlib return code */
-#if ZLIB_VERNUM >= 0x1240
-      int window_bits = 0;
-
-# if defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_MAXIMUM_INFLATE_WINDOW)
-      if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) ==
-          PNG_OPTION_ON)
-      {
-         window_bits = 15;
-         png_ptr->zstream_start = 0; /* fixed window size */
-      }
-
-      else
-      {
-         png_ptr->zstream_start = 1;
-      }
-# endif
-
-#endif /* ZLIB_VERNUM >= 0x1240 */
-
-      /* Set this for safety, just in case the previous owner left pointers to
-       * memory allocations.
-       */
-      png_ptr->zstream.next_in = NULL;
-      png_ptr->zstream.avail_in = 0;
-      png_ptr->zstream.next_out = NULL;
-      png_ptr->zstream.avail_out = 0;
-
-      if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
-      {
-#if ZLIB_VERNUM >= 0x1240
-         ret = inflateReset2(&png_ptr->zstream, window_bits);
-#else
-         ret = inflateReset(&png_ptr->zstream);
-#endif
-      }
-
-      else
-      {
-#if ZLIB_VERNUM >= 0x1240
-         ret = inflateInit2(&png_ptr->zstream, window_bits);
-#else
-         ret = inflateInit(&png_ptr->zstream);
-#endif
-
-         if (ret == Z_OK)
-            png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
-      }
-
-#if ZLIB_VERNUM >= 0x1290 && \
-   defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_IGNORE_ADLER32)
-      if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON)
-         /* Turn off validation of the ADLER32 checksum in IDAT chunks */
-         ret = inflateValidate(&png_ptr->zstream, 0);
-#endif
-
-      if (ret == Z_OK)
-         png_ptr->zowner = owner;
-
-      else
-         png_zstream_error(png_ptr, ret);
-
-      return ret;
-   }
-
-#ifdef window_bits
-# undef window_bits
-#endif
-}
-
-#if ZLIB_VERNUM >= 0x1240
-/* Handle the start of the inflate stream if we called inflateInit2(strm,0);
- * in this case some zlib versions skip validation of the CINFO field and, in
- * certain circumstances, libpng may end up displaying an invalid image, in
- * contrast to implementations that call zlib in the normal way (e.g. libpng
- * 1.5).
- */
-int /* PRIVATE */
-png_zlib_inflate(png_structrp png_ptr, int flush)
-{
-   if (png_ptr->zstream_start && png_ptr->zstream.avail_in > 0)
-   {
-      if ((*png_ptr->zstream.next_in >> 4) > 7)
-      {
-         png_ptr->zstream.msg = "invalid window size (libpng)";
-         return Z_DATA_ERROR;
-      }
-
-      png_ptr->zstream_start = 0;
-   }
-
-   return inflate(&png_ptr->zstream, flush);
-}
-#endif /* Zlib >= 1.2.4 */
-
-#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED
-#if defined(PNG_READ_zTXt_SUPPORTED) || defined (PNG_READ_iTXt_SUPPORTED)
-/* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to
- * allow the caller to do multiple calls if required.  If the 'finish' flag is
- * set Z_FINISH will be passed to the final inflate() call and Z_STREAM_END must
- * be returned or there has been a problem, otherwise Z_SYNC_FLUSH is used and
- * Z_OK or Z_STREAM_END will be returned on success.
- *
- * The input and output sizes are updated to the actual amounts of data consumed
- * or written, not the amount available (as in a z_stream).  The data pointers
- * are not changed, so the next input is (data+input_size) and the next
- * available output is (output+output_size).
- */
-static int
-png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish,
-    /* INPUT: */ png_const_bytep input, png_uint_32p input_size_ptr,
-    /* OUTPUT: */ png_bytep output, png_alloc_size_t *output_size_ptr)
-{
-   if (png_ptr->zowner == owner) /* Else not claimed */
-   {
-      int ret;
-      png_alloc_size_t avail_out = *output_size_ptr;
-      png_uint_32 avail_in = *input_size_ptr;
-
-      /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it
-       * can't even necessarily handle 65536 bytes) because the type uInt is
-       * "16 bits or more".  Consequently it is necessary to chunk the input to
-       * zlib.  This code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the
-       * maximum value that can be stored in a uInt.)  It is possible to set
-       * ZLIB_IO_MAX to a lower value in pngpriv.h and this may sometimes have
-       * a performance advantage, because it reduces the amount of data accessed
-       * at each step and that may give the OS more time to page it in.
-       */
-      png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
-      /* avail_in and avail_out are set below from 'size' */
-      png_ptr->zstream.avail_in = 0;
-      png_ptr->zstream.avail_out = 0;
-
-      /* Read directly into the output if it is available (this is set to
-       * a local buffer below if output is NULL).
-       */
-      if (output != NULL)
-         png_ptr->zstream.next_out = output;
-
-      do
-      {
-         uInt avail;
-         Byte local_buffer[PNG_INFLATE_BUF_SIZE];
-
-         /* zlib INPUT BUFFER */
-         /* The setting of 'avail_in' used to be outside the loop; by setting it
-          * inside it is possible to chunk the input to zlib and simply rely on
-          * zlib to advance the 'next_in' pointer.  This allows arbitrary
-          * amounts of data to be passed through zlib at the unavoidable cost of
-          * requiring a window save (memcpy of up to 32768 output bytes)
-          * every ZLIB_IO_MAX input bytes.
-          */
-         avail_in += png_ptr->zstream.avail_in; /* not consumed last time */
-
-         avail = ZLIB_IO_MAX;
-
-         if (avail_in < avail)
-            avail = (uInt)avail_in; /* safe: < than ZLIB_IO_MAX */
-
-         avail_in -= avail;
-         png_ptr->zstream.avail_in = avail;
-
-         /* zlib OUTPUT BUFFER */
-         avail_out += png_ptr->zstream.avail_out; /* not written last time */
-
-         avail = ZLIB_IO_MAX; /* maximum zlib can process */
-
-         if (output == NULL)
-         {
-            /* Reset the output buffer each time round if output is NULL and
-             * make available the full buffer, up to 'remaining_space'
-             */
-            png_ptr->zstream.next_out = local_buffer;
-            if ((sizeof local_buffer) < avail)
-               avail = (sizeof local_buffer);
-         }
-
-         if (avail_out < avail)
-            avail = (uInt)avail_out; /* safe: < ZLIB_IO_MAX */
-
-         png_ptr->zstream.avail_out = avail;
-         avail_out -= avail;
-
-         /* zlib inflate call */
-         /* In fact 'avail_out' may be 0 at this point, that happens at the end
-          * of the read when the final LZ end code was not passed at the end of
-          * the previous chunk of input data.  Tell zlib if we have reached the
-          * end of the output buffer.
-          */
-         ret = PNG_INFLATE(png_ptr, avail_out > 0 ? Z_NO_FLUSH :
-             (finish ? Z_FINISH : Z_SYNC_FLUSH));
-      } while (ret == Z_OK);
-
-      /* For safety kill the local buffer pointer now */
-      if (output == NULL)
-         png_ptr->zstream.next_out = NULL;
-
-      /* Claw back the 'size' and 'remaining_space' byte counts. */
-      avail_in += png_ptr->zstream.avail_in;
-      avail_out += png_ptr->zstream.avail_out;
-
-      /* Update the input and output sizes; the updated values are the amount
-       * consumed or written, effectively the inverse of what zlib uses.
-       */
-      if (avail_out > 0)
-         *output_size_ptr -= avail_out;
-
-      if (avail_in > 0)
-         *input_size_ptr -= avail_in;
-
-      /* Ensure png_ptr->zstream.msg is set (even in the success case!) */
-      png_zstream_error(png_ptr, ret);
-      return ret;
-   }
-
-   else
-   {
-      /* This is a bad internal error.  The recovery assigns to the zstream msg
-       * pointer, which is not owned by the caller, but this is safe; it's only
-       * used on errors!
-       */
-      png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed");
-      return Z_STREAM_ERROR;
-   }
-}
-
-/*
- * Decompress trailing data in a chunk.  The assumption is that read_buffer
- * points at an allocated area holding the contents of a chunk with a
- * trailing compressed part.  What we get back is an allocated area
- * holding the original prefix part and an uncompressed version of the
- * trailing part (the malloc area passed in is freed).
- */
-static int
-png_decompress_chunk(png_structrp png_ptr,
-    png_uint_32 chunklength, png_uint_32 prefix_size,
-    png_alloc_size_t *newlength /* must be initialized to the maximum! */,
-    int terminate /*add a '\0' to the end of the uncompressed data*/)
-{
-   /* TODO: implement different limits for different types of chunk.
-    *
-    * The caller supplies *newlength set to the maximum length of the
-    * uncompressed data, but this routine allocates space for the prefix and
-    * maybe a '\0' terminator too.  We have to assume that 'prefix_size' is
-    * limited only by the maximum chunk size.
-    */
-   png_alloc_size_t limit = PNG_SIZE_MAX;
-
-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (png_ptr->user_chunk_malloc_max > 0 &&
-       png_ptr->user_chunk_malloc_max < limit)
-      limit = png_ptr->user_chunk_malloc_max;
-# elif PNG_USER_CHUNK_MALLOC_MAX > 0
-   if (PNG_USER_CHUNK_MALLOC_MAX < limit)
-      limit = PNG_USER_CHUNK_MALLOC_MAX;
-# endif
-
-   if (limit >= prefix_size + (terminate != 0))
-   {
-      int ret;
-
-      limit -= prefix_size + (terminate != 0);
-
-      if (limit < *newlength)
-         *newlength = limit;
-
-      /* Now try to claim the stream. */
-      ret = png_inflate_claim(png_ptr, png_ptr->chunk_name);
-
-      if (ret == Z_OK)
-      {
-         png_uint_32 lzsize = chunklength - prefix_size;
-
-         ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,
-             /* input: */ png_ptr->read_buffer + prefix_size, &lzsize,
-             /* output: */ NULL, newlength);
-
-         if (ret == Z_STREAM_END)
-         {
-            /* Use 'inflateReset' here, not 'inflateReset2' because this
-             * preserves the previously decided window size (otherwise it would
-             * be necessary to store the previous window size.)  In practice
-             * this doesn't matter anyway, because png_inflate will call inflate
-             * with Z_FINISH in almost all cases, so the window will not be
-             * maintained.
-             */
-            if (inflateReset(&png_ptr->zstream) == Z_OK)
-            {
-               /* Because of the limit checks above we know that the new,
-                * expanded, size will fit in a size_t (let alone an
-                * png_alloc_size_t).  Use png_malloc_base here to avoid an
-                * extra OOM message.
-                */
-               png_alloc_size_t new_size = *newlength;
-               png_alloc_size_t buffer_size = prefix_size + new_size +
-                   (terminate != 0);
-               png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr,
-                   buffer_size));
-
-               if (text != NULL)
-               {
-                  memset(text, 0, buffer_size);
-
-                  ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,
-                      png_ptr->read_buffer + prefix_size, &lzsize,
-                      text + prefix_size, newlength);
-
-                  if (ret == Z_STREAM_END)
-                  {
-                     if (new_size == *newlength)
-                     {
-                        if (terminate != 0)
-                           text[prefix_size + *newlength] = 0;
-
-                        if (prefix_size > 0)
-                           memcpy(text, png_ptr->read_buffer, prefix_size);
-
-                        {
-                           png_bytep old_ptr = png_ptr->read_buffer;
-
-                           png_ptr->read_buffer = text;
-                           png_ptr->read_buffer_size = buffer_size;
-                           text = old_ptr; /* freed below */
-                        }
-                     }
-
-                     else
-                     {
-                        /* The size changed on the second read, there can be no
-                         * guarantee that anything is correct at this point.
-                         * The 'msg' pointer has been set to "unexpected end of
-                         * LZ stream", which is fine, but return an error code
-                         * that the caller won't accept.
-                         */
-                        ret = PNG_UNEXPECTED_ZLIB_RETURN;
-                     }
-                  }
-
-                  else if (ret == Z_OK)
-                     ret = PNG_UNEXPECTED_ZLIB_RETURN; /* for safety */
-
-                  /* Free the text pointer (this is the old read_buffer on
-                   * success)
-                   */
-                  png_free(png_ptr, text);
-
-                  /* This really is very benign, but it's still an error because
-                   * the extra space may otherwise be used as a Trojan Horse.
-                   */
-                  if (ret == Z_STREAM_END &&
-                      chunklength - prefix_size != lzsize)
-                     png_chunk_benign_error(png_ptr, "extra compressed data");
-               }
-
-               else
-               {
-                  /* Out of memory allocating the buffer */
-                  ret = Z_MEM_ERROR;
-                  png_zstream_error(png_ptr, Z_MEM_ERROR);
-               }
-            }
-
-            else
-            {
-               /* inflateReset failed, store the error message */
-               png_zstream_error(png_ptr, ret);
-               ret = PNG_UNEXPECTED_ZLIB_RETURN;
-            }
-         }
-
-         else if (ret == Z_OK)
-            ret = PNG_UNEXPECTED_ZLIB_RETURN;
-
-         /* Release the claimed stream */
-         png_ptr->zowner = 0;
-      }
-
-      else /* the claim failed */ if (ret == Z_STREAM_END) /* impossible! */
-         ret = PNG_UNEXPECTED_ZLIB_RETURN;
-
-      return ret;
-   }
-
-   else
-   {
-      /* Application/configuration limits exceeded */
-      png_zstream_error(png_ptr, Z_MEM_ERROR);
-      return Z_MEM_ERROR;
-   }
-}
-#endif /* READ_zTXt || READ_iTXt */
-#endif /* READ_COMPRESSED_TEXT */
-
-#ifdef PNG_READ_iCCP_SUPPORTED
-/* Perform a partial read and decompress, producing 'avail_out' bytes and
- * reading from the current chunk as required.
- */
-static int
-png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size,
-    png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size,
-    int finish)
-{
-   if (png_ptr->zowner == png_ptr->chunk_name)
-   {
-      int ret;
-
-      /* next_in and avail_in must have been initialized by the caller. */
-      png_ptr->zstream.next_out = next_out;
-      png_ptr->zstream.avail_out = 0; /* set in the loop */
-
-      do
-      {
-         if (png_ptr->zstream.avail_in == 0)
-         {
-            if (read_size > *chunk_bytes)
-               read_size = (uInt)*chunk_bytes;
-            *chunk_bytes -= read_size;
-
-            if (read_size > 0)
-               png_crc_read(png_ptr, read_buffer, read_size);
-
-            png_ptr->zstream.next_in = read_buffer;
-            png_ptr->zstream.avail_in = read_size;
-         }
-
-         if (png_ptr->zstream.avail_out == 0)
-         {
-            uInt avail = ZLIB_IO_MAX;
-            if (avail > *out_size)
-               avail = (uInt)*out_size;
-            *out_size -= avail;
-
-            png_ptr->zstream.avail_out = avail;
-         }
-
-         /* Use Z_SYNC_FLUSH when there is no more chunk data to ensure that all
-          * the available output is produced; this allows reading of truncated
-          * streams.
-          */
-         ret = PNG_INFLATE(png_ptr, *chunk_bytes > 0 ?
-             Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH));
-      }
-      while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0));
-
-      *out_size += png_ptr->zstream.avail_out;
-      png_ptr->zstream.avail_out = 0; /* Should not be required, but is safe */
-
-      /* Ensure the error message pointer is always set: */
-      png_zstream_error(png_ptr, ret);
-      return ret;
-   }
-
-   else
-   {
-      png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed");
-      return Z_STREAM_ERROR;
-   }
-}
-#endif /* READ_iCCP */
-
-/* Read and check the IDHR chunk */
-
-void /* PRIVATE */
-png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_byte buf[13];
-   png_uint_32 width, height;
-   int bit_depth, color_type, compression_type, filter_type;
-   int interlace_type;
-
-   png_debug(1, "in png_handle_IHDR");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) != 0)
-      png_chunk_error(png_ptr, "out of place");
-
-   /* Check the length */
-   if (length != 13)
-      png_chunk_error(png_ptr, "invalid");
-
-   png_ptr->mode |= PNG_HAVE_IHDR;
-
-   png_crc_read(png_ptr, buf, 13);
-   png_crc_finish(png_ptr, 0);
-
-   width = png_get_uint_31(png_ptr, buf);
-   height = png_get_uint_31(png_ptr, buf + 4);
-   bit_depth = buf[8];
-   color_type = buf[9];
-   compression_type = buf[10];
-   filter_type = buf[11];
-   interlace_type = buf[12];
-
-   /* Set internal variables */
-   png_ptr->width = width;
-   png_ptr->height = height;
-   png_ptr->bit_depth = (png_byte)bit_depth;
-   png_ptr->interlaced = (png_byte)interlace_type;
-   png_ptr->color_type = (png_byte)color_type;
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-   png_ptr->filter_type = (png_byte)filter_type;
-#endif
-   png_ptr->compression_type = (png_byte)compression_type;
-
-   /* Find number of channels */
-   switch (png_ptr->color_type)
-   {
-      default: /* invalid, png_set_IHDR calls png_error */
-      case PNG_COLOR_TYPE_GRAY:
-      case PNG_COLOR_TYPE_PALETTE:
-         png_ptr->channels = 1;
-         break;
-
-      case PNG_COLOR_TYPE_RGB:
-         png_ptr->channels = 3;
-         break;
-
-      case PNG_COLOR_TYPE_GRAY_ALPHA:
-         png_ptr->channels = 2;
-         break;
-
-      case PNG_COLOR_TYPE_RGB_ALPHA:
-         png_ptr->channels = 4;
-         break;
-   }
-
-   /* Set up other useful info */
-   png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * png_ptr->channels);
-   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
-   png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
-   png_debug1(3, "channels = %d", png_ptr->channels);
-   png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes);
-   png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
-       color_type, interlace_type, compression_type, filter_type);
-}
-
-/* Read and check the palette */
-void /* PRIVATE */
-png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_color palette[PNG_MAX_PALETTE_LENGTH];
-   int max_palette_length, num, i;
-#ifdef PNG_POINTER_INDEXING_SUPPORTED
-   png_colorp pal_ptr;
-#endif
-
-   png_debug(1, "in png_handle_PLTE");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   /* Moved to before the 'after IDAT' check below because otherwise duplicate
-    * PLTE chunks are potentially ignored (the spec says there shall not be more
-    * than one PLTE, the error is not treated as benign, so this check trumps
-    * the requirement that PLTE appears before IDAT.)
-    */
-   else if ((png_ptr->mode & PNG_HAVE_PLTE) != 0)
-      png_chunk_error(png_ptr, "duplicate");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      /* This is benign because the non-benign error happened before, when an
-       * IDAT was encountered in a color-mapped image with no PLTE.
-       */
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   png_ptr->mode |= PNG_HAVE_PLTE;
-
-   if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "ignored in grayscale PNG");
-      return;
-   }
-
-#ifndef PNG_READ_OPT_PLTE_SUPPORTED
-   if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
-   {
-      png_crc_finish(png_ptr, length);
-      return;
-   }
-#endif
-
-   if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
-   {
-      png_crc_finish(png_ptr, length);
-
-      if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
-         png_chunk_benign_error(png_ptr, "invalid");
-
-      else
-         png_chunk_error(png_ptr, "invalid");
-
-      return;
-   }
-
-   /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */
-   num = (int)length / 3;
-
-   /* If the palette has 256 or fewer entries but is too large for the bit
-    * depth, we don't issue an error, to preserve the behavior of previous
-    * libpng versions. We silently truncate the unused extra palette entries
-    * here.
-    */
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      max_palette_length = (1 << png_ptr->bit_depth);
-   else
-      max_palette_length = PNG_MAX_PALETTE_LENGTH;
-
-   if (num > max_palette_length)
-      num = max_palette_length;
-
-#ifdef PNG_POINTER_INDEXING_SUPPORTED
-   for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
-   {
-      png_byte buf[3];
-
-      png_crc_read(png_ptr, buf, 3);
-      pal_ptr->red = buf[0];
-      pal_ptr->green = buf[1];
-      pal_ptr->blue = buf[2];
-   }
-#else
-   for (i = 0; i < num; i++)
-   {
-      png_byte buf[3];
-
-      png_crc_read(png_ptr, buf, 3);
-      /* Don't depend upon png_color being any order */
-      palette[i].red = buf[0];
-      palette[i].green = buf[1];
-      palette[i].blue = buf[2];
-   }
-#endif
-
-   /* If we actually need the PLTE chunk (ie for a paletted image), we do
-    * whatever the normal CRC configuration tells us.  However, if we
-    * have an RGB image, the PLTE can be considered ancillary, so
-    * we will act as though it is.
-    */
-#ifndef PNG_READ_OPT_PLTE_SUPPORTED
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-#endif
-   {
-      png_crc_finish(png_ptr, (png_uint_32) (length - (unsigned int)num * 3));
-   }
-
-#ifndef PNG_READ_OPT_PLTE_SUPPORTED
-   else if (png_crc_error(png_ptr) != 0)  /* Only if we have a CRC error */
-   {
-      /* If we don't want to use the data from an ancillary chunk,
-       * we have two options: an error abort, or a warning and we
-       * ignore the data in this chunk (which should be OK, since
-       * it's considered ancillary for a RGB or RGBA image).
-       *
-       * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the
-       * chunk type to determine whether to check the ancillary or the critical
-       * flags.
-       */
-      if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE) == 0)
-      {
-         if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) != 0)
-            return;
-
-         else
-            png_chunk_error(png_ptr, "CRC error");
-      }
-
-      /* Otherwise, we (optionally) emit a warning and use the chunk. */
-      else if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0)
-         png_chunk_warning(png_ptr, "CRC error");
-   }
-#endif
-
-   /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its
-    * own copy of the palette.  This has the side effect that when png_start_row
-    * is called (this happens after any call to png_read_update_info) the
-    * info_ptr palette gets changed.  This is extremely unexpected and
-    * confusing.
-    *
-    * Fix this by not sharing the palette in this way.
-    */
-   png_set_PLTE(png_ptr, info_ptr, palette, num);
-
-   /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before
-    * IDAT.  Prior to 1.6.0 this was not checked; instead the code merely
-    * checked the apparent validity of a tRNS chunk inserted before PLTE on a
-    * palette PNG.  1.6.0 attempts to rigorously follow the standard and
-    * therefore does a benign error if the erroneous condition is detected *and*
-    * cancels the tRNS if the benign error returns.  The alternative is to
-    * amend the standard since it would be rather hypocritical of the standards
-    * maintainers to ignore it.
-    */
-#ifdef PNG_READ_tRNS_SUPPORTED
-   if (png_ptr->num_trans > 0 ||
-       (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0))
-   {
-      /* Cancel this because otherwise it would be used if the transforms
-       * require it.  Don't cancel the 'valid' flag because this would prevent
-       * detection of duplicate chunks.
-       */
-      png_ptr->num_trans = 0;
-
-      if (info_ptr != NULL)
-         info_ptr->num_trans = 0;
-
-      png_chunk_benign_error(png_ptr, "tRNS must be after");
-   }
-#endif
-
-#ifdef PNG_READ_hIST_SUPPORTED
-   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
-      png_chunk_benign_error(png_ptr, "hIST must be after");
-#endif
-
-#ifdef PNG_READ_bKGD_SUPPORTED
-   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
-      png_chunk_benign_error(png_ptr, "bKGD must be after");
-#endif
-}
-
-void /* PRIVATE */
-png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_debug(1, "in png_handle_IEND");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0 ||
-       (png_ptr->mode & PNG_HAVE_IDAT) == 0)
-      png_chunk_error(png_ptr, "out of place");
-
-   png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
-
-   png_crc_finish(png_ptr, length);
-
-   if (length != 0)
-      png_chunk_benign_error(png_ptr, "invalid");
-
-   PNG_UNUSED(info_ptr)
-}
-
-#ifdef PNG_READ_gAMA_SUPPORTED
-void /* PRIVATE */
-png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_fixed_point igamma;
-   png_byte buf[4];
-
-   png_debug(1, "in png_handle_gAMA");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   if (length != 4)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
-   png_crc_read(png_ptr, buf, 4);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   igamma = png_get_fixed_point(NULL, buf);
-
-   png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma);
-   png_colorspace_sync(png_ptr, info_ptr);
-}
-#endif
-
-#ifdef PNG_READ_sBIT_SUPPORTED
-void /* PRIVATE */
-png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   unsigned int truelen, i;
-   png_byte sample_depth;
-   png_byte buf[4];
-
-   png_debug(1, "in png_handle_sBIT");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-   {
-      truelen = 3;
-      sample_depth = 8;
-   }
-
-   else
-   {
-      truelen = png_ptr->channels;
-      sample_depth = png_ptr->bit_depth;
-   }
-
-   if (length != truelen || length > 4)
-   {
-      png_chunk_benign_error(png_ptr, "invalid");
-      png_crc_finish(png_ptr, length);
-      return;
-   }
-
-   buf[0] = buf[1] = buf[2] = buf[3] = sample_depth;
-   png_crc_read(png_ptr, buf, truelen);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   for (i=0; i<truelen; ++i)
-   {
-      if (buf[i] == 0 || buf[i] > sample_depth)
-      {
-         png_chunk_benign_error(png_ptr, "invalid");
-         return;
-      }
-   }
-
-   if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
-   {
-      png_ptr->sig_bit.red = buf[0];
-      png_ptr->sig_bit.green = buf[1];
-      png_ptr->sig_bit.blue = buf[2];
-      png_ptr->sig_bit.alpha = buf[3];
-   }
-
-   else
-   {
-      png_ptr->sig_bit.gray = buf[0];
-      png_ptr->sig_bit.red = buf[0];
-      png_ptr->sig_bit.green = buf[0];
-      png_ptr->sig_bit.blue = buf[0];
-      png_ptr->sig_bit.alpha = buf[1];
-   }
-
-   png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
-}
-#endif
-
-#ifdef PNG_READ_cHRM_SUPPORTED
-void /* PRIVATE */
-png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_byte buf[32];
-   png_xy xy;
-
-   png_debug(1, "in png_handle_cHRM");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   if (length != 32)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
-   png_crc_read(png_ptr, buf, 32);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   xy.whitex = png_get_fixed_point(NULL, buf);
-   xy.whitey = png_get_fixed_point(NULL, buf + 4);
-   xy.redx   = png_get_fixed_point(NULL, buf + 8);
-   xy.redy   = png_get_fixed_point(NULL, buf + 12);
-   xy.greenx = png_get_fixed_point(NULL, buf + 16);
-   xy.greeny = png_get_fixed_point(NULL, buf + 20);
-   xy.bluex  = png_get_fixed_point(NULL, buf + 24);
-   xy.bluey  = png_get_fixed_point(NULL, buf + 28);
-
-   if (xy.whitex == PNG_FIXED_ERROR ||
-       xy.whitey == PNG_FIXED_ERROR ||
-       xy.redx   == PNG_FIXED_ERROR ||
-       xy.redy   == PNG_FIXED_ERROR ||
-       xy.greenx == PNG_FIXED_ERROR ||
-       xy.greeny == PNG_FIXED_ERROR ||
-       xy.bluex  == PNG_FIXED_ERROR ||
-       xy.bluey  == PNG_FIXED_ERROR)
-   {
-      png_chunk_benign_error(png_ptr, "invalid values");
-      return;
-   }
-
-   /* If a colorspace error has already been output skip this chunk */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
-      return;
-
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0)
-   {
-      png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
-      png_colorspace_sync(png_ptr, info_ptr);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
-   (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy,
-       1/*prefer cHRM values*/);
-   png_colorspace_sync(png_ptr, info_ptr);
-}
-#endif
-
-#ifdef PNG_READ_sRGB_SUPPORTED
-void /* PRIVATE */
-png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_byte intent;
-
-   png_debug(1, "in png_handle_sRGB");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   if (length != 1)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
-   png_crc_read(png_ptr, &intent, 1);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   /* If a colorspace error has already been output skip this chunk */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
-      return;
-
-   /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
-    * this.
-    */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) != 0)
-   {
-      png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
-      png_colorspace_sync(png_ptr, info_ptr);
-      png_chunk_benign_error(png_ptr, "too many profiles");
-      return;
-   }
-
-   (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent);
-   png_colorspace_sync(png_ptr, info_ptr);
-}
-#endif /* READ_sRGB */
-
-#ifdef PNG_READ_iCCP_SUPPORTED
-void /* PRIVATE */
-png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-/* Note: this does not properly handle profiles that are > 64K under DOS */
-{
-   png_const_charp errmsg = NULL; /* error message output, or no error */
-   int finished = 0; /* crc checked */
-
-   png_debug(1, "in png_handle_iCCP");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   /* Consistent with all the above colorspace handling an obviously *invalid*
-    * chunk is just ignored, so does not invalidate the color space.  An
-    * alternative is to set the 'invalid' flags at the start of this routine
-    * and only clear them in they were not set before and all the tests pass.
-    */
-
-   /* The keyword must be at least one character and there is a
-    * terminator (0) byte and the compression method byte, and the
-    * 'zlib' datastream is at least 11 bytes.
-    */
-   if (length < 14)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "too short");
-      return;
-   }
-
-   /* If a colorspace error has already been output skip this chunk */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      return;
-   }
-
-   /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
-    * this.
-    */
-   if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0)
-   {
-      uInt read_length, keyword_length;
-      char keyword[81];
-
-      /* Find the keyword; the keyword plus separator and compression method
-       * bytes can be at most 81 characters long.
-       */
-      read_length = 81; /* maximum */
-      if (read_length > length)
-         read_length = (uInt)length;
-
-      png_crc_read(png_ptr, (png_bytep)keyword, read_length);
-      length -= read_length;
-
-      /* The minimum 'zlib' stream is assumed to be just the 2 byte header,
-       * 5 bytes minimum 'deflate' stream, and the 4 byte checksum.
-       */
-      if (length < 11)
-      {
-         png_crc_finish(png_ptr, length);
-         png_chunk_benign_error(png_ptr, "too short");
-         return;
-      }
-
-      keyword_length = 0;
-      while (keyword_length < 80 && keyword_length < read_length &&
-         keyword[keyword_length] != 0)
-         ++keyword_length;
-
-      /* TODO: make the keyword checking common */
-      if (keyword_length >= 1 && keyword_length <= 79)
-      {
-         /* We only understand '0' compression - deflate - so if we get a
-          * different value we can't safely decode the chunk.
-          */
-         if (keyword_length+1 < read_length &&
-            keyword[keyword_length+1] == PNG_COMPRESSION_TYPE_BASE)
-         {
-            read_length -= keyword_length+2;
-
-            if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK)
-            {
-               Byte profile_header[132]={0};
-               Byte local_buffer[PNG_INFLATE_BUF_SIZE];
-               png_alloc_size_t size = (sizeof profile_header);
-
-               png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2);
-               png_ptr->zstream.avail_in = read_length;
-               (void)png_inflate_read(png_ptr, local_buffer,
-                   (sizeof local_buffer), &length, profile_header, &size,
-                   0/*finish: don't, because the output is too small*/);
-
-               if (size == 0)
-               {
-                  /* We have the ICC profile header; do the basic header checks.
-                   */
-                  png_uint_32 profile_length = png_get_uint_32(profile_header);
-
-                  if (png_icc_check_length(png_ptr, &png_ptr->colorspace,
-                      keyword, profile_length) != 0)
-                  {
-                     /* The length is apparently ok, so we can check the 132
-                      * byte header.
-                      */
-                     if (png_icc_check_header(png_ptr, &png_ptr->colorspace,
-                         keyword, profile_length, profile_header,
-                         png_ptr->color_type) != 0)
-                     {
-                        /* Now read the tag table; a variable size buffer is
-                         * needed at this point, allocate one for the whole
-                         * profile.  The header check has already validated
-                         * that none of this stuff will overflow.
-                         */
-                        png_uint_32 tag_count =
-                           png_get_uint_32(profile_header + 128);
-                        png_bytep profile = png_read_buffer(png_ptr,
-                            profile_length, 2/*silent*/);
-
-                        if (profile != NULL)
-                        {
-                           memcpy(profile, profile_header,
-                               (sizeof profile_header));
-
-                           size = 12 * tag_count;
-
-                           (void)png_inflate_read(png_ptr, local_buffer,
-                               (sizeof local_buffer), &length,
-                               profile + (sizeof profile_header), &size, 0);
-
-                           /* Still expect a buffer error because we expect
-                            * there to be some tag data!
-                            */
-                           if (size == 0)
-                           {
-                              if (png_icc_check_tag_table(png_ptr,
-                                  &png_ptr->colorspace, keyword, profile_length,
-                                  profile) != 0)
-                              {
-                                 /* The profile has been validated for basic
-                                  * security issues, so read the whole thing in.
-                                  */
-                                 size = profile_length - (sizeof profile_header)
-                                     - 12 * tag_count;
-
-                                 (void)png_inflate_read(png_ptr, local_buffer,
-                                     (sizeof local_buffer), &length,
-                                     profile + (sizeof profile_header) +
-                                     12 * tag_count, &size, 1/*finish*/);
-
-                                 if (length > 0 && !(png_ptr->flags &
-                                     PNG_FLAG_BENIGN_ERRORS_WARN))
-                                    errmsg = "extra compressed data";
-
-                                 /* But otherwise allow extra data: */
-                                 else if (size == 0)
-                                 {
-                                    if (length > 0)
-                                    {
-                                       /* This can be handled completely, so
-                                        * keep going.
-                                        */
-                                       png_chunk_warning(png_ptr,
-                                           "extra compressed data");
-                                    }
-
-                                    png_crc_finish(png_ptr, length);
-                                    finished = 1;
-
-# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0
-                                    /* Check for a match against sRGB */
-                                    png_icc_set_sRGB(png_ptr,
-                                        &png_ptr->colorspace, profile,
-                                        png_ptr->zstream.adler);
-# endif
-
-                                    /* Steal the profile for info_ptr. */
-                                    if (info_ptr != NULL)
-                                    {
-                                       png_free_data(png_ptr, info_ptr,
-                                           PNG_FREE_ICCP, 0);
-
-                                       info_ptr->iccp_name = png_voidcast(char*,
-                                           png_malloc_base(png_ptr,
-                                           keyword_length+1));
-                                       if (info_ptr->iccp_name != NULL)
-                                       {
-                                          memcpy(info_ptr->iccp_name, keyword,
-                                              keyword_length+1);
-                                          info_ptr->iccp_proflen =
-                                              profile_length;
-                                          info_ptr->iccp_profile = profile;
-                                          png_ptr->read_buffer = NULL; /*steal*/
-                                          info_ptr->free_me |= PNG_FREE_ICCP;
-                                          info_ptr->valid |= PNG_INFO_iCCP;
-                                       }
-
-                                       else
-                                       {
-                                          png_ptr->colorspace.flags |=
-                                             PNG_COLORSPACE_INVALID;
-                                          errmsg = "out of memory";
-                                       }
-                                    }
-
-                                    /* else the profile remains in the read
-                                     * buffer which gets reused for subsequent
-                                     * chunks.
-                                     */
-
-                                    if (info_ptr != NULL)
-                                       png_colorspace_sync(png_ptr, info_ptr);
-
-                                    if (errmsg == NULL)
-                                    {
-                                       png_ptr->zowner = 0;
-                                       return;
-                                    }
-                                 }
-                                 if (errmsg == NULL)
-                                    errmsg = png_ptr->zstream.msg;
-                              }
-                              /* else png_icc_check_tag_table output an error */
-                           }
-                           else /* profile truncated */
-                              errmsg = png_ptr->zstream.msg;
-                        }
-
-                        else
-                           errmsg = "out of memory";
-                     }
-
-                     /* else png_icc_check_header output an error */
-                  }
-
-                  /* else png_icc_check_length output an error */
-               }
-
-               else /* profile truncated */
-                  errmsg = png_ptr->zstream.msg;
-
-               /* Release the stream */
-               png_ptr->zowner = 0;
-            }
-
-            else /* png_inflate_claim failed */
-               errmsg = png_ptr->zstream.msg;
-         }
-
-         else
-            errmsg = "bad compression method"; /* or missing */
-      }
-
-      else
-         errmsg = "bad keyword";
-   }
-
-   else
-      errmsg = "too many profiles";
-
-   /* Failure: the reason is in 'errmsg' */
-   if (finished == 0)
-      png_crc_finish(png_ptr, length);
-
-   png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
-   png_colorspace_sync(png_ptr, info_ptr);
-   if (errmsg != NULL) /* else already output */
-      png_chunk_benign_error(png_ptr, errmsg);
-}
-#endif /* READ_iCCP */
-
-#ifdef PNG_READ_sPLT_SUPPORTED
-void /* PRIVATE */
-png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-/* Note: this does not properly handle chunks that are > 64K under DOS */
-{
-   png_bytep entry_start, buffer;
-   png_sPLT_t new_palette;
-   png_sPLT_entryp pp;
-   png_uint_32 data_length;
-   int entry_size, i;
-   png_uint_32 skip = 0;
-   png_uint_32 dl;
-   size_t max_dl;
-
-   png_debug(1, "in png_handle_sPLT");
-
-#ifdef PNG_USER_LIMITS_SUPPORTED
-   if (png_ptr->user_chunk_cache_max != 0)
-   {
-      if (png_ptr->user_chunk_cache_max == 1)
-      {
-         png_crc_finish(png_ptr, length);
-         return;
-      }
-
-      if (--png_ptr->user_chunk_cache_max == 1)
-      {
-         png_warning(png_ptr, "No space in chunk cache for sPLT");
-         png_crc_finish(png_ptr, length);
-         return;
-      }
-   }
-#endif
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-#ifdef PNG_MAX_MALLOC_64K
-   if (length > 65535U)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "too large to fit in memory");
-      return;
-   }
-#endif
-
-   buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
-   if (buffer == NULL)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of memory");
-      return;
-   }
-
-
-   /* WARNING: this may break if size_t is less than 32 bits; it is assumed
-    * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a
-    * potential breakage point if the types in pngconf.h aren't exactly right.
-    */
-   png_crc_read(png_ptr, buffer, length);
-
-   if (png_crc_finish(png_ptr, skip) != 0)
-      return;
-
-   buffer[length] = 0;
-
-   for (entry_start = buffer; *entry_start; entry_start++)
-      /* Empty loop to find end of name */ ;
-
-   ++entry_start;
-
-   /* A sample depth should follow the separator, and we should be on it  */
-   if (length < 2U || entry_start > buffer + (length - 2U))
-   {
-      png_warning(png_ptr, "malformed sPLT chunk");
-      return;
-   }
-
-   new_palette.depth = *entry_start++;
-   entry_size = (new_palette.depth == 8 ? 6 : 10);
-   /* This must fit in a png_uint_32 because it is derived from the original
-    * chunk data length.
-    */
-   data_length = length - (png_uint_32)(entry_start - buffer);
-
-   /* Integrity-check the data length */
-   if ((data_length % (unsigned int)entry_size) != 0)
-   {
-      png_warning(png_ptr, "sPLT chunk has bad length");
-      return;
-   }
-
-   dl = (png_uint_32)(data_length / (unsigned int)entry_size);
-   max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry));
-
-   if (dl > max_dl)
-   {
-      png_warning(png_ptr, "sPLT chunk too long");
-      return;
-   }
-
-   new_palette.nentries = (png_int_32)(data_length / (unsigned int)entry_size);
-
-   new_palette.entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
-       (png_alloc_size_t) new_palette.nentries * (sizeof (png_sPLT_entry)));
-
-   if (new_palette.entries == NULL)
-   {
-      png_warning(png_ptr, "sPLT chunk requires too much memory");
-      return;
-   }
-
-#ifdef PNG_POINTER_INDEXING_SUPPORTED
-   for (i = 0; i < new_palette.nentries; i++)
-   {
-      pp = new_palette.entries + i;
-
-      if (new_palette.depth == 8)
-      {
-         pp->red = *entry_start++;
-         pp->green = *entry_start++;
-         pp->blue = *entry_start++;
-         pp->alpha = *entry_start++;
-      }
-
-      else
-      {
-         pp->red   = png_get_uint_16(entry_start); entry_start += 2;
-         pp->green = png_get_uint_16(entry_start); entry_start += 2;
-         pp->blue  = png_get_uint_16(entry_start); entry_start += 2;
-         pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
-      }
-
-      pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
-   }
-#else
-   pp = new_palette.entries;
-
-   for (i = 0; i < new_palette.nentries; i++)
-   {
-
-      if (new_palette.depth == 8)
-      {
-         pp[i].red   = *entry_start++;
-         pp[i].green = *entry_start++;
-         pp[i].blue  = *entry_start++;
-         pp[i].alpha = *entry_start++;
-      }
-
-      else
-      {
-         pp[i].red   = png_get_uint_16(entry_start); entry_start += 2;
-         pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
-         pp[i].blue  = png_get_uint_16(entry_start); entry_start += 2;
-         pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
-      }
-
-      pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2;
-   }
-#endif
-
-   /* Discard all chunk data except the name and stash that */
-   new_palette.name = (png_charp)buffer;
-
-   png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
-
-   png_free(png_ptr, new_palette.entries);
-}
-#endif /* READ_sPLT */
-
-#ifdef PNG_READ_tRNS_SUPPORTED
-void /* PRIVATE */
-png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
-
-   png_debug(1, "in png_handle_tRNS");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
-   {
-      png_byte buf[2];
-
-      if (length != 2)
-      {
-         png_crc_finish(png_ptr, length);
-         png_chunk_benign_error(png_ptr, "invalid");
-         return;
-      }
-
-      png_crc_read(png_ptr, buf, 2);
-      png_ptr->num_trans = 1;
-      png_ptr->trans_color.gray = png_get_uint_16(buf);
-   }
-
-   else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
-   {
-      png_byte buf[6];
-
-      if (length != 6)
-      {
-         png_crc_finish(png_ptr, length);
-         png_chunk_benign_error(png_ptr, "invalid");
-         return;
-      }
-
-      png_crc_read(png_ptr, buf, length);
-      png_ptr->num_trans = 1;
-      png_ptr->trans_color.red = png_get_uint_16(buf);
-      png_ptr->trans_color.green = png_get_uint_16(buf + 2);
-      png_ptr->trans_color.blue = png_get_uint_16(buf + 4);
-   }
-
-   else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-   {
-      if ((png_ptr->mode & PNG_HAVE_PLTE) == 0)
-      {
-         /* TODO: is this actually an error in the ISO spec? */
-         png_crc_finish(png_ptr, length);
-         png_chunk_benign_error(png_ptr, "out of place");
-         return;
-      }
-
-      if (length > (unsigned int) png_ptr->num_palette ||
-         length > (unsigned int) PNG_MAX_PALETTE_LENGTH ||
-         length == 0)
-      {
-         png_crc_finish(png_ptr, length);
-         png_chunk_benign_error(png_ptr, "invalid");
-         return;
-      }
-
-      png_crc_read(png_ptr, readbuf, length);
-      png_ptr->num_trans = (png_uint_16)length;
-   }
-
-   else
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid with alpha channel");
-      return;
-   }
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-   {
-      png_ptr->num_trans = 0;
-      return;
-   }
-
-   /* TODO: this is a horrible side effect in the palette case because the
-    * png_struct ends up with a pointer to the tRNS buffer owned by the
-    * png_info.  Fix this.
-    */
-   png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
-       &(png_ptr->trans_color));
-}
-#endif
-
-#ifdef PNG_READ_bKGD_SUPPORTED
-void /* PRIVATE */
-png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   unsigned int truelen;
-   png_byte buf[6];
-   png_color_16 background;
-
-   png_debug(1, "in png_handle_bKGD");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
-       (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
-       (png_ptr->mode & PNG_HAVE_PLTE) == 0))
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      truelen = 1;
-
-   else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
-      truelen = 6;
-
-   else
-      truelen = 2;
-
-   if (length != truelen)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
-   png_crc_read(png_ptr, buf, truelen);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   /* We convert the index value into RGB components so that we can allow
-    * arbitrary RGB values for background when we have transparency, and
-    * so it is easy to determine the RGB values of the background color
-    * from the info_ptr struct.
-    */
-   if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-   {
-      background.index = buf[0];
-
-      if (info_ptr != NULL && info_ptr->num_palette != 0)
-      {
-         if (buf[0] >= info_ptr->num_palette)
-         {
-            png_chunk_benign_error(png_ptr, "invalid index");
-            return;
-         }
-
-         background.red = (png_uint_16)png_ptr->palette[buf[0]].red;
-         background.green = (png_uint_16)png_ptr->palette[buf[0]].green;
-         background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue;
-      }
-
-      else
-         background.red = background.green = background.blue = 0;
-
-      background.gray = 0;
-   }
-
-   else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) /* GRAY */
-   {
-      if (png_ptr->bit_depth <= 8)
-      {
-         if (buf[0] != 0 || buf[1] >= (unsigned int)(1 << png_ptr->bit_depth))
-         {
-            png_chunk_benign_error(png_ptr, "invalid gray level");
-            return;
-         }
-      }
-
-      background.index = 0;
-      background.red =
-      background.green =
-      background.blue =
-      background.gray = png_get_uint_16(buf);
-   }
-
-   else
-   {
-      if (png_ptr->bit_depth <= 8)
-      {
-         if (buf[0] != 0 || buf[2] != 0 || buf[4] != 0)
-         {
-            png_chunk_benign_error(png_ptr, "invalid color");
-            return;
-         }
-      }
-
-      background.index = 0;
-      background.red = png_get_uint_16(buf);
-      background.green = png_get_uint_16(buf + 2);
-      background.blue = png_get_uint_16(buf + 4);
-      background.gray = 0;
-   }
-
-   png_set_bKGD(png_ptr, info_ptr, &background);
-}
-#endif
-
-#ifdef PNG_READ_eXIf_SUPPORTED
-void /* PRIVATE */
-png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   unsigned int i;
-
-   png_debug(1, "in png_handle_eXIf");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   if (length < 2)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "too short");
-      return;
-   }
-
-   else if (info_ptr == NULL || (info_ptr->valid & PNG_INFO_eXIf) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   info_ptr->free_me |= PNG_FREE_EXIF;
-
-   info_ptr->eXIf_buf = png_voidcast(png_bytep,
-             png_malloc_warn(png_ptr, length));
-
-   if (info_ptr->eXIf_buf == NULL)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of memory");
-      return;
-   }
-
-   for (i = 0; i < length; i++)
-   {
-      png_byte buf[1];
-      png_crc_read(png_ptr, buf, 1);
-      info_ptr->eXIf_buf[i] = buf[0];
-      if (i == 1 && buf[0] != 'M' && buf[0] != 'I'
-                 && info_ptr->eXIf_buf[0] != buf[0])
-      {
-         png_crc_finish(png_ptr, length);
-         png_chunk_benign_error(png_ptr, "incorrect byte-order specifier");
-         png_free(png_ptr, info_ptr->eXIf_buf);
-         info_ptr->eXIf_buf = NULL;
-         return;
-      }
-   }
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   png_set_eXIf_1(png_ptr, info_ptr, length, info_ptr->eXIf_buf);
-
-   png_free(png_ptr, info_ptr->eXIf_buf);
-   info_ptr->eXIf_buf = NULL;
-}
-#endif
-
-#ifdef PNG_READ_hIST_SUPPORTED
-void /* PRIVATE */
-png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   unsigned int num, i;
-   png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
-
-   png_debug(1, "in png_handle_hIST");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
-       (png_ptr->mode & PNG_HAVE_PLTE) == 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   num = length / 2 ;
-
-   if (num != (unsigned int) png_ptr->num_palette ||
-       num > (unsigned int) PNG_MAX_PALETTE_LENGTH)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
-   for (i = 0; i < num; i++)
-   {
-      png_byte buf[2];
-
-      png_crc_read(png_ptr, buf, 2);
-      readbuf[i] = png_get_uint_16(buf);
-   }
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   png_set_hIST(png_ptr, info_ptr, readbuf);
-}
-#endif
-
-#ifdef PNG_READ_pHYs_SUPPORTED
-void /* PRIVATE */
-png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_byte buf[9];
-   png_uint_32 res_x, res_y;
-   int unit_type;
-
-   png_debug(1, "in png_handle_pHYs");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   if (length != 9)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
-   png_crc_read(png_ptr, buf, 9);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   res_x = png_get_uint_32(buf);
-   res_y = png_get_uint_32(buf + 4);
-   unit_type = buf[8];
-   png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
-}
-#endif
-
-#ifdef PNG_READ_oFFs_SUPPORTED
-void /* PRIVATE */
-png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_byte buf[9];
-   png_int_32 offset_x, offset_y;
-   int unit_type;
-
-   png_debug(1, "in png_handle_oFFs");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   if (length != 9)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
-   png_crc_read(png_ptr, buf, 9);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   offset_x = png_get_int_32(buf);
-   offset_y = png_get_int_32(buf + 4);
-   unit_type = buf[8];
-   png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
-}
-#endif
-
-#ifdef PNG_READ_pCAL_SUPPORTED
-/* Read the pCAL chunk (described in the PNG Extensions document) */
-void /* PRIVATE */
-png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_int_32 X0, X1;
-   png_byte type, nparams;
-   png_bytep buffer, buf, units, endptr;
-   png_charpp params;
-   int i;
-
-   png_debug(1, "in png_handle_pCAL");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",
-       length + 1);
-
-   buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
-
-   if (buffer == NULL)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of memory");
-      return;
-   }
-
-   png_crc_read(png_ptr, buffer, length);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   buffer[length] = 0; /* Null terminate the last string */
-
-   png_debug(3, "Finding end of pCAL purpose string");
-   for (buf = buffer; *buf; buf++)
-      /* Empty loop */ ;
-
-   endptr = buffer + length;
-
-   /* We need to have at least 12 bytes after the purpose string
-    * in order to get the parameter information.
-    */
-   if (endptr - buf <= 12)
-   {
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
-   png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
-   X0 = png_get_int_32((png_bytep)buf+1);
-   X1 = png_get_int_32((png_bytep)buf+5);
-   type = buf[9];
-   nparams = buf[10];
-   units = buf + 11;
-
-   png_debug(3, "Checking pCAL equation type and number of parameters");
-   /* Check that we have the right number of parameters for known
-    * equation types.
-    */
-   if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
-       (type == PNG_EQUATION_BASE_E && nparams != 3) ||
-       (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
-       (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
-   {
-      png_chunk_benign_error(png_ptr, "invalid parameter count");
-      return;
-   }
-
-   else if (type >= PNG_EQUATION_LAST)
-   {
-      png_chunk_benign_error(png_ptr, "unrecognized equation type");
-   }
-
-   for (buf = units; *buf; buf++)
-      /* Empty loop to move past the units string. */ ;
-
-   png_debug(3, "Allocating pCAL parameters array");
-
-   params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
-       nparams * (sizeof (png_charp))));
-
-   if (params == NULL)
-   {
-      png_chunk_benign_error(png_ptr, "out of memory");
-      return;
-   }
-
-   /* Get pointers to the start of each parameter string. */
-   for (i = 0; i < nparams; i++)
-   {
-      buf++; /* Skip the null string terminator from previous parameter. */
-
-      png_debug1(3, "Reading pCAL parameter %d", i);
-
-      for (params[i] = (png_charp)buf; buf <= endptr && *buf != 0; buf++)
-         /* Empty loop to move past each parameter string */ ;
-
-      /* Make sure we haven't run out of data yet */
-      if (buf > endptr)
-      {
-         png_free(png_ptr, params);
-         png_chunk_benign_error(png_ptr, "invalid data");
-         return;
-      }
-   }
-
-   png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams,
-       (png_charp)units, params);
-
-   png_free(png_ptr, params);
-}
-#endif
-
-#ifdef PNG_READ_sCAL_SUPPORTED
-/* Read the sCAL chunk */
-void /* PRIVATE */
-png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_bytep buffer;
-   size_t i;
-   int state;
-
-   png_debug(1, "in png_handle_sCAL");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of place");
-      return;
-   }
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   /* Need unit type, width, \0, height: minimum 4 bytes */
-   else if (length < 4)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
-   png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",
-       length + 1);
-
-   buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
-
-   if (buffer == NULL)
-   {
-      png_chunk_benign_error(png_ptr, "out of memory");
-      png_crc_finish(png_ptr, length);
-      return;
-   }
-
-   png_crc_read(png_ptr, buffer, length);
-   buffer[length] = 0; /* Null terminate the last string */
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   /* Validate the unit. */
-   if (buffer[0] != 1 && buffer[0] != 2)
-   {
-      png_chunk_benign_error(png_ptr, "invalid unit");
-      return;
-   }
-
-   /* Validate the ASCII numbers, need two ASCII numbers separated by
-    * a '\0' and they need to fit exactly in the chunk data.
-    */
-   i = 1;
-   state = 0;
-
-   if (png_check_fp_number((png_const_charp)buffer, length, &state, &i) == 0 ||
-       i >= length || buffer[i++] != 0)
-      png_chunk_benign_error(png_ptr, "bad width format");
-
-   else if (PNG_FP_IS_POSITIVE(state) == 0)
-      png_chunk_benign_error(png_ptr, "non-positive width");
-
-   else
-   {
-      size_t heighti = i;
-
-      state = 0;
-      if (png_check_fp_number((png_const_charp)buffer, length,
-          &state, &i) == 0 || i != length)
-         png_chunk_benign_error(png_ptr, "bad height format");
-
-      else if (PNG_FP_IS_POSITIVE(state) == 0)
-         png_chunk_benign_error(png_ptr, "non-positive height");
-
-      else
-         /* This is the (only) success case. */
-         png_set_sCAL_s(png_ptr, info_ptr, buffer[0],
-             (png_charp)buffer+1, (png_charp)buffer+heighti);
-   }
-}
-#endif
-
-#ifdef PNG_READ_tIME_SUPPORTED
-void /* PRIVATE */
-png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_byte buf[7];
-   png_time mod_time;
-
-   png_debug(1, "in png_handle_tIME");
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) != 0)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "duplicate");
-      return;
-   }
-
-   if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-      png_ptr->mode |= PNG_AFTER_IDAT;
-
-   if (length != 7)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "invalid");
-      return;
-   }
-
-   png_crc_read(png_ptr, buf, 7);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   mod_time.second = buf[6];
-   mod_time.minute = buf[5];
-   mod_time.hour = buf[4];
-   mod_time.day = buf[3];
-   mod_time.month = buf[2];
-   mod_time.year = png_get_uint_16(buf);
-
-   png_set_tIME(png_ptr, info_ptr, &mod_time);
-}
-#endif
-
-#ifdef PNG_READ_tEXt_SUPPORTED
-/* Note: this does not properly handle chunks that are > 64K under DOS */
-void /* PRIVATE */
-png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_text  text_info;
-   png_bytep buffer;
-   png_charp key;
-   png_charp text;
-   png_uint_32 skip = 0;
-
-   png_debug(1, "in png_handle_tEXt");
-
-#ifdef PNG_USER_LIMITS_SUPPORTED
-   if (png_ptr->user_chunk_cache_max != 0)
-   {
-      if (png_ptr->user_chunk_cache_max == 1)
-      {
-         png_crc_finish(png_ptr, length);
-         return;
-      }
-
-      if (--png_ptr->user_chunk_cache_max == 1)
-      {
-         png_crc_finish(png_ptr, length);
-         png_chunk_benign_error(png_ptr, "no space in chunk cache");
-         return;
-      }
-   }
-#endif
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-      png_ptr->mode |= PNG_AFTER_IDAT;
-
-#ifdef PNG_MAX_MALLOC_64K
-   if (length > 65535U)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "too large to fit in memory");
-      return;
-   }
-#endif
-
-   buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
-
-   if (buffer == NULL)
-   {
-      png_chunk_benign_error(png_ptr, "out of memory");
-      return;
-   }
-
-   png_crc_read(png_ptr, buffer, length);
-
-   if (png_crc_finish(png_ptr, skip) != 0)
-      return;
-
-   key = (png_charp)buffer;
-   key[length] = 0;
-
-   for (text = key; *text; text++)
-      /* Empty loop to find end of key */ ;
-
-   if (text != key + length)
-      text++;
-
-   text_info.compression = PNG_TEXT_COMPRESSION_NONE;
-   text_info.key = key;
-   text_info.lang = NULL;
-   text_info.lang_key = NULL;
-   text_info.itxt_length = 0;
-   text_info.text = text;
-   text_info.text_length = strlen(text);
-
-   if (png_set_text_2(png_ptr, info_ptr, &text_info, 1) != 0)
-      png_warning(png_ptr, "Insufficient memory to process text chunk");
-}
-#endif
-
-#ifdef PNG_READ_zTXt_SUPPORTED
-/* Note: this does not correctly handle chunks that are > 64K under DOS */
-void /* PRIVATE */
-png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_const_charp errmsg = NULL;
-   png_bytep       buffer;
-   png_uint_32     keyword_length;
-
-   png_debug(1, "in png_handle_zTXt");
-
-#ifdef PNG_USER_LIMITS_SUPPORTED
-   if (png_ptr->user_chunk_cache_max != 0)
-   {
-      if (png_ptr->user_chunk_cache_max == 1)
-      {
-         png_crc_finish(png_ptr, length);
-         return;
-      }
-
-      if (--png_ptr->user_chunk_cache_max == 1)
-      {
-         png_crc_finish(png_ptr, length);
-         png_chunk_benign_error(png_ptr, "no space in chunk cache");
-         return;
-      }
-   }
-#endif
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-      png_ptr->mode |= PNG_AFTER_IDAT;
-
-   /* Note, "length" is sufficient here; we won't be adding
-    * a null terminator later.
-    */
-   buffer = png_read_buffer(png_ptr, length, 2/*silent*/);
-
-   if (buffer == NULL)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of memory");
-      return;
-   }
-
-   png_crc_read(png_ptr, buffer, length);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   /* TODO: also check that the keyword contents match the spec! */
-   for (keyword_length = 0;
-      keyword_length < length && buffer[keyword_length] != 0;
-      ++keyword_length)
-      /* Empty loop to find end of name */ ;
-
-   if (keyword_length > 79 || keyword_length < 1)
-      errmsg = "bad keyword";
-
-   /* zTXt must have some LZ data after the keyword, although it may expand to
-    * zero bytes; we need a '\0' at the end of the keyword, the compression type
-    * then the LZ data:
-    */
-   else if (keyword_length + 3 > length)
-      errmsg = "truncated";
-
-   else if (buffer[keyword_length+1] != PNG_COMPRESSION_TYPE_BASE)
-      errmsg = "unknown compression type";
-
-   else
-   {
-      png_alloc_size_t uncompressed_length = PNG_SIZE_MAX;
-
-      /* TODO: at present png_decompress_chunk imposes a single application
-       * level memory limit, this should be split to different values for iCCP
-       * and text chunks.
-       */
-      if (png_decompress_chunk(png_ptr, length, keyword_length+2,
-          &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)
-      {
-         png_text text;
-
-         if (png_ptr->read_buffer == NULL)
-           errmsg="Read failure in png_handle_zTXt";
-         else
-         {
-            /* It worked; png_ptr->read_buffer now looks like a tEXt chunk
-             * except for the extra compression type byte and the fact that
-             * it isn't necessarily '\0' terminated.
-             */
-            buffer = png_ptr->read_buffer;
-            buffer[uncompressed_length+(keyword_length+2)] = 0;
-
-            text.compression = PNG_TEXT_COMPRESSION_zTXt;
-            text.key = (png_charp)buffer;
-            text.text = (png_charp)(buffer + keyword_length+2);
-            text.text_length = uncompressed_length;
-            text.itxt_length = 0;
-            text.lang = NULL;
-            text.lang_key = NULL;
-
-            if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
-               errmsg = "insufficient memory";
-         }
-      }
-
-      else
-         errmsg = png_ptr->zstream.msg;
-   }
-
-   if (errmsg != NULL)
-      png_chunk_benign_error(png_ptr, errmsg);
-}
-#endif
-
-#ifdef PNG_READ_iTXt_SUPPORTED
-/* Note: this does not correctly handle chunks that are > 64K under DOS */
-void /* PRIVATE */
-png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
-{
-   png_const_charp errmsg = NULL;
-   png_bytep buffer;
-   png_uint_32 prefix_length;
-
-   png_debug(1, "in png_handle_iTXt");
-
-#ifdef PNG_USER_LIMITS_SUPPORTED
-   if (png_ptr->user_chunk_cache_max != 0)
-   {
-      if (png_ptr->user_chunk_cache_max == 1)
-      {
-         png_crc_finish(png_ptr, length);
-         return;
-      }
-
-      if (--png_ptr->user_chunk_cache_max == 1)
-      {
-         png_crc_finish(png_ptr, length);
-         png_chunk_benign_error(png_ptr, "no space in chunk cache");
-         return;
-      }
-   }
-#endif
-
-   if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
-      png_chunk_error(png_ptr, "missing IHDR");
-
-   if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
-      png_ptr->mode |= PNG_AFTER_IDAT;
-
-   buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
-
-   if (buffer == NULL)
-   {
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "out of memory");
-      return;
-   }
-
-   png_crc_read(png_ptr, buffer, length);
-
-   if (png_crc_finish(png_ptr, 0) != 0)
-      return;
-
-   /* First the keyword. */
-   for (prefix_length=0;
-      prefix_length < length && buffer[prefix_length] != 0;
-      ++prefix_length)
-      /* Empty loop */ ;
-
-   /* Perform a basic check on the keyword length here. */
-   if (prefix_length > 79 || prefix_length < 1)
-      errmsg = "bad keyword";
-
-   /* Expect keyword, compression flag, compression type, language, translated
-    * keyword (both may be empty but are 0 terminated) then the text, which may
-    * be empty.
-    */
-   else if (prefix_length + 5 > length)
-      errmsg = "truncated";
-
-   else if (buffer[prefix_length+1] == 0 ||
-      (buffer[prefix_length+1] == 1 &&
-      buffer[prefix_length+2] == PNG_COMPRESSION_TYPE_BASE))
-   {
-      int compressed = buffer[prefix_length+1] != 0;
-      png_uint_32 language_offset, translated_keyword_offset;
-      png_alloc_size_t uncompressed_length = 0;
-
-      /* Now the language tag */
-      prefix_length += 3;
-      language_offset = prefix_length;
-
-      for (; prefix_length < length && buffer[prefix_length] != 0;
-         ++prefix_length)
-         /* Empty loop */ ;
-
-      /* WARNING: the length may be invalid here, this is checked below. */
-      translated_keyword_offset = ++prefix_length;
-
-      for (; prefix_length < length && buffer[prefix_length] != 0;
-         ++prefix_length)
-         /* Empty loop */ ;
-
-      /* prefix_length should now be at the trailing '\0' of the translated
-       * keyword, but it may already be over the end.  None of this arithmetic
-       * can overflow because chunks are at most 2^31 bytes long, but on 16-bit
-       * systems the available allocation may overflow.
-       */
-      ++prefix_length;
-
-      if (compressed == 0 && prefix_length <= length)
-         uncompressed_length = length - prefix_length;
-
-      else if (compressed != 0 && prefix_length < length)
-      {
-         uncompressed_length = PNG_SIZE_MAX;
-
-         /* TODO: at present png_decompress_chunk imposes a single application
-          * level memory limit, this should be split to different values for
-          * iCCP and text chunks.
-          */
-         if (png_decompress_chunk(png_ptr, length, prefix_length,
-             &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)
-            buffer = png_ptr->read_buffer;
-
-         else
-            errmsg = png_ptr->zstream.msg;
-      }
-
-      else
-         errmsg = "truncated";
-
-      if (errmsg == NULL)
-      {
-         png_text text;
-
-         buffer[uncompressed_length+prefix_length] = 0;
-
-         if (compressed == 0)
-            text.compression = PNG_ITXT_COMPRESSION_NONE;
-
-         else
-            text.compression = PNG_ITXT_COMPRESSION_zTXt;
-
-         text.key = (png_charp)buffer;
-         text.lang = (png_charp)buffer + language_offset;
-         text.lang_key = (png_charp)buffer + translated_keyword_offset;
-         text.text = (png_charp)buffer + prefix_length;
-         text.text_length = 0;
-         text.itxt_length = uncompressed_length;
-
-         if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
-            errmsg = "insufficient memory";
-      }
-   }
-
-   else
-      errmsg = "bad compression info";
-
-   if (errmsg != NULL)
-      png_chunk_benign_error(png_ptr, errmsg);
-}
-#endif
-
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
-static int
-png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
-{
-   png_alloc_size_t limit = PNG_SIZE_MAX;
-
-   if (png_ptr->unknown_chunk.data != NULL)
-   {
-      png_free(png_ptr, png_ptr->unknown_chunk.data);
-      png_ptr->unknown_chunk.data = NULL;
-   }
-
-#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (png_ptr->user_chunk_malloc_max > 0 &&
-       png_ptr->user_chunk_malloc_max < limit)
-      limit = png_ptr->user_chunk_malloc_max;
-
-#  elif PNG_USER_CHUNK_MALLOC_MAX > 0
-   if (PNG_USER_CHUNK_MALLOC_MAX < limit)
-      limit = PNG_USER_CHUNK_MALLOC_MAX;
-#  endif
-
-   if (length <= limit)
-   {
-      PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
-      /* The following is safe because of the PNG_SIZE_MAX init above */
-      png_ptr->unknown_chunk.size = (size_t)length/*SAFE*/;
-      /* 'mode' is a flag array, only the bottom four bits matter here */
-      png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/;
-
-      if (length == 0)
-         png_ptr->unknown_chunk.data = NULL;
-
-      else
-      {
-         /* Do a 'warn' here - it is handled below. */
-         png_ptr->unknown_chunk.data = png_voidcast(png_bytep,
-             png_malloc_warn(png_ptr, length));
-      }
-   }
-
-   if (png_ptr->unknown_chunk.data == NULL && length > 0)
-   {
-      /* This is benign because we clean up correctly */
-      png_crc_finish(png_ptr, length);
-      png_chunk_benign_error(png_ptr, "unknown chunk exceeds memory limits");
-      return 0;
-   }
-
-   else
-   {
-      if (length > 0)
-         png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length);
-      png_crc_finish(png_ptr, 0);
-      return 1;
-   }
-}
-#endif /* READ_UNKNOWN_CHUNKS */
-
-/* Handle an unknown, or known but disabled, chunk */
-void /* PRIVATE */
-png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
-    png_uint_32 length, int keep)
-{
-   int handled = 0; /* the chunk was handled */
-
-   png_debug(1, "in png_handle_unknown");
-
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-   /* NOTE: this code is based on the code in libpng-1.4.12 except for fixing
-    * the bug which meant that setting a non-default behavior for a specific
-    * chunk would be ignored (the default was always used unless a user
-    * callback was installed).
-    *
-    * 'keep' is the value from the png_chunk_unknown_handling, the setting for
-    * this specific chunk_name, if PNG_HANDLE_AS_UNKNOWN_SUPPORTED, if not it
-    * will always be PNG_HANDLE_CHUNK_AS_DEFAULT and it needs to be set here.
-    * This is just an optimization to avoid multiple calls to the lookup
-    * function.
-    */
-#  ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-#     ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-   keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name);
-#     endif
-#  endif
-
-   /* One of the following methods will read the chunk or skip it (at least one
-    * of these is always defined because this is the only way to switch on
-    * PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
-    */
-#  ifdef PNG_READ_USER_CHUNKS_SUPPORTED
-   /* The user callback takes precedence over the chunk keep value, but the
-    * keep value is still required to validate a save of a critical chunk.
-    */
-   if (png_ptr->read_user_chunk_fn != NULL)
-   {
-      if (png_cache_unknown_chunk(png_ptr, length) != 0)
-      {
-         /* Callback to user unknown chunk handler */
-         int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr,
-             &png_ptr->unknown_chunk);
-
-         /* ret is:
-          * negative: An error occurred; png_chunk_error will be called.
-          *     zero: The chunk was not handled, the chunk will be discarded
-          *           unless png_set_keep_unknown_chunks has been used to set
-          *           a 'keep' behavior for this particular chunk, in which
-          *           case that will be used.  A critical chunk will cause an
-          *           error at this point unless it is to be saved.
-          * positive: The chunk was handled, libpng will ignore/discard it.
-          */
-         if (ret < 0)
-            png_chunk_error(png_ptr, "error in user chunk");
-
-         else if (ret == 0)
-         {
-            /* If the keep value is 'default' or 'never' override it, but
-             * still error out on critical chunks unless the keep value is
-             * 'always'  While this is weird it is the behavior in 1.4.12.
-             * A possible improvement would be to obey the value set for the
-             * chunk, but this would be an API change that would probably
-             * damage some applications.
-             *
-             * The png_app_warning below catches the case that matters, where
-             * the application has not set specific save or ignore for this
-             * chunk or global save or ignore.
-             */
-            if (keep < PNG_HANDLE_CHUNK_IF_SAFE)
-            {
-#              ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-               if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE)
-               {
-                  png_chunk_warning(png_ptr, "Saving unknown chunk:");
-                  png_app_warning(png_ptr,
-                      "forcing save of an unhandled chunk;"
-                      " please call png_set_keep_unknown_chunks");
-                      /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */
-               }
-#              endif
-               keep = PNG_HANDLE_CHUNK_IF_SAFE;
-            }
-         }
-
-         else /* chunk was handled */
-         {
-            handled = 1;
-            /* Critical chunks can be safely discarded at this point. */
-            keep = PNG_HANDLE_CHUNK_NEVER;
-         }
-      }
-
-      else
-         keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */
-   }
-
-   else
-   /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */
-#  endif /* READ_USER_CHUNKS */
-
-#  ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
-   {
-      /* keep is currently just the per-chunk setting, if there was no
-       * setting change it to the global default now (not that this may
-       * still be AS_DEFAULT) then obtain the cache of the chunk if required,
-       * if not simply skip the chunk.
-       */
-      if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT)
-         keep = png_ptr->unknown_default;
-
-      if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
-         (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
-          PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
-      {
-         if (png_cache_unknown_chunk(png_ptr, length) == 0)
-            keep = PNG_HANDLE_CHUNK_NEVER;
-      }
-
-      else
-         png_crc_finish(png_ptr, length);
-   }
-#  else
-#     ifndef PNG_READ_USER_CHUNKS_SUPPORTED
-#        error no method to support READ_UNKNOWN_CHUNKS
-#     endif
-
-   {
-      /* If here there is no read callback pointer set and no support is
-       * compiled in to just save the unknown chunks, so simply skip this
-       * chunk.  If 'keep' is something other than AS_DEFAULT or NEVER then
-       * the app has erroneously asked for unknown chunk saving when there
-       * is no support.
-       */
-      if (keep > PNG_HANDLE_CHUNK_NEVER)
-         png_app_error(png_ptr, "no unknown chunk support available");
-
-      png_crc_finish(png_ptr, length);
-   }
-#  endif
-
-#  ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-   /* Now store the chunk in the chunk list if appropriate, and if the limits
-    * permit it.
-    */
-   if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
-      (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
-       PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
-   {
-#     ifdef PNG_USER_LIMITS_SUPPORTED
-      switch (png_ptr->user_chunk_cache_max)
-      {
-         case 2:
-            png_ptr->user_chunk_cache_max = 1;
-            png_chunk_benign_error(png_ptr, "no space in chunk cache");
-            /* FALLTHROUGH */
-         case 1:
-            /* NOTE: prior to 1.6.0 this case resulted in an unknown critical
-             * chunk being skipped, now there will be a hard error below.
-             */
-            break;
-
-         default: /* not at limit */
-            --(png_ptr->user_chunk_cache_max);
-            /* FALLTHROUGH */
-         case 0: /* no limit */
-#  endif /* USER_LIMITS */
-            /* Here when the limit isn't reached or when limits are compiled
-             * out; store the chunk.
-             */
-            png_set_unknown_chunks(png_ptr, info_ptr,
-                &png_ptr->unknown_chunk, 1);
-            handled = 1;
-#  ifdef PNG_USER_LIMITS_SUPPORTED
-            break;
-      }
-#  endif
-   }
-#  else /* no store support: the chunk must be handled by the user callback */
-   PNG_UNUSED(info_ptr)
-#  endif
-
-   /* Regardless of the error handling below the cached data (if any) can be
-    * freed now.  Notice that the data is not freed if there is a png_error, but
-    * it will be freed by destroy_read_struct.
-    */
-   if (png_ptr->unknown_chunk.data != NULL)
-      png_free(png_ptr, png_ptr->unknown_chunk.data);
-   png_ptr->unknown_chunk.data = NULL;
-
-#else /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */
-   /* There is no support to read an unknown chunk, so just skip it. */
-   png_crc_finish(png_ptr, length);
-   PNG_UNUSED(info_ptr)
-   PNG_UNUSED(keep)
-#endif /* !READ_UNKNOWN_CHUNKS */
-
-   /* Check for unhandled critical chunks */
-   if (handled == 0 && PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
-      png_chunk_error(png_ptr, "unhandled critical chunk");
-}
-
-/* This function is called to verify that a chunk name is valid.
- * This function can't have the "critical chunk check" incorporated
- * into it, since in the future we will need to be able to call user
- * functions to handle unknown critical chunks after we check that
- * the chunk name itself is valid.
- */
-
-/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is:
- *
- * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
- */
-
-void /* PRIVATE */
-png_check_chunk_name(png_const_structrp png_ptr, png_uint_32 chunk_name)
-{
-   int i;
-   png_uint_32 cn=chunk_name;
-
-   png_debug(1, "in png_check_chunk_name");
-
-   for (i=1; i<=4; ++i)
-   {
-      int c = cn & 0xff;
-
-      if (c < 65 || c > 122 || (c > 90 && c < 97))
-         png_chunk_error(png_ptr, "invalid chunk type");
-
-      cn >>= 8;
-   }
-}
-
-void /* PRIVATE */
-png_check_chunk_length(png_const_structrp png_ptr, png_uint_32 length)
-{
-   png_alloc_size_t limit = PNG_UINT_31_MAX;
-
-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
-   if (png_ptr->user_chunk_malloc_max > 0 &&
-       png_ptr->user_chunk_malloc_max < limit)
-      limit = png_ptr->user_chunk_malloc_max;
-# elif PNG_USER_CHUNK_MALLOC_MAX > 0
-   if (PNG_USER_CHUNK_MALLOC_MAX < limit)
-      limit = PNG_USER_CHUNK_MALLOC_MAX;
-# endif
-   if (png_ptr->chunk_name == png_IDAT)
-   {
-      png_alloc_size_t idat_limit = PNG_UINT_31_MAX;
-      size_t row_factor =
-         (size_t)png_ptr->width
-         * (size_t)png_ptr->channels
-         * (png_ptr->bit_depth > 8? 2: 1)
-         + 1
-         + (png_ptr->interlaced? 6: 0);
-      if (png_ptr->height > PNG_UINT_32_MAX/row_factor)
-         idat_limit = PNG_UINT_31_MAX;
-      else
-         idat_limit = png_ptr->height * row_factor;
-      row_factor = row_factor > 32566? 32566 : row_factor;
-      idat_limit += 6 + 5*(idat_limit/row_factor+1); /* zlib+deflate overhead */
-      idat_limit=idat_limit < PNG_UINT_31_MAX? idat_limit : PNG_UINT_31_MAX;
-      limit = limit < idat_limit? idat_limit : limit;
-   }
-
-   if (length > limit)
-   {
-      png_debug2(0," length = %lu, limit = %lu",
-         (unsigned long)length,(unsigned long)limit);
-      png_benign_error(png_ptr, "chunk data is too large");
-   }
-}
-
-/* Combines the row recently read in with the existing pixels in the row.  This
- * routine takes care of alpha and transparency if requested.  This routine also
- * handles the two methods of progressive display of interlaced images,
- * depending on the 'display' value; if 'display' is true then the whole row
- * (dp) is filled from the start by replicating the available pixels.  If
- * 'display' is false only those pixels present in the pass are filled in.
- */
-void /* PRIVATE */
-png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
-{
-   unsigned int pixel_depth = png_ptr->transformed_pixel_depth;
-   png_const_bytep sp = png_ptr->row_buf + 1;
-   png_alloc_size_t row_width = png_ptr->width;
-   unsigned int pass = png_ptr->pass;
-   png_bytep end_ptr = 0;
-   png_byte end_byte = 0;
-   unsigned int end_mask;
-
-   png_debug(1, "in png_combine_row");
-
-   /* Added in 1.5.6: it should not be possible to enter this routine until at
-    * least one row has been read from the PNG data and transformed.
-    */
-   if (pixel_depth == 0)
-      png_error(png_ptr, "internal row logic error");
-
-   /* Added in 1.5.4: the pixel depth should match the information returned by
-    * any call to png_read_update_info at this point.  Do not continue if we got
-    * this wrong.
-    */
-   if (png_ptr->info_rowbytes != 0 && png_ptr->info_rowbytes !=
-          PNG_ROWBYTES(pixel_depth, row_width))
-      png_error(png_ptr, "internal row size calculation error");
-
-   /* Don't expect this to ever happen: */
-   if (row_width == 0)
-      png_error(png_ptr, "internal row width error");
-
-   /* Preserve the last byte in cases where only part of it will be overwritten,
-    * the multiply below may overflow, we don't care because ANSI-C guarantees
-    * we get the low bits.
-    */
-   end_mask = (pixel_depth * row_width) & 7;
-   if (end_mask != 0)
-   {
-      /* end_ptr == NULL is a flag to say do nothing */
-      end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1;
-      end_byte = *end_ptr;
-#     ifdef PNG_READ_PACKSWAP_SUPPORTED
-      if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
-         /* little-endian byte */
-         end_mask = (unsigned int)(0xff << end_mask);
-
-      else /* big-endian byte */
-#     endif
-      end_mask = 0xff >> end_mask;
-      /* end_mask is now the bits to *keep* from the destination row */
-   }
-
-   /* For non-interlaced images this reduces to a memcpy(). A memcpy()
-    * will also happen if interlacing isn't supported or if the application
-    * does not call png_set_interlace_handling().  In the latter cases the
-    * caller just gets a sequence of the unexpanded rows from each interlace
-    * pass.
-    */
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   if (png_ptr->interlaced != 0 &&
-       (png_ptr->transformations & PNG_INTERLACE) != 0 &&
-       pass < 6 && (display == 0 ||
-       /* The following copies everything for 'display' on passes 0, 2 and 4. */
-       (display == 1 && (pass & 1) != 0)))
-   {
-      /* Narrow images may have no bits in a pass; the caller should handle
-       * this, but this test is cheap:
-       */
-      if (row_width <= PNG_PASS_START_COL(pass))
-         return;
-
-      if (pixel_depth < 8)
-      {
-         /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit
-          * into 32 bits, then a single loop over the bytes using the four byte
-          * values in the 32-bit mask can be used.  For the 'display' option the
-          * expanded mask may also not require any masking within a byte.  To
-          * make this work the PACKSWAP option must be taken into account - it
-          * simply requires the pixels to be reversed in each byte.
-          *
-          * The 'regular' case requires a mask for each of the first 6 passes,
-          * the 'display' case does a copy for the even passes in the range
-          * 0..6.  This has already been handled in the test above.
-          *
-          * The masks are arranged as four bytes with the first byte to use in
-          * the lowest bits (little-endian) regardless of the order (PACKSWAP or
-          * not) of the pixels in each byte.
-          *
-          * NOTE: the whole of this logic depends on the caller of this function
-          * only calling it on rows appropriate to the pass.  This function only
-          * understands the 'x' logic; the 'y' logic is handled by the caller.
-          *
-          * The following defines allow generation of compile time constant bit
-          * masks for each pixel depth and each possibility of swapped or not
-          * swapped bytes.  Pass 'p' is in the range 0..6; 'x', a pixel index,
-          * is in the range 0..7; and the result is 1 if the pixel is to be
-          * copied in the pass, 0 if not.  'S' is for the sparkle method, 'B'
-          * for the block method.
-          *
-          * With some compilers a compile time expression of the general form:
-          *
-          *    (shift >= 32) ? (a >> (shift-32)) : (b >> shift)
-          *
-          * Produces warnings with values of 'shift' in the range 33 to 63
-          * because the right hand side of the ?: expression is evaluated by
-          * the compiler even though it isn't used.  Microsoft Visual C (various
-          * versions) and the Intel C compiler are known to do this.  To avoid
-          * this the following macros are used in 1.5.6.  This is a temporary
-          * solution to avoid destabilizing the code during the release process.
-          */
-#        if PNG_USE_COMPILE_TIME_MASKS
-#           define PNG_LSR(x,s) ((x)>>((s) & 0x1f))
-#           define PNG_LSL(x,s) ((x)<<((s) & 0x1f))
-#        else
-#           define PNG_LSR(x,s) ((x)>>(s))
-#           define PNG_LSL(x,s) ((x)<<(s))
-#        endif
-#        define S_COPY(p,x) (((p)<4 ? PNG_LSR(0x80088822,(3-(p))*8+(7-(x))) :\
-           PNG_LSR(0xaa55ff00,(7-(p))*8+(7-(x)))) & 1)
-#        define B_COPY(p,x) (((p)<4 ? PNG_LSR(0xff0fff33,(3-(p))*8+(7-(x))) :\
-           PNG_LSR(0xff55ff00,(7-(p))*8+(7-(x)))) & 1)
-
-         /* Return a mask for pass 'p' pixel 'x' at depth 'd'.  The mask is
-          * little endian - the first pixel is at bit 0 - however the extra
-          * parameter 's' can be set to cause the mask position to be swapped
-          * within each byte, to match the PNG format.  This is done by XOR of
-          * the shift with 7, 6 or 4 for bit depths 1, 2 and 4.
-          */
-#        define PIXEL_MASK(p,x,d,s) \
-            (PNG_LSL(((PNG_LSL(1U,(d)))-1),(((x)*(d))^((s)?8-(d):0))))
-
-         /* Hence generate the appropriate 'block' or 'sparkle' pixel copy mask.
-          */
-#        define S_MASKx(p,x,d,s) (S_COPY(p,x)?PIXEL_MASK(p,x,d,s):0)
-#        define B_MASKx(p,x,d,s) (B_COPY(p,x)?PIXEL_MASK(p,x,d,s):0)
-
-         /* Combine 8 of these to get the full mask.  For the 1-bpp and 2-bpp
-          * cases the result needs replicating, for the 4-bpp case the above
-          * generates a full 32 bits.
-          */
-#        define MASK_EXPAND(m,d) ((m)*((d)==1?0x01010101:((d)==2?0x00010001:1)))
-
-#        define S_MASK(p,d,s) MASK_EXPAND(S_MASKx(p,0,d,s) + S_MASKx(p,1,d,s) +\
-            S_MASKx(p,2,d,s) + S_MASKx(p,3,d,s) + S_MASKx(p,4,d,s) +\
-            S_MASKx(p,5,d,s) + S_MASKx(p,6,d,s) + S_MASKx(p,7,d,s), d)
-
-#        define B_MASK(p,d,s) MASK_EXPAND(B_MASKx(p,0,d,s) + B_MASKx(p,1,d,s) +\
-            B_MASKx(p,2,d,s) + B_MASKx(p,3,d,s) + B_MASKx(p,4,d,s) +\
-            B_MASKx(p,5,d,s) + B_MASKx(p,6,d,s) + B_MASKx(p,7,d,s), d)
-
-#if PNG_USE_COMPILE_TIME_MASKS
-         /* Utility macros to construct all the masks for a depth/swap
-          * combination.  The 's' parameter says whether the format is PNG
-          * (big endian bytes) or not.  Only the three odd-numbered passes are
-          * required for the display/block algorithm.
-          */
-#        define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\
-            S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) }
-
-#        define B_MASKS(d,s) { B_MASK(1,d,s), B_MASK(3,d,s), B_MASK(5,d,s) }
-
-#        define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2))
-
-         /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and
-          * then pass:
-          */
-         static const png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] =
-         {
-            /* Little-endian byte masks for PACKSWAP */
-            { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) },
-            /* Normal (big-endian byte) masks - PNG format */
-            { S_MASKS(1,1), S_MASKS(2,1), S_MASKS(4,1) }
-         };
-
-         /* display_mask has only three entries for the odd passes, so index by
-          * pass>>1.
-          */
-         static const png_uint_32 display_mask[2][3][3] =
-         {
-            /* Little-endian byte masks for PACKSWAP */
-            { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) },
-            /* Normal (big-endian byte) masks - PNG format */
-            { B_MASKS(1,1), B_MASKS(2,1), B_MASKS(4,1) }
-         };
-
-#        define MASK(pass,depth,display,png)\
-            ((display)?display_mask[png][DEPTH_INDEX(depth)][pass>>1]:\
-               row_mask[png][DEPTH_INDEX(depth)][pass])
-
-#else /* !PNG_USE_COMPILE_TIME_MASKS */
-         /* This is the runtime alternative: it seems unlikely that this will
-          * ever be either smaller or faster than the compile time approach.
-          */
-#        define MASK(pass,depth,display,png)\
-            ((display)?B_MASK(pass,depth,png):S_MASK(pass,depth,png))
-#endif /* !USE_COMPILE_TIME_MASKS */
-
-         /* Use the appropriate mask to copy the required bits.  In some cases
-          * the byte mask will be 0 or 0xff; optimize these cases.  row_width is
-          * the number of pixels, but the code copies bytes, so it is necessary
-          * to special case the end.
-          */
-         png_uint_32 pixels_per_byte = 8 / pixel_depth;
-         png_uint_32 mask;
-
-#        ifdef PNG_READ_PACKSWAP_SUPPORTED
-         if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
-            mask = MASK(pass, pixel_depth, display, 0);
-
-         else
-#        endif
-         mask = MASK(pass, pixel_depth, display, 1);
-
-         for (;;)
-         {
-            png_uint_32 m;
-
-            /* It doesn't matter in the following if png_uint_32 has more than
-             * 32 bits because the high bits always match those in m<<24; it is,
-             * however, essential to use OR here, not +, because of this.
-             */
-            m = mask;
-            mask = (m >> 8) | (m << 24); /* rotate right to good compilers */
-            m &= 0xff;
-
-            if (m != 0) /* something to copy */
-            {
-               if (m != 0xff)
-                  *dp = (png_byte)((*dp & ~m) | (*sp & m));
-               else
-                  *dp = *sp;
-            }
-
-            /* NOTE: this may overwrite the last byte with garbage if the image
-             * is not an exact number of bytes wide; libpng has always done
-             * this.
-             */
-            if (row_width <= pixels_per_byte)
-               break; /* May need to restore part of the last byte */
-
-            row_width -= pixels_per_byte;
-            ++dp;
-            ++sp;
-         }
-      }
-
-      else /* pixel_depth >= 8 */
-      {
-         unsigned int bytes_to_copy, bytes_to_jump;
-
-         /* Validate the depth - it must be a multiple of 8 */
-         if (pixel_depth & 7)
-            png_error(png_ptr, "invalid user transform pixel depth");
-
-         pixel_depth >>= 3; /* now in bytes */
-         row_width *= pixel_depth;
-
-         /* Regardless of pass number the Adam 7 interlace always results in a
-          * fixed number of pixels to copy then to skip.  There may be a
-          * different number of pixels to skip at the start though.
-          */
-         {
-            unsigned int offset = PNG_PASS_START_COL(pass) * pixel_depth;
-
-            row_width -= offset;
-            dp += offset;
-            sp += offset;
-         }
-
-         /* Work out the bytes to copy. */
-         if (display != 0)
-         {
-            /* When doing the 'block' algorithm the pixel in the pass gets
-             * replicated to adjacent pixels.  This is why the even (0,2,4,6)
-             * passes are skipped above - the entire expanded row is copied.
-             */
-            bytes_to_copy = (1<<((6-pass)>>1)) * pixel_depth;
-
-            /* But don't allow this number to exceed the actual row width. */
-            if (bytes_to_copy > row_width)
-               bytes_to_copy = (unsigned int)/*SAFE*/row_width;
-         }
-
-         else /* normal row; Adam7 only ever gives us one pixel to copy. */
-            bytes_to_copy = pixel_depth;
-
-         /* In Adam7 there is a constant offset between where the pixels go. */
-         bytes_to_jump = PNG_PASS_COL_OFFSET(pass) * pixel_depth;
-
-         /* And simply copy these bytes.  Some optimization is possible here,
-          * depending on the value of 'bytes_to_copy'.  Special case the low
-          * byte counts, which we know to be frequent.
-          *
-          * Notice that these cases all 'return' rather than 'break' - this
-          * avoids an unnecessary test on whether to restore the last byte
-          * below.
-          */
-         switch (bytes_to_copy)
-         {
-            case 1:
-               for (;;)
-               {
-                  *dp = *sp;
-
-                  if (row_width <= bytes_to_jump)
-                     return;
-
-                  dp += bytes_to_jump;
-                  sp += bytes_to_jump;
-                  row_width -= bytes_to_jump;
-               }
-
-            case 2:
-               /* There is a possibility of a partial copy at the end here; this
-                * slows the code down somewhat.
-                */
-               do
-               {
-                  dp[0] = sp[0]; dp[1] = sp[1];
-
-                  if (row_width <= bytes_to_jump)
-                     return;
-
-                  sp += bytes_to_jump;
-                  dp += bytes_to_jump;
-                  row_width -= bytes_to_jump;
-               }
-               while (row_width > 1);
-
-               /* And there can only be one byte left at this point: */
-               *dp = *sp;
-               return;
-
-            case 3:
-               /* This can only be the RGB case, so each copy is exactly one
-                * pixel and it is not necessary to check for a partial copy.
-                */
-               for (;;)
-               {
-                  dp[0] = sp[0]; dp[1] = sp[1]; dp[2] = sp[2];
-
-                  if (row_width <= bytes_to_jump)
-                     return;
-
-                  sp += bytes_to_jump;
-                  dp += bytes_to_jump;
-                  row_width -= bytes_to_jump;
-               }
-
-            default:
-#if PNG_ALIGN_TYPE != PNG_ALIGN_NONE
-               /* Check for double byte alignment and, if possible, use a
-                * 16-bit copy.  Don't attempt this for narrow images - ones that
-                * are less than an interlace panel wide.  Don't attempt it for
-                * wide bytes_to_copy either - use the memcpy there.
-                */
-               if (bytes_to_copy < 16 /*else use memcpy*/ &&
-                   png_isaligned(dp, png_uint_16) &&
-                   png_isaligned(sp, png_uint_16) &&
-                   bytes_to_copy % (sizeof (png_uint_16)) == 0 &&
-                   bytes_to_jump % (sizeof (png_uint_16)) == 0)
-               {
-                  /* Everything is aligned for png_uint_16 copies, but try for
-                   * png_uint_32 first.
-                   */
-                  if (png_isaligned(dp, png_uint_32) &&
-                      png_isaligned(sp, png_uint_32) &&
-                      bytes_to_copy % (sizeof (png_uint_32)) == 0 &&
-                      bytes_to_jump % (sizeof (png_uint_32)) == 0)
-                  {
-                     png_uint_32p dp32 = png_aligncast(png_uint_32p,dp);
-                     png_const_uint_32p sp32 = png_aligncastconst(
-                         png_const_uint_32p, sp);
-                     size_t skip = (bytes_to_jump-bytes_to_copy) /
-                         (sizeof (png_uint_32));
-
-                     do
-                     {
-                        size_t c = bytes_to_copy;
-                        do
-                        {
-                           *dp32++ = *sp32++;
-                           c -= (sizeof (png_uint_32));
-                        }
-                        while (c > 0);
-
-                        if (row_width <= bytes_to_jump)
-                           return;
-
-                        dp32 += skip;
-                        sp32 += skip;
-                        row_width -= bytes_to_jump;
-                     }
-                     while (bytes_to_copy <= row_width);
-
-                     /* Get to here when the row_width truncates the final copy.
-                      * There will be 1-3 bytes left to copy, so don't try the
-                      * 16-bit loop below.
-                      */
-                     dp = (png_bytep)dp32;
-                     sp = (png_const_bytep)sp32;
-                     do
-                        *dp++ = *sp++;
-                     while (--row_width > 0);
-                     return;
-                  }
-
-                  /* Else do it in 16-bit quantities, but only if the size is
-                   * not too large.
-                   */
-                  else
-                  {
-                     png_uint_16p dp16 = png_aligncast(png_uint_16p, dp);
-                     png_const_uint_16p sp16 = png_aligncastconst(
-                        png_const_uint_16p, sp);
-                     size_t skip = (bytes_to_jump-bytes_to_copy) /
-                        (sizeof (png_uint_16));
-
-                     do
-                     {
-                        size_t c = bytes_to_copy;
-                        do
-                        {
-                           *dp16++ = *sp16++;
-                           c -= (sizeof (png_uint_16));
-                        }
-                        while (c > 0);
-
-                        if (row_width <= bytes_to_jump)
-                           return;
-
-                        dp16 += skip;
-                        sp16 += skip;
-                        row_width -= bytes_to_jump;
-                     }
-                     while (bytes_to_copy <= row_width);
-
-                     /* End of row - 1 byte left, bytes_to_copy > row_width: */
-                     dp = (png_bytep)dp16;
-                     sp = (png_const_bytep)sp16;
-                     do
-                        *dp++ = *sp++;
-                     while (--row_width > 0);
-                     return;
-                  }
-               }
-#endif /* ALIGN_TYPE code */
-
-               /* The true default - use a memcpy: */
-               for (;;)
-               {
-                  memcpy(dp, sp, bytes_to_copy);
-
-                  if (row_width <= bytes_to_jump)
-                     return;
-
-                  sp += bytes_to_jump;
-                  dp += bytes_to_jump;
-                  row_width -= bytes_to_jump;
-                  if (bytes_to_copy > row_width)
-                     bytes_to_copy = (unsigned int)/*SAFE*/row_width;
-               }
-         }
-
-         /* NOT REACHED*/
-      } /* pixel_depth >= 8 */
-
-      /* Here if pixel_depth < 8 to check 'end_ptr' below. */
-   }
-   else
-#endif /* READ_INTERLACING */
-
-   /* If here then the switch above wasn't used so just memcpy the whole row
-    * from the temporary row buffer (notice that this overwrites the end of the
-    * destination row if it is a partial byte.)
-    */
-   memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width));
-
-   /* Restore the overwritten bits from the last byte if necessary. */
-   if (end_ptr != NULL)
-      *end_ptr = (png_byte)((end_byte & end_mask) | (*end_ptr & ~end_mask));
-}
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-void /* PRIVATE */
-png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
-    png_uint_32 transformations /* Because these may affect the byte layout */)
-{
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-   /* Offset to next interlace block */
-   static const unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-
-   png_debug(1, "in png_do_read_interlace");
-   if (row != NULL && row_info != NULL)
-   {
-      png_uint_32 final_width;
-
-      final_width = row_info->width * png_pass_inc[pass];
-
-      switch (row_info->pixel_depth)
-      {
-         case 1:
-         {
-            png_bytep sp = row + (size_t)((row_info->width - 1) >> 3);
-            png_bytep dp = row + (size_t)((final_width - 1) >> 3);
-            unsigned int sshift, dshift;
-            unsigned int s_start, s_end;
-            int s_inc;
-            int jstop = (int)png_pass_inc[pass];
-            png_byte v;
-            png_uint_32 i;
-            int j;
-
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
-            if ((transformations & PNG_PACKSWAP) != 0)
-            {
-                sshift = ((row_info->width + 7) & 0x07);
-                dshift = ((final_width + 7) & 0x07);
-                s_start = 7;
-                s_end = 0;
-                s_inc = -1;
-            }
-
-            else
-#endif
-            {
-                sshift = 7 - ((row_info->width + 7) & 0x07);
-                dshift = 7 - ((final_width + 7) & 0x07);
-                s_start = 0;
-                s_end = 7;
-                s_inc = 1;
-            }
-
-            for (i = 0; i < row_info->width; i++)
-            {
-               v = (png_byte)((*sp >> sshift) & 0x01);
-               for (j = 0; j < jstop; j++)
-               {
-                  unsigned int tmp = *dp & (0x7f7f >> (7 - dshift));
-                  tmp |= (unsigned int)(v << dshift);
-                  *dp = (png_byte)(tmp & 0xff);
-
-                  if (dshift == s_end)
-                  {
-                     dshift = s_start;
-                     dp--;
-                  }
-
-                  else
-                     dshift = (unsigned int)((int)dshift + s_inc);
-               }
-
-               if (sshift == s_end)
-               {
-                  sshift = s_start;
-                  sp--;
-               }
-
-               else
-                  sshift = (unsigned int)((int)sshift + s_inc);
-            }
-            break;
-         }
-
-         case 2:
-         {
-            png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
-            png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
-            unsigned int sshift, dshift;
-            unsigned int s_start, s_end;
-            int s_inc;
-            int jstop = (int)png_pass_inc[pass];
-            png_uint_32 i;
-
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
-            if ((transformations & PNG_PACKSWAP) != 0)
-            {
-               sshift = (((row_info->width + 3) & 0x03) << 1);
-               dshift = (((final_width + 3) & 0x03) << 1);
-               s_start = 6;
-               s_end = 0;
-               s_inc = -2;
-            }
-
-            else
-#endif
-            {
-               sshift = ((3 - ((row_info->width + 3) & 0x03)) << 1);
-               dshift = ((3 - ((final_width + 3) & 0x03)) << 1);
-               s_start = 0;
-               s_end = 6;
-               s_inc = 2;
-            }
-
-            for (i = 0; i < row_info->width; i++)
-            {
-               png_byte v;
-               int j;
-
-               v = (png_byte)((*sp >> sshift) & 0x03);
-               for (j = 0; j < jstop; j++)
-               {
-                  unsigned int tmp = *dp & (0x3f3f >> (6 - dshift));
-                  tmp |= (unsigned int)(v << dshift);
-                  *dp = (png_byte)(tmp & 0xff);
-
-                  if (dshift == s_end)
-                  {
-                     dshift = s_start;
-                     dp--;
-                  }
-
-                  else
-                     dshift = (unsigned int)((int)dshift + s_inc);
-               }
-
-               if (sshift == s_end)
-               {
-                  sshift = s_start;
-                  sp--;
-               }
-
-               else
-                  sshift = (unsigned int)((int)sshift + s_inc);
-            }
-            break;
-         }
-
-         case 4:
-         {
-            png_bytep sp = row + (size_t)((row_info->width - 1) >> 1);
-            png_bytep dp = row + (size_t)((final_width - 1) >> 1);
-            unsigned int sshift, dshift;
-            unsigned int s_start, s_end;
-            int s_inc;
-            png_uint_32 i;
-            int jstop = (int)png_pass_inc[pass];
-
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
-            if ((transformations & PNG_PACKSWAP) != 0)
-            {
-               sshift = (((row_info->width + 1) & 0x01) << 2);
-               dshift = (((final_width + 1) & 0x01) << 2);
-               s_start = 4;
-               s_end = 0;
-               s_inc = -4;
-            }
-
-            else
-#endif
-            {
-               sshift = ((1 - ((row_info->width + 1) & 0x01)) << 2);
-               dshift = ((1 - ((final_width + 1) & 0x01)) << 2);
-               s_start = 0;
-               s_end = 4;
-               s_inc = 4;
-            }
-
-            for (i = 0; i < row_info->width; i++)
-            {
-               png_byte v = (png_byte)((*sp >> sshift) & 0x0f);
-               int j;
-
-               for (j = 0; j < jstop; j++)
-               {
-                  unsigned int tmp = *dp & (0xf0f >> (4 - dshift));
-                  tmp |= (unsigned int)(v << dshift);
-                  *dp = (png_byte)(tmp & 0xff);
-
-                  if (dshift == s_end)
-                  {
-                     dshift = s_start;
-                     dp--;
-                  }
-
-                  else
-                     dshift = (unsigned int)((int)dshift + s_inc);
-               }
-
-               if (sshift == s_end)
-               {
-                  sshift = s_start;
-                  sp--;
-               }
-
-               else
-                  sshift = (unsigned int)((int)sshift + s_inc);
-            }
-            break;
-         }
-
-         default:
-         {
-            size_t pixel_bytes = (row_info->pixel_depth >> 3);
-
-            png_bytep sp = row + (size_t)(row_info->width - 1)
-                * pixel_bytes;
-
-            png_bytep dp = row + (size_t)(final_width - 1) * pixel_bytes;
-
-            int jstop = (int)png_pass_inc[pass];
-            png_uint_32 i;
-
-            for (i = 0; i < row_info->width; i++)
-            {
-               png_byte v[8]; /* SAFE; pixel_depth does not exceed 64 */
-               int j;
-
-               memcpy(v, sp, pixel_bytes);
-
-               for (j = 0; j < jstop; j++)
-               {
-                  memcpy(dp, v, pixel_bytes);
-                  dp -= pixel_bytes;
-               }
-
-               sp -= pixel_bytes;
-            }
-            break;
-         }
-      }
-
-      row_info->width = final_width;
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
-   }
-#ifndef PNG_READ_PACKSWAP_SUPPORTED
-   PNG_UNUSED(transformations)  /* Silence compiler warning */
-#endif
-}
-#endif /* READ_INTERLACING */
-
-static void
-png_read_filter_row_sub(png_row_infop row_info, png_bytep row,
-    png_const_bytep prev_row)
-{
-   size_t i;
-   size_t istop = row_info->rowbytes;
-   unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
-   png_bytep rp = row + bpp;
-
-   PNG_UNUSED(prev_row)
-
-   for (i = bpp; i < istop; i++)
-   {
-      *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
-      rp++;
-   }
-}
-
-static void
-png_read_filter_row_up(png_row_infop row_info, png_bytep row,
-    png_const_bytep prev_row)
-{
-   size_t i;
-   size_t istop = row_info->rowbytes;
-   png_bytep rp = row;
-   png_const_bytep pp = prev_row;
-
-   for (i = 0; i < istop; i++)
-   {
-      *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
-      rp++;
-   }
-}
-
-static void
-png_read_filter_row_avg(png_row_infop row_info, png_bytep row,
-    png_const_bytep prev_row)
-{
-   size_t i;
-   png_bytep rp = row;
-   png_const_bytep pp = prev_row;
-   unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
-   size_t istop = row_info->rowbytes - bpp;
-
-   for (i = 0; i < bpp; i++)
-   {
-      *rp = (png_byte)(((int)(*rp) +
-         ((int)(*pp++) / 2 )) & 0xff);
-
-      rp++;
-   }
-
-   for (i = 0; i < istop; i++)
-   {
-      *rp = (png_byte)(((int)(*rp) +
-         (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
-
-      rp++;
-   }
-}
-
-static void
-png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row,
-    png_const_bytep prev_row)
-{
-   png_bytep rp_end = row + row_info->rowbytes;
-   int a, c;
-
-   /* First pixel/byte */
-   c = *prev_row++;
-   a = *row + c;
-   *row++ = (png_byte)a;
-
-   /* Remainder */
-   while (row < rp_end)
-   {
-      int b, pa, pb, pc, p;
-
-      a &= 0xff; /* From previous iteration or start */
-      b = *prev_row++;
-
-      p = b - c;
-      pc = a - c;
-
-#ifdef PNG_USE_ABS
-      pa = abs(p);
-      pb = abs(pc);
-      pc = abs(p + pc);
-#else
-      pa = p < 0 ? -p : p;
-      pb = pc < 0 ? -pc : pc;
-      pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-#endif
-
-      /* Find the best predictor, the least of pa, pb, pc favoring the earlier
-       * ones in the case of a tie.
-       */
-      if (pb < pa)
-      {
-         pa = pb; a = b;
-      }
-      if (pc < pa) a = c;
-
-      /* Calculate the current pixel in a, and move the previous row pixel to c
-       * for the next time round the loop
-       */
-      c = b;
-      a += *row;
-      *row++ = (png_byte)a;
-   }
-}
-
-static void
-png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row,
-    png_const_bytep prev_row)
-{
-   unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
-   png_bytep rp_end = row + bpp;
-
-   /* Process the first pixel in the row completely (this is the same as 'up'
-    * because there is only one candidate predictor for the first row).
-    */
-   while (row < rp_end)
-   {
-      int a = *row + *prev_row++;
-      *row++ = (png_byte)a;
-   }
-
-   /* Remainder */
-   rp_end = rp_end + (row_info->rowbytes - bpp);
-
-   while (row < rp_end)
-   {
-      int a, b, c, pa, pb, pc, p;
-
-      c = *(prev_row - bpp);
-      a = *(row - bpp);
-      b = *prev_row++;
-
-      p = b - c;
-      pc = a - c;
-
-#ifdef PNG_USE_ABS
-      pa = abs(p);
-      pb = abs(pc);
-      pc = abs(p + pc);
-#else
-      pa = p < 0 ? -p : p;
-      pb = pc < 0 ? -pc : pc;
-      pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-#endif
-
-      if (pb < pa)
-      {
-         pa = pb; a = b;
-      }
-      if (pc < pa) a = c;
-
-      a += *row;
-      *row++ = (png_byte)a;
-   }
-}
-
-static void
-png_init_filter_functions(png_structrp pp)
-   /* This function is called once for every PNG image (except for PNG images
-    * that only use PNG_FILTER_VALUE_NONE for all rows) to set the
-    * implementations required to reverse the filtering of PNG rows.  Reversing
-    * the filter is the first transformation performed on the row data.  It is
-    * performed in place, therefore an implementation can be selected based on
-    * the image pixel format.  If the implementation depends on image width then
-    * take care to ensure that it works correctly if the image is interlaced -
-    * interlacing causes the actual row width to vary.
-    */
-{
-   unsigned int bpp = (pp->pixel_depth + 7) >> 3;
-
-   pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub;
-   pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up;
-   pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg;
-   if (bpp == 1)
-      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
-         png_read_filter_row_paeth_1byte_pixel;
-   else
-      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
-         png_read_filter_row_paeth_multibyte_pixel;
-
-#ifdef PNG_FILTER_OPTIMIZATIONS
-   /* To use this define PNG_FILTER_OPTIMIZATIONS as the name of a function to
-    * call to install hardware optimizations for the above functions; simply
-    * replace whatever elements of the pp->read_filter[] array with a hardware
-    * specific (or, for that matter, generic) optimization.
-    *
-    * To see an example of this examine what configure.ac does when
-    * --enable-arm-neon is specified on the command line.
-    */
-   PNG_FILTER_OPTIMIZATIONS(pp, bpp);
-#endif
-}
-
-void /* PRIVATE */
-png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row,
-    png_const_bytep prev_row, int filter)
-{
-   /* OPTIMIZATION: DO NOT MODIFY THIS FUNCTION, instead #define
-    * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic
-    * implementations.  See png_init_filter_functions above.
-    */
-   if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST)
-   {
-      if (pp->read_filter[0] == NULL)
-         png_init_filter_functions(pp);
-
-      pp->read_filter[filter-1](row_info, row, prev_row);
-   }
-}
-
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-void /* PRIVATE */
-png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
-    png_alloc_size_t avail_out)
-{
-   /* Loop reading IDATs and decompressing the result into output[avail_out] */
-   png_ptr->zstream.next_out = output;
-   png_ptr->zstream.avail_out = 0; /* safety: set below */
-
-   if (output == NULL)
-      avail_out = 0;
-
-   do
-   {
-      int ret;
-      png_byte tmpbuf[PNG_INFLATE_BUF_SIZE];
-
-      if (png_ptr->zstream.avail_in == 0)
-      {
-         uInt avail_in;
-         png_bytep buffer;
-
-         while (png_ptr->idat_size == 0)
-         {
-            png_crc_finish(png_ptr, 0);
-
-            png_ptr->idat_size = png_read_chunk_header(png_ptr);
-            /* This is an error even in the 'check' case because the code just
-             * consumed a non-IDAT header.
-             */
-            if (png_ptr->chunk_name != png_IDAT)
-               png_error(png_ptr, "Not enough image data");
-         }
-
-         avail_in = png_ptr->IDAT_read_size;
-
-         if (avail_in > png_ptr->idat_size)
-            avail_in = (uInt)png_ptr->idat_size;
-
-         /* A PNG with a gradually increasing IDAT size will defeat this attempt
-          * to minimize memory usage by causing lots of re-allocs, but
-          * realistically doing IDAT_read_size re-allocs is not likely to be a
-          * big problem.
-          */
-         buffer = png_read_buffer(png_ptr, avail_in, 0/*error*/);
-
-         png_crc_read(png_ptr, buffer, avail_in);
-         png_ptr->idat_size -= avail_in;
-
-         png_ptr->zstream.next_in = buffer;
-         png_ptr->zstream.avail_in = avail_in;
-      }
-
-      /* And set up the output side. */
-      if (output != NULL) /* standard read */
-      {
-         uInt out = ZLIB_IO_MAX;
-
-         if (out > avail_out)
-            out = (uInt)avail_out;
-
-         avail_out -= out;
-         png_ptr->zstream.avail_out = out;
-      }
-
-      else /* after last row, checking for end */
-      {
-         png_ptr->zstream.next_out = tmpbuf;
-         png_ptr->zstream.avail_out = (sizeof tmpbuf);
-      }
-
-      /* Use NO_FLUSH; this gives zlib the maximum opportunity to optimize the
-       * process.  If the LZ stream is truncated the sequential reader will
-       * terminally damage the stream, above, by reading the chunk header of the
-       * following chunk (it then exits with png_error).
-       *
-       * TODO: deal more elegantly with truncated IDAT lists.
-       */
-      ret = PNG_INFLATE(png_ptr, Z_NO_FLUSH);
-
-      /* Take the unconsumed output back. */
-      if (output != NULL)
-         avail_out += png_ptr->zstream.avail_out;
-
-      else /* avail_out counts the extra bytes */
-         avail_out += (sizeof tmpbuf) - png_ptr->zstream.avail_out;
-
-      png_ptr->zstream.avail_out = 0;
-
-      if (ret == Z_STREAM_END)
-      {
-         /* Do this for safety; we won't read any more into this row. */
-         png_ptr->zstream.next_out = NULL;
-
-         png_ptr->mode |= PNG_AFTER_IDAT;
-         png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
-
-         if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
-            png_chunk_benign_error(png_ptr, "Extra compressed data");
-         break;
-      }
-
-      if (ret != Z_OK)
-      {
-         png_zstream_error(png_ptr, ret);
-
-         if (output != NULL)
-            png_chunk_error(png_ptr, png_ptr->zstream.msg);
-
-         else /* checking */
-         {
-            png_chunk_benign_error(png_ptr, png_ptr->zstream.msg);
-            return;
-         }
-      }
-   } while (avail_out > 0);
-
-   if (avail_out > 0)
-   {
-      /* The stream ended before the image; this is the same as too few IDATs so
-       * should be handled the same way.
-       */
-      if (output != NULL)
-         png_error(png_ptr, "Not enough image data");
-
-      else /* the deflate stream contained extra data */
-         png_chunk_benign_error(png_ptr, "Too much image data");
-   }
-}
-
-void /* PRIVATE */
-png_read_finish_IDAT(png_structrp png_ptr)
-{
-   /* We don't need any more data and the stream should have ended, however the
-    * LZ end code may actually not have been processed.  In this case we must
-    * read it otherwise stray unread IDAT data or, more likely, an IDAT chunk
-    * may still remain to be consumed.
-    */
-   if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
-   {
-      /* The NULL causes png_read_IDAT_data to swallow any remaining bytes in
-       * the compressed stream, but the stream may be damaged too, so even after
-       * this call we may need to terminate the zstream ownership.
-       */
-      png_read_IDAT_data(png_ptr, NULL, 0);
-      png_ptr->zstream.next_out = NULL; /* safety */
-
-      /* Now clear everything out for safety; the following may not have been
-       * done.
-       */
-      if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
-      {
-         png_ptr->mode |= PNG_AFTER_IDAT;
-         png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
-      }
-   }
-
-   /* If the zstream has not been released do it now *and* terminate the reading
-    * of the final IDAT chunk.
-    */
-   if (png_ptr->zowner == png_IDAT)
-   {
-      /* Always do this; the pointers otherwise point into the read buffer. */
-      png_ptr->zstream.next_in = NULL;
-      png_ptr->zstream.avail_in = 0;
-
-      /* Now we no longer own the zstream. */
-      png_ptr->zowner = 0;
-
-      /* The slightly weird semantics of the sequential IDAT reading is that we
-       * are always in or at the end of an IDAT chunk, so we always need to do a
-       * crc_finish here.  If idat_size is non-zero we also need to read the
-       * spurious bytes at the end of the chunk now.
-       */
-      (void)png_crc_finish(png_ptr, png_ptr->idat_size);
-   }
-}
-
-void /* PRIVATE */
-png_read_finish_row(png_structrp png_ptr)
-{
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-
-   /* Start of interlace block */
-   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
-
-   /* Offset to next interlace block */
-   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-
-   /* Start of interlace block in the y direction */
-   static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
-
-   /* Offset to next interlace block in the y direction */
-   static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-
-   png_debug(1, "in png_read_finish_row");
-   png_ptr->row_number++;
-   if (png_ptr->row_number < png_ptr->num_rows)
-      return;
-
-   if (png_ptr->interlaced != 0)
-   {
-      png_ptr->row_number = 0;
-
-      /* TO DO: don't do this if prev_row isn't needed (requires
-       * read-ahead of the next row's filter byte.
-       */
-      memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
-
-      do
-      {
-         png_ptr->pass++;
-
-         if (png_ptr->pass >= 7)
-            break;
-
-         png_ptr->iwidth = (png_ptr->width +
-            png_pass_inc[png_ptr->pass] - 1 -
-            png_pass_start[png_ptr->pass]) /
-            png_pass_inc[png_ptr->pass];
-
-         if ((png_ptr->transformations & PNG_INTERLACE) == 0)
-         {
-            png_ptr->num_rows = (png_ptr->height +
-                png_pass_yinc[png_ptr->pass] - 1 -
-                png_pass_ystart[png_ptr->pass]) /
-                png_pass_yinc[png_ptr->pass];
-         }
-
-         else  /* if (png_ptr->transformations & PNG_INTERLACE) */
-            break; /* libpng deinterlacing sees every row */
-
-      } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0);
-
-      if (png_ptr->pass < 7)
-         return;
-   }
-
-   /* Here after at the end of the last row of the last pass. */
-   png_read_finish_IDAT(png_ptr);
-}
-#endif /* SEQUENTIAL_READ */
-
-void /* PRIVATE */
-png_read_start_row(png_structrp png_ptr)
-{
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-
-   /* Start of interlace block */
-   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
-
-   /* Offset to next interlace block */
-   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-
-   /* Start of interlace block in the y direction */
-   static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
-
-   /* Offset to next interlace block in the y direction */
-   static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-
-   unsigned int max_pixel_depth;
-   size_t row_bytes;
-
-   png_debug(1, "in png_read_start_row");
-
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-   png_init_read_transformations(png_ptr);
-#endif
-   if (png_ptr->interlaced != 0)
-   {
-      if ((png_ptr->transformations & PNG_INTERLACE) == 0)
-         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
-             png_pass_ystart[0]) / png_pass_yinc[0];
-
-      else
-         png_ptr->num_rows = png_ptr->height;
-
-      png_ptr->iwidth = (png_ptr->width +
-          png_pass_inc[png_ptr->pass] - 1 -
-          png_pass_start[png_ptr->pass]) /
-          png_pass_inc[png_ptr->pass];
-   }
-
-   else
-   {
-      png_ptr->num_rows = png_ptr->height;
-      png_ptr->iwidth = png_ptr->width;
-   }
-
-   max_pixel_depth = (unsigned int)png_ptr->pixel_depth;
-
-   /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpler set of
-    * calculations to calculate the final pixel depth, then
-    * png_do_read_transforms actually does the transforms.  This means that the
-    * code which effectively calculates this value is actually repeated in three
-    * separate places.  They must all match.  Innocent changes to the order of
-    * transformations can and will break libpng in a way that causes memory
-    * overwrites.
-    *
-    * TODO: fix this.
-    */
-#ifdef PNG_READ_PACK_SUPPORTED
-   if ((png_ptr->transformations & PNG_PACK) != 0 && png_ptr->bit_depth < 8)
-      max_pixel_depth = 8;
-#endif
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
-   if ((png_ptr->transformations & PNG_EXPAND) != 0)
-   {
-      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      {
-         if (png_ptr->num_trans != 0)
-            max_pixel_depth = 32;
-
-         else
-            max_pixel_depth = 24;
-      }
-
-      else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
-      {
-         if (max_pixel_depth < 8)
-            max_pixel_depth = 8;
-
-         if (png_ptr->num_trans != 0)
-            max_pixel_depth *= 2;
-      }
-
-      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
-      {
-         if (png_ptr->num_trans != 0)
-         {
-            max_pixel_depth *= 4;
-            max_pixel_depth /= 3;
-         }
-      }
-   }
-#endif
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
-   if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
-   {
-#  ifdef PNG_READ_EXPAND_SUPPORTED
-      /* In fact it is an error if it isn't supported, but checking is
-       * the safe way.
-       */
-      if ((png_ptr->transformations & PNG_EXPAND) != 0)
-      {
-         if (png_ptr->bit_depth < 16)
-            max_pixel_depth *= 2;
-      }
-      else
-#  endif
-      png_ptr->transformations &= ~PNG_EXPAND_16;
-   }
-#endif
-
-#ifdef PNG_READ_FILLER_SUPPORTED
-   if ((png_ptr->transformations & (PNG_FILLER)) != 0)
-   {
-      if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
-      {
-         if (max_pixel_depth <= 8)
-            max_pixel_depth = 16;
-
-         else
-            max_pixel_depth = 32;
-      }
-
-      else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB ||
-         png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      {
-         if (max_pixel_depth <= 32)
-            max_pixel_depth = 32;
-
-         else
-            max_pixel_depth = 64;
-      }
-   }
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-   if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
-   {
-      if (
-#ifdef PNG_READ_EXPAND_SUPPORTED
-          (png_ptr->num_trans != 0 &&
-          (png_ptr->transformations & PNG_EXPAND) != 0) ||
-#endif
-#ifdef PNG_READ_FILLER_SUPPORTED
-          (png_ptr->transformations & (PNG_FILLER)) != 0 ||
-#endif
-          png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-      {
-         if (max_pixel_depth <= 16)
-            max_pixel_depth = 32;
-
-         else
-            max_pixel_depth = 64;
-      }
-
-      else
-      {
-         if (max_pixel_depth <= 8)
-         {
-            if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-               max_pixel_depth = 32;
-
-            else
-               max_pixel_depth = 24;
-         }
-
-         else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-            max_pixel_depth = 64;
-
-         else
-            max_pixel_depth = 48;
-      }
-   }
-#endif
-
-#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
-defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
-   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
-   {
-      unsigned int user_pixel_depth = png_ptr->user_transform_depth *
-         png_ptr->user_transform_channels;
-
-      if (user_pixel_depth > max_pixel_depth)
-         max_pixel_depth = user_pixel_depth;
-   }
-#endif
-
-   /* This value is stored in png_struct and double checked in the row read
-    * code.
-    */
-   png_ptr->maximum_pixel_depth = (png_byte)max_pixel_depth;
-   png_ptr->transformed_pixel_depth = 0; /* calculated on demand */
-
-   /* Align the width on the next larger 8 pixels.  Mainly used
-    * for interlacing
-    */
-   row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
-   /* Calculate the maximum bytes needed, adding a byte and a pixel
-    * for safety's sake
-    */
-   row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
-       1 + ((max_pixel_depth + 7) >> 3U);
-
-#ifdef PNG_MAX_MALLOC_64K
-   if (row_bytes > (png_uint_32)65536L)
-      png_error(png_ptr, "This image requires a row greater than 64KB");
-#endif
-
-   if (row_bytes + 48 > png_ptr->old_big_row_buf_size)
-   {
-      png_free(png_ptr, png_ptr->big_row_buf);
-      png_free(png_ptr, png_ptr->big_prev_row);
-
-      if (png_ptr->interlaced != 0)
-         png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
-             row_bytes + 48);
-
-      else
-         png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48);
-
-      png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48);
-
-#ifdef PNG_ALIGNED_MEMORY_SUPPORTED
-      /* Use 16-byte aligned memory for row_buf with at least 16 bytes
-       * of padding before and after row_buf; treat prev_row similarly.
-       * NOTE: the alignment is to the start of the pixels, one beyond the start
-       * of the buffer, because of the filter byte.  Prior to libpng 1.5.6 this
-       * was incorrect; the filter byte was aligned, which had the exact
-       * opposite effect of that intended.
-       */
-      {
-         png_bytep temp = png_ptr->big_row_buf + 32;
-         int extra = (int)((temp - (png_bytep)0) & 0x0f);
-         png_ptr->row_buf = temp - extra - 1/*filter byte*/;
-
-         temp = png_ptr->big_prev_row + 32;
-         extra = (int)((temp - (png_bytep)0) & 0x0f);
-         png_ptr->prev_row = temp - extra - 1/*filter byte*/;
-      }
-
-#else
-      /* Use 31 bytes of padding before and 17 bytes after row_buf. */
-      png_ptr->row_buf = png_ptr->big_row_buf + 31;
-      png_ptr->prev_row = png_ptr->big_prev_row + 31;
-#endif
-      png_ptr->old_big_row_buf_size = row_bytes + 48;
-   }
-
-#ifdef PNG_MAX_MALLOC_64K
-   if (png_ptr->rowbytes > 65535)
-      png_error(png_ptr, "This image requires a row greater than 64KB");
-
-#endif
-   if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1))
-      png_error(png_ptr, "Row has too many bytes to allocate in memory");
-
-   memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
-
-   png_debug1(3, "width = %u,", png_ptr->width);
-   png_debug1(3, "height = %u,", png_ptr->height);
-   png_debug1(3, "iwidth = %u,", png_ptr->iwidth);
-   png_debug1(3, "num_rows = %u,", png_ptr->num_rows);
-   png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes);
-   png_debug1(3, "irowbytes = %lu",
-       (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
-
-   /* The sequential reader needs a buffer for IDAT, but the progressive reader
-    * does not, so free the read buffer now regardless; the sequential reader
-    * reallocates it on demand.
-    */
-   if (png_ptr->read_buffer != NULL)
-   {
-      png_bytep buffer = png_ptr->read_buffer;
-
-      png_ptr->read_buffer_size = 0;
-      png_ptr->read_buffer = NULL;
-      png_free(png_ptr, buffer);
-   }
-
-   /* Finally claim the zstream for the inflate of the IDAT data, use the bits
-    * value from the stream (note that this will result in a fatal error if the
-    * IDAT stream has a bogus deflate header window_bits value, but this should
-    * not be happening any longer!)
-    */
-   if (png_inflate_claim(png_ptr, png_IDAT) != Z_OK)
-      png_error(png_ptr, png_ptr->zstream.msg);
-
-   png_ptr->flags |= PNG_FLAG_ROW_INIT;
-}
-#endif /* READ */
diff --git a/third_party/libpng16/pngset.c b/third_party/libpng16/pngset.c
deleted file mode 100644
index ec75dbe..0000000
--- a/third_party/libpng16/pngset.c
+++ /dev/null
@@ -1,1802 +0,0 @@
-
-/* pngset.c - storage of image information into info struct
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- *
- * The functions here are used during reads to store data from the file
- * into the info struct, and during writes to store application data
- * into the info struct for writing into the file.  This abstracts the
- * info struct and allows us to change the structure in the future.
- */
-
-#include "pngpriv.h"
-
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-
-#ifdef PNG_bKGD_SUPPORTED
-void PNGAPI
-png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_const_color_16p background)
-{
-   png_debug1(1, "in %s storage function", "bKGD");
-
-   if (png_ptr == NULL || info_ptr == NULL || background == NULL)
-      return;
-
-   info_ptr->background = *background;
-   info_ptr->valid |= PNG_INFO_bKGD;
-}
-#endif
-
-#ifdef PNG_cHRM_SUPPORTED
-void PNGFAPI
-png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
-    png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
-    png_fixed_point blue_x, png_fixed_point blue_y)
-{
-   png_xy xy;
-
-   png_debug1(1, "in %s storage function", "cHRM fixed");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   xy.redx = red_x;
-   xy.redy = red_y;
-   xy.greenx = green_x;
-   xy.greeny = green_y;
-   xy.bluex = blue_x;
-   xy.bluey = blue_y;
-   xy.whitex = white_x;
-   xy.whitey = white_y;
-
-   if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
-       2/* override with app values*/) != 0)
-      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
-
-   png_colorspace_sync_info(png_ptr, info_ptr);
-}
-
-void PNGFAPI
-png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_fixed_point int_red_X, png_fixed_point int_red_Y,
-    png_fixed_point int_red_Z, png_fixed_point int_green_X,
-    png_fixed_point int_green_Y, png_fixed_point int_green_Z,
-    png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
-    png_fixed_point int_blue_Z)
-{
-   png_XYZ XYZ;
-
-   png_debug1(1, "in %s storage function", "cHRM XYZ fixed");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   XYZ.red_X = int_red_X;
-   XYZ.red_Y = int_red_Y;
-   XYZ.red_Z = int_red_Z;
-   XYZ.green_X = int_green_X;
-   XYZ.green_Y = int_green_Y;
-   XYZ.green_Z = int_green_Z;
-   XYZ.blue_X = int_blue_X;
-   XYZ.blue_Y = int_blue_Y;
-   XYZ.blue_Z = int_blue_Z;
-
-   if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
-       &XYZ, 2) != 0)
-      info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
-
-   png_colorspace_sync_info(png_ptr, info_ptr);
-}
-
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-void PNGAPI
-png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
-    double white_x, double white_y, double red_x, double red_y,
-    double green_x, double green_y, double blue_x, double blue_y)
-{
-   png_set_cHRM_fixed(png_ptr, info_ptr,
-       png_fixed(png_ptr, white_x, "cHRM White X"),
-       png_fixed(png_ptr, white_y, "cHRM White Y"),
-       png_fixed(png_ptr, red_x, "cHRM Red X"),
-       png_fixed(png_ptr, red_y, "cHRM Red Y"),
-       png_fixed(png_ptr, green_x, "cHRM Green X"),
-       png_fixed(png_ptr, green_y, "cHRM Green Y"),
-       png_fixed(png_ptr, blue_x, "cHRM Blue X"),
-       png_fixed(png_ptr, blue_y, "cHRM Blue Y"));
-}
-
-void PNGAPI
-png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
-    double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
-    double blue_X, double blue_Y, double blue_Z)
-{
-   png_set_cHRM_XYZ_fixed(png_ptr, info_ptr,
-       png_fixed(png_ptr, red_X, "cHRM Red X"),
-       png_fixed(png_ptr, red_Y, "cHRM Red Y"),
-       png_fixed(png_ptr, red_Z, "cHRM Red Z"),
-       png_fixed(png_ptr, green_X, "cHRM Green X"),
-       png_fixed(png_ptr, green_Y, "cHRM Green Y"),
-       png_fixed(png_ptr, green_Z, "cHRM Green Z"),
-       png_fixed(png_ptr, blue_X, "cHRM Blue X"),
-       png_fixed(png_ptr, blue_Y, "cHRM Blue Y"),
-       png_fixed(png_ptr, blue_Z, "cHRM Blue Z"));
-}
-#  endif /* FLOATING_POINT */
-
-#endif /* cHRM */
-
-#ifdef PNG_eXIf_SUPPORTED
-void PNGAPI
-png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_bytep eXIf_buf)
-{
-  png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1");
-  PNG_UNUSED(info_ptr)
-  PNG_UNUSED(eXIf_buf)
-}
-
-void PNGAPI
-png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_uint_32 num_exif, png_bytep eXIf_buf)
-{
-   int i;
-
-   png_debug1(1, "in %s storage function", "eXIf");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   if (info_ptr->exif)
-   {
-      png_free(png_ptr, info_ptr->exif);
-      info_ptr->exif = NULL;
-   }
-
-   info_ptr->num_exif = num_exif;
-
-   info_ptr->exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr,
-       info_ptr->num_exif));
-
-   if (info_ptr->exif == NULL)
-   {
-      png_warning(png_ptr, "Insufficient memory for eXIf chunk data");
-      return;
-   }
-
-   info_ptr->free_me |= PNG_FREE_EXIF;
-
-   for (i = 0; i < (int) info_ptr->num_exif; i++)
-      info_ptr->exif[i] = eXIf_buf[i];
-
-   info_ptr->valid |= PNG_INFO_eXIf;
-}
-#endif /* eXIf */
-
-#ifdef PNG_gAMA_SUPPORTED
-void PNGFAPI
-png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_fixed_point file_gamma)
-{
-   png_debug1(1, "in %s storage function", "gAMA");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
-   png_colorspace_sync_info(png_ptr, info_ptr);
-}
-
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-void PNGAPI
-png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma)
-{
-   png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
-       "png_set_gAMA"));
-}
-#  endif
-#endif
-
-#ifdef PNG_hIST_SUPPORTED
-void PNGAPI
-png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_const_uint_16p hist)
-{
-   int i;
-
-   png_debug1(1, "in %s storage function", "hIST");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   if (info_ptr->num_palette == 0 || info_ptr->num_palette
-       > PNG_MAX_PALETTE_LENGTH)
-   {
-      png_warning(png_ptr,
-          "Invalid palette size, hIST allocation skipped");
-
-      return;
-   }
-
-   png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
-
-   /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
-    * version 1.2.1
-    */
-   info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr,
-       PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16))));
-
-   if (info_ptr->hist == NULL)
-   {
-      png_warning(png_ptr, "Insufficient memory for hIST chunk data");
-
-      return;
-   }
-
-   info_ptr->free_me |= PNG_FREE_HIST;
-
-   for (i = 0; i < info_ptr->num_palette; i++)
-      info_ptr->hist[i] = hist[i];
-
-   info_ptr->valid |= PNG_INFO_hIST;
-}
-#endif
-
-void PNGAPI
-png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_uint_32 width, png_uint_32 height, int bit_depth,
-    int color_type, int interlace_type, int compression_type,
-    int filter_type)
-{
-   png_debug1(1, "in %s storage function", "IHDR");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   info_ptr->width = width;
-   info_ptr->height = height;
-   info_ptr->bit_depth = (png_byte)bit_depth;
-   info_ptr->color_type = (png_byte)color_type;
-   info_ptr->compression_type = (png_byte)compression_type;
-   info_ptr->filter_type = (png_byte)filter_type;
-   info_ptr->interlace_type = (png_byte)interlace_type;
-
-   png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
-       info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
-       info_ptr->compression_type, info_ptr->filter_type);
-
-   if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      info_ptr->channels = 1;
-
-   else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
-      info_ptr->channels = 3;
-
-   else
-      info_ptr->channels = 1;
-
-   if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
-      info_ptr->channels++;
-
-   info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
-
-   info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
-}
-
-#ifdef PNG_oFFs_SUPPORTED
-void PNGAPI
-png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_int_32 offset_x, png_int_32 offset_y, int unit_type)
-{
-   png_debug1(1, "in %s storage function", "oFFs");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   info_ptr->x_offset = offset_x;
-   info_ptr->y_offset = offset_y;
-   info_ptr->offset_unit_type = (png_byte)unit_type;
-   info_ptr->valid |= PNG_INFO_oFFs;
-}
-#endif
-
-#ifdef PNG_pCAL_SUPPORTED
-void PNGAPI
-png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
-    int nparams, png_const_charp units, png_charpp params)
-{
-   size_t length;
-   int i;
-
-   png_debug1(1, "in %s storage function", "pCAL");
-
-   if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
-       || (nparams > 0 && params == NULL))
-      return;
-
-   length = strlen(purpose) + 1;
-   png_debug1(3, "allocating purpose for info (%lu bytes)",
-       (unsigned long)length);
-
-   /* TODO: validate format of calibration name and unit name */
-
-   /* Check that the type matches the specification. */
-   if (type < 0 || type > 3)
-   {
-      png_chunk_report(png_ptr, "Invalid pCAL equation type",
-            PNG_CHUNK_WRITE_ERROR);
-      return;
-   }
-
-   if (nparams < 0 || nparams > 255)
-   {
-      png_chunk_report(png_ptr, "Invalid pCAL parameter count",
-            PNG_CHUNK_WRITE_ERROR);
-      return;
-   }
-
-   /* Validate params[nparams] */
-   for (i=0; i<nparams; ++i)
-   {
-      if (params[i] == NULL ||
-          !png_check_fp_string(params[i], strlen(params[i])))
-      {
-         png_chunk_report(png_ptr, "Invalid format for pCAL parameter",
-               PNG_CHUNK_WRITE_ERROR);
-         return;
-      }
-   }
-
-   info_ptr->pcal_purpose = png_voidcast(png_charp,
-       png_malloc_warn(png_ptr, length));
-
-   if (info_ptr->pcal_purpose == NULL)
-   {
-      png_chunk_report(png_ptr, "Insufficient memory for pCAL purpose",
-            PNG_CHUNK_WRITE_ERROR);
-      return;
-   }
-
-   memcpy(info_ptr->pcal_purpose, purpose, length);
-
-   png_debug(3, "storing X0, X1, type, and nparams in info");
-   info_ptr->pcal_X0 = X0;
-   info_ptr->pcal_X1 = X1;
-   info_ptr->pcal_type = (png_byte)type;
-   info_ptr->pcal_nparams = (png_byte)nparams;
-
-   length = strlen(units) + 1;
-   png_debug1(3, "allocating units for info (%lu bytes)",
-       (unsigned long)length);
-
-   info_ptr->pcal_units = png_voidcast(png_charp,
-       png_malloc_warn(png_ptr, length));
-
-   if (info_ptr->pcal_units == NULL)
-   {
-      png_warning(png_ptr, "Insufficient memory for pCAL units");
-
-      return;
-   }
-
-   memcpy(info_ptr->pcal_units, units, length);
-
-   info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
-       (size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp)))));
-
-   if (info_ptr->pcal_params == NULL)
-   {
-      png_warning(png_ptr, "Insufficient memory for pCAL params");
-
-      return;
-   }
-
-   memset(info_ptr->pcal_params, 0, ((unsigned int)nparams + 1) *
-       (sizeof (png_charp)));
-
-   for (i = 0; i < nparams; i++)
-   {
-      length = strlen(params[i]) + 1;
-      png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
-          (unsigned long)length);
-
-      info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length);
-
-      if (info_ptr->pcal_params[i] == NULL)
-      {
-         png_warning(png_ptr, "Insufficient memory for pCAL parameter");
-
-         return;
-      }
-
-      memcpy(info_ptr->pcal_params[i], params[i], length);
-   }
-
-   info_ptr->valid |= PNG_INFO_pCAL;
-   info_ptr->free_me |= PNG_FREE_PCAL;
-}
-#endif
-
-#ifdef PNG_sCAL_SUPPORTED
-void PNGAPI
-png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
-    int unit, png_const_charp swidth, png_const_charp sheight)
-{
-   size_t lengthw = 0, lengthh = 0;
-
-   png_debug1(1, "in %s storage function", "sCAL");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   /* Double check the unit (should never get here with an invalid
-    * unit unless this is an API call.)
-    */
-   if (unit != 1 && unit != 2)
-      png_error(png_ptr, "Invalid sCAL unit");
-
-   if (swidth == NULL || (lengthw = strlen(swidth)) == 0 ||
-       swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
-      png_error(png_ptr, "Invalid sCAL width");
-
-   if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
-       sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
-      png_error(png_ptr, "Invalid sCAL height");
-
-   info_ptr->scal_unit = (png_byte)unit;
-
-   ++lengthw;
-
-   png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw);
-
-   info_ptr->scal_s_width = png_voidcast(png_charp,
-       png_malloc_warn(png_ptr, lengthw));
-
-   if (info_ptr->scal_s_width == NULL)
-   {
-      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
-
-      return;
-   }
-
-   memcpy(info_ptr->scal_s_width, swidth, lengthw);
-
-   ++lengthh;
-
-   png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh);
-
-   info_ptr->scal_s_height = png_voidcast(png_charp,
-       png_malloc_warn(png_ptr, lengthh));
-
-   if (info_ptr->scal_s_height == NULL)
-   {
-      png_free (png_ptr, info_ptr->scal_s_width);
-      info_ptr->scal_s_width = NULL;
-
-      png_warning(png_ptr, "Memory allocation failed while processing sCAL");
-
-      return;
-   }
-
-   memcpy(info_ptr->scal_s_height, sheight, lengthh);
-
-   info_ptr->valid |= PNG_INFO_sCAL;
-   info_ptr->free_me |= PNG_FREE_SCAL;
-}
-
-#  ifdef PNG_FLOATING_POINT_SUPPORTED
-void PNGAPI
-png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
-    double width, double height)
-{
-   png_debug1(1, "in %s storage function", "sCAL");
-
-   /* Check the arguments. */
-   if (width <= 0)
-      png_warning(png_ptr, "Invalid sCAL width ignored");
-
-   else if (height <= 0)
-      png_warning(png_ptr, "Invalid sCAL height ignored");
-
-   else
-   {
-      /* Convert 'width' and 'height' to ASCII. */
-      char swidth[PNG_sCAL_MAX_DIGITS+1];
-      char sheight[PNG_sCAL_MAX_DIGITS+1];
-
-      png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
-          PNG_sCAL_PRECISION);
-      png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
-          PNG_sCAL_PRECISION);
-
-      png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
-   }
-}
-#  endif
-
-#  ifdef PNG_FIXED_POINT_SUPPORTED
-void PNGAPI
-png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
-    png_fixed_point width, png_fixed_point height)
-{
-   png_debug1(1, "in %s storage function", "sCAL");
-
-   /* Check the arguments. */
-   if (width <= 0)
-      png_warning(png_ptr, "Invalid sCAL width ignored");
-
-   else if (height <= 0)
-      png_warning(png_ptr, "Invalid sCAL height ignored");
-
-   else
-   {
-      /* Convert 'width' and 'height' to ASCII. */
-      char swidth[PNG_sCAL_MAX_DIGITS+1];
-      char sheight[PNG_sCAL_MAX_DIGITS+1];
-
-      png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width);
-      png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height);
-
-      png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
-   }
-}
-#  endif
-#endif
-
-#ifdef PNG_pHYs_SUPPORTED
-void PNGAPI
-png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_uint_32 res_x, png_uint_32 res_y, int unit_type)
-{
-   png_debug1(1, "in %s storage function", "pHYs");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   info_ptr->x_pixels_per_unit = res_x;
-   info_ptr->y_pixels_per_unit = res_y;
-   info_ptr->phys_unit_type = (png_byte)unit_type;
-   info_ptr->valid |= PNG_INFO_pHYs;
-}
-#endif
-
-void PNGAPI
-png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
-    png_const_colorp palette, int num_palette)
-{
-
-   png_uint_32 max_palette_length;
-
-   png_debug1(1, "in %s storage function", "PLTE");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
-      (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
-
-   if (num_palette < 0 || num_palette > (int) max_palette_length)
-   {
-      if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-         png_error(png_ptr, "Invalid palette length");
-
-      else
-      {
-         png_warning(png_ptr, "Invalid palette length");
-
-         return;
-      }
-   }
-
-   if ((num_palette > 0 && palette == NULL) ||
-      (num_palette == 0
-#        ifdef PNG_MNG_FEATURES_SUPPORTED
-            && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
-#        endif
-      ))
-   {
-      png_error(png_ptr, "Invalid palette");
-   }
-
-   /* It may not actually be necessary to set png_ptr->palette here;
-    * we do it for backward compatibility with the way the png_handle_tRNS
-    * function used to do the allocation.
-    *
-    * 1.6.0: the above statement appears to be incorrect; something has to set
-    * the palette inside png_struct on read.
-    */
-   png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
-
-   /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead
-    * of num_palette entries, in case of an invalid PNG file or incorrect
-    * call to png_set_PLTE() with too-large sample values.
-    */
-   png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
-       PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
-
-   if (num_palette > 0)
-      memcpy(png_ptr->palette, palette, (unsigned int)num_palette *
-          (sizeof (png_color)));
-   info_ptr->palette = png_ptr->palette;
-   info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
-
-   info_ptr->free_me |= PNG_FREE_PLTE;
-
-   info_ptr->valid |= PNG_INFO_PLTE;
-}
-
-#ifdef PNG_sBIT_SUPPORTED
-void PNGAPI
-png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_const_color_8p sig_bit)
-{
-   png_debug1(1, "in %s storage function", "sBIT");
-
-   if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
-      return;
-
-   info_ptr->sig_bit = *sig_bit;
-   info_ptr->valid |= PNG_INFO_sBIT;
-}
-#endif
-
-#ifdef PNG_sRGB_SUPPORTED
-void PNGAPI
-png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
-{
-   png_debug1(1, "in %s storage function", "sRGB");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
-   png_colorspace_sync_info(png_ptr, info_ptr);
-}
-
-void PNGAPI
-png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
-    int srgb_intent)
-{
-   png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
-       srgb_intent) != 0)
-   {
-      /* This causes the gAMA and cHRM to be written too */
-      info_ptr->colorspace.flags |=
-         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
-   }
-
-   png_colorspace_sync_info(png_ptr, info_ptr);
-}
-#endif /* sRGB */
-
-
-#ifdef PNG_iCCP_SUPPORTED
-void PNGAPI
-png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_const_charp name, int compression_type,
-    png_const_bytep profile, png_uint_32 proflen)
-{
-   png_charp new_iccp_name;
-   png_bytep new_iccp_profile;
-   size_t length;
-
-   png_debug1(1, "in %s storage function", "iCCP");
-
-   if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
-      return;
-
-   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
-      png_app_error(png_ptr, "Invalid iCCP compression method");
-
-   /* Set the colorspace first because this validates the profile; do not
-    * override previously set app cHRM or gAMA here (because likely as not the
-    * application knows better than libpng what the correct values are.)  Pass
-    * the info_ptr color_type field to png_colorspace_set_ICC because in the
-    * write case it has not yet been stored in png_ptr.
-    */
-   {
-      int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
-          proflen, profile, info_ptr->color_type);
-
-      png_colorspace_sync_info(png_ptr, info_ptr);
-
-      /* Don't do any of the copying if the profile was bad, or inconsistent. */
-      if (result == 0)
-         return;
-
-      /* But do write the gAMA and cHRM chunks from the profile. */
-      info_ptr->colorspace.flags |=
-         PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
-   }
-
-   length = strlen(name)+1;
-   new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
-
-   if (new_iccp_name == NULL)
-   {
-      png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");
-
-      return;
-   }
-
-   memcpy(new_iccp_name, name, length);
-   new_iccp_profile = png_voidcast(png_bytep,
-       png_malloc_warn(png_ptr, proflen));
-
-   if (new_iccp_profile == NULL)
-   {
-      png_free(png_ptr, new_iccp_name);
-      png_benign_error(png_ptr,
-          "Insufficient memory to process iCCP profile");
-
-      return;
-   }
-
-   memcpy(new_iccp_profile, profile, proflen);
-
-   png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
-
-   info_ptr->iccp_proflen = proflen;
-   info_ptr->iccp_name = new_iccp_name;
-   info_ptr->iccp_profile = new_iccp_profile;
-   info_ptr->free_me |= PNG_FREE_ICCP;
-   info_ptr->valid |= PNG_INFO_iCCP;
-}
-#endif
-
-#ifdef PNG_TEXT_SUPPORTED
-void PNGAPI
-png_set_text(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_const_textp text_ptr, int num_text)
-{
-   int ret;
-   ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
-
-   if (ret != 0)
-      png_error(png_ptr, "Insufficient memory to store text");
-}
-
-int /* PRIVATE */
-png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_const_textp text_ptr, int num_text)
-{
-   int i;
-
-   png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U :
-      (unsigned long)png_ptr->chunk_name);
-
-   if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
-      return(0);
-
-   /* Make sure we have enough space in the "text" array in info_struct
-    * to hold all of the incoming text_ptr objects.  This compare can't overflow
-    * because max_text >= num_text (anyway, subtract of two positive integers
-    * can't overflow in any case.)
-    */
-   if (num_text > info_ptr->max_text - info_ptr->num_text)
-   {
-      int old_num_text = info_ptr->num_text;
-      int max_text;
-      png_textp new_text = NULL;
-
-      /* Calculate an appropriate max_text, checking for overflow. */
-      max_text = old_num_text;
-      if (num_text <= INT_MAX - max_text)
-      {
-         max_text += num_text;
-
-         /* Round up to a multiple of 8 */
-         if (max_text < INT_MAX-8)
-            max_text = (max_text + 8) & ~0x7;
-
-         else
-            max_text = INT_MAX;
-
-         /* Now allocate a new array and copy the old members in; this does all
-          * the overflow checks.
-          */
-         new_text = png_voidcast(png_textp,png_realloc_array(png_ptr,
-             info_ptr->text, old_num_text, max_text-old_num_text,
-             sizeof *new_text));
-      }
-
-      if (new_text == NULL)
-      {
-         png_chunk_report(png_ptr, "too many text chunks",
-             PNG_CHUNK_WRITE_ERROR);
-
-         return 1;
-      }
-
-      png_free(png_ptr, info_ptr->text);
-
-      info_ptr->text = new_text;
-      info_ptr->free_me |= PNG_FREE_TEXT;
-      info_ptr->max_text = max_text;
-      /* num_text is adjusted below as the entries are copied in */
-
-      png_debug1(3, "allocated %d entries for info_ptr->text", max_text);
-   }
-
-   for (i = 0; i < num_text; i++)
-   {
-      size_t text_length, key_len;
-      size_t lang_len, lang_key_len;
-      png_textp textp = &(info_ptr->text[info_ptr->num_text]);
-
-      if (text_ptr[i].key == NULL)
-          continue;
-
-      if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
-          text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
-      {
-         png_chunk_report(png_ptr, "text compression mode is out of range",
-             PNG_CHUNK_WRITE_ERROR);
-         continue;
-      }
-
-      key_len = strlen(text_ptr[i].key);
-
-      if (text_ptr[i].compression <= 0)
-      {
-         lang_len = 0;
-         lang_key_len = 0;
-      }
-
-      else
-#  ifdef PNG_iTXt_SUPPORTED
-      {
-         /* Set iTXt data */
-
-         if (text_ptr[i].lang != NULL)
-            lang_len = strlen(text_ptr[i].lang);
-
-         else
-            lang_len = 0;
-
-         if (text_ptr[i].lang_key != NULL)
-            lang_key_len = strlen(text_ptr[i].lang_key);
-
-         else
-            lang_key_len = 0;
-      }
-#  else /* iTXt */
-      {
-         png_chunk_report(png_ptr, "iTXt chunk not supported",
-             PNG_CHUNK_WRITE_ERROR);
-         continue;
-      }
-#  endif
-
-      if (text_ptr[i].text == NULL || text_ptr[i].text[0] == '\0')
-      {
-         text_length = 0;
-#  ifdef PNG_iTXt_SUPPORTED
-         if (text_ptr[i].compression > 0)
-            textp->compression = PNG_ITXT_COMPRESSION_NONE;
-
-         else
-#  endif
-            textp->compression = PNG_TEXT_COMPRESSION_NONE;
-      }
-
-      else
-      {
-         text_length = strlen(text_ptr[i].text);
-         textp->compression = text_ptr[i].compression;
-      }
-
-      textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr,
-          key_len + text_length + lang_len + lang_key_len + 4));
-
-      if (textp->key == NULL)
-      {
-         png_chunk_report(png_ptr, "text chunk: out of memory",
-             PNG_CHUNK_WRITE_ERROR);
-
-         return 1;
-      }
-
-      png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
-          (unsigned long)(png_uint_32)
-          (key_len + lang_len + lang_key_len + text_length + 4),
-          textp->key);
-
-      memcpy(textp->key, text_ptr[i].key, key_len);
-      *(textp->key + key_len) = '\0';
-
-      if (text_ptr[i].compression > 0)
-      {
-         textp->lang = textp->key + key_len + 1;
-         memcpy(textp->lang, text_ptr[i].lang, lang_len);
-         *(textp->lang + lang_len) = '\0';
-         textp->lang_key = textp->lang + lang_len + 1;
-         memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
-         *(textp->lang_key + lang_key_len) = '\0';
-         textp->text = textp->lang_key + lang_key_len + 1;
-      }
-
-      else
-      {
-         textp->lang=NULL;
-         textp->lang_key=NULL;
-         textp->text = textp->key + key_len + 1;
-      }
-
-      if (text_length != 0)
-         memcpy(textp->text, text_ptr[i].text, text_length);
-
-      *(textp->text + text_length) = '\0';
-
-#  ifdef PNG_iTXt_SUPPORTED
-      if (textp->compression > 0)
-      {
-         textp->text_length = 0;
-         textp->itxt_length = text_length;
-      }
-
-      else
-#  endif
-      {
-         textp->text_length = text_length;
-         textp->itxt_length = 0;
-      }
-
-      info_ptr->num_text++;
-      png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
-   }
-
-   return(0);
-}
-#endif
-
-#ifdef PNG_tIME_SUPPORTED
-void PNGAPI
-png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_const_timep mod_time)
-{
-   png_debug1(1, "in %s storage function", "tIME");
-
-   if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
-       (png_ptr->mode & PNG_WROTE_tIME) != 0)
-      return;
-
-   if (mod_time->month == 0   || mod_time->month > 12  ||
-       mod_time->day   == 0   || mod_time->day   > 31  ||
-       mod_time->hour  > 23   || mod_time->minute > 59 ||
-       mod_time->second > 60)
-   {
-      png_warning(png_ptr, "Ignoring invalid time value");
-
-      return;
-   }
-
-   info_ptr->mod_time = *mod_time;
-   info_ptr->valid |= PNG_INFO_tIME;
-}
-#endif
-
-#ifdef PNG_tRNS_SUPPORTED
-void PNGAPI
-png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
-    png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
-{
-   png_debug1(1, "in %s storage function", "tRNS");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-
-      return;
-
-   if (trans_alpha != NULL)
-   {
-       /* It may not actually be necessary to set png_ptr->trans_alpha here;
-        * we do it for backward compatibility with the way the png_handle_tRNS
-        * function used to do the allocation.
-        *
-        * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
-        * relies on png_set_tRNS storing the information in png_struct
-        * (otherwise it won't be there for the code in pngrtran.c).
-        */
-
-       png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
-
-       if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
-       {
-         /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
-          info_ptr->trans_alpha = png_voidcast(png_bytep,
-              png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
-          memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans);
-       }
-       png_ptr->trans_alpha = info_ptr->trans_alpha;
-   }
-
-   if (trans_color != NULL)
-   {
-#ifdef PNG_WARNINGS_SUPPORTED
-      if (info_ptr->bit_depth < 16)
-      {
-         int sample_max = (1 << info_ptr->bit_depth) - 1;
-
-         if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
-             trans_color->gray > sample_max) ||
-             (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
-             (trans_color->red > sample_max ||
-             trans_color->green > sample_max ||
-             trans_color->blue > sample_max)))
-            png_warning(png_ptr,
-                "tRNS chunk has out-of-range samples for bit_depth");
-      }
-#endif
-
-      info_ptr->trans_color = *trans_color;
-
-      if (num_trans == 0)
-         num_trans = 1;
-   }
-
-   info_ptr->num_trans = (png_uint_16)num_trans;
-
-   if (num_trans != 0)
-   {
-      info_ptr->valid |= PNG_INFO_tRNS;
-      info_ptr->free_me |= PNG_FREE_TRNS;
-   }
-}
-#endif
-
-#ifdef PNG_sPLT_SUPPORTED
-void PNGAPI
-png_set_sPLT(png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
-/*
- *  entries        - array of png_sPLT_t structures
- *                   to be added to the list of palettes
- *                   in the info structure.
- *
- *  nentries       - number of palette structures to be
- *                   added.
- */
-{
-   png_sPLT_tp np;
-
-   if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
-      return;
-
-   /* Use the internal realloc function, which checks for all the possible
-    * overflows.  Notice that the parameters are (int) and (size_t)
-    */
-   np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr,
-       info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
-       sizeof *np));
-
-   if (np == NULL)
-   {
-      /* Out of memory or too many chunks */
-      png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);
-
-      return;
-   }
-
-   png_free(png_ptr, info_ptr->splt_palettes);
-   info_ptr->splt_palettes = np;
-   info_ptr->free_me |= PNG_FREE_SPLT;
-
-   np += info_ptr->splt_palettes_num;
-
-   do
-   {
-      size_t length;
-
-      /* Skip invalid input entries */
-      if (entries->name == NULL || entries->entries == NULL)
-      {
-         /* png_handle_sPLT doesn't do this, so this is an app error */
-         png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
-         /* Just skip the invalid entry */
-         continue;
-      }
-
-      np->depth = entries->depth;
-
-      /* In the event of out-of-memory just return - there's no point keeping
-       * on trying to add sPLT chunks.
-       */
-      length = strlen(entries->name) + 1;
-      np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length));
-
-      if (np->name == NULL)
-         break;
-
-      memcpy(np->name, entries->name, length);
-
-      /* IMPORTANT: we have memory now that won't get freed if something else
-       * goes wrong; this code must free it.  png_malloc_array produces no
-       * warnings; use a png_chunk_report (below) if there is an error.
-       */
-      np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr,
-          entries->nentries, sizeof (png_sPLT_entry)));
-
-      if (np->entries == NULL)
-      {
-         png_free(png_ptr, np->name);
-         np->name = NULL;
-         break;
-      }
-
-      np->nentries = entries->nentries;
-      /* This multiply can't overflow because png_malloc_array has already
-       * checked it when doing the allocation.
-       */
-      memcpy(np->entries, entries->entries,
-          (unsigned int)entries->nentries * sizeof (png_sPLT_entry));
-
-      /* Note that 'continue' skips the advance of the out pointer and out
-       * count, so an invalid entry is not added.
-       */
-      info_ptr->valid |= PNG_INFO_sPLT;
-      ++(info_ptr->splt_palettes_num);
-      ++np;
-      ++entries;
-   }
-   while (--nentries);
-
-   if (nentries > 0)
-      png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
-}
-#endif /* sPLT */
-
-#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-static png_byte
-check_location(png_const_structrp png_ptr, int location)
-{
-   location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
-
-   /* New in 1.6.0; copy the location and check it.  This is an API
-    * change; previously the app had to use the
-    * png_set_unknown_chunk_location API below for each chunk.
-    */
-   if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
-   {
-      /* Write struct, so unknown chunks come from the app */
-      png_app_warning(png_ptr,
-          "png_set_unknown_chunks now expects a valid location");
-      /* Use the old behavior */
-      location = (png_byte)(png_ptr->mode &
-          (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
-   }
-
-   /* This need not be an internal error - if the app calls
-    * png_set_unknown_chunks on a read pointer it must get the location right.
-    */
-   if (location == 0)
-      png_error(png_ptr, "invalid location in png_set_unknown_chunks");
-
-   /* Now reduce the location to the top-most set bit by removing each least
-    * significant bit in turn.
-    */
-   while (location != (location & -location))
-      location &= ~(location & -location);
-
-   /* The cast is safe because 'location' is a bit mask and only the low four
-    * bits are significant.
-    */
-   return (png_byte)location;
-}
-
-void PNGAPI
-png_set_unknown_chunks(png_const_structrp png_ptr,
-    png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
-{
-   png_unknown_chunkp np;
-
-   if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
-       unknowns == NULL)
-      return;
-
-   /* Check for the failure cases where support has been disabled at compile
-    * time.  This code is hardly ever compiled - it's here because
-    * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
-    * code) but may be meaningless if the read or write handling of unknown
-    * chunks is not compiled in.
-    */
-#  if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
-      defined(PNG_READ_SUPPORTED)
-      if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
-      {
-         png_app_error(png_ptr, "no unknown chunk support on read");
-
-         return;
-      }
-#  endif
-#  if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
-      defined(PNG_WRITE_SUPPORTED)
-      if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
-      {
-         png_app_error(png_ptr, "no unknown chunk support on write");
-
-         return;
-      }
-#  endif
-
-   /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
-    * unknown critical chunks could be lost with just a warning resulting in
-    * undefined behavior.  Now png_chunk_report is used to provide behavior
-    * appropriate to read or write.
-    */
-   np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr,
-       info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
-       sizeof *np));
-
-   if (np == NULL)
-   {
-      png_chunk_report(png_ptr, "too many unknown chunks",
-          PNG_CHUNK_WRITE_ERROR);
-
-      return;
-   }
-
-   png_free(png_ptr, info_ptr->unknown_chunks);
-   info_ptr->unknown_chunks = np; /* safe because it is initialized */
-   info_ptr->free_me |= PNG_FREE_UNKN;
-
-   np += info_ptr->unknown_chunks_num;
-
-   /* Increment unknown_chunks_num each time round the loop to protect the
-    * just-allocated chunk data.
-    */
-   for (; num_unknowns > 0; --num_unknowns, ++unknowns)
-   {
-      memcpy(np->name, unknowns->name, (sizeof np->name));
-      np->name[(sizeof np->name)-1] = '\0';
-      np->location = check_location(png_ptr, unknowns->location);
-
-      if (unknowns->size == 0)
-      {
-         np->data = NULL;
-         np->size = 0;
-      }
-
-      else
-      {
-         np->data = png_voidcast(png_bytep,
-             png_malloc_base(png_ptr, unknowns->size));
-
-         if (np->data == NULL)
-         {
-            png_chunk_report(png_ptr, "unknown chunk: out of memory",
-                PNG_CHUNK_WRITE_ERROR);
-            /* But just skip storing the unknown chunk */
-            continue;
-         }
-
-         memcpy(np->data, unknowns->data, unknowns->size);
-         np->size = unknowns->size;
-      }
-
-      /* These increments are skipped on out-of-memory for the data - the
-       * unknown chunk entry gets overwritten if the png_chunk_report returns.
-       * This is correct in the read case (the chunk is just dropped.)
-       */
-      ++np;
-      ++(info_ptr->unknown_chunks_num);
-   }
-}
-
-void PNGAPI
-png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
-    int chunk, int location)
-{
-   /* This API is pretty pointless in 1.6.0 because the location can be set
-    * before the call to png_set_unknown_chunks.
-    *
-    * TODO: add a png_app_warning in 1.7
-    */
-   if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
-      chunk < info_ptr->unknown_chunks_num)
-   {
-      if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
-      {
-         png_app_error(png_ptr, "invalid unknown chunk location");
-         /* Fake out the pre 1.6.0 behavior: */
-         if (((unsigned int)location & PNG_HAVE_IDAT) != 0) /* undocumented! */
-            location = PNG_AFTER_IDAT;
-
-         else
-            location = PNG_HAVE_IHDR; /* also undocumented */
-      }
-
-      info_ptr->unknown_chunks[chunk].location =
-         check_location(png_ptr, location);
-   }
-}
-#endif /* STORE_UNKNOWN_CHUNKS */
-
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-png_uint_32 PNGAPI
-png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
-{
-   png_debug(1, "in png_permit_mng_features");
-
-   if (png_ptr == NULL)
-      return 0;
-
-   png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
-
-   return png_ptr->mng_features_permitted;
-}
-#endif
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-static unsigned int
-add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep)
-{
-   unsigned int i;
-
-   /* Utility function: update the 'keep' state of a chunk if it is already in
-    * the list, otherwise add it to the list.
-    */
-   for (i=0; i<count; ++i, list += 5)
-   {
-      if (memcmp(list, add, 4) == 0)
-      {
-         list[4] = (png_byte)keep;
-
-         return count;
-      }
-   }
-
-   if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
-   {
-      ++count;
-      memcpy(list, add, 4);
-      list[4] = (png_byte)keep;
-   }
-
-   return count;
-}
-
-void PNGAPI
-png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
-    png_const_bytep chunk_list, int num_chunks_in)
-{
-   png_bytep new_list;
-   unsigned int num_chunks, old_num_chunks;
-
-   if (png_ptr == NULL)
-      return;
-
-   if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
-   {
-      png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
-
-      return;
-   }
-
-   if (num_chunks_in <= 0)
-   {
-      png_ptr->unknown_default = keep;
-
-      /* '0' means just set the flags, so stop here */
-      if (num_chunks_in == 0)
-        return;
-   }
-
-   if (num_chunks_in < 0)
-   {
-      /* Ignore all unknown chunks and all chunks recognized by
-       * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
-       */
-      static const png_byte chunks_to_ignore[] = {
-         98,  75,  71,  68, '\0',  /* bKGD */
-         99,  72,  82,  77, '\0',  /* cHRM */
-        101,  88,  73, 102, '\0',  /* eXIf */
-        103,  65,  77,  65, '\0',  /* gAMA */
-        104,  73,  83,  84, '\0',  /* hIST */
-        105,  67,  67,  80, '\0',  /* iCCP */
-        105,  84,  88, 116, '\0',  /* iTXt */
-        111,  70,  70, 115, '\0',  /* oFFs */
-        112,  67,  65,  76, '\0',  /* pCAL */
-        112,  72,  89, 115, '\0',  /* pHYs */
-        115,  66,  73,  84, '\0',  /* sBIT */
-        115,  67,  65,  76, '\0',  /* sCAL */
-        115,  80,  76,  84, '\0',  /* sPLT */
-        115,  84,  69,  82, '\0',  /* sTER */
-        115,  82,  71,  66, '\0',  /* sRGB */
-        116,  69,  88, 116, '\0',  /* tEXt */
-        116,  73,  77,  69, '\0',  /* tIME */
-        122,  84,  88, 116, '\0'   /* zTXt */
-      };
-
-      chunk_list = chunks_to_ignore;
-      num_chunks = (unsigned int)/*SAFE*/(sizeof chunks_to_ignore)/5U;
-   }
-
-   else /* num_chunks_in > 0 */
-   {
-      if (chunk_list == NULL)
-      {
-         /* Prior to 1.6.0 this was silently ignored, now it is an app_error
-          * which can be switched off.
-          */
-         png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
-
-         return;
-      }
-
-      num_chunks = (unsigned int)num_chunks_in;
-   }
-
-   old_num_chunks = png_ptr->num_chunk_list;
-   if (png_ptr->chunk_list == NULL)
-      old_num_chunks = 0;
-
-   /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
-    */
-   if (num_chunks + old_num_chunks > UINT_MAX/5)
-   {
-      png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
-
-      return;
-   }
-
-   /* If these chunks are being reset to the default then no more memory is
-    * required because add_one_chunk above doesn't extend the list if the 'keep'
-    * parameter is the default.
-    */
-   if (keep != 0)
-   {
-      new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
-          5 * (num_chunks + old_num_chunks)));
-
-      if (old_num_chunks > 0)
-         memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
-   }
-
-   else if (old_num_chunks > 0)
-      new_list = png_ptr->chunk_list;
-
-   else
-      new_list = NULL;
-
-   /* Add the new chunks together with each one's handling code.  If the chunk
-    * already exists the code is updated, otherwise the chunk is added to the
-    * end.  (In libpng 1.6.0 order no longer matters because this code enforces
-    * the earlier convention that the last setting is the one that is used.)
-    */
-   if (new_list != NULL)
-   {
-      png_const_bytep inlist;
-      png_bytep outlist;
-      unsigned int i;
-
-      for (i=0; i<num_chunks; ++i)
-      {
-         old_num_chunks = add_one_chunk(new_list, old_num_chunks,
-             chunk_list+5*i, keep);
-      }
-
-      /* Now remove any spurious 'default' entries. */
-      num_chunks = 0;
-      for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5)
-      {
-         if (inlist[4])
-         {
-            if (outlist != inlist)
-               memcpy(outlist, inlist, 5);
-            outlist += 5;
-            ++num_chunks;
-         }
-      }
-
-      /* This means the application has removed all the specialized handling. */
-      if (num_chunks == 0)
-      {
-         if (png_ptr->chunk_list != new_list)
-            png_free(png_ptr, new_list);
-
-         new_list = NULL;
-      }
-   }
-
-   else
-      num_chunks = 0;
-
-   png_ptr->num_chunk_list = num_chunks;
-
-   if (png_ptr->chunk_list != new_list)
-   {
-      if (png_ptr->chunk_list != NULL)
-         png_free(png_ptr, png_ptr->chunk_list);
-
-      png_ptr->chunk_list = new_list;
-   }
-}
-#endif
-
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
-void PNGAPI
-png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
-    png_user_chunk_ptr read_user_chunk_fn)
-{
-   png_debug(1, "in png_set_read_user_chunk_fn");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->read_user_chunk_fn = read_user_chunk_fn;
-   png_ptr->user_chunk_ptr = user_chunk_ptr;
-}
-#endif
-
-#ifdef PNG_INFO_IMAGE_SUPPORTED
-void PNGAPI
-png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
-    png_bytepp row_pointers)
-{
-   png_debug1(1, "in %s storage function", "rows");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   if (info_ptr->row_pointers != NULL &&
-       (info_ptr->row_pointers != row_pointers))
-      png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
-
-   info_ptr->row_pointers = row_pointers;
-
-   if (row_pointers != NULL)
-      info_ptr->valid |= PNG_INFO_IDAT;
-}
-#endif
-
-void PNGAPI
-png_set_compression_buffer_size(png_structrp png_ptr, size_t size)
-{
-   if (png_ptr == NULL)
-      return;
-
-   if (size == 0 || size > PNG_UINT_31_MAX)
-      png_error(png_ptr, "invalid compression buffer size");
-
-#  ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
-   {
-      png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
-      return;
-   }
-#  endif
-
-#  ifdef PNG_WRITE_SUPPORTED
-   if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
-   {
-      if (png_ptr->zowner != 0)
-      {
-         png_warning(png_ptr,
-             "Compression buffer size cannot be changed because it is in use");
-
-         return;
-      }
-
-#ifndef __COVERITY__
-      /* Some compilers complain that this is always false.  However, it
-       * can be true when integer overflow happens.
-       */
-      if (size > ZLIB_IO_MAX)
-      {
-         png_warning(png_ptr,
-             "Compression buffer size limited to system maximum");
-         size = ZLIB_IO_MAX; /* must fit */
-      }
-#endif
-
-      if (size < 6)
-      {
-         /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
-          * if this is permitted.
-          */
-         png_warning(png_ptr,
-             "Compression buffer size cannot be reduced below 6");
-
-         return;
-      }
-
-      if (png_ptr->zbuffer_size != size)
-      {
-         png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
-         png_ptr->zbuffer_size = (uInt)size;
-      }
-   }
-#  endif
-}
-
-void PNGAPI
-png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
-{
-   if (png_ptr != NULL && info_ptr != NULL)
-      info_ptr->valid &= (unsigned int)(~mask);
-}
-
-
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-/* This function was added to libpng 1.2.6 */
-void PNGAPI
-png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
-    png_uint_32 user_height_max)
-{
-   /* Images with dimensions larger than these limits will be
-    * rejected by png_set_IHDR().  To accept any PNG datastream
-    * regardless of dimensions, set both limits to 0x7fffffff.
-    */
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->user_width_max = user_width_max;
-   png_ptr->user_height_max = user_height_max;
-}
-
-/* This function was added to libpng 1.4.0 */
-void PNGAPI
-png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
-{
-   if (png_ptr != NULL)
-      png_ptr->user_chunk_cache_max = user_chunk_cache_max;
-}
-
-/* This function was added to libpng 1.4.1 */
-void PNGAPI
-png_set_chunk_malloc_max (png_structrp png_ptr,
-    png_alloc_size_t user_chunk_malloc_max)
-{
-   if (png_ptr != NULL)
-      png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
-}
-#endif /* ?SET_USER_LIMITS */
-
-
-#ifdef PNG_BENIGN_ERRORS_SUPPORTED
-void PNGAPI
-png_set_benign_errors(png_structrp png_ptr, int allowed)
-{
-   png_debug(1, "in png_set_benign_errors");
-
-   /* If allowed is 1, png_benign_error() is treated as a warning.
-    *
-    * If allowed is 0, png_benign_error() is treated as an error (which
-    * is the default behavior if png_set_benign_errors() is not called).
-    */
-
-   if (allowed != 0)
-      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN |
-         PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
-
-   else
-      png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
-         PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
-}
-#endif /* BENIGN_ERRORS */
-
-#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
-   /* Whether to report invalid palette index; added at libng-1.5.10.
-    * It is possible for an indexed (color-type==3) PNG file to contain
-    * pixels with invalid (out-of-range) indexes if the PLTE chunk has
-    * fewer entries than the image's bit-depth would allow. We recover
-    * from this gracefully by filling any incomplete palette with zeros
-    * (opaque black).  By default, when this occurs libpng will issue
-    * a benign error.  This API can be used to override that behavior.
-    */
-void PNGAPI
-png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
-{
-   png_debug(1, "in png_set_check_for_invalid_index");
-
-   if (allowed > 0)
-      png_ptr->num_palette_max = 0;
-
-   else
-      png_ptr->num_palette_max = -1;
-}
-#endif
-
-#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \
-    defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
-/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
- * and if invalid, correct the keyword rather than discarding the entire
- * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
- * length, forbids leading or trailing whitespace, multiple internal spaces,
- * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
- *
- * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
- * trailing '\0').  If this routine returns 0 then there was no keyword, or a
- * valid one could not be generated, and the caller must png_error.
- */
-png_uint_32 /* PRIVATE */
-png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
-{
-#ifdef PNG_WARNINGS_SUPPORTED
-   png_const_charp orig_key = key;
-#endif
-   png_uint_32 key_len = 0;
-   int bad_character = 0;
-   int space = 1;
-
-   png_debug(1, "in png_check_keyword");
-
-   if (key == NULL)
-   {
-      *new_key = 0;
-      return 0;
-   }
-
-   while (*key && key_len < 79)
-   {
-      png_byte ch = (png_byte)*key++;
-
-      if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
-      {
-         *new_key++ = ch; ++key_len; space = 0;
-      }
-
-      else if (space == 0)
-      {
-         /* A space or an invalid character when one wasn't seen immediately
-          * before; output just a space.
-          */
-         *new_key++ = 32; ++key_len; space = 1;
-
-         /* If the character was not a space then it is invalid. */
-         if (ch != 32)
-            bad_character = ch;
-      }
-
-      else if (bad_character == 0)
-         bad_character = ch; /* just skip it, record the first error */
-   }
-
-   if (key_len > 0 && space != 0) /* trailing space */
-   {
-      --key_len; --new_key;
-      if (bad_character == 0)
-         bad_character = 32;
-   }
-
-   /* Terminate the keyword */
-   *new_key = 0;
-
-   if (key_len == 0)
-      return 0;
-
-#ifdef PNG_WARNINGS_SUPPORTED
-   /* Try to only output one warning per keyword: */
-   if (*key != 0) /* keyword too long */
-      png_warning(png_ptr, "keyword truncated");
-
-   else if (bad_character != 0)
-   {
-      PNG_WARNING_PARAMETERS(p)
-
-      png_warning_parameter(p, 1, orig_key);
-      png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
-
-      png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
-   }
-#else /* !WARNINGS */
-   PNG_UNUSED(png_ptr)
-#endif /* !WARNINGS */
-
-   return key_len;
-}
-#endif /* TEXT || pCAL || iCCP || sPLT */
-#endif /* READ || WRITE */
diff --git a/third_party/libpng16/pngstruct.h b/third_party/libpng16/pngstruct.h
deleted file mode 100644
index 8bdc7ce..0000000
--- a/third_party/libpng16/pngstruct.h
+++ /dev/null
@@ -1,489 +0,0 @@
-
-/* pngstruct.h - header file for PNG reference library
- *
- * Copyright (c) 2018-2019 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-/* The structure that holds the information to read and write PNG files.
- * The only people who need to care about what is inside of this are the
- * people who will be modifying the library for their own special needs.
- * It should NOT be accessed directly by an application.
- */
-
-#ifndef PNGSTRUCT_H
-#define PNGSTRUCT_H
-/* 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) png_constcast(char*,s)
-#  define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b)
-#else
-#  define PNGZ_MSG_CAST(s) (s)
-#  define PNGZ_INPUT_CAST(b) (b)
-#endif
-
-/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib
- * can handle at once.  This type need be no larger than 16 bits (so maximum of
- * 65535), this define allows us to discover how big it is, but limited by the
- * maximum for size_t.  The value can be overridden in a library build
- * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably
- * lower value (e.g. 255 works).  A lower value may help memory usage (slightly)
- * and may even improve performance on some systems (and degrade it on others.)
- */
-#ifndef ZLIB_IO_MAX
-#  define ZLIB_IO_MAX ((uInt)-1)
-#endif
-
-#ifdef PNG_WRITE_SUPPORTED
-/* The type of a compression buffer list used by the write code. */
-typedef struct png_compression_buffer
-{
-   struct png_compression_buffer *next;
-   png_byte                       output[1]; /* actually zbuf_size */
-} png_compression_buffer, *png_compression_bufferp;
-
-#define PNG_COMPRESSION_BUFFER_SIZE(pp)\
-   (offsetof(png_compression_buffer, output) + (pp)->zbuffer_size)
-#endif
-
-/* Colorspace support; structures used in png_struct, png_info and in internal
- * functions to hold and communicate information about the color space.
- *
- * PNG_COLORSPACE_SUPPORTED is only required if the application will perform
- * colorspace corrections, otherwise all the colorspace information can be
- * skipped and the size of libpng can be reduced (significantly) by compiling
- * out the colorspace support.
- */
-#ifdef PNG_COLORSPACE_SUPPORTED
-/* The chromaticities of the red, green and blue colorants and the chromaticity
- * of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
- */
-typedef struct png_xy
-{
-   png_fixed_point redx, redy;
-   png_fixed_point greenx, greeny;
-   png_fixed_point bluex, bluey;
-   png_fixed_point whitex, whitey;
-} png_xy;
-
-/* The same data as above but encoded as CIE XYZ values.  When this data comes
- * from chromaticities the sum of the Y values is assumed to be 1.0
- */
-typedef struct png_XYZ
-{
-   png_fixed_point red_X, red_Y, red_Z;
-   png_fixed_point green_X, green_Y, green_Z;
-   png_fixed_point blue_X, blue_Y, blue_Z;
-} png_XYZ;
-#endif /* COLORSPACE */
-
-#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
-/* A colorspace is all the above plus, potentially, profile information;
- * however at present libpng does not use the profile internally so it is only
- * stored in the png_info struct (if iCCP is supported.)  The rendering intent
- * is retained here and is checked.
- *
- * The file gamma encoding information is also stored here and gamma correction
- * is done by libpng, whereas color correction must currently be done by the
- * application.
- */
-typedef struct png_colorspace
-{
-#ifdef PNG_GAMMA_SUPPORTED
-   png_fixed_point gamma;        /* File gamma */
-#endif
-
-#ifdef PNG_COLORSPACE_SUPPORTED
-   png_xy      end_points_xy;    /* End points as chromaticities */
-   png_XYZ     end_points_XYZ;   /* End points as CIE XYZ colorant values */
-   png_uint_16 rendering_intent; /* Rendering intent of a profile */
-#endif
-
-   /* Flags are always defined to simplify the code. */
-   png_uint_16 flags;            /* As defined below */
-} png_colorspace, * PNG_RESTRICT png_colorspacerp;
-
-typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
-
-/* General flags for the 'flags' field */
-#define PNG_COLORSPACE_HAVE_GAMMA           0x0001
-#define PNG_COLORSPACE_HAVE_ENDPOINTS       0x0002
-#define PNG_COLORSPACE_HAVE_INTENT          0x0004
-#define PNG_COLORSPACE_FROM_gAMA            0x0008
-#define PNG_COLORSPACE_FROM_cHRM            0x0010
-#define PNG_COLORSPACE_FROM_sRGB            0x0020
-#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040
-#define PNG_COLORSPACE_MATCHES_sRGB         0x0080 /* exact match on profile */
-#define PNG_COLORSPACE_INVALID              0x8000
-#define PNG_COLORSPACE_CANCEL(flags)        (0xffff ^ (flags))
-#endif /* COLORSPACE || GAMMA */
-
-struct png_struct_def
-{
-#ifdef PNG_SETJMP_SUPPORTED
-   jmp_buf jmp_buf_local;     /* New name in 1.6.0 for jmp_buf in png_struct */
-   png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */
-   jmp_buf *jmp_buf_ptr;      /* passed to longjmp_fn */
-   size_t jmp_buf_size;       /* size of the above, if allocated */
-#endif
-   png_error_ptr error_fn;    /* function for printing errors and aborting */
-#ifdef PNG_WARNINGS_SUPPORTED
-   png_error_ptr warning_fn;  /* function for printing warnings */
-#endif
-   png_voidp error_ptr;       /* user supplied struct for error functions */
-   png_rw_ptr write_data_fn;  /* function for writing output data */
-   png_rw_ptr read_data_fn;   /* function for reading input data */
-   png_voidp io_ptr;          /* ptr to application struct for I/O functions */
-
-#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
-   png_user_transform_ptr read_user_transform_fn; /* user read transform */
-#endif
-
-#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
-   png_user_transform_ptr write_user_transform_fn; /* user write transform */
-#endif
-
-/* These were added in libpng-1.0.2 */
-#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
-#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
-    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
-   png_voidp user_transform_ptr; /* user supplied struct for user transform */
-   png_byte user_transform_depth;    /* bit depth of user transformed pixels */
-   png_byte user_transform_channels; /* channels in user transformed pixels */
-#endif
-#endif
-
-   png_uint_32 mode;          /* tells us where we are in the PNG file */
-   png_uint_32 flags;         /* flags indicating various things to libpng */
-   png_uint_32 transformations; /* which transformations to perform */
-
-   png_uint_32 zowner;        /* ID (chunk type) of zstream owner, 0 if none */
-   z_stream    zstream;       /* decompression structure */
-
-#ifdef PNG_WRITE_SUPPORTED
-   png_compression_bufferp zbuffer_list; /* Created on demand during write */
-   uInt                    zbuffer_size; /* size of the actual buffer */
-
-   int zlib_level;            /* holds zlib compression level */
-   int zlib_method;           /* holds zlib compression method */
-   int zlib_window_bits;      /* holds zlib compression window bits */
-   int zlib_mem_level;        /* holds zlib compression memory level */
-   int zlib_strategy;         /* holds zlib compression strategy */
-#endif
-/* Added at libpng 1.5.4 */
-#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
-   int zlib_text_level;            /* holds zlib compression level */
-   int zlib_text_method;           /* holds zlib compression method */
-   int zlib_text_window_bits;      /* holds zlib compression window bits */
-   int zlib_text_mem_level;        /* holds zlib compression memory level */
-   int zlib_text_strategy;         /* holds zlib compression strategy */
-#endif
-/* End of material added at libpng 1.5.4 */
-/* Added at libpng 1.6.0 */
-#ifdef PNG_WRITE_SUPPORTED
-   int zlib_set_level;        /* Actual values set into the zstream on write */
-   int zlib_set_method;
-   int zlib_set_window_bits;
-   int zlib_set_mem_level;
-   int zlib_set_strategy;
-#endif
-
-   png_uint_32 width;         /* width of image in pixels */
-   png_uint_32 height;        /* height of image in pixels */
-   png_uint_32 num_rows;      /* number of rows in current pass */
-   png_uint_32 usr_width;     /* width of row at start of write */
-   size_t rowbytes;           /* size of row in bytes */
-   png_uint_32 iwidth;        /* width of current interlaced row in pixels */
-   png_uint_32 row_number;    /* current row in interlace pass */
-   png_uint_32 chunk_name;    /* PNG_CHUNK() id of current chunk */
-   png_bytep prev_row;        /* buffer to save previous (unfiltered) row.
-                               * While reading this is a pointer into
-                               * big_prev_row; while writing it is separately
-                               * allocated if needed.
-                               */
-   png_bytep row_buf;         /* buffer to save current (unfiltered) row.
-                               * While reading, this is a pointer into
-                               * big_row_buf; while writing it is separately
-                               * allocated.
-                               */
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-   png_bytep try_row;    /* buffer to save trial row when filtering */
-   png_bytep tst_row;    /* buffer to save best trial row when filtering */
-#endif
-   size_t info_rowbytes;      /* Added in 1.5.4: cache of updated row bytes */
-
-   png_uint_32 idat_size;     /* current IDAT size for read */
-   png_uint_32 crc;           /* current chunk CRC value */
-   png_colorp palette;        /* palette from the input file */
-   png_uint_16 num_palette;   /* number of color entries in palette */
-
-/* Added at libpng-1.5.10 */
-#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
-   int num_palette_max;       /* maximum palette index found in IDAT */
-#endif
-
-   png_uint_16 num_trans;     /* number of transparency values */
-   png_byte compression;      /* file compression type (always 0) */
-   png_byte filter;           /* file filter type (always 0) */
-   png_byte interlaced;       /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
-   png_byte pass;             /* current interlace pass (0 - 6) */
-   png_byte do_filter;        /* row filter flags (see PNG_FILTER_ in png.h ) */
-   png_byte color_type;       /* color type of file */
-   png_byte bit_depth;        /* bit depth of file */
-   png_byte usr_bit_depth;    /* bit depth of users row: write only */
-   png_byte pixel_depth;      /* number of bits per pixel */
-   png_byte channels;         /* number of channels in file */
-#ifdef PNG_WRITE_SUPPORTED
-   png_byte usr_channels;     /* channels at start of write: write only */
-#endif
-   png_byte sig_bytes;        /* magic bytes read/written from start of file */
-   png_byte maximum_pixel_depth;
-                              /* pixel depth used for the row buffers */
-   png_byte transformed_pixel_depth;
-                              /* pixel depth after read/write transforms */
-#if ZLIB_VERNUM >= 0x1240
-   png_byte zstream_start;    /* at start of an input zlib stream */
-#endif /* Zlib >= 1.2.4 */
-#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
-   png_uint_16 filler;           /* filler bytes for pixel expansion */
-#endif
-
-#if defined(PNG_bKGD_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED)
-   png_byte background_gamma_type;
-   png_fixed_point background_gamma;
-   png_color_16 background;   /* background color in screen gamma space */
-#ifdef PNG_READ_GAMMA_SUPPORTED
-   png_color_16 background_1; /* background normalized to gamma 1.0 */
-#endif
-#endif /* bKGD */
-
-#ifdef PNG_WRITE_FLUSH_SUPPORTED
-   png_flush_ptr output_flush_fn; /* Function for flushing output */
-   png_uint_32 flush_dist;    /* how many rows apart to flush, 0 - no flush */
-   png_uint_32 flush_rows;    /* number of rows written since last flush */
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-   int gamma_shift;      /* number of "insignificant" bits in 16-bit gamma */
-   png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */
-
-   png_bytep gamma_table;     /* gamma table for 8-bit depth files */
-   png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
-   defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
-   defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
-   png_bytep gamma_from_1;    /* converts from 1.0 to screen */
-   png_bytep gamma_to_1;      /* converts from file to 1.0 */
-   png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */
-   png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */
-#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
-#endif
-
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED)
-   png_color_8 sig_bit;       /* significant bits in each available channel */
-#endif
-
-#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
-   png_color_8 shift;         /* shift for significant bit transformation */
-#endif
-
-#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \
- || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
-   png_bytep trans_alpha;           /* alpha values for paletted files */
-   png_color_16 trans_color;  /* transparent color for non-paletted files */
-#endif
-
-   png_read_status_ptr read_row_fn;   /* called after each row is decoded */
-   png_write_status_ptr write_row_fn; /* called after each row is encoded */
-#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-   png_progressive_info_ptr info_fn; /* called after header data fully read */
-   png_progressive_row_ptr row_fn;   /* called after a prog. row is decoded */
-   png_progressive_end_ptr end_fn;   /* called after image is complete */
-   png_bytep save_buffer_ptr;        /* current location in save_buffer */
-   png_bytep save_buffer;            /* buffer for previously read data */
-   png_bytep current_buffer_ptr;     /* current location in current_buffer */
-   png_bytep current_buffer;         /* buffer for recently used data */
-   png_uint_32 push_length;          /* size of current input chunk */
-   png_uint_32 skip_length;          /* bytes to skip in input data */
-   size_t save_buffer_size;          /* amount of data now in save_buffer */
-   size_t save_buffer_max;           /* total size of save_buffer */
-   size_t buffer_size;               /* total amount of available input data */
-   size_t current_buffer_size;       /* amount of data now in current_buffer */
-   int process_mode;                 /* what push library is currently doing */
-   int cur_palette;                  /* current push library palette index */
-
-#endif /* PROGRESSIVE_READ */
-
-#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
-/* For the Borland special 64K segment handler */
-   png_bytepp offset_table_ptr;
-   png_bytep offset_table;
-   png_uint_16 offset_table_number;
-   png_uint_16 offset_table_count;
-   png_uint_16 offset_table_count_free;
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-   png_bytep palette_lookup; /* lookup table for quantizing */
-   png_bytep quantize_index; /* index translation for palette files */
-#endif
-
-/* Options */
-#ifdef PNG_SET_OPTION_SUPPORTED
-   png_uint_32 options;           /* On/off state (up to 16 options) */
-#endif
-
-#if PNG_LIBPNG_VER < 10700
-/* To do: remove this from libpng-1.7 */
-#ifdef PNG_TIME_RFC1123_SUPPORTED
-   char time_buffer[29]; /* String to hold RFC 1123 time text */
-#endif
-#endif
-
-/* New members added in libpng-1.0.6 */
-
-   png_uint_32 free_me;    /* flags items libpng is responsible for freeing */
-
-#ifdef PNG_USER_CHUNKS_SUPPORTED
-   png_voidp user_chunk_ptr;
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
-   png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
-#endif
-#endif
-
-#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-   int          unknown_default; /* As PNG_HANDLE_* */
-   unsigned int num_chunk_list;  /* Number of entries in the list */
-   png_bytep    chunk_list;      /* List of png_byte[5]; the textual chunk name
-                                  * followed by a PNG_HANDLE_* byte */
-#endif
-
-/* New members added in libpng-1.0.3 */
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-   png_byte rgb_to_gray_status;
-   /* Added in libpng 1.5.5 to record setting of coefficients: */
-   png_byte rgb_to_gray_coefficients_set;
-   /* These were changed from png_byte in libpng-1.0.6 */
-   png_uint_16 rgb_to_gray_red_coeff;
-   png_uint_16 rgb_to_gray_green_coeff;
-   /* deleted in 1.5.5: rgb_to_gray_blue_coeff; */
-#endif
-
-/* New member added in libpng-1.6.36 */
-#if defined(PNG_READ_EXPAND_SUPPORTED) && \
-    defined(PNG_ARM_NEON_IMPLEMENTATION)
-   png_bytep riffled_palette; /* buffer for accelerated palette expansion */
-#endif
-
-/* New member added in libpng-1.0.4 (renamed in 1.0.9) */
-#if defined(PNG_MNG_FEATURES_SUPPORTED)
-/* Changed from png_byte to png_uint_32 at version 1.2.0 */
-   png_uint_32 mng_features_permitted;
-#endif
-
-/* New member added in libpng-1.0.9, ifdef'ed out in 1.0.12, enabled in 1.2.0 */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-   png_byte filter_type;
-#endif
-
-/* New members added in libpng-1.2.0 */
-
-/* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */
-#ifdef PNG_USER_MEM_SUPPORTED
-   png_voidp mem_ptr;             /* user supplied struct for mem functions */
-   png_malloc_ptr malloc_fn;      /* function for allocating memory */
-   png_free_ptr free_fn;          /* function for freeing memory */
-#endif
-
-/* New member added in libpng-1.0.13 and 1.2.0 */
-   png_bytep big_row_buf;         /* buffer to save current (unfiltered) row */
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-/* The following three members were added at version 1.0.14 and 1.2.4 */
-   png_bytep quantize_sort;          /* working sort array */
-   png_bytep index_to_palette;       /* where the original index currently is
-                                        in the palette */
-   png_bytep palette_to_index;       /* which original index points to this
-                                         palette color */
-#endif
-
-/* New members added in libpng-1.0.16 and 1.2.6 */
-   png_byte compression_type;
-
-#ifdef PNG_USER_LIMITS_SUPPORTED
-   png_uint_32 user_width_max;
-   png_uint_32 user_height_max;
-
-   /* Added in libpng-1.4.0: Total number of sPLT, text, and unknown
-    * chunks that can be stored (0 means unlimited).
-    */
-   png_uint_32 user_chunk_cache_max;
-
-   /* Total memory that a zTXt, sPLT, iTXt, iCCP, or unknown chunk
-    * can occupy when decompressed.  0 means unlimited.
-    */
-   png_alloc_size_t user_chunk_malloc_max;
-#endif
-
-/* New member added in libpng-1.0.25 and 1.2.17 */
-#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
-   /* Temporary storage for unknown chunk that the library doesn't recognize,
-    * used while reading the chunk.
-    */
-   png_unknown_chunk unknown_chunk;
-#endif
-
-/* New member added in libpng-1.2.26 */
-   size_t old_big_row_buf_size;
-
-#ifdef PNG_READ_SUPPORTED
-/* New member added in libpng-1.2.30 */
-  png_bytep        read_buffer;      /* buffer for reading chunk data */
-  png_alloc_size_t read_buffer_size; /* current size of the buffer */
-#endif
-#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-  uInt             IDAT_read_size;   /* limit on read buffer size for IDAT */
-#endif
-
-#ifdef PNG_IO_STATE_SUPPORTED
-/* New member added in libpng-1.4.0 */
-   png_uint_32 io_state;
-#endif
-
-/* New member added in libpng-1.5.6 */
-   png_bytep big_prev_row;
-
-/* New member added in libpng-1.5.7 */
-   void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info,
-      png_bytep row, png_const_bytep prev_row);
-
-#ifdef PNG_READ_SUPPORTED
-#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
-   png_colorspace   colorspace;
-#endif
-#endif
-};
-#endif /* PNGSTRUCT_H */
diff --git a/third_party/libpng16/pngtrans.c b/third_party/libpng16/pngtrans.c
deleted file mode 100644
index 1100f46..0000000
--- a/third_party/libpng16/pngtrans.c
+++ /dev/null
@@ -1,864 +0,0 @@
-
-/* pngtrans.c - transforms the data in a row (used by both readers and writers)
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include "pngpriv.h"
-
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-
-#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
-/* Turn on BGR-to-RGB mapping */
-void PNGAPI
-png_set_bgr(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_bgr");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->transformations |= PNG_BGR;
-}
-#endif
-
-#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-/* Turn on 16-bit byte swapping */
-void PNGAPI
-png_set_swap(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_swap");
-
-   if (png_ptr == NULL)
-      return;
-
-   if (png_ptr->bit_depth == 16)
-      png_ptr->transformations |= PNG_SWAP_BYTES;
-}
-#endif
-
-#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
-/* Turn on pixel packing */
-void PNGAPI
-png_set_packing(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_packing");
-
-   if (png_ptr == NULL)
-      return;
-
-   if (png_ptr->bit_depth < 8)
-   {
-      png_ptr->transformations |= PNG_PACK;
-#     ifdef PNG_WRITE_SUPPORTED
-         png_ptr->usr_bit_depth = 8;
-#     endif
-   }
-}
-#endif
-
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-/* Turn on packed pixel swapping */
-void PNGAPI
-png_set_packswap(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_packswap");
-
-   if (png_ptr == NULL)
-      return;
-
-   if (png_ptr->bit_depth < 8)
-      png_ptr->transformations |= PNG_PACKSWAP;
-}
-#endif
-
-#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
-void PNGAPI
-png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
-{
-   png_debug(1, "in png_set_shift");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->transformations |= PNG_SHIFT;
-   png_ptr->shift = *true_bits;
-}
-#endif
-
-#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
-    defined(PNG_WRITE_INTERLACING_SUPPORTED)
-int PNGAPI
-png_set_interlace_handling(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_interlace handling");
-
-   if (png_ptr != 0 && png_ptr->interlaced != 0)
-   {
-      png_ptr->transformations |= PNG_INTERLACE;
-      return (7);
-   }
-
-   return (1);
-}
-#endif
-
-#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
-/* Add a filler byte on read, or remove a filler or alpha byte on write.
- * The filler type has changed in v0.95 to allow future 2-byte fillers
- * for 48-bit input data, as well as to avoid problems with some compilers
- * that don't like bytes as parameters.
- */
-void PNGAPI
-png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
-{
-   png_debug(1, "in png_set_filler");
-
-   if (png_ptr == NULL)
-      return;
-
-   /* In libpng 1.6 it is possible to determine whether this is a read or write
-    * operation and therefore to do more checking here for a valid call.
-    */
-   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
-   {
-#     ifdef PNG_READ_FILLER_SUPPORTED
-         /* On read png_set_filler is always valid, regardless of the base PNG
-          * format, because other transformations can give a format where the
-          * filler code can execute (basically an 8 or 16-bit component RGB or G
-          * format.)
-          *
-          * NOTE: usr_channels is not used by the read code!  (This has led to
-          * confusion in the past.)  The filler is only used in the read code.
-          */
-         png_ptr->filler = (png_uint_16)filler;
-#     else
-         png_app_error(png_ptr, "png_set_filler not supported on read");
-         PNG_UNUSED(filler) /* not used in the write case */
-         return;
-#     endif
-   }
-
-   else /* write */
-   {
-#     ifdef PNG_WRITE_FILLER_SUPPORTED
-         /* On write the usr_channels parameter must be set correctly at the
-          * start to record the number of channels in the app-supplied data.
-          */
-         switch (png_ptr->color_type)
-         {
-            case PNG_COLOR_TYPE_RGB:
-               png_ptr->usr_channels = 4;
-               break;
-
-            case PNG_COLOR_TYPE_GRAY:
-               if (png_ptr->bit_depth >= 8)
-               {
-                  png_ptr->usr_channels = 2;
-                  break;
-               }
-
-               else
-               {
-                  /* There simply isn't any code in libpng to strip out bits
-                   * from bytes when the components are less than a byte in
-                   * size!
-                   */
-                  png_app_error(png_ptr,
-                      "png_set_filler is invalid for"
-                      " low bit depth gray output");
-                  return;
-               }
-
-            default:
-               png_app_error(png_ptr,
-                   "png_set_filler: inappropriate color type");
-               return;
-         }
-#     else
-         png_app_error(png_ptr, "png_set_filler not supported on write");
-         return;
-#     endif
-   }
-
-   /* Here on success - libpng supports the operation, set the transformation
-    * and the flag to say where the filler channel is.
-    */
-   png_ptr->transformations |= PNG_FILLER;
-
-   if (filler_loc == PNG_FILLER_AFTER)
-      png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
-
-   else
-      png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
-}
-
-/* Added to libpng-1.2.7 */
-void PNGAPI
-png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
-{
-   png_debug(1, "in png_set_add_alpha");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_set_filler(png_ptr, filler, filler_loc);
-   /* The above may fail to do anything. */
-   if ((png_ptr->transformations & PNG_FILLER) != 0)
-      png_ptr->transformations |= PNG_ADD_ALPHA;
-}
-
-#endif
-
-#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
-    defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
-void PNGAPI
-png_set_swap_alpha(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_swap_alpha");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->transformations |= PNG_SWAP_ALPHA;
-}
-#endif
-
-#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
-    defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
-void PNGAPI
-png_set_invert_alpha(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_invert_alpha");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->transformations |= PNG_INVERT_ALPHA;
-}
-#endif
-
-#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
-void PNGAPI
-png_set_invert_mono(png_structrp png_ptr)
-{
-   png_debug(1, "in png_set_invert_mono");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->transformations |= PNG_INVERT_MONO;
-}
-
-/* Invert monochrome grayscale data */
-void /* PRIVATE */
-png_do_invert(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_invert");
-
-  /* This test removed from libpng version 1.0.13 and 1.2.0:
-   *   if (row_info->bit_depth == 1 &&
-   */
-   if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
-   {
-      png_bytep rp = row;
-      size_t i;
-      size_t istop = row_info->rowbytes;
-
-      for (i = 0; i < istop; i++)
-      {
-         *rp = (png_byte)(~(*rp));
-         rp++;
-      }
-   }
-
-   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
-      row_info->bit_depth == 8)
-   {
-      png_bytep rp = row;
-      size_t i;
-      size_t istop = row_info->rowbytes;
-
-      for (i = 0; i < istop; i += 2)
-      {
-         *rp = (png_byte)(~(*rp));
-         rp += 2;
-      }
-   }
-
-#ifdef PNG_16BIT_SUPPORTED
-   else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
-      row_info->bit_depth == 16)
-   {
-      png_bytep rp = row;
-      size_t i;
-      size_t istop = row_info->rowbytes;
-
-      for (i = 0; i < istop; i += 4)
-      {
-         *rp = (png_byte)(~(*rp));
-         *(rp + 1) = (png_byte)(~(*(rp + 1)));
-         rp += 4;
-      }
-   }
-#endif
-}
-#endif
-
-#ifdef PNG_16BIT_SUPPORTED
-#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-/* Swaps byte order on 16-bit depth images */
-void /* PRIVATE */
-png_do_swap(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_swap");
-
-   if (row_info->bit_depth == 16)
-   {
-      png_bytep rp = row;
-      png_uint_32 i;
-      png_uint_32 istop= row_info->width * row_info->channels;
-
-      for (i = 0; i < istop; i++, rp += 2)
-      {
-#ifdef PNG_BUILTIN_BSWAP16_SUPPORTED
-         /* Feature added to libpng-1.6.11 for testing purposes, not
-          * enabled by default.
-          */
-         *(png_uint_16*)rp = __builtin_bswap16(*(png_uint_16*)rp);
-#else
-         png_byte t = *rp;
-         *rp = *(rp + 1);
-         *(rp + 1) = t;
-#endif
-      }
-   }
-}
-#endif
-#endif
-
-#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-static const png_byte onebppswaptable[256] = {
-   0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
-   0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
-   0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
-   0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
-   0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
-   0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
-   0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
-   0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
-   0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
-   0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
-   0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
-   0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
-   0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
-   0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
-   0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
-   0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
-   0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
-   0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
-   0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
-   0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
-   0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
-   0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
-   0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
-   0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
-   0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
-   0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
-   0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
-   0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
-   0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
-   0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
-   0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
-   0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
-};
-
-static const png_byte twobppswaptable[256] = {
-   0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
-   0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
-   0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
-   0x24, 0x64, 0xA4, 0xE4, 0x34, 0x74, 0xB4, 0xF4,
-   0x08, 0x48, 0x88, 0xC8, 0x18, 0x58, 0x98, 0xD8,
-   0x28, 0x68, 0xA8, 0xE8, 0x38, 0x78, 0xB8, 0xF8,
-   0x0C, 0x4C, 0x8C, 0xCC, 0x1C, 0x5C, 0x9C, 0xDC,
-   0x2C, 0x6C, 0xAC, 0xEC, 0x3C, 0x7C, 0xBC, 0xFC,
-   0x01, 0x41, 0x81, 0xC1, 0x11, 0x51, 0x91, 0xD1,
-   0x21, 0x61, 0xA1, 0xE1, 0x31, 0x71, 0xB1, 0xF1,
-   0x05, 0x45, 0x85, 0xC5, 0x15, 0x55, 0x95, 0xD5,
-   0x25, 0x65, 0xA5, 0xE5, 0x35, 0x75, 0xB5, 0xF5,
-   0x09, 0x49, 0x89, 0xC9, 0x19, 0x59, 0x99, 0xD9,
-   0x29, 0x69, 0xA9, 0xE9, 0x39, 0x79, 0xB9, 0xF9,
-   0x0D, 0x4D, 0x8D, 0xCD, 0x1D, 0x5D, 0x9D, 0xDD,
-   0x2D, 0x6D, 0xAD, 0xED, 0x3D, 0x7D, 0xBD, 0xFD,
-   0x02, 0x42, 0x82, 0xC2, 0x12, 0x52, 0x92, 0xD2,
-   0x22, 0x62, 0xA2, 0xE2, 0x32, 0x72, 0xB2, 0xF2,
-   0x06, 0x46, 0x86, 0xC6, 0x16, 0x56, 0x96, 0xD6,
-   0x26, 0x66, 0xA6, 0xE6, 0x36, 0x76, 0xB6, 0xF6,
-   0x0A, 0x4A, 0x8A, 0xCA, 0x1A, 0x5A, 0x9A, 0xDA,
-   0x2A, 0x6A, 0xAA, 0xEA, 0x3A, 0x7A, 0xBA, 0xFA,
-   0x0E, 0x4E, 0x8E, 0xCE, 0x1E, 0x5E, 0x9E, 0xDE,
-   0x2E, 0x6E, 0xAE, 0xEE, 0x3E, 0x7E, 0xBE, 0xFE,
-   0x03, 0x43, 0x83, 0xC3, 0x13, 0x53, 0x93, 0xD3,
-   0x23, 0x63, 0xA3, 0xE3, 0x33, 0x73, 0xB3, 0xF3,
-   0x07, 0x47, 0x87, 0xC7, 0x17, 0x57, 0x97, 0xD7,
-   0x27, 0x67, 0xA7, 0xE7, 0x37, 0x77, 0xB7, 0xF7,
-   0x0B, 0x4B, 0x8B, 0xCB, 0x1B, 0x5B, 0x9B, 0xDB,
-   0x2B, 0x6B, 0xAB, 0xEB, 0x3B, 0x7B, 0xBB, 0xFB,
-   0x0F, 0x4F, 0x8F, 0xCF, 0x1F, 0x5F, 0x9F, 0xDF,
-   0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
-};
-
-static const png_byte fourbppswaptable[256] = {
-   0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
-   0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
-   0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
-   0x81, 0x91, 0xA1, 0xB1, 0xC1, 0xD1, 0xE1, 0xF1,
-   0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72,
-   0x82, 0x92, 0xA2, 0xB2, 0xC2, 0xD2, 0xE2, 0xF2,
-   0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73,
-   0x83, 0x93, 0xA3, 0xB3, 0xC3, 0xD3, 0xE3, 0xF3,
-   0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74,
-   0x84, 0x94, 0xA4, 0xB4, 0xC4, 0xD4, 0xE4, 0xF4,
-   0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75,
-   0x85, 0x95, 0xA5, 0xB5, 0xC5, 0xD5, 0xE5, 0xF5,
-   0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76,
-   0x86, 0x96, 0xA6, 0xB6, 0xC6, 0xD6, 0xE6, 0xF6,
-   0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77,
-   0x87, 0x97, 0xA7, 0xB7, 0xC7, 0xD7, 0xE7, 0xF7,
-   0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78,
-   0x88, 0x98, 0xA8, 0xB8, 0xC8, 0xD8, 0xE8, 0xF8,
-   0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79,
-   0x89, 0x99, 0xA9, 0xB9, 0xC9, 0xD9, 0xE9, 0xF9,
-   0x0A, 0x1A, 0x2A, 0x3A, 0x4A, 0x5A, 0x6A, 0x7A,
-   0x8A, 0x9A, 0xAA, 0xBA, 0xCA, 0xDA, 0xEA, 0xFA,
-   0x0B, 0x1B, 0x2B, 0x3B, 0x4B, 0x5B, 0x6B, 0x7B,
-   0x8B, 0x9B, 0xAB, 0xBB, 0xCB, 0xDB, 0xEB, 0xFB,
-   0x0C, 0x1C, 0x2C, 0x3C, 0x4C, 0x5C, 0x6C, 0x7C,
-   0x8C, 0x9C, 0xAC, 0xBC, 0xCC, 0xDC, 0xEC, 0xFC,
-   0x0D, 0x1D, 0x2D, 0x3D, 0x4D, 0x5D, 0x6D, 0x7D,
-   0x8D, 0x9D, 0xAD, 0xBD, 0xCD, 0xDD, 0xED, 0xFD,
-   0x0E, 0x1E, 0x2E, 0x3E, 0x4E, 0x5E, 0x6E, 0x7E,
-   0x8E, 0x9E, 0xAE, 0xBE, 0xCE, 0xDE, 0xEE, 0xFE,
-   0x0F, 0x1F, 0x2F, 0x3F, 0x4F, 0x5F, 0x6F, 0x7F,
-   0x8F, 0x9F, 0xAF, 0xBF, 0xCF, 0xDF, 0xEF, 0xFF
-};
-
-/* Swaps pixel packing order within bytes */
-void /* PRIVATE */
-png_do_packswap(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_packswap");
-
-   if (row_info->bit_depth < 8)
-   {
-      png_bytep rp;
-      png_const_bytep end, table;
-
-      end = row + row_info->rowbytes;
-
-      if (row_info->bit_depth == 1)
-         table = onebppswaptable;
-
-      else if (row_info->bit_depth == 2)
-         table = twobppswaptable;
-
-      else if (row_info->bit_depth == 4)
-         table = fourbppswaptable;
-
-      else
-         return;
-
-      for (rp = row; rp < end; rp++)
-         *rp = table[*rp];
-   }
-}
-#endif /* PACKSWAP || WRITE_PACKSWAP */
-
-#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
-    defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
-/* Remove a channel - this used to be 'png_do_strip_filler' but it used a
- * somewhat weird combination of flags to determine what to do.  All the calls
- * to png_do_strip_filler are changed in 1.5.2 to call this instead with the
- * correct arguments.
- *
- * The routine isn't general - the channel must be the channel at the start or
- * end (not in the middle) of each pixel.
- */
-void /* PRIVATE */
-png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
-{
-   png_bytep sp = row; /* source pointer */
-   png_bytep dp = row; /* destination pointer */
-   png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
-
-   /* At the start sp will point to the first byte to copy and dp to where
-    * it is copied to.  ep always points just beyond the end of the row, so
-    * the loop simply copies (channels-1) channels until sp reaches ep.
-    *
-    * at_start:        0 -- convert AG, XG, ARGB, XRGB, AAGG, XXGG, etc.
-    *            nonzero -- convert GA, GX, RGBA, RGBX, GGAA, RRGGBBXX, etc.
-    */
-
-   /* GA, GX, XG cases */
-   if (row_info->channels == 2)
-   {
-      if (row_info->bit_depth == 8)
-      {
-         if (at_start != 0) /* Skip initial filler */
-            ++sp;
-         else          /* Skip initial channel and, for sp, the filler */
-         {
-            sp += 2; ++dp;
-         }
-
-         /* For a 1 pixel wide image there is nothing to do */
-         while (sp < ep)
-         {
-            *dp++ = *sp; sp += 2;
-         }
-
-         row_info->pixel_depth = 8;
-      }
-
-      else if (row_info->bit_depth == 16)
-      {
-         if (at_start != 0) /* Skip initial filler */
-            sp += 2;
-         else          /* Skip initial channel and, for sp, the filler */
-         {
-            sp += 4; dp += 2;
-         }
-
-         while (sp < ep)
-         {
-            *dp++ = *sp++; *dp++ = *sp; sp += 3;
-         }
-
-         row_info->pixel_depth = 16;
-      }
-
-      else
-         return; /* bad bit depth */
-
-      row_info->channels = 1;
-
-      /* Finally fix the color type if it records an alpha channel */
-      if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-         row_info->color_type = PNG_COLOR_TYPE_GRAY;
-   }
-
-   /* RGBA, RGBX, XRGB cases */
-   else if (row_info->channels == 4)
-   {
-      if (row_info->bit_depth == 8)
-      {
-         if (at_start != 0) /* Skip initial filler */
-            ++sp;
-         else          /* Skip initial channels and, for sp, the filler */
-         {
-            sp += 4; dp += 3;
-         }
-
-         /* Note that the loop adds 3 to dp and 4 to sp each time. */
-         while (sp < ep)
-         {
-            *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp; sp += 2;
-         }
-
-         row_info->pixel_depth = 24;
-      }
-
-      else if (row_info->bit_depth == 16)
-      {
-         if (at_start != 0) /* Skip initial filler */
-            sp += 2;
-         else          /* Skip initial channels and, for sp, the filler */
-         {
-            sp += 8; dp += 6;
-         }
-
-         while (sp < ep)
-         {
-            /* Copy 6 bytes, skip 2 */
-            *dp++ = *sp++; *dp++ = *sp++;
-            *dp++ = *sp++; *dp++ = *sp++;
-            *dp++ = *sp++; *dp++ = *sp; sp += 3;
-         }
-
-         row_info->pixel_depth = 48;
-      }
-
-      else
-         return; /* bad bit depth */
-
-      row_info->channels = 3;
-
-      /* Finally fix the color type if it records an alpha channel */
-      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-         row_info->color_type = PNG_COLOR_TYPE_RGB;
-   }
-
-   else
-      return; /* The filler channel has gone already */
-
-   /* Fix the rowbytes value. */
-   row_info->rowbytes = (size_t)(dp-row);
-}
-#endif
-
-#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
-/* Swaps red and blue bytes within a pixel */
-void /* PRIVATE */
-png_do_bgr(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_bgr");
-
-   if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
-   {
-      png_uint_32 row_width = row_info->width;
-      if (row_info->bit_depth == 8)
-      {
-         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
-         {
-            png_bytep rp;
-            png_uint_32 i;
-
-            for (i = 0, rp = row; i < row_width; i++, rp += 3)
-            {
-               png_byte save = *rp;
-               *rp = *(rp + 2);
-               *(rp + 2) = save;
-            }
-         }
-
-         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-         {
-            png_bytep rp;
-            png_uint_32 i;
-
-            for (i = 0, rp = row; i < row_width; i++, rp += 4)
-            {
-               png_byte save = *rp;
-               *rp = *(rp + 2);
-               *(rp + 2) = save;
-            }
-         }
-      }
-
-#ifdef PNG_16BIT_SUPPORTED
-      else if (row_info->bit_depth == 16)
-      {
-         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
-         {
-            png_bytep rp;
-            png_uint_32 i;
-
-            for (i = 0, rp = row; i < row_width; i++, rp += 6)
-            {
-               png_byte save = *rp;
-               *rp = *(rp + 4);
-               *(rp + 4) = save;
-               save = *(rp + 1);
-               *(rp + 1) = *(rp + 5);
-               *(rp + 5) = save;
-            }
-         }
-
-         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-         {
-            png_bytep rp;
-            png_uint_32 i;
-
-            for (i = 0, rp = row; i < row_width; i++, rp += 8)
-            {
-               png_byte save = *rp;
-               *rp = *(rp + 4);
-               *(rp + 4) = save;
-               save = *(rp + 1);
-               *(rp + 1) = *(rp + 5);
-               *(rp + 5) = save;
-            }
-         }
-      }
-#endif
-   }
-}
-#endif /* READ_BGR || WRITE_BGR */
-
-#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
-    defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
-/* Added at libpng-1.5.10 */
-void /* PRIVATE */
-png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
-{
-   if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
-      png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
-   {
-      /* Calculations moved outside switch in an attempt to stop different
-       * compiler warnings.  'padding' is in *bits* within the last byte, it is
-       * an 'int' because pixel_depth becomes an 'int' in the expression below,
-       * and this calculation is used because it avoids warnings that other
-       * forms produced on either GCC or MSVC.
-       */
-      int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
-      png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1;
-
-      switch (row_info->bit_depth)
-      {
-         case 1:
-         {
-            /* in this case, all bytes must be 0 so we don't need
-             * to unpack the pixels except for the rightmost one.
-             */
-            for (; rp > png_ptr->row_buf; rp--)
-            {
-              if ((*rp >> padding) != 0)
-                 png_ptr->num_palette_max = 1;
-              padding = 0;
-            }
-
-            break;
-         }
-
-         case 2:
-         {
-            for (; rp > png_ptr->row_buf; rp--)
-            {
-              int i = ((*rp >> padding) & 0x03);
-
-              if (i > png_ptr->num_palette_max)
-                 png_ptr->num_palette_max = i;
-
-              i = (((*rp >> padding) >> 2) & 0x03);
-
-              if (i > png_ptr->num_palette_max)
-                 png_ptr->num_palette_max = i;
-
-              i = (((*rp >> padding) >> 4) & 0x03);
-
-              if (i > png_ptr->num_palette_max)
-                 png_ptr->num_palette_max = i;
-
-              i = (((*rp >> padding) >> 6) & 0x03);
-
-              if (i > png_ptr->num_palette_max)
-                 png_ptr->num_palette_max = i;
-
-              padding = 0;
-            }
-
-            break;
-         }
-
-         case 4:
-         {
-            for (; rp > png_ptr->row_buf; rp--)
-            {
-              int i = ((*rp >> padding) & 0x0f);
-
-              if (i > png_ptr->num_palette_max)
-                 png_ptr->num_palette_max = i;
-
-              i = (((*rp >> padding) >> 4) & 0x0f);
-
-              if (i > png_ptr->num_palette_max)
-                 png_ptr->num_palette_max = i;
-
-              padding = 0;
-            }
-
-            break;
-         }
-
-         case 8:
-         {
-            for (; rp > png_ptr->row_buf; rp--)
-            {
-               if (*rp > png_ptr->num_palette_max)
-                  png_ptr->num_palette_max = (int) *rp;
-            }
-
-            break;
-         }
-
-         default:
-            break;
-      }
-   }
-}
-#endif /* CHECK_FOR_INVALID_INDEX */
-
-#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
-    defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
-#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
-void PNGAPI
-png_set_user_transform_info(png_structrp png_ptr, png_voidp
-   user_transform_ptr, int user_transform_depth, int user_transform_channels)
-{
-   png_debug(1, "in png_set_user_transform_info");
-
-   if (png_ptr == NULL)
-      return;
-
-#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
-   if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
-      (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
-   {
-      png_app_error(png_ptr,
-          "info change after png_start_read_image or png_read_update_info");
-      return;
-   }
-#endif
-
-   png_ptr->user_transform_ptr = user_transform_ptr;
-   png_ptr->user_transform_depth = (png_byte)user_transform_depth;
-   png_ptr->user_transform_channels = (png_byte)user_transform_channels;
-}
-#endif
-
-/* This function returns a pointer to the user_transform_ptr associated with
- * the user transform functions.  The application should free any memory
- * associated with this pointer before png_write_destroy and png_read_destroy
- * are called.
- */
-#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
-png_voidp PNGAPI
-png_get_user_transform_ptr(png_const_structrp png_ptr)
-{
-   if (png_ptr == NULL)
-      return (NULL);
-
-   return png_ptr->user_transform_ptr;
-}
-#endif
-
-#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
-png_uint_32 PNGAPI
-png_get_current_row_number(png_const_structrp png_ptr)
-{
-   /* See the comments in png.h - this is the sub-image row when reading an
-    * interlaced image.
-    */
-   if (png_ptr != NULL)
-      return png_ptr->row_number;
-
-   return PNG_UINT_32_MAX; /* help the app not to fail silently */
-}
-
-png_byte PNGAPI
-png_get_current_pass_number(png_const_structrp png_ptr)
-{
-   if (png_ptr != NULL)
-      return png_ptr->pass;
-   return 8; /* invalid */
-}
-#endif /* USER_TRANSFORM_INFO */
-#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */
-#endif /* READ || WRITE */
diff --git a/third_party/libpng16/pngwio.c b/third_party/libpng16/pngwio.c
deleted file mode 100644
index 10e919d..0000000
--- a/third_party/libpng16/pngwio.c
+++ /dev/null
@@ -1,168 +0,0 @@
-
-/* pngwio.c - functions for data output
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2014,2016,2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- *
- * This file provides a location for all output.  Users who need
- * special handling are expected to write functions that have the same
- * arguments as these and perform similar functions, but that possibly
- * use different output methods.  Note that you shouldn't change these
- * functions, but rather write replacement functions and then change
- * them at run time with png_set_write_fn(...).
- */
-
-#include "pngpriv.h"
-
-#ifdef PNG_WRITE_SUPPORTED
-
-/* Write the data to whatever output you are using.  The default routine
- * writes to a file pointer.  Note that this routine sometimes gets called
- * with very small lengths, so you should implement some kind of simple
- * buffering if you are using unbuffered writes.  This should never be asked
- * to write more than 64K on a 16-bit machine.
- */
-
-void /* PRIVATE */
-png_write_data(png_structrp png_ptr, png_const_bytep data, size_t length)
-{
-   /* NOTE: write_data_fn must not change the buffer! */
-   if (png_ptr->write_data_fn != NULL )
-      (*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data),
-          length);
-
-   else
-      png_error(png_ptr, "Call to NULL write function");
-}
-
-#ifdef PNG_STDIO_SUPPORTED
-/* This is the function that does the actual writing of data.  If you are
- * not writing to a standard C stream, you should create a replacement
- * write_data function and use it at run time with png_set_write_fn(), rather
- * than changing the library.
- */
-void PNGCBAPI
-png_default_write_data(png_structp png_ptr, png_bytep data, size_t length)
-{
-   size_t check;
-
-   if (png_ptr == NULL)
-      return;
-
-   check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr));
-
-   if (check != length)
-      png_error(png_ptr, "Write Error");
-}
-#endif
-
-/* This function is called to output any data pending writing (normally
- * to disk).  After png_flush is called, there should be no data pending
- * writing in any buffers.
- */
-#ifdef PNG_WRITE_FLUSH_SUPPORTED
-void /* PRIVATE */
-png_flush(png_structrp png_ptr)
-{
-   if (png_ptr->output_flush_fn != NULL)
-      (*(png_ptr->output_flush_fn))(png_ptr);
-}
-
-#  ifdef PNG_STDIO_SUPPORTED
-void PNGCBAPI
-png_default_flush(png_structp png_ptr)
-{
-   png_FILE_p io_ptr;
-
-   if (png_ptr == NULL)
-      return;
-
-   io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr));
-   fflush(io_ptr);
-}
-#  endif
-#endif
-
-/* This function allows the application to supply new output functions for
- * libpng if standard C streams aren't being used.
- *
- * This function takes as its arguments:
- * png_ptr       - pointer to a png output data structure
- * io_ptr        - pointer to user supplied structure containing info about
- *                 the output functions.  May be NULL.
- * write_data_fn - pointer to a new output function that takes as its
- *                 arguments a pointer to a png_struct, a pointer to
- *                 data to be written, and a 32-bit unsigned int that is
- *                 the number of bytes to be written.  The new write
- *                 function should call png_error(png_ptr, "Error msg")
- *                 to exit and output any fatal error messages.  May be
- *                 NULL, in which case libpng's default function will
- *                 be used.
- * flush_data_fn - pointer to a new flush function that takes as its
- *                 arguments a pointer to a png_struct.  After a call to
- *                 the flush function, there should be no data in any buffers
- *                 or pending transmission.  If the output method doesn't do
- *                 any buffering of output, a function prototype must still be
- *                 supplied although it doesn't have to do anything.  If
- *                 PNG_WRITE_FLUSH_SUPPORTED is not defined at libpng compile
- *                 time, output_flush_fn will be ignored, although it must be
- *                 supplied for compatibility.  May be NULL, in which case
- *                 libpng's default function will be used, if
- *                 PNG_WRITE_FLUSH_SUPPORTED is defined.  This is not
- *                 a good idea if io_ptr does not point to a standard
- *                 *FILE structure.
- */
-void PNGAPI
-png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr,
-    png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
-{
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->io_ptr = io_ptr;
-
-#ifdef PNG_STDIO_SUPPORTED
-   if (write_data_fn != NULL)
-      png_ptr->write_data_fn = write_data_fn;
-
-   else
-      png_ptr->write_data_fn = png_default_write_data;
-#else
-   png_ptr->write_data_fn = write_data_fn;
-#endif
-
-#ifdef PNG_WRITE_FLUSH_SUPPORTED
-#  ifdef PNG_STDIO_SUPPORTED
-
-   if (output_flush_fn != NULL)
-      png_ptr->output_flush_fn = output_flush_fn;
-
-   else
-      png_ptr->output_flush_fn = png_default_flush;
-
-#  else
-   png_ptr->output_flush_fn = output_flush_fn;
-#  endif
-#else
-   PNG_UNUSED(output_flush_fn)
-#endif /* WRITE_FLUSH */
-
-#ifdef PNG_READ_SUPPORTED
-   /* It is an error to read while writing a png file */
-   if (png_ptr->read_data_fn != NULL)
-   {
-      png_ptr->read_data_fn = NULL;
-
-      png_warning(png_ptr,
-          "Can't set both read_data_fn and write_data_fn in the"
-          " same structure");
-   }
-#endif
-}
-#endif /* WRITE */
diff --git a/third_party/libpng16/pngwrite.c b/third_party/libpng16/pngwrite.c
deleted file mode 100644
index 59377a4..0000000
--- a/third_party/libpng16/pngwrite.c
+++ /dev/null
@@ -1,2395 +0,0 @@
-
-/* pngwrite.c - general routines to write a PNG file
- *
- * Copyright (c) 2018-2019 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include "pngpriv.h"
-#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
-#  include <errno.h>
-#endif /* SIMPLIFIED_WRITE_STDIO */
-
-#ifdef PNG_WRITE_SUPPORTED
-
-#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
-/* Write out all the unknown chunks for the current given location */
-static void
-write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
-    unsigned int where)
-{
-   if (info_ptr->unknown_chunks_num != 0)
-   {
-      png_const_unknown_chunkp up;
-
-      png_debug(5, "writing extra chunks");
-
-      for (up = info_ptr->unknown_chunks;
-           up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
-           ++up)
-         if ((up->location & where) != 0)
-      {
-         /* If per-chunk unknown chunk handling is enabled use it, otherwise
-          * just write the chunks the application has set.
-          */
-#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-         int keep = png_handle_as_unknown(png_ptr, up->name);
-
-         /* NOTE: this code is radically different from the read side in the
-          * matter of handling an ancillary unknown chunk.  In the read side
-          * the default behavior is to discard it, in the code below the default
-          * behavior is to write it.  Critical chunks are, however, only
-          * written if explicitly listed or if the default is set to write all
-          * unknown chunks.
-          *
-          * The default handling is also slightly weird - it is not possible to
-          * stop the writing of all unsafe-to-copy chunks!
-          *
-          * TODO: REVIEW: this would seem to be a bug.
-          */
-         if (keep != PNG_HANDLE_CHUNK_NEVER &&
-             ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ ||
-              keep == PNG_HANDLE_CHUNK_ALWAYS ||
-              (keep == PNG_HANDLE_CHUNK_AS_DEFAULT &&
-               png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS)))
-#endif
-         {
-            /* TODO: review, what is wrong with a zero length unknown chunk? */
-            if (up->size == 0)
-               png_warning(png_ptr, "Writing zero-length unknown chunk");
-
-            png_write_chunk(png_ptr, up->name, up->data, up->size);
-         }
-      }
-   }
-}
-#endif /* WRITE_UNKNOWN_CHUNKS */
-
-/* Writes all the PNG information.  This is the suggested way to use the
- * library.  If you have a new chunk to add, make a function to write it,
- * and put it in the correct location here.  If you want the chunk written
- * after the image data, put it in png_write_end().  I strongly encourage
- * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
- * the chunk, as that will keep the code from breaking if you want to just
- * write a plain PNG file.  If you have long comments, I suggest writing
- * them in png_write_end(), and compressing them.
- */
-void PNGAPI
-png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
-{
-   png_debug(1, "in png_write_info_before_PLTE");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
-   {
-      /* Write PNG signature */
-      png_write_sig(png_ptr);
-
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-      if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \
-          png_ptr->mng_features_permitted != 0)
-      {
-         png_warning(png_ptr,
-             "MNG features are not allowed in a PNG datastream");
-         png_ptr->mng_features_permitted = 0;
-      }
-#endif
-
-      /* Write IHDR information. */
-      png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height,
-          info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
-          info_ptr->filter_type,
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-          info_ptr->interlace_type
-#else
-          0
-#endif
-         );
-
-      /* The rest of these check to see if the valid field has the appropriate
-       * flag set, and if it does, writes the chunk.
-       *
-       * 1.6.0: COLORSPACE support controls the writing of these chunks too, and
-       * the chunks will be written if the WRITE routine is there and
-       * information * is available in the COLORSPACE. (See
-       * png_colorspace_sync_info in png.c for where the valid flags get set.)
-       *
-       * Under certain circumstances the colorspace can be invalidated without
-       * syncing the info_struct 'valid' flags; this happens if libpng detects
-       * an error and calls png_error while the color space is being set, yet
-       * the application continues writing the PNG.  So check the 'invalid'
-       * flag here too.
-       */
-#ifdef PNG_GAMMA_SUPPORTED
-#  ifdef PNG_WRITE_gAMA_SUPPORTED
-      if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
-          (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 &&
-          (info_ptr->valid & PNG_INFO_gAMA) != 0)
-         png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
-#  endif
-#endif
-
-#ifdef PNG_COLORSPACE_SUPPORTED
-      /* Write only one of sRGB or an ICC profile.  If a profile was supplied
-       * and it matches one of the known sRGB ones issue a warning.
-       */
-#  ifdef PNG_WRITE_iCCP_SUPPORTED
-         if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
-             (info_ptr->valid & PNG_INFO_iCCP) != 0)
-         {
-#    ifdef PNG_WRITE_sRGB_SUPPORTED
-               if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
-                  png_app_warning(png_ptr,
-                      "profile matches sRGB but writing iCCP instead");
-#     endif
-
-            png_write_iCCP(png_ptr, info_ptr->iccp_name,
-                info_ptr->iccp_profile);
-         }
-#     ifdef PNG_WRITE_sRGB_SUPPORTED
-         else
-#     endif
-#  endif
-
-#  ifdef PNG_WRITE_sRGB_SUPPORTED
-         if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
-             (info_ptr->valid & PNG_INFO_sRGB) != 0)
-            png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent);
-#  endif /* WRITE_sRGB */
-#endif /* COLORSPACE */
-
-#ifdef PNG_WRITE_sBIT_SUPPORTED
-         if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
-            png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
-#endif
-
-#ifdef PNG_COLORSPACE_SUPPORTED
-#  ifdef PNG_WRITE_cHRM_SUPPORTED
-         if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
-             (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 &&
-             (info_ptr->valid & PNG_INFO_cHRM) != 0)
-            png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy);
-#  endif
-#endif
-
-#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
-         write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
-#endif
-
-      png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
-   }
-}
-
-void PNGAPI
-png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
-{
-#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
-   int i;
-#endif
-
-   png_debug(1, "in png_write_info");
-
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   png_write_info_before_PLTE(png_ptr, info_ptr);
-
-   if ((info_ptr->valid & PNG_INFO_PLTE) != 0)
-      png_write_PLTE(png_ptr, info_ptr->palette,
-          (png_uint_32)info_ptr->num_palette);
-
-   else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      png_error(png_ptr, "Valid palette required for paletted images");
-
-#ifdef PNG_WRITE_tRNS_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_tRNS) !=0)
-   {
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-      /* Invert the alpha channel (in tRNS) */
-      if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
-          info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      {
-         int j, jend;
-
-         jend = info_ptr->num_trans;
-         if (jend > PNG_MAX_PALETTE_LENGTH)
-            jend = PNG_MAX_PALETTE_LENGTH;
-
-         for (j = 0; j<jend; ++j)
-            info_ptr->trans_alpha[j] =
-               (png_byte)(255 - info_ptr->trans_alpha[j]);
-      }
-#endif
-      png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color),
-          info_ptr->num_trans, info_ptr->color_type);
-   }
-#endif
-#ifdef PNG_WRITE_bKGD_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_bKGD) != 0)
-      png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
-#endif
-
-#ifdef PNG_WRITE_eXIf_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_eXIf) != 0)
-      png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
-#endif
-
-#ifdef PNG_WRITE_hIST_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_hIST) != 0)
-      png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
-#endif
-
-#ifdef PNG_WRITE_oFFs_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_oFFs) != 0)
-      png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
-          info_ptr->offset_unit_type);
-#endif
-
-#ifdef PNG_WRITE_pCAL_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_pCAL) != 0)
-      png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
-          info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
-          info_ptr->pcal_units, info_ptr->pcal_params);
-#endif
-
-#ifdef PNG_WRITE_sCAL_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_sCAL) != 0)
-      png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
-          info_ptr->scal_s_width, info_ptr->scal_s_height);
-#endif /* sCAL */
-
-#ifdef PNG_WRITE_pHYs_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_pHYs) != 0)
-      png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
-          info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
-#endif /* pHYs */
-
-#ifdef PNG_WRITE_tIME_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_tIME) != 0)
-   {
-      png_write_tIME(png_ptr, &(info_ptr->mod_time));
-      png_ptr->mode |= PNG_WROTE_tIME;
-   }
-#endif /* tIME */
-
-#ifdef PNG_WRITE_sPLT_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_sPLT) != 0)
-      for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
-         png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
-#endif /* sPLT */
-
-#ifdef PNG_WRITE_TEXT_SUPPORTED
-   /* Check to see if we need to write text chunks */
-   for (i = 0; i < info_ptr->num_text; i++)
-   {
-      png_debug2(2, "Writing header text chunk %d, type %d", i,
-          info_ptr->text[i].compression);
-      /* An internationalized chunk? */
-      if (info_ptr->text[i].compression > 0)
-      {
-#ifdef PNG_WRITE_iTXt_SUPPORTED
-         /* Write international chunk */
-         png_write_iTXt(png_ptr,
-             info_ptr->text[i].compression,
-             info_ptr->text[i].key,
-             info_ptr->text[i].lang,
-             info_ptr->text[i].lang_key,
-             info_ptr->text[i].text);
-         /* Mark this chunk as written */
-         if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
-            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
-         else
-            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
-#else
-         png_warning(png_ptr, "Unable to write international text");
-#endif
-      }
-
-      /* If we want a compressed text chunk */
-      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt)
-      {
-#ifdef PNG_WRITE_zTXt_SUPPORTED
-         /* Write compressed chunk */
-         png_write_zTXt(png_ptr, info_ptr->text[i].key,
-             info_ptr->text[i].text, info_ptr->text[i].compression);
-         /* Mark this chunk as written */
-         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
-#else
-         png_warning(png_ptr, "Unable to write compressed text");
-#endif
-      }
-
-      else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
-      {
-#ifdef PNG_WRITE_tEXt_SUPPORTED
-         /* Write uncompressed chunk */
-         png_write_tEXt(png_ptr, info_ptr->text[i].key,
-             info_ptr->text[i].text,
-             0);
-         /* Mark this chunk as written */
-         info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
-#else
-         /* Can't get here */
-         png_warning(png_ptr, "Unable to write uncompressed text");
-#endif
-      }
-   }
-#endif /* tEXt */
-
-#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
-   write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE);
-#endif
-}
-
-/* Writes the end of the PNG file.  If you don't want to write comments or
- * time information, you can pass NULL for info.  If you already wrote these
- * in png_write_info(), do not write them again here.  If you have long
- * comments, I suggest writing them here, and compressing them.
- */
-void PNGAPI
-png_write_end(png_structrp png_ptr, png_inforp info_ptr)
-{
-   png_debug(1, "in png_write_end");
-
-   if (png_ptr == NULL)
-      return;
-
-   if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
-      png_error(png_ptr, "No IDATs written into file");
-
-#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
-   if (png_ptr->num_palette_max > png_ptr->num_palette)
-      png_benign_error(png_ptr, "Wrote palette index exceeding num_palette");
-#endif
-
-   /* See if user wants us to write information chunks */
-   if (info_ptr != NULL)
-   {
-#ifdef PNG_WRITE_TEXT_SUPPORTED
-      int i; /* local index variable */
-#endif
-#ifdef PNG_WRITE_tIME_SUPPORTED
-      /* Check to see if user has supplied a time chunk */
-      if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
-          (png_ptr->mode & PNG_WROTE_tIME) == 0)
-         png_write_tIME(png_ptr, &(info_ptr->mod_time));
-
-#endif
-#ifdef PNG_WRITE_TEXT_SUPPORTED
-      /* Loop through comment chunks */
-      for (i = 0; i < info_ptr->num_text; i++)
-      {
-         png_debug2(2, "Writing trailer text chunk %d, type %d", i,
-             info_ptr->text[i].compression);
-         /* An internationalized chunk? */
-         if (info_ptr->text[i].compression > 0)
-         {
-#ifdef PNG_WRITE_iTXt_SUPPORTED
-            /* Write international chunk */
-            png_write_iTXt(png_ptr,
-                info_ptr->text[i].compression,
-                info_ptr->text[i].key,
-                info_ptr->text[i].lang,
-                info_ptr->text[i].lang_key,
-                info_ptr->text[i].text);
-            /* Mark this chunk as written */
-            if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
-               info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
-            else
-               info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
-#else
-            png_warning(png_ptr, "Unable to write international text");
-#endif
-         }
-
-         else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
-         {
-#ifdef PNG_WRITE_zTXt_SUPPORTED
-            /* Write compressed chunk */
-            png_write_zTXt(png_ptr, info_ptr->text[i].key,
-                info_ptr->text[i].text, info_ptr->text[i].compression);
-            /* Mark this chunk as written */
-            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
-#else
-            png_warning(png_ptr, "Unable to write compressed text");
-#endif
-         }
-
-         else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
-         {
-#ifdef PNG_WRITE_tEXt_SUPPORTED
-            /* Write uncompressed chunk */
-            png_write_tEXt(png_ptr, info_ptr->text[i].key,
-                info_ptr->text[i].text, 0);
-            /* Mark this chunk as written */
-            info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
-#else
-            png_warning(png_ptr, "Unable to write uncompressed text");
-#endif
-         }
-      }
-#endif
-
-#ifdef PNG_WRITE_eXIf_SUPPORTED
-   if ((info_ptr->valid & PNG_INFO_eXIf) != 0)
-      png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
-#endif
-
-#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
-      write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
-#endif
-   }
-
-   png_ptr->mode |= PNG_AFTER_IDAT;
-
-   /* Write end of PNG file */
-   png_write_IEND(png_ptr);
-
-   /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
-    * and restored again in libpng-1.2.30, may cause some applications that
-    * do not set png_ptr->output_flush_fn to crash.  If your application
-    * experiences a problem, please try building libpng with
-    * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to
-    * png-mng-implement at lists.sf.net .
-    */
-#ifdef PNG_WRITE_FLUSH_SUPPORTED
-#  ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
-   png_flush(png_ptr);
-#  endif
-#endif
-}
-
-#ifdef PNG_CONVERT_tIME_SUPPORTED
-void PNGAPI
-png_convert_from_struct_tm(png_timep ptime, const struct tm * ttime)
-{
-   png_debug(1, "in png_convert_from_struct_tm");
-
-   ptime->year = (png_uint_16)(1900 + ttime->tm_year);
-   ptime->month = (png_byte)(ttime->tm_mon + 1);
-   ptime->day = (png_byte)ttime->tm_mday;
-   ptime->hour = (png_byte)ttime->tm_hour;
-   ptime->minute = (png_byte)ttime->tm_min;
-   ptime->second = (png_byte)ttime->tm_sec;
-}
-
-void PNGAPI
-png_convert_from_time_t(png_timep ptime, time_t ttime)
-{
-   struct tm *tbuf;
-
-   png_debug(1, "in png_convert_from_time_t");
-
-   tbuf = gmtime(&ttime);
-   png_convert_from_struct_tm(ptime, tbuf);
-}
-#endif
-
-/* Initialize png_ptr structure, and allocate any memory needed */
-PNG_FUNCTION(png_structp,PNGAPI
-png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
-{
-#ifndef PNG_USER_MEM_SUPPORTED
-   png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
-       error_fn, warn_fn, NULL, NULL, NULL);
-#else
-   return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
-       warn_fn, NULL, NULL, NULL);
-}
-
-/* Alternate initialize png_ptr structure, and allocate any memory needed */
-PNG_FUNCTION(png_structp,PNGAPI
-png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
-    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
-    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
-{
-   png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
-       error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
-#endif /* USER_MEM */
-   if (png_ptr != NULL)
-   {
-      /* Set the zlib control values to defaults; they can be overridden by the
-       * application after the struct has been created.
-       */
-      png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
-
-      /* The 'zlib_strategy' setting is irrelevant because png_default_claim in
-       * pngwutil.c defaults it according to whether or not filters will be
-       * used, and ignores this setting.
-       */
-      png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY;
-      png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION;
-      png_ptr->zlib_mem_level = 8;
-      png_ptr->zlib_window_bits = 15;
-      png_ptr->zlib_method = 8;
-
-#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
-      png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY;
-      png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION;
-      png_ptr->zlib_text_mem_level = 8;
-      png_ptr->zlib_text_window_bits = 15;
-      png_ptr->zlib_text_method = 8;
-#endif /* WRITE_COMPRESSED_TEXT */
-
-      /* This is a highly dubious configuration option; by default it is off,
-       * but it may be appropriate for private builds that are testing
-       * extensions not conformant to the current specification, or of
-       * applications that must not fail to write at all costs!
-       */
-#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
-      /* In stable builds only warn if an application error can be completely
-       * handled.
-       */
-      png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
-#endif
-
-      /* App warnings are warnings in release (or release candidate) builds but
-       * are errors during development.
-       */
-#if PNG_RELEASE_BUILD
-      png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
-#endif
-
-      /* TODO: delay this, it can be done in png_init_io() (if the app doesn't
-       * do it itself) avoiding setting the default function if it is not
-       * required.
-       */
-      png_set_write_fn(png_ptr, NULL, NULL, NULL);
-   }
-
-   return png_ptr;
-}
-
-
-/* Write a few rows of image data.  If the image is interlaced,
- * either you will have to write the 7 sub images, or, if you
- * have called png_set_interlace_handling(), you will have to
- * "write" the image seven times.
- */
-void PNGAPI
-png_write_rows(png_structrp png_ptr, png_bytepp row,
-    png_uint_32 num_rows)
-{
-   png_uint_32 i; /* row counter */
-   png_bytepp rp; /* row pointer */
-
-   png_debug(1, "in png_write_rows");
-
-   if (png_ptr == NULL)
-      return;
-
-   /* Loop through the rows */
-   for (i = 0, rp = row; i < num_rows; i++, rp++)
-   {
-      png_write_row(png_ptr, *rp);
-   }
-}
-
-/* Write the image.  You only need to call this function once, even
- * if you are writing an interlaced image.
- */
-void PNGAPI
-png_write_image(png_structrp png_ptr, png_bytepp image)
-{
-   png_uint_32 i; /* row index */
-   int pass, num_pass; /* pass variables */
-   png_bytepp rp; /* points to current row */
-
-   if (png_ptr == NULL)
-      return;
-
-   png_debug(1, "in png_write_image");
-
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-   /* Initialize interlace handling.  If image is not interlaced,
-    * this will set pass to 1
-    */
-   num_pass = png_set_interlace_handling(png_ptr);
-#else
-   num_pass = 1;
-#endif
-   /* Loop through passes */
-   for (pass = 0; pass < num_pass; pass++)
-   {
-      /* Loop through image */
-      for (i = 0, rp = image; i < png_ptr->height; i++, rp++)
-      {
-         png_write_row(png_ptr, *rp);
-      }
-   }
-}
-
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-/* Performs intrapixel differencing  */
-static void
-png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_write_intrapixel");
-
-   if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
-   {
-      int bytes_per_pixel;
-      png_uint_32 row_width = row_info->width;
-      if (row_info->bit_depth == 8)
-      {
-         png_bytep rp;
-         png_uint_32 i;
-
-         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
-            bytes_per_pixel = 3;
-
-         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-            bytes_per_pixel = 4;
-
-         else
-            return;
-
-         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
-         {
-            *(rp)     = (png_byte)(*rp       - *(rp + 1));
-            *(rp + 2) = (png_byte)(*(rp + 2) - *(rp + 1));
-         }
-      }
-
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-      else if (row_info->bit_depth == 16)
-      {
-         png_bytep rp;
-         png_uint_32 i;
-
-         if (row_info->color_type == PNG_COLOR_TYPE_RGB)
-            bytes_per_pixel = 6;
-
-         else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-            bytes_per_pixel = 8;
-
-         else
-            return;
-
-         for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
-         {
-            png_uint_32 s0   = (png_uint_32)(*(rp    ) << 8) | *(rp + 1);
-            png_uint_32 s1   = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3);
-            png_uint_32 s2   = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5);
-            png_uint_32 red  = (png_uint_32)((s0 - s1) & 0xffffL);
-            png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
-            *(rp    ) = (png_byte)(red >> 8);
-            *(rp + 1) = (png_byte)red;
-            *(rp + 4) = (png_byte)(blue >> 8);
-            *(rp + 5) = (png_byte)blue;
-         }
-      }
-#endif /* WRITE_16BIT */
-   }
-}
-#endif /* MNG_FEATURES */
-
-/* Called by user to write a row of image data */
-void PNGAPI
-png_write_row(png_structrp png_ptr, png_const_bytep row)
-{
-   /* 1.5.6: moved from png_struct to be a local structure: */
-   png_row_info row_info;
-
-   if (png_ptr == NULL)
-      return;
-
-   png_debug2(1, "in png_write_row (row %u, pass %d)",
-       png_ptr->row_number, png_ptr->pass);
-
-   /* Initialize transformations and other stuff if first time */
-   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
-   {
-      /* Make sure we wrote the header info */
-      if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
-         png_error(png_ptr,
-             "png_write_info was never called before png_write_row");
-
-      /* Check for transforms that have been set but were defined out */
-#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
-      if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
-         png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined");
-#endif
-
-#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
-      if ((png_ptr->transformations & PNG_FILLER) != 0)
-         png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined");
-#endif
-#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
-    defined(PNG_READ_PACKSWAP_SUPPORTED)
-      if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
-         png_warning(png_ptr,
-             "PNG_WRITE_PACKSWAP_SUPPORTED is not defined");
-#endif
-
-#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
-      if ((png_ptr->transformations & PNG_PACK) != 0)
-         png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined");
-#endif
-
-#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
-      if ((png_ptr->transformations & PNG_SHIFT) != 0)
-         png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined");
-#endif
-
-#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
-      if ((png_ptr->transformations & PNG_BGR) != 0)
-         png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined");
-#endif
-
-#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
-      if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
-         png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined");
-#endif
-
-      png_write_start_row(png_ptr);
-   }
-
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-   /* If interlaced and not interested in row, return */
-   if (png_ptr->interlaced != 0 &&
-       (png_ptr->transformations & PNG_INTERLACE) != 0)
-   {
-      switch (png_ptr->pass)
-      {
-         case 0:
-            if ((png_ptr->row_number & 0x07) != 0)
-            {
-               png_write_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 1:
-            if ((png_ptr->row_number & 0x07) != 0 || png_ptr->width < 5)
-            {
-               png_write_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 2:
-            if ((png_ptr->row_number & 0x07) != 4)
-            {
-               png_write_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 3:
-            if ((png_ptr->row_number & 0x03) != 0 || png_ptr->width < 3)
-            {
-               png_write_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 4:
-            if ((png_ptr->row_number & 0x03) != 2)
-            {
-               png_write_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 5:
-            if ((png_ptr->row_number & 0x01) != 0 || png_ptr->width < 2)
-            {
-               png_write_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         case 6:
-            if ((png_ptr->row_number & 0x01) == 0)
-            {
-               png_write_finish_row(png_ptr);
-               return;
-            }
-            break;
-
-         default: /* error: ignore it */
-            break;
-      }
-   }
-#endif
-
-   /* Set up row info for transformations */
-   row_info.color_type = png_ptr->color_type;
-   row_info.width = png_ptr->usr_width;
-   row_info.channels = png_ptr->usr_channels;
-   row_info.bit_depth = png_ptr->usr_bit_depth;
-   row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels);
-   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
-
-   png_debug1(3, "row_info->color_type = %d", row_info.color_type);
-   png_debug1(3, "row_info->width = %u", row_info.width);
-   png_debug1(3, "row_info->channels = %d", row_info.channels);
-   png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth);
-   png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth);
-   png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes);
-
-   /* Copy user's row into buffer, leaving room for filter byte. */
-   memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
-
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-   /* Handle interlacing */
-   if (png_ptr->interlaced && png_ptr->pass < 6 &&
-       (png_ptr->transformations & PNG_INTERLACE) != 0)
-   {
-      png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
-      /* This should always get caught above, but still ... */
-      if (row_info.width == 0)
-      {
-         png_write_finish_row(png_ptr);
-         return;
-      }
-   }
-#endif
-
-#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
-   /* Handle other transformations */
-   if (png_ptr->transformations != 0)
-      png_do_write_transformations(png_ptr, &row_info);
-#endif
-
-   /* At this point the row_info pixel depth must match the 'transformed' depth,
-    * which is also the output depth.
-    */
-   if (row_info.pixel_depth != png_ptr->pixel_depth ||
-       row_info.pixel_depth != png_ptr->transformed_pixel_depth)
-      png_error(png_ptr, "internal write transform logic error");
-
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-   /* Write filter_method 64 (intrapixel differencing) only if
-    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
-    * 2. Libpng did not write a PNG signature (this filter_method is only
-    *    used in PNG datastreams that are embedded in MNG datastreams) and
-    * 3. The application called png_permit_mng_features with a mask that
-    *    included PNG_FLAG_MNG_FILTER_64 and
-    * 4. The filter_method is 64 and
-    * 5. The color_type is RGB or RGBA
-    */
-   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
-       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
-   {
-      /* Intrapixel differencing */
-      png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1);
-   }
-#endif
-
-/* Added at libpng-1.5.10 */
-#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
-   /* Check for out-of-range palette index */
-   if (row_info.color_type == PNG_COLOR_TYPE_PALETTE &&
-       png_ptr->num_palette_max >= 0)
-      png_do_check_palette_indexes(png_ptr, &row_info);
-#endif
-
-   /* Find a filter if necessary, filter the row and write it out. */
-   png_write_find_filter(png_ptr, &row_info);
-
-   if (png_ptr->write_row_fn != NULL)
-      (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
-}
-
-#ifdef PNG_WRITE_FLUSH_SUPPORTED
-/* Set the automatic flush interval or 0 to turn flushing off */
-void PNGAPI
-png_set_flush(png_structrp png_ptr, int nrows)
-{
-   png_debug(1, "in png_set_flush");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->flush_dist = (nrows < 0 ? 0 : (png_uint_32)nrows);
-}
-
-/* Flush the current output buffers now */
-void PNGAPI
-png_write_flush(png_structrp png_ptr)
-{
-   png_debug(1, "in png_write_flush");
-
-   if (png_ptr == NULL)
-      return;
-
-   /* We have already written out all of the data */
-   if (png_ptr->row_number >= png_ptr->num_rows)
-      return;
-
-   png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH);
-   png_ptr->flush_rows = 0;
-   png_flush(png_ptr);
-}
-#endif /* WRITE_FLUSH */
-
-/* Free any memory used in png_ptr struct without freeing the struct itself. */
-static void
-png_write_destroy(png_structrp png_ptr)
-{
-   png_debug(1, "in png_write_destroy");
-
-   /* Free any memory zlib uses */
-   if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
-      deflateEnd(&png_ptr->zstream);
-
-   /* Free our memory.  png_free checks NULL for us. */
-   png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
-   png_free(png_ptr, png_ptr->row_buf);
-   png_ptr->row_buf = NULL;
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-   png_free(png_ptr, png_ptr->prev_row);
-   png_free(png_ptr, png_ptr->try_row);
-   png_free(png_ptr, png_ptr->tst_row);
-   png_ptr->prev_row = NULL;
-   png_ptr->try_row = NULL;
-   png_ptr->tst_row = NULL;
-#endif
-
-#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
-   png_free(png_ptr, png_ptr->chunk_list);
-   png_ptr->chunk_list = NULL;
-#endif
-
-   /* The error handling and memory handling information is left intact at this
-    * point: the jmp_buf may still have to be freed.  See png_destroy_png_struct
-    * for how this happens.
-    */
-}
-
-/* Free all memory used by the write.
- * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
- * *png_ptr_ptr.  Prior to 1.6.0 it would accept such a value and it would free
- * the passed in info_structs but it would quietly fail to free any of the data
- * inside them.  In 1.6.0 it quietly does nothing (it has to be quiet because it
- * has no png_ptr.)
- */
-void PNGAPI
-png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
-{
-   png_debug(1, "in png_destroy_write_struct");
-
-   if (png_ptr_ptr != NULL)
-   {
-      png_structrp png_ptr = *png_ptr_ptr;
-
-      if (png_ptr != NULL) /* added in libpng 1.6.0 */
-      {
-         png_destroy_info_struct(png_ptr, info_ptr_ptr);
-
-         *png_ptr_ptr = NULL;
-         png_write_destroy(png_ptr);
-         png_destroy_png_struct(png_ptr);
-      }
-   }
-}
-
-/* Allow the application to select one or more row filters to use. */
-void PNGAPI
-png_set_filter(png_structrp png_ptr, int method, int filters)
-{
-   png_debug(1, "in png_set_filter");
-
-   if (png_ptr == NULL)
-      return;
-
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
-       (method == PNG_INTRAPIXEL_DIFFERENCING))
-      method = PNG_FILTER_TYPE_BASE;
-
-#endif
-   if (method == PNG_FILTER_TYPE_BASE)
-   {
-      switch (filters & (PNG_ALL_FILTERS | 0x07))
-      {
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-         case 5:
-         case 6:
-         case 7: png_app_error(png_ptr, "Unknown row filter for method 0");
-#endif /* WRITE_FILTER */
-            /* FALLTHROUGH */
-         case PNG_FILTER_VALUE_NONE:
-            png_ptr->do_filter = PNG_FILTER_NONE; break;
-
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-         case PNG_FILTER_VALUE_SUB:
-            png_ptr->do_filter = PNG_FILTER_SUB; break;
-
-         case PNG_FILTER_VALUE_UP:
-            png_ptr->do_filter = PNG_FILTER_UP; break;
-
-         case PNG_FILTER_VALUE_AVG:
-            png_ptr->do_filter = PNG_FILTER_AVG; break;
-
-         case PNG_FILTER_VALUE_PAETH:
-            png_ptr->do_filter = PNG_FILTER_PAETH; break;
-
-         default:
-            png_ptr->do_filter = (png_byte)filters; break;
-#else
-         default:
-            png_app_error(png_ptr, "Unknown row filter for method 0");
-#endif /* WRITE_FILTER */
-      }
-
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-      /* If we have allocated the row_buf, this means we have already started
-       * with the image and we should have allocated all of the filter buffers
-       * that have been selected.  If prev_row isn't already allocated, then
-       * it is too late to start using the filters that need it, since we
-       * will be missing the data in the previous row.  If an application
-       * wants to start and stop using particular filters during compression,
-       * it should start out with all of the filters, and then remove them
-       * or add them back after the start of compression.
-       *
-       * NOTE: this is a nasty constraint on the code, because it means that the
-       * prev_row buffer must be maintained even if there are currently no
-       * 'prev_row' requiring filters active.
-       */
-      if (png_ptr->row_buf != NULL)
-      {
-         int num_filters;
-         png_alloc_size_t buf_size;
-
-         /* Repeat the checks in png_write_start_row; 1 pixel high or wide
-          * images cannot benefit from certain filters.  If this isn't done here
-          * the check below will fire on 1 pixel high images.
-          */
-         if (png_ptr->height == 1)
-            filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
-
-         if (png_ptr->width == 1)
-            filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH);
-
-         if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0
-            && png_ptr->prev_row == NULL)
-         {
-            /* This is the error case, however it is benign - the previous row
-             * is not available so the filter can't be used.  Just warn here.
-             */
-            png_app_warning(png_ptr,
-                "png_set_filter: UP/AVG/PAETH cannot be added after start");
-            filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
-         }
-
-         num_filters = 0;
-
-         if (filters & PNG_FILTER_SUB)
-            num_filters++;
-
-         if (filters & PNG_FILTER_UP)
-            num_filters++;
-
-         if (filters & PNG_FILTER_AVG)
-            num_filters++;
-
-         if (filters & PNG_FILTER_PAETH)
-            num_filters++;
-
-         /* Allocate needed row buffers if they have not already been
-          * allocated.
-          */
-         buf_size = PNG_ROWBYTES(png_ptr->usr_channels * png_ptr->usr_bit_depth,
-             png_ptr->width) + 1;
-
-         if (png_ptr->try_row == NULL)
-            png_ptr->try_row = png_voidcast(png_bytep,
-                png_malloc(png_ptr, buf_size));
-
-         if (num_filters > 1)
-         {
-            if (png_ptr->tst_row == NULL)
-               png_ptr->tst_row = png_voidcast(png_bytep,
-                   png_malloc(png_ptr, buf_size));
-         }
-      }
-      png_ptr->do_filter = (png_byte)filters;
-#endif
-   }
-   else
-      png_error(png_ptr, "Unknown custom filter method");
-}
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
-/* Provide floating and fixed point APIs */
-#ifdef PNG_FLOATING_POINT_SUPPORTED
-void PNGAPI
-png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
-    int num_weights, png_const_doublep filter_weights,
-    png_const_doublep filter_costs)
-{
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(heuristic_method)
-   PNG_UNUSED(num_weights)
-   PNG_UNUSED(filter_weights)
-   PNG_UNUSED(filter_costs)
-}
-#endif /* FLOATING_POINT */
-
-#ifdef PNG_FIXED_POINT_SUPPORTED
-void PNGAPI
-png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method,
-    int num_weights, png_const_fixed_point_p filter_weights,
-    png_const_fixed_point_p filter_costs)
-{
-   PNG_UNUSED(png_ptr)
-   PNG_UNUSED(heuristic_method)
-   PNG_UNUSED(num_weights)
-   PNG_UNUSED(filter_weights)
-   PNG_UNUSED(filter_costs)
-}
-#endif /* FIXED_POINT */
-#endif /* WRITE_WEIGHTED_FILTER */
-
-#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
-void PNGAPI
-png_set_compression_level(png_structrp png_ptr, int level)
-{
-   png_debug(1, "in png_set_compression_level");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->zlib_level = level;
-}
-
-void PNGAPI
-png_set_compression_mem_level(png_structrp png_ptr, int mem_level)
-{
-   png_debug(1, "in png_set_compression_mem_level");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->zlib_mem_level = mem_level;
-}
-
-void PNGAPI
-png_set_compression_strategy(png_structrp png_ptr, int strategy)
-{
-   png_debug(1, "in png_set_compression_strategy");
-
-   if (png_ptr == NULL)
-      return;
-
-   /* The flag setting here prevents the libpng dynamic selection of strategy.
-    */
-   png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
-   png_ptr->zlib_strategy = strategy;
-}
-
-/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
- * smaller value of window_bits if it can do so safely.
- */
-void PNGAPI
-png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
-{
-   if (png_ptr == NULL)
-      return;
-
-   /* Prior to 1.6.0 this would warn but then set the window_bits value. This
-    * meant that negative window bits values could be selected that would cause
-    * libpng to write a non-standard PNG file with raw deflate or gzip
-    * compressed IDAT or ancillary chunks.  Such files can be read and there is
-    * no warning on read, so this seems like a very bad idea.
-    */
-   if (window_bits > 15)
-   {
-      png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
-      window_bits = 15;
-   }
-
-   else if (window_bits < 8)
-   {
-      png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
-      window_bits = 8;
-   }
-
-   png_ptr->zlib_window_bits = window_bits;
-}
-
-void PNGAPI
-png_set_compression_method(png_structrp png_ptr, int method)
-{
-   png_debug(1, "in png_set_compression_method");
-
-   if (png_ptr == NULL)
-      return;
-
-   /* This would produce an invalid PNG file if it worked, but it doesn't and
-    * deflate will fault it, so it is harmless to just warn here.
-    */
-   if (method != 8)
-      png_warning(png_ptr, "Only compression method 8 is supported by PNG");
-
-   png_ptr->zlib_method = method;
-}
-#endif /* WRITE_CUSTOMIZE_COMPRESSION */
-
-/* The following were added to libpng-1.5.4 */
-#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
-void PNGAPI
-png_set_text_compression_level(png_structrp png_ptr, int level)
-{
-   png_debug(1, "in png_set_text_compression_level");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->zlib_text_level = level;
-}
-
-void PNGAPI
-png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level)
-{
-   png_debug(1, "in png_set_text_compression_mem_level");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->zlib_text_mem_level = mem_level;
-}
-
-void PNGAPI
-png_set_text_compression_strategy(png_structrp png_ptr, int strategy)
-{
-   png_debug(1, "in png_set_text_compression_strategy");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->zlib_text_strategy = strategy;
-}
-
-/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
- * smaller value of window_bits if it can do so safely.
- */
-void PNGAPI
-png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits)
-{
-   if (png_ptr == NULL)
-      return;
-
-   if (window_bits > 15)
-   {
-      png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
-      window_bits = 15;
-   }
-
-   else if (window_bits < 8)
-   {
-      png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
-      window_bits = 8;
-   }
-
-   png_ptr->zlib_text_window_bits = window_bits;
-}
-
-void PNGAPI
-png_set_text_compression_method(png_structrp png_ptr, int method)
-{
-   png_debug(1, "in png_set_text_compression_method");
-
-   if (png_ptr == NULL)
-      return;
-
-   if (method != 8)
-      png_warning(png_ptr, "Only compression method 8 is supported by PNG");
-
-   png_ptr->zlib_text_method = method;
-}
-#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
-/* end of API added to libpng-1.5.4 */
-
-void PNGAPI
-png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
-{
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->write_row_fn = write_row_fn;
-}
-
-#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
-void PNGAPI
-png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
-    write_user_transform_fn)
-{
-   png_debug(1, "in png_set_write_user_transform_fn");
-
-   if (png_ptr == NULL)
-      return;
-
-   png_ptr->transformations |= PNG_USER_TRANSFORM;
-   png_ptr->write_user_transform_fn = write_user_transform_fn;
-}
-#endif
-
-
-#ifdef PNG_INFO_IMAGE_SUPPORTED
-void PNGAPI
-png_write_png(png_structrp png_ptr, png_inforp info_ptr,
-    int transforms, voidp params)
-{
-   if (png_ptr == NULL || info_ptr == NULL)
-      return;
-
-   if ((info_ptr->valid & PNG_INFO_IDAT) == 0)
-   {
-      png_app_error(png_ptr, "no rows for png_write_image to write");
-      return;
-   }
-
-   /* Write the file header information. */
-   png_write_info(png_ptr, info_ptr);
-
-   /* ------ these transformations don't touch the info structure ------- */
-
-   /* Invert monochrome pixels */
-   if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
-#ifdef PNG_WRITE_INVERT_SUPPORTED
-      png_set_invert_mono(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
-#endif
-
-   /* Shift the pixels up to a legal bit depth and fill in
-    * as appropriate to correctly scale the image.
-    */
-   if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
-      if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
-         png_set_shift(png_ptr, &info_ptr->sig_bit);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
-#endif
-
-   /* Pack pixels into bytes */
-   if ((transforms & PNG_TRANSFORM_PACKING) != 0)
-#ifdef PNG_WRITE_PACK_SUPPORTED
-      png_set_packing(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
-#endif
-
-   /* Swap location of alpha bytes from ARGB to RGBA */
-   if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
-      png_set_swap_alpha(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
-#endif
-
-   /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
-    * RGB, note that the code expects the input color type to be G or RGB; no
-    * alpha channel.
-    */
-   if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER|
-       PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0)
-   {
-#ifdef PNG_WRITE_FILLER_SUPPORTED
-      if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0)
-      {
-         if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
-            png_app_error(png_ptr,
-                "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
-
-         /* Continue if ignored - this is the pre-1.6.10 behavior */
-         png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
-      }
-
-      else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
-         png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported");
-#endif
-   }
-
-   /* Flip BGR pixels to RGB */
-   if ((transforms & PNG_TRANSFORM_BGR) != 0)
-#ifdef PNG_WRITE_BGR_SUPPORTED
-      png_set_bgr(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
-#endif
-
-   /* Swap bytes of 16-bit files to most significant byte first */
-   if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
-#ifdef PNG_WRITE_SWAP_SUPPORTED
-      png_set_swap(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
-#endif
-
-   /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */
-   if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
-#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
-      png_set_packswap(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
-#endif
-
-   /* Invert the alpha channel from opacity to transparency */
-   if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-      png_set_invert_alpha(png_ptr);
-#else
-      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
-#endif
-
-   /* ----------------------- end of transformations ------------------- */
-
-   /* Write the bits */
-   png_write_image(png_ptr, info_ptr->row_pointers);
-
-   /* It is REQUIRED to call this to finish writing the rest of the file */
-   png_write_end(png_ptr, info_ptr);
-
-   PNG_UNUSED(params)
-}
-#endif
-
-
-#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
-/* Initialize the write structure - general purpose utility. */
-static int
-png_image_write_init(png_imagep image)
-{
-   png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
-       png_safe_error, png_safe_warning);
-
-   if (png_ptr != NULL)
-   {
-      png_infop info_ptr = png_create_info_struct(png_ptr);
-
-      if (info_ptr != NULL)
-      {
-         png_controlp control = png_voidcast(png_controlp,
-             png_malloc_warn(png_ptr, (sizeof *control)));
-
-         if (control != NULL)
-         {
-            memset(control, 0, (sizeof *control));
-
-            control->png_ptr = png_ptr;
-            control->info_ptr = info_ptr;
-            control->for_write = 1;
-
-            image->opaque = control;
-            return 1;
-         }
-
-         /* Error clean up */
-         png_destroy_info_struct(png_ptr, &info_ptr);
-      }
-
-      png_destroy_write_struct(&png_ptr, NULL);
-   }
-
-   return png_image_error(image, "png_image_write_: out of memory");
-}
-
-/* Arguments to png_image_write_main: */
-typedef struct
-{
-   /* Arguments: */
-   png_imagep      image;
-   png_const_voidp buffer;
-   png_int_32      row_stride;
-   png_const_voidp colormap;
-   int             convert_to_8bit;
-   /* Local variables: */
-   png_const_voidp first_row;
-   ptrdiff_t       row_bytes;
-   png_voidp       local_row;
-   /* Byte count for memory writing */
-   png_bytep        memory;
-   png_alloc_size_t memory_bytes; /* not used for STDIO */
-   png_alloc_size_t output_bytes; /* running total */
-} png_image_write_control;
-
-/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
- * do any necessary byte swapping.  The component order is defined by the
- * png_image format value.
- */
-static int
-png_write_image_16bit(png_voidp argument)
-{
-   png_image_write_control *display = png_voidcast(png_image_write_control*,
-       argument);
-   png_imagep image = display->image;
-   png_structrp png_ptr = image->opaque->png_ptr;
-
-   png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
-       display->first_row);
-   png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
-   png_uint_16p row_end;
-   unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
-       3 : 1;
-   int aindex = 0;
-   png_uint_32 y = image->height;
-
-   if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
-   {
-#   ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
-      if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
-      {
-         aindex = -1;
-         ++input_row; /* To point to the first component */
-         ++output_row;
-      }
-         else
-            aindex = (int)channels;
-#     else
-         aindex = (int)channels;
-#     endif
-   }
-
-   else
-      png_error(png_ptr, "png_write_image: internal call error");
-
-   /* Work out the output row end and count over this, note that the increment
-    * above to 'row' means that row_end can actually be beyond the end of the
-    * row; this is correct.
-    */
-   row_end = output_row + image->width * (channels+1);
-
-   for (; y > 0; --y)
-   {
-      png_const_uint_16p in_ptr = input_row;
-      png_uint_16p out_ptr = output_row;
-
-      while (out_ptr < row_end)
-      {
-         png_uint_16 alpha = in_ptr[aindex];
-         png_uint_32 reciprocal = 0;
-         int c;
-
-         out_ptr[aindex] = alpha;
-
-         /* Calculate a reciprocal.  The correct calculation is simply
-          * component/alpha*65535 << 15. (I.e. 15 bits of precision); this
-          * allows correct rounding by adding .5 before the shift.  'reciprocal'
-          * is only initialized when required.
-          */
-         if (alpha > 0 && alpha < 65535)
-            reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
-
-         c = (int)channels;
-         do /* always at least one channel */
-         {
-            png_uint_16 component = *in_ptr++;
-
-            /* The following gives 65535 for an alpha of 0, which is fine,
-             * otherwise if 0/0 is represented as some other value there is more
-             * likely to be a discontinuity which will probably damage
-             * compression when moving from a fully transparent area to a
-             * nearly transparent one.  (The assumption here is that opaque
-             * areas tend not to be 0 intensity.)
-             */
-            if (component >= alpha)
-               component = 65535;
-
-            /* component<alpha, so component/alpha is less than one and
-             * component*reciprocal is less than 2^31.
-             */
-            else if (component > 0 && alpha < 65535)
-            {
-               png_uint_32 calc = component * reciprocal;
-               calc += 16384; /* round to nearest */
-               component = (png_uint_16)(calc >> 15);
-            }
-
-            *out_ptr++ = component;
-         }
-         while (--c > 0);
-
-         /* Skip to next component (skip the intervening alpha channel) */
-         ++in_ptr;
-         ++out_ptr;
-      }
-
-      png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
-      input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
-   }
-
-   return 1;
-}
-
-/* Given 16-bit input (1 to 4 channels) write 8-bit output.  If an alpha channel
- * is present it must be removed from the components, the components are then
- * written in sRGB encoding.  No components are added or removed.
- *
- * Calculate an alpha reciprocal to reverse pre-multiplication.  As above the
- * calculation can be done to 15 bits of accuracy; however, the output needs to
- * be scaled in the range 0..255*65535, so include that scaling here.
- */
-#   define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+((alpha)>>1))/(alpha))
-
-static png_byte
-png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
-    png_uint_32 reciprocal/*from the above macro*/)
-{
-   /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
-    * is represented as some other value there is more likely to be a
-    * discontinuity which will probably damage compression when moving from a
-    * fully transparent area to a nearly transparent one.  (The assumption here
-    * is that opaque areas tend not to be 0 intensity.)
-    *
-    * There is a rounding problem here; if alpha is less than 128 it will end up
-    * as 0 when scaled to 8 bits.  To avoid introducing spurious colors into the
-    * output change for this too.
-    */
-   if (component >= alpha || alpha < 128)
-      return 255;
-
-   /* component<alpha, so component/alpha is less than one and
-    * component*reciprocal is less than 2^31.
-    */
-   else if (component > 0)
-   {
-      /* The test is that alpha/257 (rounded) is less than 255, the first value
-       * that becomes 255 is 65407.
-       * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
-       * be exact!)  [Could also test reciprocal != 0]
-       */
-      if (alpha < 65407)
-      {
-         component *= reciprocal;
-         component += 64; /* round to nearest */
-         component >>= 7;
-      }
-
-      else
-         component *= 255;
-
-      /* Convert the component to sRGB. */
-      return (png_byte)PNG_sRGB_FROM_LINEAR(component);
-   }
-
-   else
-      return 0;
-}
-
-static int
-png_write_image_8bit(png_voidp argument)
-{
-   png_image_write_control *display = png_voidcast(png_image_write_control*,
-       argument);
-   png_imagep image = display->image;
-   png_structrp png_ptr = image->opaque->png_ptr;
-
-   png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
-       display->first_row);
-   png_bytep output_row = png_voidcast(png_bytep, display->local_row);
-   png_uint_32 y = image->height;
-   unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
-       3 : 1;
-
-   if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
-   {
-      png_bytep row_end;
-      int aindex;
-
-#   ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
-      if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
-      {
-         aindex = -1;
-         ++input_row; /* To point to the first component */
-         ++output_row;
-      }
-
-      else
-#   endif
-      aindex = (int)channels;
-
-      /* Use row_end in place of a loop counter: */
-      row_end = output_row + image->width * (channels+1);
-
-      for (; y > 0; --y)
-      {
-         png_const_uint_16p in_ptr = input_row;
-         png_bytep out_ptr = output_row;
-
-         while (out_ptr < row_end)
-         {
-            png_uint_16 alpha = in_ptr[aindex];
-            png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
-            png_uint_32 reciprocal = 0;
-            int c;
-
-            /* Scale and write the alpha channel. */
-            out_ptr[aindex] = alphabyte;
-
-            if (alphabyte > 0 && alphabyte < 255)
-               reciprocal = UNP_RECIPROCAL(alpha);
-
-            c = (int)channels;
-            do /* always at least one channel */
-               *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
-            while (--c > 0);
-
-            /* Skip to next component (skip the intervening alpha channel) */
-            ++in_ptr;
-            ++out_ptr;
-         } /* while out_ptr < row_end */
-
-         png_write_row(png_ptr, png_voidcast(png_const_bytep,
-             display->local_row));
-         input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
-      } /* while y */
-   }
-
-   else
-   {
-      /* No alpha channel, so the row_end really is the end of the row and it
-       * is sufficient to loop over the components one by one.
-       */
-      png_bytep row_end = output_row + image->width * channels;
-
-      for (; y > 0; --y)
-      {
-         png_const_uint_16p in_ptr = input_row;
-         png_bytep out_ptr = output_row;
-
-         while (out_ptr < row_end)
-         {
-            png_uint_32 component = *in_ptr++;
-
-            component *= 255;
-            *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
-         }
-
-         png_write_row(png_ptr, output_row);
-         input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
-      }
-   }
-
-   return 1;
-}
-
-static void
-png_image_set_PLTE(png_image_write_control *display)
-{
-   png_imagep image = display->image;
-   const void *cmap = display->colormap;
-   int entries = image->colormap_entries > 256 ? 256 :
-       (int)image->colormap_entries;
-
-   /* NOTE: the caller must check for cmap != NULL and entries != 0 */
-   png_uint_32 format = image->format;
-   unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
-
-#   if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
-      defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
-      int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
-          (format & PNG_FORMAT_FLAG_ALPHA) != 0;
-#   else
-#     define afirst 0
-#   endif
-
-#   ifdef PNG_FORMAT_BGR_SUPPORTED
-      int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
-#   else
-#     define bgr 0
-#   endif
-
-   int i, num_trans;
-   png_color palette[256];
-   png_byte tRNS[256];
-
-   memset(tRNS, 255, (sizeof tRNS));
-   memset(palette, 0, (sizeof palette));
-
-   for (i=num_trans=0; i<entries; ++i)
-   {
-      /* This gets automatically converted to sRGB with reversal of the
-       * pre-multiplication if the color-map has an alpha channel.
-       */
-      if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
-      {
-         png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
-
-         entry += (unsigned int)i * channels;
-
-         if ((channels & 1) != 0) /* no alpha */
-         {
-            if (channels >= 3) /* RGB */
-            {
-               palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
-                   entry[(2 ^ bgr)]);
-               palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
-                   entry[1]);
-               palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
-                   entry[bgr]);
-            }
-
-            else /* Gray */
-               palette[i].blue = palette[i].red = palette[i].green =
-                  (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
-         }
-
-         else /* alpha */
-         {
-            png_uint_16 alpha = entry[afirst ? 0 : channels-1];
-            png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
-            png_uint_32 reciprocal = 0;
-
-            /* Calculate a reciprocal, as in the png_write_image_8bit code above
-             * this is designed to produce a value scaled to 255*65535 when
-             * divided by 128 (i.e. asr 7).
-             */
-            if (alphabyte > 0 && alphabyte < 255)
-               reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
-
-            tRNS[i] = alphabyte;
-            if (alphabyte < 255)
-               num_trans = i+1;
-
-            if (channels >= 3) /* RGB */
-            {
-               palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
-                   alpha, reciprocal);
-               palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
-                   reciprocal);
-               palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
-                   reciprocal);
-            }
-
-            else /* gray */
-               palette[i].blue = palette[i].red = palette[i].green =
-                   png_unpremultiply(entry[afirst], alpha, reciprocal);
-         }
-      }
-
-      else /* Color-map has sRGB values */
-      {
-         png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
-
-         entry += (unsigned int)i * channels;
-
-         switch (channels)
-         {
-            case 4:
-               tRNS[i] = entry[afirst ? 0 : 3];
-               if (tRNS[i] < 255)
-                  num_trans = i+1;
-               /* FALLTHROUGH */
-            case 3:
-               palette[i].blue = entry[afirst + (2 ^ bgr)];
-               palette[i].green = entry[afirst + 1];
-               palette[i].red = entry[afirst + bgr];
-               break;
-
-            case 2:
-               tRNS[i] = entry[1 ^ afirst];
-               if (tRNS[i] < 255)
-                  num_trans = i+1;
-               /* FALLTHROUGH */
-            case 1:
-               palette[i].blue = palette[i].red = palette[i].green =
-                  entry[afirst];
-               break;
-
-            default:
-               break;
-         }
-      }
-   }
-
-#   ifdef afirst
-#     undef afirst
-#   endif
-#   ifdef bgr
-#     undef bgr
-#   endif
-
-   png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
-       entries);
-
-   if (num_trans > 0)
-      png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
-          num_trans, NULL);
-
-   image->colormap_entries = (png_uint_32)entries;
-}
-
-static int
-png_image_write_main(png_voidp argument)
-{
-   png_image_write_control *display = png_voidcast(png_image_write_control*,
-       argument);
-   png_imagep image = display->image;
-   png_structrp png_ptr = image->opaque->png_ptr;
-   png_inforp info_ptr = image->opaque->info_ptr;
-   png_uint_32 format = image->format;
-
-   /* The following four ints are actually booleans */
-   int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
-   int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
-   int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
-   int write_16bit = linear && (display->convert_to_8bit == 0);
-
-#   ifdef PNG_BENIGN_ERRORS_SUPPORTED
-      /* Make sure we error out on any bad situation */
-      png_set_benign_errors(png_ptr, 0/*error*/);
-#   endif
-
-   /* Default the 'row_stride' parameter if required, also check the row stride
-    * and total image size to ensure that they are within the system limits.
-    */
-   {
-      unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
-
-      if (image->width <= 0x7fffffffU/channels) /* no overflow */
-      {
-         png_uint_32 check;
-         png_uint_32 png_row_stride = image->width * channels;
-
-         if (display->row_stride == 0)
-            display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
-
-         if (display->row_stride < 0)
-            check = (png_uint_32)(-display->row_stride);
-
-         else
-            check = (png_uint_32)display->row_stride;
-
-         if (check >= png_row_stride)
-         {
-            /* Now check for overflow of the image buffer calculation; this
-             * limits the whole image size to 32 bits for API compatibility with
-             * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
-             */
-            if (image->height > 0xffffffffU/png_row_stride)
-               png_error(image->opaque->png_ptr, "memory image too large");
-         }
-
-         else
-            png_error(image->opaque->png_ptr, "supplied row stride too small");
-      }
-
-      else
-         png_error(image->opaque->png_ptr, "image row stride too large");
-   }
-
-   /* Set the required transforms then write the rows in the correct order. */
-   if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
-   {
-      if (display->colormap != NULL && image->colormap_entries > 0)
-      {
-         png_uint_32 entries = image->colormap_entries;
-
-         png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
-             entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
-             PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
-             PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
-         png_image_set_PLTE(display);
-      }
-
-      else
-         png_error(image->opaque->png_ptr,
-             "no color-map for color-mapped image");
-   }
-
-   else
-      png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
-          write_16bit ? 16 : 8,
-          ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
-          ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
-          PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
-   /* Counter-intuitively the data transformations must be called *after*
-    * png_write_info, not before as in the read code, but the 'set' functions
-    * must still be called before.  Just set the color space information, never
-    * write an interlaced image.
-    */
-
-   if (write_16bit != 0)
-   {
-      /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
-      png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR);
-
-      if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
-         png_set_cHRM_fixed(png_ptr, info_ptr,
-             /* color      x       y */
-             /* white */ 31270, 32900,
-             /* red   */ 64000, 33000,
-             /* green */ 30000, 60000,
-             /* blue  */ 15000,  6000
-         );
-   }
-
-   else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
-      png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
-
-   /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
-    * space must still be gamma encoded.
-    */
-   else
-      png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
-
-   /* Write the file header. */
-   png_write_info(png_ptr, info_ptr);
-
-   /* Now set up the data transformations (*after* the header is written),
-    * remove the handled transformations from the 'format' flags for checking.
-    *
-    * First check for a little endian system if writing 16-bit files.
-    */
-   if (write_16bit != 0)
-   {
-      png_uint_16 le = 0x0001;
-
-      if ((*(png_const_bytep) & le) != 0)
-         png_set_swap(png_ptr);
-   }
-
-#   ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
-      if ((format & PNG_FORMAT_FLAG_BGR) != 0)
-      {
-         if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0)
-            png_set_bgr(png_ptr);
-         format &= ~PNG_FORMAT_FLAG_BGR;
-      }
-#   endif
-
-#   ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
-      if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
-      {
-         if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
-            png_set_swap_alpha(png_ptr);
-         format &= ~PNG_FORMAT_FLAG_AFIRST;
-      }
-#   endif
-
-   /* If there are 16 or fewer color-map entries we wrote a lower bit depth
-    * above, but the application data is still byte packed.
-    */
-   if (colormap != 0 && image->colormap_entries <= 16)
-      png_set_packing(png_ptr);
-
-   /* That should have handled all (both) the transforms. */
-   if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
-         PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
-      png_error(png_ptr, "png_write_image: unsupported transformation");
-
-   {
-      png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
-      ptrdiff_t row_bytes = display->row_stride;
-
-      if (linear != 0)
-         row_bytes *= (sizeof (png_uint_16));
-
-      if (row_bytes < 0)
-         row += (image->height-1) * (-row_bytes);
-
-      display->first_row = row;
-      display->row_bytes = row_bytes;
-   }
-
-   /* Apply 'fast' options if the flag is set. */
-   if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0)
-   {
-      png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS);
-      /* NOTE: determined by experiment using pngstest, this reflects some
-       * balance between the time to write the image once and the time to read
-       * it about 50 times.  The speed-up in pngstest was about 10-20% of the
-       * total (user) time on a heavily loaded system.
-       */
-#   ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
-      png_set_compression_level(png_ptr, 3);
-#   endif
-   }
-
-   /* Check for the cases that currently require a pre-transform on the row
-    * before it is written.  This only applies when the input is 16-bit and
-    * either there is an alpha channel or it is converted to 8-bit.
-    */
-   if ((linear != 0 && alpha != 0 ) ||
-       (colormap == 0 && display->convert_to_8bit != 0))
-   {
-      png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
-          png_get_rowbytes(png_ptr, info_ptr)));
-      int result;
-
-      display->local_row = row;
-      if (write_16bit != 0)
-         result = png_safe_execute(image, png_write_image_16bit, display);
-      else
-         result = png_safe_execute(image, png_write_image_8bit, display);
-      display->local_row = NULL;
-
-      png_free(png_ptr, row);
-
-      /* Skip the 'write_end' on error: */
-      if (result == 0)
-         return 0;
-   }
-
-   /* Otherwise this is the case where the input is in a format currently
-    * supported by the rest of the libpng write code; call it directly.
-    */
-   else
-   {
-      png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
-      ptrdiff_t row_bytes = display->row_bytes;
-      png_uint_32 y = image->height;
-
-      for (; y > 0; --y)
-      {
-         png_write_row(png_ptr, row);
-         row += row_bytes;
-      }
-   }
-
-   png_write_end(png_ptr, info_ptr);
-   return 1;
-}
-
-
-static void (PNGCBAPI
-image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, size_t size)
-{
-   png_image_write_control *display = png_voidcast(png_image_write_control*,
-       png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
-   png_alloc_size_t ob = display->output_bytes;
-
-   /* Check for overflow; this should never happen: */
-   if (size <= ((png_alloc_size_t)-1) - ob)
-   {
-      /* I don't think libpng ever does this, but just in case: */
-      if (size > 0)
-      {
-         if (display->memory_bytes >= ob+size) /* writing */
-            memcpy(display->memory+ob, data, size);
-
-         /* Always update the size: */
-         display->output_bytes = ob+size;
-      }
-   }
-
-   else
-      png_error(png_ptr, "png_image_write_to_memory: PNG too big");
-}
-
-static void (PNGCBAPI
-image_memory_flush)(png_structp png_ptr)
-{
-   PNG_UNUSED(png_ptr)
-}
-
-static int
-png_image_write_memory(png_voidp argument)
-{
-   png_image_write_control *display = png_voidcast(png_image_write_control*,
-       argument);
-
-   /* The rest of the memory-specific init and write_main in an error protected
-    * environment.  This case needs to use callbacks for the write operations
-    * since libpng has no built in support for writing to memory.
-    */
-   png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/,
-       image_memory_write, image_memory_flush);
-
-   return png_image_write_main(display);
-}
-
-int PNGAPI
-png_image_write_to_memory(png_imagep image, void *memory,
-    png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
-    const void *buffer, png_int_32 row_stride, const void *colormap)
-{
-   /* Write the image to the given buffer, or count the bytes if it is NULL */
-   if (image != NULL && image->version == PNG_IMAGE_VERSION)
-   {
-      if (memory_bytes != NULL && buffer != NULL)
-      {
-         /* This is to give the caller an easier error detection in the NULL
-          * case and guard against uninitialized variable problems:
-          */
-         if (memory == NULL)
-            *memory_bytes = 0;
-
-         if (png_image_write_init(image) != 0)
-         {
-            png_image_write_control display;
-            int result;
-
-            memset(&display, 0, (sizeof display));
-            display.image = image;
-            display.buffer = buffer;
-            display.row_stride = row_stride;
-            display.colormap = colormap;
-            display.convert_to_8bit = convert_to_8bit;
-            display.memory = png_voidcast(png_bytep, memory);
-            display.memory_bytes = *memory_bytes;
-            display.output_bytes = 0;
-
-            result = png_safe_execute(image, png_image_write_memory, &display);
-            png_image_free(image);
-
-            /* write_memory returns true even if we ran out of buffer. */
-            if (result)
-            {
-               /* On out-of-buffer this function returns '0' but still updates
-                * memory_bytes:
-                */
-               if (memory != NULL && display.output_bytes > *memory_bytes)
-                  result = 0;
-
-               *memory_bytes = display.output_bytes;
-            }
-
-            return result;
-         }
-
-         else
-            return 0;
-      }
-
-      else
-         return png_image_error(image,
-             "png_image_write_to_memory: invalid argument");
-   }
-
-   else if (image != NULL)
-      return png_image_error(image,
-          "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
-
-   else
-      return 0;
-}
-
-#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
-int PNGAPI
-png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
-    const void *buffer, png_int_32 row_stride, const void *colormap)
-{
-   /* Write the image to the given (FILE*). */
-   if (image != NULL && image->version == PNG_IMAGE_VERSION)
-   {
-      if (file != NULL && buffer != NULL)
-      {
-         if (png_image_write_init(image) != 0)
-         {
-            png_image_write_control display;
-            int result;
-
-            /* This is slightly evil, but png_init_io doesn't do anything other
-             * than this and we haven't changed the standard IO functions so
-             * this saves a 'safe' function.
-             */
-            image->opaque->png_ptr->io_ptr = file;
-
-            memset(&display, 0, (sizeof display));
-            display.image = image;
-            display.buffer = buffer;
-            display.row_stride = row_stride;
-            display.colormap = colormap;
-            display.convert_to_8bit = convert_to_8bit;
-
-            result = png_safe_execute(image, png_image_write_main, &display);
-            png_image_free(image);
-            return result;
-         }
-
-         else
-            return 0;
-      }
-
-      else
-         return png_image_error(image,
-             "png_image_write_to_stdio: invalid argument");
-   }
-
-   else if (image != NULL)
-      return png_image_error(image,
-          "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
-
-   else
-      return 0;
-}
-
-int PNGAPI
-png_image_write_to_file(png_imagep image, const char *file_name,
-    int convert_to_8bit, const void *buffer, png_int_32 row_stride,
-    const void *colormap)
-{
-   /* Write the image to the named file. */
-   if (image != NULL && image->version == PNG_IMAGE_VERSION)
-   {
-      if (file_name != NULL && buffer != NULL)
-      {
-         FILE *fp = fopen(file_name, "wb");
-
-         if (fp != NULL)
-         {
-            if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
-                row_stride, colormap) != 0)
-            {
-               int error; /* from fflush/fclose */
-
-               /* Make sure the file is flushed correctly. */
-               if (fflush(fp) == 0 && ferror(fp) == 0)
-               {
-                  if (fclose(fp) == 0)
-                     return 1;
-
-                  error = errno; /* from fclose */
-               }
-
-               else
-               {
-                  error = errno; /* from fflush or ferror */
-                  (void)fclose(fp);
-               }
-
-               (void)remove(file_name);
-               /* The image has already been cleaned up; this is just used to
-                * set the error (because the original write succeeded).
-                */
-               return png_image_error(image, strerror(error));
-            }
-
-            else
-            {
-               /* Clean up: just the opened file. */
-               (void)fclose(fp);
-               (void)remove(file_name);
-               return 0;
-            }
-         }
-
-         else
-            return png_image_error(image, strerror(errno));
-      }
-
-      else
-         return png_image_error(image,
-             "png_image_write_to_file: invalid argument");
-   }
-
-   else if (image != NULL)
-      return png_image_error(image,
-          "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
-
-   else
-      return 0;
-}
-#endif /* SIMPLIFIED_WRITE_STDIO */
-#endif /* SIMPLIFIED_WRITE */
-#endif /* WRITE */
diff --git a/third_party/libpng16/pngwtran.c b/third_party/libpng16/pngwtran.c
deleted file mode 100644
index 49a13c1..0000000
--- a/third_party/libpng16/pngwtran.c
+++ /dev/null
@@ -1,575 +0,0 @@
-
-/* pngwtran.c - transforms the data in a row for PNG writers
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include "pngpriv.h"
-
-#ifdef PNG_WRITE_SUPPORTED
-#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
-
-#ifdef PNG_WRITE_PACK_SUPPORTED
-/* Pack pixels into bytes.  Pass the true bit depth in bit_depth.  The
- * row_info bit depth should be 8 (one pixel per byte).  The channels
- * should be 1 (this only happens on grayscale and paletted images).
- */
-static void
-png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
-{
-   png_debug(1, "in png_do_pack");
-
-   if (row_info->bit_depth == 8 &&
-      row_info->channels == 1)
-   {
-      switch ((int)bit_depth)
-      {
-         case 1:
-         {
-            png_bytep sp, dp;
-            int mask, v;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            sp = row;
-            dp = row;
-            mask = 0x80;
-            v = 0;
-
-            for (i = 0; i < row_width; i++)
-            {
-               if (*sp != 0)
-                  v |= mask;
-
-               sp++;
-
-               if (mask > 1)
-                  mask >>= 1;
-
-               else
-               {
-                  mask = 0x80;
-                  *dp = (png_byte)v;
-                  dp++;
-                  v = 0;
-               }
-            }
-
-            if (mask != 0x80)
-               *dp = (png_byte)v;
-
-            break;
-         }
-
-         case 2:
-         {
-            png_bytep sp, dp;
-            unsigned int shift;
-            int v;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            sp = row;
-            dp = row;
-            shift = 6;
-            v = 0;
-
-            for (i = 0; i < row_width; i++)
-            {
-               png_byte value;
-
-               value = (png_byte)(*sp & 0x03);
-               v |= (value << shift);
-
-               if (shift == 0)
-               {
-                  shift = 6;
-                  *dp = (png_byte)v;
-                  dp++;
-                  v = 0;
-               }
-
-               else
-                  shift -= 2;
-
-               sp++;
-            }
-
-            if (shift != 6)
-               *dp = (png_byte)v;
-
-            break;
-         }
-
-         case 4:
-         {
-            png_bytep sp, dp;
-            unsigned int shift;
-            int v;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            sp = row;
-            dp = row;
-            shift = 4;
-            v = 0;
-
-            for (i = 0; i < row_width; i++)
-            {
-               png_byte value;
-
-               value = (png_byte)(*sp & 0x0f);
-               v |= (value << shift);
-
-               if (shift == 0)
-               {
-                  shift = 4;
-                  *dp = (png_byte)v;
-                  dp++;
-                  v = 0;
-               }
-
-               else
-                  shift -= 4;
-
-               sp++;
-            }
-
-            if (shift != 4)
-               *dp = (png_byte)v;
-
-            break;
-         }
-
-         default:
-            break;
-      }
-
-      row_info->bit_depth = (png_byte)bit_depth;
-      row_info->pixel_depth = (png_byte)(bit_depth * row_info->channels);
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
-          row_info->width);
-   }
-}
-#endif
-
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
-/* Shift pixel values to take advantage of whole range.  Pass the
- * true number of bits in bit_depth.  The row should be packed
- * according to row_info->bit_depth.  Thus, if you had a row of
- * bit depth 4, but the pixels only had values from 0 to 7, you
- * would pass 3 as bit_depth, and this routine would translate the
- * data to 0 to 15.
- */
-static void
-png_do_shift(png_row_infop row_info, png_bytep row,
-    png_const_color_8p bit_depth)
-{
-   png_debug(1, "in png_do_shift");
-
-   if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
-   {
-      int shift_start[4], shift_dec[4];
-      unsigned int channels = 0;
-
-      if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
-      {
-         shift_start[channels] = row_info->bit_depth - bit_depth->red;
-         shift_dec[channels] = bit_depth->red;
-         channels++;
-
-         shift_start[channels] = row_info->bit_depth - bit_depth->green;
-         shift_dec[channels] = bit_depth->green;
-         channels++;
-
-         shift_start[channels] = row_info->bit_depth - bit_depth->blue;
-         shift_dec[channels] = bit_depth->blue;
-         channels++;
-      }
-
-      else
-      {
-         shift_start[channels] = row_info->bit_depth - bit_depth->gray;
-         shift_dec[channels] = bit_depth->gray;
-         channels++;
-      }
-
-      if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
-      {
-         shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
-         shift_dec[channels] = bit_depth->alpha;
-         channels++;
-      }
-
-      /* With low row depths, could only be grayscale, so one channel */
-      if (row_info->bit_depth < 8)
-      {
-         png_bytep bp = row;
-         size_t i;
-         unsigned int mask;
-         size_t row_bytes = row_info->rowbytes;
-
-         if (bit_depth->gray == 1 && row_info->bit_depth == 2)
-            mask = 0x55;
-
-         else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
-            mask = 0x11;
-
-         else
-            mask = 0xff;
-
-         for (i = 0; i < row_bytes; i++, bp++)
-         {
-            int j;
-            unsigned int v, out;
-
-            v = *bp;
-            out = 0;
-
-            for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
-            {
-               if (j > 0)
-                  out |= v << j;
-
-               else
-                  out |= (v >> (-j)) & mask;
-            }
-
-            *bp = (png_byte)(out & 0xff);
-         }
-      }
-
-      else if (row_info->bit_depth == 8)
-      {
-         png_bytep bp = row;
-         png_uint_32 i;
-         png_uint_32 istop = channels * row_info->width;
-
-         for (i = 0; i < istop; i++, bp++)
-         {
-            unsigned int c = i%channels;
-            int j;
-            unsigned int v, out;
-
-            v = *bp;
-            out = 0;
-
-            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
-            {
-               if (j > 0)
-                  out |= v << j;
-
-               else
-                  out |= v >> (-j);
-            }
-
-            *bp = (png_byte)(out & 0xff);
-         }
-      }
-
-      else
-      {
-         png_bytep bp;
-         png_uint_32 i;
-         png_uint_32 istop = channels * row_info->width;
-
-         for (bp = row, i = 0; i < istop; i++)
-         {
-            unsigned int c = i%channels;
-            int j;
-            unsigned int value, v;
-
-            v = png_get_uint_16(bp);
-            value = 0;
-
-            for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
-            {
-               if (j > 0)
-                  value |= v << j;
-
-               else
-                  value |= v >> (-j);
-            }
-            *bp++ = (png_byte)((value >> 8) & 0xff);
-            *bp++ = (png_byte)(value & 0xff);
-         }
-      }
-   }
-}
-#endif
-
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
-static void
-png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_write_swap_alpha");
-
-   {
-      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-      {
-         if (row_info->bit_depth == 8)
-         {
-            /* This converts from ARGB to RGBA */
-            png_bytep sp, dp;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            for (i = 0, sp = dp = row; i < row_width; i++)
-            {
-               png_byte save = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = save;
-            }
-         }
-
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-         else
-         {
-            /* This converts from AARRGGBB to RRGGBBAA */
-            png_bytep sp, dp;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            for (i = 0, sp = dp = row; i < row_width; i++)
-            {
-               png_byte save[2];
-               save[0] = *(sp++);
-               save[1] = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = save[0];
-               *(dp++) = save[1];
-            }
-         }
-#endif /* WRITE_16BIT */
-      }
-
-      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-      {
-         if (row_info->bit_depth == 8)
-         {
-            /* This converts from AG to GA */
-            png_bytep sp, dp;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            for (i = 0, sp = dp = row; i < row_width; i++)
-            {
-               png_byte save = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = save;
-            }
-         }
-
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-         else
-         {
-            /* This converts from AAGG to GGAA */
-            png_bytep sp, dp;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            for (i = 0, sp = dp = row; i < row_width; i++)
-            {
-               png_byte save[2];
-               save[0] = *(sp++);
-               save[1] = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = save[0];
-               *(dp++) = save[1];
-            }
-         }
-#endif /* WRITE_16BIT */
-      }
-   }
-}
-#endif
-
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-static void
-png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
-{
-   png_debug(1, "in png_do_write_invert_alpha");
-
-   {
-      if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
-      {
-         if (row_info->bit_depth == 8)
-         {
-            /* This inverts the alpha channel in RGBA */
-            png_bytep sp, dp;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            for (i = 0, sp = dp = row; i < row_width; i++)
-            {
-               /* Does nothing
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               */
-               sp+=3; dp = sp;
-               *dp = (png_byte)(255 - *(sp++));
-            }
-         }
-
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-         else
-         {
-            /* This inverts the alpha channel in RRGGBBAA */
-            png_bytep sp, dp;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            for (i = 0, sp = dp = row; i < row_width; i++)
-            {
-               /* Does nothing
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               */
-               sp+=6; dp = sp;
-               *(dp++) = (png_byte)(255 - *(sp++));
-               *dp     = (png_byte)(255 - *(sp++));
-            }
-         }
-#endif /* WRITE_16BIT */
-      }
-
-      else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-      {
-         if (row_info->bit_depth == 8)
-         {
-            /* This inverts the alpha channel in GA */
-            png_bytep sp, dp;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            for (i = 0, sp = dp = row; i < row_width; i++)
-            {
-               *(dp++) = *(sp++);
-               *(dp++) = (png_byte)(255 - *(sp++));
-            }
-         }
-
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-         else
-         {
-            /* This inverts the alpha channel in GGAA */
-            png_bytep sp, dp;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            for (i = 0, sp = dp = row; i < row_width; i++)
-            {
-               /* Does nothing
-               *(dp++) = *(sp++);
-               *(dp++) = *(sp++);
-               */
-               sp+=2; dp = sp;
-               *(dp++) = (png_byte)(255 - *(sp++));
-               *dp     = (png_byte)(255 - *(sp++));
-            }
-         }
-#endif /* WRITE_16BIT */
-      }
-   }
-}
-#endif
-
-/* Transform the data according to the user's wishes.  The order of
- * transformations is significant.
- */
-void /* PRIVATE */
-png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
-{
-   png_debug(1, "in png_do_write_transformations");
-
-   if (png_ptr == NULL)
-      return;
-
-#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
-   if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
-      if (png_ptr->write_user_transform_fn != NULL)
-         (*(png_ptr->write_user_transform_fn)) /* User write transform
-                                                 function */
-             (png_ptr,  /* png_ptr */
-             row_info,  /* row_info: */
-                /*  png_uint_32 width;       width of row */
-                /*  size_t rowbytes;         number of bytes in row */
-                /*  png_byte color_type;     color type of pixels */
-                /*  png_byte bit_depth;      bit depth of samples */
-                /*  png_byte channels;       number of channels (1-4) */
-                /*  png_byte pixel_depth;    bits per pixel (depth*channels) */
-             png_ptr->row_buf + 1);      /* start of pixel data for row */
-#endif
-
-#ifdef PNG_WRITE_FILLER_SUPPORTED
-   if ((png_ptr->transformations & PNG_FILLER) != 0)
-      png_do_strip_channel(row_info, png_ptr->row_buf + 1,
-          !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
-#endif
-
-#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
-   if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
-      png_do_packswap(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_PACK_SUPPORTED
-   if ((png_ptr->transformations & PNG_PACK) != 0)
-      png_do_pack(row_info, png_ptr->row_buf + 1,
-          (png_uint_32)png_ptr->bit_depth);
-#endif
-
-#ifdef PNG_WRITE_SWAP_SUPPORTED
-#  ifdef PNG_16BIT_SUPPORTED
-   if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
-      png_do_swap(row_info, png_ptr->row_buf + 1);
-#  endif
-#endif
-
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
-   if ((png_ptr->transformations & PNG_SHIFT) != 0)
-      png_do_shift(row_info, png_ptr->row_buf + 1,
-           &(png_ptr->shift));
-#endif
-
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
-   if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
-      png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-   if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
-      png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_BGR_SUPPORTED
-   if ((png_ptr->transformations & PNG_BGR) != 0)
-      png_do_bgr(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_INVERT_SUPPORTED
-   if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
-      png_do_invert(row_info, png_ptr->row_buf + 1);
-#endif
-}
-#endif /* WRITE_TRANSFORMS */
-#endif /* WRITE */
diff --git a/third_party/libpng16/pngwutil.c b/third_party/libpng16/pngwutil.c
deleted file mode 100644
index 16345e4..0000000
--- a/third_party/libpng16/pngwutil.c
+++ /dev/null
@@ -1,2781 +0,0 @@
-
-/* pngwutil.c - utilities to write a PNG file
- *
- * Copyright (c) 2018 Cosmin Truta
- * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
- * Copyright (c) 1996-1997 Andreas Dilger
- * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
- *
- * This code is released under the libpng license.
- * For conditions of distribution and use, see the disclaimer
- * and license in png.h
- */
-
-#include "pngpriv.h"
-
-#ifdef PNG_WRITE_SUPPORTED
-
-#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
-/* Place a 32-bit number into a buffer in PNG byte order.  We work
- * with unsigned numbers for convenience, although one supported
- * ancillary chunk uses signed (two's complement) numbers.
- */
-void PNGAPI
-png_save_uint_32(png_bytep buf, png_uint_32 i)
-{
-   buf[0] = (png_byte)((i >> 24) & 0xffU);
-   buf[1] = (png_byte)((i >> 16) & 0xffU);
-   buf[2] = (png_byte)((i >>  8) & 0xffU);
-   buf[3] = (png_byte)( i        & 0xffU);
-}
-
-/* Place a 16-bit number into a buffer in PNG byte order.
- * The parameter is declared unsigned int, not png_uint_16,
- * just to avoid potential problems on pre-ANSI C compilers.
- */
-void PNGAPI
-png_save_uint_16(png_bytep buf, unsigned int i)
-{
-   buf[0] = (png_byte)((i >> 8) & 0xffU);
-   buf[1] = (png_byte)( i       & 0xffU);
-}
-#endif
-
-/* Simple function to write the signature.  If we have already written
- * the magic bytes of the signature, or more likely, the PNG stream is
- * being embedded into another stream and doesn't need its own signature,
- * we should call png_set_sig_bytes() to tell libpng how many of the
- * bytes have already been written.
- */
-void PNGAPI
-png_write_sig(png_structrp png_ptr)
-{
-   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
-
-#ifdef PNG_IO_STATE_SUPPORTED
-   /* Inform the I/O callback that the signature is being written */
-   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE;
-#endif
-
-   /* Write the rest of the 8 byte signature */
-   png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
-       (size_t)(8 - png_ptr->sig_bytes));
-
-   if (png_ptr->sig_bytes < 3)
-      png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
-}
-
-/* Write the start of a PNG chunk.  The type is the chunk type.
- * The total_length is the sum of the lengths of all the data you will be
- * passing in png_write_chunk_data().
- */
-static void
-png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name,
-    png_uint_32 length)
-{
-   png_byte buf[8];
-
-#if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
-   PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
-   png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
-#endif
-
-   if (png_ptr == NULL)
-      return;
-
-#ifdef PNG_IO_STATE_SUPPORTED
-   /* Inform the I/O callback that the chunk header is being written.
-    * PNG_IO_CHUNK_HDR requires a single I/O call.
-    */
-   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR;
-#endif
-
-   /* Write the length and the chunk name */
-   png_save_uint_32(buf, length);
-   png_save_uint_32(buf + 4, chunk_name);
-   png_write_data(png_ptr, buf, 8);
-
-   /* Put the chunk name into png_ptr->chunk_name */
-   png_ptr->chunk_name = chunk_name;
-
-   /* Reset the crc and run it over the chunk name */
-   png_reset_crc(png_ptr);
-
-   png_calculate_crc(png_ptr, buf + 4, 4);
-
-#ifdef PNG_IO_STATE_SUPPORTED
-   /* Inform the I/O callback that chunk data will (possibly) be written.
-    * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
-    */
-   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA;
-#endif
-}
-
-void PNGAPI
-png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
-    png_uint_32 length)
-{
-   png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
-}
-
-/* Write the data of a PNG chunk started with png_write_chunk_header().
- * Note that multiple calls to this function are allowed, and that the
- * sum of the lengths from these calls *must* add up to the total_length
- * given to png_write_chunk_header().
- */
-void PNGAPI
-png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, size_t length)
-{
-   /* Write the data, and run the CRC over it */
-   if (png_ptr == NULL)
-      return;
-
-   if (data != NULL && length > 0)
-   {
-      png_write_data(png_ptr, data, length);
-
-      /* Update the CRC after writing the data,
-       * in case the user I/O routine alters it.
-       */
-      png_calculate_crc(png_ptr, data, length);
-   }
-}
-
-/* Finish a chunk started with png_write_chunk_header(). */
-void PNGAPI
-png_write_chunk_end(png_structrp png_ptr)
-{
-   png_byte buf[4];
-
-   if (png_ptr == NULL) return;
-
-#ifdef PNG_IO_STATE_SUPPORTED
-   /* Inform the I/O callback that the chunk CRC is being written.
-    * PNG_IO_CHUNK_CRC requires a single I/O function call.
-    */
-   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC;
-#endif
-
-   /* Write the crc in a single operation */
-   png_save_uint_32(buf, png_ptr->crc);
-
-   png_write_data(png_ptr, buf, 4);
-}
-
-/* Write a PNG chunk all at once.  The type is an array of ASCII characters
- * representing the chunk name.  The array must be at least 4 bytes in
- * length, and does not need to be null terminated.  To be safe, pass the
- * pre-defined chunk names here, and if you need a new one, define it
- * where the others are defined.  The length is the length of the data.
- * All the data must be present.  If that is not possible, use the
- * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
- * functions instead.
- */
-static void
-png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
-    png_const_bytep data, size_t length)
-{
-   if (png_ptr == NULL)
-      return;
-
-   /* On 64-bit architectures 'length' may not fit in a png_uint_32. */
-   if (length > PNG_UINT_31_MAX)
-      png_error(png_ptr, "length exceeds PNG maximum");
-
-   png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
-   png_write_chunk_data(png_ptr, data, length);
-   png_write_chunk_end(png_ptr);
-}
-
-/* This is the API that calls the internal function above. */
-void PNGAPI
-png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
-    png_const_bytep data, size_t length)
-{
-   png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
-       length);
-}
-
-/* This is used below to find the size of an image to pass to png_deflate_claim,
- * so it only needs to be accurate if the size is less than 16384 bytes (the
- * point at which a lower LZ window size can be used.)
- */
-static png_alloc_size_t
-png_image_size(png_structrp png_ptr)
-{
-   /* Only return sizes up to the maximum of a png_uint_32; do this by limiting
-    * the width and height used to 15 bits.
-    */
-   png_uint_32 h = png_ptr->height;
-
-   if (png_ptr->rowbytes < 32768 && h < 32768)
-   {
-      if (png_ptr->interlaced != 0)
-      {
-         /* Interlacing makes the image larger because of the replication of
-          * both the filter byte and the padding to a byte boundary.
-          */
-         png_uint_32 w = png_ptr->width;
-         unsigned int pd = png_ptr->pixel_depth;
-         png_alloc_size_t cb_base;
-         int pass;
-
-         for (cb_base=0, pass=0; pass<=6; ++pass)
-         {
-            png_uint_32 pw = PNG_PASS_COLS(w, pass);
-
-            if (pw > 0)
-               cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass);
-         }
-
-         return cb_base;
-      }
-
-      else
-         return (png_ptr->rowbytes+1) * h;
-   }
-
-   else
-      return 0xffffffffU;
-}
-
-#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
-   /* This is the code to hack the first two bytes of the deflate stream (the
-    * deflate header) to correct the windowBits value to match the actual data
-    * size.  Note that the second argument is the *uncompressed* size but the
-    * first argument is the *compressed* data (and it must be deflate
-    * compressed.)
-    */
-static void
-optimize_cmf(png_bytep data, png_alloc_size_t data_size)
-{
-   /* Optimize the CMF field in the zlib stream.  The resultant zlib stream is
-    * still compliant to the stream specification.
-    */
-   if (data_size <= 16384) /* else windowBits must be 15 */
-   {
-      unsigned int z_cmf = data[0];  /* zlib compression method and flags */
-
-      if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
-      {
-         unsigned int z_cinfo;
-         unsigned int half_z_window_size;
-
-         z_cinfo = z_cmf >> 4;
-         half_z_window_size = 1U << (z_cinfo + 7);
-
-         if (data_size <= half_z_window_size) /* else no change */
-         {
-            unsigned int tmp;
-
-            do
-            {
-               half_z_window_size >>= 1;
-               --z_cinfo;
-            }
-            while (z_cinfo > 0 && data_size <= half_z_window_size);
-
-            z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
-
-            data[0] = (png_byte)z_cmf;
-            tmp = data[1] & 0xe0;
-            tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
-            data[1] = (png_byte)tmp;
-         }
-      }
-   }
-}
-#endif /* WRITE_OPTIMIZE_CMF */
-
-/* Initialize the compressor for the appropriate type of compression. */
-static int
-png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
-    png_alloc_size_t data_size)
-{
-   if (png_ptr->zowner != 0)
-   {
-#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
-      char msg[64];
-
-      PNG_STRING_FROM_CHUNK(msg, owner);
-      msg[4] = ':';
-      msg[5] = ' ';
-      PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner);
-      /* So the message that results is "<chunk> using zstream"; this is an
-       * internal error, but is very useful for debugging.  i18n requirements
-       * are minimal.
-       */
-      (void)png_safecat(msg, (sizeof msg), 10, " using zstream");
-#endif
-#if PNG_RELEASE_BUILD
-         png_warning(png_ptr, msg);
-
-         /* Attempt sane error recovery */
-         if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */
-         {
-            png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT");
-            return Z_STREAM_ERROR;
-         }
-
-         png_ptr->zowner = 0;
-#else
-         png_error(png_ptr, msg);
-#endif
-   }
-
-   {
-      int level = png_ptr->zlib_level;
-      int method = png_ptr->zlib_method;
-      int windowBits = png_ptr->zlib_window_bits;
-      int memLevel = png_ptr->zlib_mem_level;
-      int strategy; /* set below */
-      int ret; /* zlib return code */
-
-      if (owner == png_IDAT)
-      {
-         if ((png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) != 0)
-            strategy = png_ptr->zlib_strategy;
-
-         else if (png_ptr->do_filter != PNG_FILTER_NONE)
-            strategy = PNG_Z_DEFAULT_STRATEGY;
-
-         else
-            strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY;
-      }
-
-      else
-      {
-#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
-            level = png_ptr->zlib_text_level;
-            method = png_ptr->zlib_text_method;
-            windowBits = png_ptr->zlib_text_window_bits;
-            memLevel = png_ptr->zlib_text_mem_level;
-            strategy = png_ptr->zlib_text_strategy;
-#else
-            /* If customization is not supported the values all come from the
-             * IDAT values except for the strategy, which is fixed to the
-             * default.  (This is the pre-1.6.0 behavior too, although it was
-             * implemented in a very different way.)
-             */
-            strategy = Z_DEFAULT_STRATEGY;
-#endif
-      }
-
-      /* Adjust 'windowBits' down if larger than 'data_size'; to stop this
-       * happening just pass 32768 as the data_size parameter.  Notice that zlib
-       * requires an extra 262 bytes in the window in addition to the data to be
-       * able to see the whole of the data, so if data_size+262 takes us to the
-       * next windowBits size we need to fix up the value later.  (Because even
-       * though deflate needs the extra window, inflate does not!)
-       */
-      if (data_size <= 16384)
-      {
-         /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to
-          * work round a Microsoft Visual C misbehavior which, contrary to C-90,
-          * widens the result of the following shift to 64-bits if (and,
-          * apparently, only if) it is used in a test.
-          */
-         unsigned int half_window_size = 1U << (windowBits-1);
-
-         while (data_size + 262 <= half_window_size)
-         {
-            half_window_size >>= 1;
-            --windowBits;
-         }
-      }
-
-      /* Check against the previous initialized values, if any. */
-      if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0 &&
-         (png_ptr->zlib_set_level != level ||
-         png_ptr->zlib_set_method != method ||
-         png_ptr->zlib_set_window_bits != windowBits ||
-         png_ptr->zlib_set_mem_level != memLevel ||
-         png_ptr->zlib_set_strategy != strategy))
-      {
-         if (deflateEnd(&png_ptr->zstream) != Z_OK)
-            png_warning(png_ptr, "deflateEnd failed (ignored)");
-
-         png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED;
-      }
-
-      /* For safety clear out the input and output pointers (currently zlib
-       * doesn't use them on Init, but it might in the future).
-       */
-      png_ptr->zstream.next_in = NULL;
-      png_ptr->zstream.avail_in = 0;
-      png_ptr->zstream.next_out = NULL;
-      png_ptr->zstream.avail_out = 0;
-
-      /* Now initialize if required, setting the new parameters, otherwise just
-       * do a simple reset to the previous parameters.
-       */
-      if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
-         ret = deflateReset(&png_ptr->zstream);
-
-      else
-      {
-         ret = deflateInit2(&png_ptr->zstream, level, method, windowBits,
-             memLevel, strategy);
-
-         if (ret == Z_OK)
-            png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
-      }
-
-      /* The return code is from either deflateReset or deflateInit2; they have
-       * pretty much the same set of error codes.
-       */
-      if (ret == Z_OK)
-         png_ptr->zowner = owner;
-
-      else
-         png_zstream_error(png_ptr, ret);
-
-      return ret;
-   }
-}
-
-/* Clean up (or trim) a linked list of compression buffers. */
-void /* PRIVATE */
-png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
-{
-   png_compression_bufferp list = *listp;
-
-   if (list != NULL)
-   {
-      *listp = NULL;
-
-      do
-      {
-         png_compression_bufferp next = list->next;
-
-         png_free(png_ptr, list);
-         list = next;
-      }
-      while (list != NULL);
-   }
-}
-
-#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
-/* This pair of functions encapsulates the operation of (a) compressing a
- * text string, and (b) issuing it later as a series of chunk data writes.
- * The compression_state structure is shared context for these functions
- * set up by the caller to allow access to the relevant local variables.
- *
- * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size
- * temporary buffers.  From 1.6.0 it is retained in png_struct so that it will
- * be correctly freed in the event of a write error (previous implementations
- * just leaked memory.)
- */
-typedef struct
-{
-   png_const_bytep      input;        /* The uncompressed input data */
-   png_alloc_size_t     input_len;    /* Its length */
-   png_uint_32          output_len;   /* Final compressed length */
-   png_byte             output[1024]; /* First block of output */
-} compression_state;
-
-static void
-png_text_compress_init(compression_state *comp, png_const_bytep input,
-    png_alloc_size_t input_len)
-{
-   comp->input = input;
-   comp->input_len = input_len;
-   comp->output_len = 0;
-}
-
-/* Compress the data in the compression state input */
-static int
-png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
-    compression_state *comp, png_uint_32 prefix_len)
-{
-   int ret;
-
-   /* To find the length of the output it is necessary to first compress the
-    * input. The result is buffered rather than using the two-pass algorithm
-    * that is used on the inflate side; deflate is assumed to be slower and a
-    * PNG writer is assumed to have more memory available than a PNG reader.
-    *
-    * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an
-    * upper limit on the output size, but it is always bigger than the input
-    * size so it is likely to be more efficient to use this linked-list
-    * approach.
-    */
-   ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len);
-
-   if (ret != Z_OK)
-      return ret;
-
-   /* Set up the compression buffers, we need a loop here to avoid overflowing a
-    * uInt.  Use ZLIB_IO_MAX to limit the input.  The output is always limited
-    * by the output buffer size, so there is no need to check that.  Since this
-    * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits
-    * in size.
-    */
-   {
-      png_compression_bufferp *end = &png_ptr->zbuffer_list;
-      png_alloc_size_t input_len = comp->input_len; /* may be zero! */
-      png_uint_32 output_len;
-
-      /* zlib updates these for us: */
-      png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input);
-      png_ptr->zstream.avail_in = 0; /* Set below */
-      png_ptr->zstream.next_out = comp->output;
-      png_ptr->zstream.avail_out = (sizeof comp->output);
-
-      output_len = png_ptr->zstream.avail_out;
-
-      do
-      {
-         uInt avail_in = ZLIB_IO_MAX;
-
-         if (avail_in > input_len)
-            avail_in = (uInt)input_len;
-
-         input_len -= avail_in;
-
-         png_ptr->zstream.avail_in = avail_in;
-
-         if (png_ptr->zstream.avail_out == 0)
-         {
-            png_compression_buffer *next;
-
-            /* Chunk data is limited to 2^31 bytes in length, so the prefix
-             * length must be counted here.
-             */
-            if (output_len + prefix_len > PNG_UINT_31_MAX)
-            {
-               ret = Z_MEM_ERROR;
-               break;
-            }
-
-            /* Need a new (malloc'ed) buffer, but there may be one present
-             * already.
-             */
-            next = *end;
-            if (next == NULL)
-            {
-               next = png_voidcast(png_compression_bufferp, png_malloc_base
-                  (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
-
-               if (next == NULL)
-               {
-                  ret = Z_MEM_ERROR;
-                  break;
-               }
-
-               /* Link in this buffer (so that it will be freed later) */
-               next->next = NULL;
-               *end = next;
-            }
-
-            png_ptr->zstream.next_out = next->output;
-            png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
-            output_len += png_ptr->zstream.avail_out;
-
-            /* Move 'end' to the next buffer pointer. */
-            end = &next->next;
-         }
-
-         /* Compress the data */
-         ret = deflate(&png_ptr->zstream,
-             input_len > 0 ? Z_NO_FLUSH : Z_FINISH);
-
-         /* Claw back input data that was not consumed (because avail_in is
-          * reset above every time round the loop).
-          */
-         input_len += png_ptr->zstream.avail_in;
-         png_ptr->zstream.avail_in = 0; /* safety */
-      }
-      while (ret == Z_OK);
-
-      /* There may be some space left in the last output buffer. This needs to
-       * be subtracted from output_len.
-       */
-      output_len -= png_ptr->zstream.avail_out;
-      png_ptr->zstream.avail_out = 0; /* safety */
-      comp->output_len = output_len;
-
-      /* Now double check the output length, put in a custom message if it is
-       * too long.  Otherwise ensure the z_stream::msg pointer is set to
-       * something.
-       */
-      if (output_len + prefix_len >= PNG_UINT_31_MAX)
-      {
-         png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long");
-         ret = Z_MEM_ERROR;
-      }
-
-      else
-         png_zstream_error(png_ptr, ret);
-
-      /* Reset zlib for another zTXt/iTXt or image data */
-      png_ptr->zowner = 0;
-
-      /* The only success case is Z_STREAM_END, input_len must be 0; if not this
-       * is an internal error.
-       */
-      if (ret == Z_STREAM_END && input_len == 0)
-      {
-#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
-         /* Fix up the deflate header, if required */
-         optimize_cmf(comp->output, comp->input_len);
-#endif
-         /* But Z_OK is returned, not Z_STREAM_END; this allows the claim
-          * function above to return Z_STREAM_END on an error (though it never
-          * does in the current versions of zlib.)
-          */
-         return Z_OK;
-      }
-
-      else
-         return ret;
-   }
-}
-
-/* Ship the compressed text out via chunk writes */
-static void
-png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
-{
-   png_uint_32 output_len = comp->output_len;
-   png_const_bytep output = comp->output;
-   png_uint_32 avail = (sizeof comp->output);
-   png_compression_buffer *next = png_ptr->zbuffer_list;
-
-   for (;;)
-   {
-      if (avail > output_len)
-         avail = output_len;
-
-      png_write_chunk_data(png_ptr, output, avail);
-
-      output_len -= avail;
-
-      if (output_len == 0 || next == NULL)
-         break;
-
-      avail = png_ptr->zbuffer_size;
-      output = next->output;
-      next = next->next;
-   }
-
-   /* This is an internal error; 'next' must have been NULL! */
-   if (output_len > 0)
-      png_error(png_ptr, "error writing ancillary chunked compressed data");
-}
-#endif /* WRITE_COMPRESSED_TEXT */
-
-/* Write the IHDR chunk, and update the png_struct with the necessary
- * information.  Note that the rest of this code depends upon this
- * information being correct.
- */
-void /* PRIVATE */
-png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
-    int bit_depth, int color_type, int compression_type, int filter_type,
-    int interlace_type)
-{
-   png_byte buf[13]; /* Buffer to store the IHDR info */
-   int is_invalid_depth;
-
-   png_debug(1, "in png_write_IHDR");
-
-   /* Check that we have valid input data from the application info */
-   switch (color_type)
-   {
-      case PNG_COLOR_TYPE_GRAY:
-         switch (bit_depth)
-         {
-            case 1:
-            case 2:
-            case 4:
-            case 8:
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-            case 16:
-#endif
-               png_ptr->channels = 1; break;
-
-            default:
-               png_error(png_ptr,
-                   "Invalid bit depth for grayscale image");
-         }
-         break;
-
-      case PNG_COLOR_TYPE_RGB:
-         is_invalid_depth = (bit_depth != 8);
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-         is_invalid_depth = (is_invalid_depth && bit_depth != 16);
-#endif
-         if (is_invalid_depth)
-            png_error(png_ptr, "Invalid bit depth for RGB image");
-
-         png_ptr->channels = 3;
-         break;
-
-      case PNG_COLOR_TYPE_PALETTE:
-         switch (bit_depth)
-         {
-            case 1:
-            case 2:
-            case 4:
-            case 8:
-               png_ptr->channels = 1;
-               break;
-
-            default:
-               png_error(png_ptr, "Invalid bit depth for paletted image");
-         }
-         break;
-
-      case PNG_COLOR_TYPE_GRAY_ALPHA:
-         is_invalid_depth = (bit_depth != 8);
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-         is_invalid_depth = (is_invalid_depth && bit_depth != 16);
-#endif
-         if (is_invalid_depth)
-            png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
-
-         png_ptr->channels = 2;
-         break;
-
-      case PNG_COLOR_TYPE_RGB_ALPHA:
-         is_invalid_depth = (bit_depth != 8);
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-         is_invalid_depth = (is_invalid_depth && bit_depth != 16);
-#endif
-         if (is_invalid_depth)
-            png_error(png_ptr, "Invalid bit depth for RGBA image");
-
-         png_ptr->channels = 4;
-         break;
-
-      default:
-         png_error(png_ptr, "Invalid image color type specified");
-   }
-
-   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
-   {
-      png_warning(png_ptr, "Invalid compression type specified");
-      compression_type = PNG_COMPRESSION_TYPE_BASE;
-   }
-
-   /* Write filter_method 64 (intrapixel differencing) only if
-    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
-    * 2. Libpng did not write a PNG signature (this filter_method is only
-    *    used in PNG datastreams that are embedded in MNG datastreams) and
-    * 3. The application called png_permit_mng_features with a mask that
-    *    included PNG_FLAG_MNG_FILTER_64 and
-    * 4. The filter_method is 64 and
-    * 5. The color_type is RGB or RGBA
-    */
-   if (
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-       !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
-       ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
-       (color_type == PNG_COLOR_TYPE_RGB ||
-        color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
-       (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
-#endif
-       filter_type != PNG_FILTER_TYPE_BASE)
-   {
-      png_warning(png_ptr, "Invalid filter type specified");
-      filter_type = PNG_FILTER_TYPE_BASE;
-   }
-
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-   if (interlace_type != PNG_INTERLACE_NONE &&
-       interlace_type != PNG_INTERLACE_ADAM7)
-   {
-      png_warning(png_ptr, "Invalid interlace type specified");
-      interlace_type = PNG_INTERLACE_ADAM7;
-   }
-#else
-   interlace_type=PNG_INTERLACE_NONE;
-#endif
-
-   /* Save the relevant information */
-   png_ptr->bit_depth = (png_byte)bit_depth;
-   png_ptr->color_type = (png_byte)color_type;
-   png_ptr->interlaced = (png_byte)interlace_type;
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-   png_ptr->filter_type = (png_byte)filter_type;
-#endif
-   png_ptr->compression_type = (png_byte)compression_type;
-   png_ptr->width = width;
-   png_ptr->height = height;
-
-   png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
-   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
-   /* Set the usr info, so any transformations can modify it */
-   png_ptr->usr_width = png_ptr->width;
-   png_ptr->usr_bit_depth = png_ptr->bit_depth;
-   png_ptr->usr_channels = png_ptr->channels;
-
-   /* Pack the header information into the buffer */
-   png_save_uint_32(buf, width);
-   png_save_uint_32(buf + 4, height);
-   buf[8] = (png_byte)bit_depth;
-   buf[9] = (png_byte)color_type;
-   buf[10] = (png_byte)compression_type;
-   buf[11] = (png_byte)filter_type;
-   buf[12] = (png_byte)interlace_type;
-
-   /* Write the chunk */
-   png_write_complete_chunk(png_ptr, png_IHDR, buf, 13);
-
-   if ((png_ptr->do_filter) == PNG_NO_FILTERS)
-   {
-      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
-          png_ptr->bit_depth < 8)
-         png_ptr->do_filter = PNG_FILTER_NONE;
-
-      else
-         png_ptr->do_filter = PNG_ALL_FILTERS;
-   }
-
-   png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
-}
-
-/* Write the palette.  We are careful not to trust png_color to be in the
- * correct order for PNG, so people can redefine it to any convenient
- * structure.
- */
-void /* PRIVATE */
-png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
-    png_uint_32 num_pal)
-{
-   png_uint_32 max_palette_length, i;
-   png_const_colorp pal_ptr;
-   png_byte buf[3];
-
-   png_debug(1, "in png_write_PLTE");
-
-   max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
-      (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
-
-   if ((
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-       (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 &&
-#endif
-       num_pal == 0) || num_pal > max_palette_length)
-   {
-      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
-      {
-         png_error(png_ptr, "Invalid number of colors in palette");
-      }
-
-      else
-      {
-         png_warning(png_ptr, "Invalid number of colors in palette");
-         return;
-      }
-   }
-
-   if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
-   {
-      png_warning(png_ptr,
-          "Ignoring request to write a PLTE chunk in grayscale PNG");
-
-      return;
-   }
-
-   png_ptr->num_palette = (png_uint_16)num_pal;
-   png_debug1(3, "num_palette = %d", png_ptr->num_palette);
-
-   png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
-#ifdef PNG_POINTER_INDEXING_SUPPORTED
-
-   for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
-   {
-      buf[0] = pal_ptr->red;
-      buf[1] = pal_ptr->green;
-      buf[2] = pal_ptr->blue;
-      png_write_chunk_data(png_ptr, buf, 3);
-   }
-
-#else
-   /* This is a little slower but some buggy compilers need to do this
-    * instead
-    */
-   pal_ptr=palette;
-
-   for (i = 0; i < num_pal; i++)
-   {
-      buf[0] = pal_ptr[i].red;
-      buf[1] = pal_ptr[i].green;
-      buf[2] = pal_ptr[i].blue;
-      png_write_chunk_data(png_ptr, buf, 3);
-   }
-
-#endif
-   png_write_chunk_end(png_ptr);
-   png_ptr->mode |= PNG_HAVE_PLTE;
-}
-
-/* This is similar to png_text_compress, above, except that it does not require
- * all of the data at once and, instead of buffering the compressed result,
- * writes it as IDAT chunks.  Unlike png_text_compress it *can* png_error out
- * because it calls the write interface.  As a result it does its own error
- * reporting and does not return an error code.  In the event of error it will
- * just call png_error.  The input data length may exceed 32-bits.  The 'flush'
- * parameter is exactly the same as that to deflate, with the following
- * meanings:
- *
- * Z_NO_FLUSH: normal incremental output of compressed data
- * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush
- * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
- *
- * The routine manages the acquire and release of the png_ptr->zstream by
- * checking and (at the end) clearing png_ptr->zowner; it does some sanity
- * checks on the 'mode' flags while doing this.
- */
-void /* PRIVATE */
-png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
-    png_alloc_size_t input_len, int flush)
-{
-   if (png_ptr->zowner != png_IDAT)
-   {
-      /* First time.   Ensure we have a temporary buffer for compression and
-       * trim the buffer list if it has more than one entry to free memory.
-       * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been
-       * created at this point, but the check here is quick and safe.
-       */
-      if (png_ptr->zbuffer_list == NULL)
-      {
-         png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp,
-             png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
-         png_ptr->zbuffer_list->next = NULL;
-      }
-
-      else
-         png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next);
-
-      /* It is a terminal error if we can't claim the zstream. */
-      if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK)
-         png_error(png_ptr, png_ptr->zstream.msg);
-
-      /* The output state is maintained in png_ptr->zstream, so it must be
-       * initialized here after the claim.
-       */
-      png_ptr->zstream.next_out = png_ptr->zbuffer_list->output;
-      png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
-   }
-
-   /* Now loop reading and writing until all the input is consumed or an error
-    * terminates the operation.  The _out values are maintained across calls to
-    * this function, but the input must be reset each time.
-    */
-   png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
-   png_ptr->zstream.avail_in = 0; /* set below */
-   for (;;)
-   {
-      int ret;
-
-      /* INPUT: from the row data */
-      uInt avail = ZLIB_IO_MAX;
-
-      if (avail > input_len)
-         avail = (uInt)input_len; /* safe because of the check */
-
-      png_ptr->zstream.avail_in = avail;
-      input_len -= avail;
-
-      ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush);
-
-      /* Include as-yet unconsumed input */
-      input_len += png_ptr->zstream.avail_in;
-      png_ptr->zstream.avail_in = 0;
-
-      /* OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note
-       * that these two zstream fields are preserved across the calls, therefore
-       * there is no need to set these up on entry to the loop.
-       */
-      if (png_ptr->zstream.avail_out == 0)
-      {
-         png_bytep data = png_ptr->zbuffer_list->output;
-         uInt size = png_ptr->zbuffer_size;
-
-         /* Write an IDAT containing the data then reset the buffer.  The
-          * first IDAT may need deflate header optimization.
-          */
-#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
-            if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
-                png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
-               optimize_cmf(data, png_image_size(png_ptr));
-#endif
-
-         if (size > 0)
-            png_write_complete_chunk(png_ptr, png_IDAT, data, size);
-         png_ptr->mode |= PNG_HAVE_IDAT;
-
-         png_ptr->zstream.next_out = data;
-         png_ptr->zstream.avail_out = size;
-
-         /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with
-          * the same flush parameter until it has finished output, for NO_FLUSH
-          * it doesn't matter.
-          */
-         if (ret == Z_OK && flush != Z_NO_FLUSH)
-            continue;
-      }
-
-      /* The order of these checks doesn't matter much; it just affects which
-       * possible error might be detected if multiple things go wrong at once.
-       */
-      if (ret == Z_OK) /* most likely return code! */
-      {
-         /* If all the input has been consumed then just return.  If Z_FINISH
-          * was used as the flush parameter something has gone wrong if we get
-          * here.
-          */
-         if (input_len == 0)
-         {
-            if (flush == Z_FINISH)
-               png_error(png_ptr, "Z_OK on Z_FINISH with output space");
-
-            return;
-         }
-      }
-
-      else if (ret == Z_STREAM_END && flush == Z_FINISH)
-      {
-         /* This is the end of the IDAT data; any pending output must be
-          * flushed.  For small PNG files we may still be at the beginning.
-          */
-         png_bytep data = png_ptr->zbuffer_list->output;
-         uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out;
-
-#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
-         if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
-             png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
-            optimize_cmf(data, png_image_size(png_ptr));
-#endif
-
-         if (size > 0)
-            png_write_complete_chunk(png_ptr, png_IDAT, data, size);
-         png_ptr->zstream.avail_out = 0;
-         png_ptr->zstream.next_out = NULL;
-         png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
-
-         png_ptr->zowner = 0; /* Release the stream */
-         return;
-      }
-
-      else
-      {
-         /* This is an error condition. */
-         png_zstream_error(png_ptr, ret);
-         png_error(png_ptr, png_ptr->zstream.msg);
-      }
-   }
-}
-
-/* Write an IEND chunk */
-void /* PRIVATE */
-png_write_IEND(png_structrp png_ptr)
-{
-   png_debug(1, "in png_write_IEND");
-
-   png_write_complete_chunk(png_ptr, png_IEND, NULL, 0);
-   png_ptr->mode |= PNG_HAVE_IEND;
-}
-
-#ifdef PNG_WRITE_gAMA_SUPPORTED
-/* Write a gAMA chunk */
-void /* PRIVATE */
-png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
-{
-   png_byte buf[4];
-
-   png_debug(1, "in png_write_gAMA");
-
-   /* file_gamma is saved in 1/100,000ths */
-   png_save_uint_32(buf, (png_uint_32)file_gamma);
-   png_write_complete_chunk(png_ptr, png_gAMA, buf, 4);
-}
-#endif
-
-#ifdef PNG_WRITE_sRGB_SUPPORTED
-/* Write a sRGB chunk */
-void /* PRIVATE */
-png_write_sRGB(png_structrp png_ptr, int srgb_intent)
-{
-   png_byte buf[1];
-
-   png_debug(1, "in png_write_sRGB");
-
-   if (srgb_intent >= PNG_sRGB_INTENT_LAST)
-      png_warning(png_ptr,
-          "Invalid sRGB rendering intent specified");
-
-   buf[0]=(png_byte)srgb_intent;
-   png_write_complete_chunk(png_ptr, png_sRGB, buf, 1);
-}
-#endif
-
-#ifdef PNG_WRITE_iCCP_SUPPORTED
-/* Write an iCCP chunk */
-void /* PRIVATE */
-png_write_iCCP(png_structrp png_ptr, png_const_charp name,
-    png_const_bytep profile)
-{
-   png_uint_32 name_len;
-   png_uint_32 profile_len;
-   png_byte new_name[81]; /* 1 byte for the compression byte */
-   compression_state comp;
-   png_uint_32 temp;
-
-   png_debug(1, "in png_write_iCCP");
-
-   /* These are all internal problems: the profile should have been checked
-    * before when it was stored.
-    */
-   if (profile == NULL)
-      png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */
-
-   profile_len = png_get_uint_32(profile);
-
-   if (profile_len < 132)
-      png_error(png_ptr, "ICC profile too short");
-
-   temp = (png_uint_32) (*(profile+8));
-   if (temp > 3 && (profile_len & 0x03))
-      png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
-
-   {
-      png_uint_32 embedded_profile_len = png_get_uint_32(profile);
-
-      if (profile_len != embedded_profile_len)
-         png_error(png_ptr, "Profile length does not match profile");
-   }
-
-   name_len = png_check_keyword(png_ptr, name, new_name);
-
-   if (name_len == 0)
-      png_error(png_ptr, "iCCP: invalid keyword");
-
-   new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
-
-   /* Make sure we include the NULL after the name and the compression type */
-   ++name_len;
-
-   png_text_compress_init(&comp, profile, profile_len);
-
-   /* Allow for keyword terminator and compression byte */
-   if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
-      png_error(png_ptr, png_ptr->zstream.msg);
-
-   png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
-
-   png_write_chunk_data(png_ptr, new_name, name_len);
-
-   png_write_compressed_data_out(png_ptr, &comp);
-
-   png_write_chunk_end(png_ptr);
-}
-#endif
-
-#ifdef PNG_WRITE_sPLT_SUPPORTED
-/* Write a sPLT chunk */
-void /* PRIVATE */
-png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
-{
-   png_uint_32 name_len;
-   png_byte new_name[80];
-   png_byte entrybuf[10];
-   size_t entry_size = (spalette->depth == 8 ? 6 : 10);
-   size_t palette_size = entry_size * (size_t)spalette->nentries;
-   png_sPLT_entryp ep;
-#ifndef PNG_POINTER_INDEXING_SUPPORTED
-   int i;
-#endif
-
-   png_debug(1, "in png_write_sPLT");
-
-   name_len = png_check_keyword(png_ptr, spalette->name, new_name);
-
-   if (name_len == 0)
-      png_error(png_ptr, "sPLT: invalid keyword");
-
-   /* Make sure we include the NULL after the name */
-   png_write_chunk_header(png_ptr, png_sPLT,
-       (png_uint_32)(name_len + 2 + palette_size));
-
-   png_write_chunk_data(png_ptr, (png_bytep)new_name, (size_t)(name_len + 1));
-
-   png_write_chunk_data(png_ptr, &spalette->depth, 1);
-
-   /* Loop through each palette entry, writing appropriately */
-#ifdef PNG_POINTER_INDEXING_SUPPORTED
-   for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
-   {
-      if (spalette->depth == 8)
-      {
-         entrybuf[0] = (png_byte)ep->red;
-         entrybuf[1] = (png_byte)ep->green;
-         entrybuf[2] = (png_byte)ep->blue;
-         entrybuf[3] = (png_byte)ep->alpha;
-         png_save_uint_16(entrybuf + 4, ep->frequency);
-      }
-
-      else
-      {
-         png_save_uint_16(entrybuf + 0, ep->red);
-         png_save_uint_16(entrybuf + 2, ep->green);
-         png_save_uint_16(entrybuf + 4, ep->blue);
-         png_save_uint_16(entrybuf + 6, ep->alpha);
-         png_save_uint_16(entrybuf + 8, ep->frequency);
-      }
-
-      png_write_chunk_data(png_ptr, entrybuf, entry_size);
-   }
-#else
-   ep=spalette->entries;
-   for (i = 0; i>spalette->nentries; i++)
-   {
-      if (spalette->depth == 8)
-      {
-         entrybuf[0] = (png_byte)ep[i].red;
-         entrybuf[1] = (png_byte)ep[i].green;
-         entrybuf[2] = (png_byte)ep[i].blue;
-         entrybuf[3] = (png_byte)ep[i].alpha;
-         png_save_uint_16(entrybuf + 4, ep[i].frequency);
-      }
-
-      else
-      {
-         png_save_uint_16(entrybuf + 0, ep[i].red);
-         png_save_uint_16(entrybuf + 2, ep[i].green);
-         png_save_uint_16(entrybuf + 4, ep[i].blue);
-         png_save_uint_16(entrybuf + 6, ep[i].alpha);
-         png_save_uint_16(entrybuf + 8, ep[i].frequency);
-      }
-
-      png_write_chunk_data(png_ptr, entrybuf, entry_size);
-   }
-#endif
-
-   png_write_chunk_end(png_ptr);
-}
-#endif
-
-#ifdef PNG_WRITE_sBIT_SUPPORTED
-/* Write the sBIT chunk */
-void /* PRIVATE */
-png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
-{
-   png_byte buf[4];
-   size_t size;
-
-   png_debug(1, "in png_write_sBIT");
-
-   /* Make sure we don't depend upon the order of PNG_COLOR_8 */
-   if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
-   {
-      png_byte maxbits;
-
-      maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
-          png_ptr->usr_bit_depth);
-
-      if (sbit->red == 0 || sbit->red > maxbits ||
-          sbit->green == 0 || sbit->green > maxbits ||
-          sbit->blue == 0 || sbit->blue > maxbits)
-      {
-         png_warning(png_ptr, "Invalid sBIT depth specified");
-         return;
-      }
-
-      buf[0] = sbit->red;
-      buf[1] = sbit->green;
-      buf[2] = sbit->blue;
-      size = 3;
-   }
-
-   else
-   {
-      if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
-      {
-         png_warning(png_ptr, "Invalid sBIT depth specified");
-         return;
-      }
-
-      buf[0] = sbit->gray;
-      size = 1;
-   }
-
-   if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
-   {
-      if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
-      {
-         png_warning(png_ptr, "Invalid sBIT depth specified");
-         return;
-      }
-
-      buf[size++] = sbit->alpha;
-   }
-
-   png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
-}
-#endif
-
-#ifdef PNG_WRITE_cHRM_SUPPORTED
-/* Write the cHRM chunk */
-void /* PRIVATE */
-png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy)
-{
-   png_byte buf[32];
-
-   png_debug(1, "in png_write_cHRM");
-
-   /* Each value is saved in 1/100,000ths */
-   png_save_int_32(buf,      xy->whitex);
-   png_save_int_32(buf +  4, xy->whitey);
-
-   png_save_int_32(buf +  8, xy->redx);
-   png_save_int_32(buf + 12, xy->redy);
-
-   png_save_int_32(buf + 16, xy->greenx);
-   png_save_int_32(buf + 20, xy->greeny);
-
-   png_save_int_32(buf + 24, xy->bluex);
-   png_save_int_32(buf + 28, xy->bluey);
-
-   png_write_complete_chunk(png_ptr, png_cHRM, buf, 32);
-}
-#endif
-
-#ifdef PNG_WRITE_tRNS_SUPPORTED
-/* Write the tRNS chunk */
-void /* PRIVATE */
-png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
-    png_const_color_16p tran, int num_trans, int color_type)
-{
-   png_byte buf[6];
-
-   png_debug(1, "in png_write_tRNS");
-
-   if (color_type == PNG_COLOR_TYPE_PALETTE)
-   {
-      if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
-      {
-         png_app_warning(png_ptr,
-             "Invalid number of transparent colors specified");
-         return;
-      }
-
-      /* Write the chunk out as it is */
-      png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
-          (size_t)num_trans);
-   }
-
-   else if (color_type == PNG_COLOR_TYPE_GRAY)
-   {
-      /* One 16-bit value */
-      if (tran->gray >= (1 << png_ptr->bit_depth))
-      {
-         png_app_warning(png_ptr,
-             "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
-
-         return;
-      }
-
-      png_save_uint_16(buf, tran->gray);
-      png_write_complete_chunk(png_ptr, png_tRNS, buf, 2);
-   }
-
-   else if (color_type == PNG_COLOR_TYPE_RGB)
-   {
-      /* Three 16-bit values */
-      png_save_uint_16(buf, tran->red);
-      png_save_uint_16(buf + 2, tran->green);
-      png_save_uint_16(buf + 4, tran->blue);
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
-#else
-      if ((buf[0] | buf[2] | buf[4]) != 0)
-#endif
-      {
-         png_app_warning(png_ptr,
-             "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
-         return;
-      }
-
-      png_write_complete_chunk(png_ptr, png_tRNS, buf, 6);
-   }
-
-   else
-   {
-      png_app_warning(png_ptr, "Can't write tRNS with an alpha channel");
-   }
-}
-#endif
-
-#ifdef PNG_WRITE_bKGD_SUPPORTED
-/* Write the background chunk */
-void /* PRIVATE */
-png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
-{
-   png_byte buf[6];
-
-   png_debug(1, "in png_write_bKGD");
-
-   if (color_type == PNG_COLOR_TYPE_PALETTE)
-   {
-      if (
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-          (png_ptr->num_palette != 0 ||
-          (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) &&
-#endif
-         back->index >= png_ptr->num_palette)
-      {
-         png_warning(png_ptr, "Invalid background palette index");
-         return;
-      }
-
-      buf[0] = back->index;
-      png_write_complete_chunk(png_ptr, png_bKGD, buf, 1);
-   }
-
-   else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
-   {
-      png_save_uint_16(buf, back->red);
-      png_save_uint_16(buf + 2, back->green);
-      png_save_uint_16(buf + 4, back->blue);
-#ifdef PNG_WRITE_16BIT_SUPPORTED
-      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
-#else
-      if ((buf[0] | buf[2] | buf[4]) != 0)
-#endif
-      {
-         png_warning(png_ptr,
-             "Ignoring attempt to write 16-bit bKGD chunk "
-             "when bit_depth is 8");
-
-         return;
-      }
-
-      png_write_complete_chunk(png_ptr, png_bKGD, buf, 6);
-   }
-
-   else
-   {
-      if (back->gray >= (1 << png_ptr->bit_depth))
-      {
-         png_warning(png_ptr,
-             "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
-
-         return;
-      }
-
-      png_save_uint_16(buf, back->gray);
-      png_write_complete_chunk(png_ptr, png_bKGD, buf, 2);
-   }
-}
-#endif
-
-#ifdef PNG_WRITE_eXIf_SUPPORTED
-/* Write the Exif data */
-void /* PRIVATE */
-png_write_eXIf(png_structrp png_ptr, png_bytep exif, int num_exif)
-{
-   int i;
-   png_byte buf[1];
-
-   png_debug(1, "in png_write_eXIf");
-
-   png_write_chunk_header(png_ptr, png_eXIf, (png_uint_32)(num_exif));
-
-   for (i = 0; i < num_exif; i++)
-   {
-      buf[0] = exif[i];
-      png_write_chunk_data(png_ptr, buf, 1);
-   }
-
-   png_write_chunk_end(png_ptr);
-}
-#endif
-
-#ifdef PNG_WRITE_hIST_SUPPORTED
-/* Write the histogram */
-void /* PRIVATE */
-png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
-{
-   int i;
-   png_byte buf[3];
-
-   png_debug(1, "in png_write_hIST");
-
-   if (num_hist > (int)png_ptr->num_palette)
-   {
-      png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
-          png_ptr->num_palette);
-
-      png_warning(png_ptr, "Invalid number of histogram entries specified");
-      return;
-   }
-
-   png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
-
-   for (i = 0; i < num_hist; i++)
-   {
-      png_save_uint_16(buf, hist[i]);
-      png_write_chunk_data(png_ptr, buf, 2);
-   }
-
-   png_write_chunk_end(png_ptr);
-}
-#endif
-
-#ifdef PNG_WRITE_tEXt_SUPPORTED
-/* Write a tEXt chunk */
-void /* PRIVATE */
-png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
-    size_t text_len)
-{
-   png_uint_32 key_len;
-   png_byte new_key[80];
-
-   png_debug(1, "in png_write_tEXt");
-
-   key_len = png_check_keyword(png_ptr, key, new_key);
-
-   if (key_len == 0)
-      png_error(png_ptr, "tEXt: invalid keyword");
-
-   if (text == NULL || *text == '\0')
-      text_len = 0;
-
-   else
-      text_len = strlen(text);
-
-   if (text_len > PNG_UINT_31_MAX - (key_len+1))
-      png_error(png_ptr, "tEXt: text too long");
-
-   /* Make sure we include the 0 after the key */
-   png_write_chunk_header(png_ptr, png_tEXt,
-       (png_uint_32)/*checked above*/(key_len + text_len + 1));
-   /*
-    * We leave it to the application to meet PNG-1.0 requirements on the
-    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
-    * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
-    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
-    */
-   png_write_chunk_data(png_ptr, new_key, key_len + 1);
-
-   if (text_len != 0)
-      png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len);
-
-   png_write_chunk_end(png_ptr);
-}
-#endif
-
-#ifdef PNG_WRITE_zTXt_SUPPORTED
-/* Write a compressed text chunk */
-void /* PRIVATE */
-png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
-    int compression)
-{
-   png_uint_32 key_len;
-   png_byte new_key[81];
-   compression_state comp;
-
-   png_debug(1, "in png_write_zTXt");
-
-   if (compression == PNG_TEXT_COMPRESSION_NONE)
-   {
-      png_write_tEXt(png_ptr, key, text, 0);
-      return;
-   }
-
-   if (compression != PNG_TEXT_COMPRESSION_zTXt)
-      png_error(png_ptr, "zTXt: invalid compression type");
-
-   key_len = png_check_keyword(png_ptr, key, new_key);
-
-   if (key_len == 0)
-      png_error(png_ptr, "zTXt: invalid keyword");
-
-   /* Add the compression method and 1 for the keyword separator. */
-   new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
-   ++key_len;
-
-   /* Compute the compressed data; do it now for the length */
-   png_text_compress_init(&comp, (png_const_bytep)text,
-       text == NULL ? 0 : strlen(text));
-
-   if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
-      png_error(png_ptr, png_ptr->zstream.msg);
-
-   /* Write start of chunk */
-   png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
-
-   /* Write key */
-   png_write_chunk_data(png_ptr, new_key, key_len);
-
-   /* Write the compressed data */
-   png_write_compressed_data_out(png_ptr, &comp);
-
-   /* Close the chunk */
-   png_write_chunk_end(png_ptr);
-}
-#endif
-
-#ifdef PNG_WRITE_iTXt_SUPPORTED
-/* Write an iTXt chunk */
-void /* PRIVATE */
-png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
-    png_const_charp lang, png_const_charp lang_key, png_const_charp text)
-{
-   png_uint_32 key_len, prefix_len;
-   size_t lang_len, lang_key_len;
-   png_byte new_key[82];
-   compression_state comp;
-
-   png_debug(1, "in png_write_iTXt");
-
-   key_len = png_check_keyword(png_ptr, key, new_key);
-
-   if (key_len == 0)
-      png_error(png_ptr, "iTXt: invalid keyword");
-
-   /* Set the compression flag */
-   switch (compression)
-   {
-      case PNG_ITXT_COMPRESSION_NONE:
-      case PNG_TEXT_COMPRESSION_NONE:
-         compression = new_key[++key_len] = 0; /* no compression */
-         break;
-
-      case PNG_TEXT_COMPRESSION_zTXt:
-      case PNG_ITXT_COMPRESSION_zTXt:
-         compression = new_key[++key_len] = 1; /* compressed */
-         break;
-
-      default:
-         png_error(png_ptr, "iTXt: invalid compression");
-   }
-
-   new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
-   ++key_len; /* for the keywod separator */
-
-   /* We leave it to the application to meet PNG-1.0 requirements on the
-    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
-    * any non-Latin-1 characters except for NEWLINE.  ISO PNG, however,
-    * specifies that the text is UTF-8 and this really doesn't require any
-    * checking.
-    *
-    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
-    *
-    * TODO: validate the language tag correctly (see the spec.)
-    */
-   if (lang == NULL) lang = ""; /* empty language is valid */
-   lang_len = strlen(lang)+1;
-   if (lang_key == NULL) lang_key = ""; /* may be empty */
-   lang_key_len = strlen(lang_key)+1;
-   if (text == NULL) text = ""; /* may be empty */
-
-   prefix_len = key_len;
-   if (lang_len > PNG_UINT_31_MAX-prefix_len)
-      prefix_len = PNG_UINT_31_MAX;
-   else
-      prefix_len = (png_uint_32)(prefix_len + lang_len);
-
-   if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
-      prefix_len = PNG_UINT_31_MAX;
-   else
-      prefix_len = (png_uint_32)(prefix_len + lang_key_len);
-
-   png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
-
-   if (compression != 0)
-   {
-      if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
-         png_error(png_ptr, png_ptr->zstream.msg);
-   }
-
-   else
-   {
-      if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
-         png_error(png_ptr, "iTXt: uncompressed text too long");
-
-      /* So the string will fit in a chunk: */
-      comp.output_len = (png_uint_32)/*SAFE*/comp.input_len;
-   }
-
-   png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
-
-   png_write_chunk_data(png_ptr, new_key, key_len);
-
-   png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
-
-   png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);
-
-   if (compression != 0)
-      png_write_compressed_data_out(png_ptr, &comp);
-
-   else
-      png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len);
-
-   png_write_chunk_end(png_ptr);
-}
-#endif
-
-#ifdef PNG_WRITE_oFFs_SUPPORTED
-/* Write the oFFs chunk */
-void /* PRIVATE */
-png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
-    int unit_type)
-{
-   png_byte buf[9];
-
-   png_debug(1, "in png_write_oFFs");
-
-   if (unit_type >= PNG_OFFSET_LAST)
-      png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
-
-   png_save_int_32(buf, x_offset);
-   png_save_int_32(buf + 4, y_offset);
-   buf[8] = (png_byte)unit_type;
-
-   png_write_complete_chunk(png_ptr, png_oFFs, buf, 9);
-}
-#endif
-#ifdef PNG_WRITE_pCAL_SUPPORTED
-/* Write the pCAL chunk (described in the PNG extensions document) */
-void /* PRIVATE */
-png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
-    png_int_32 X1, int type, int nparams, png_const_charp units,
-    png_charpp params)
-{
-   png_uint_32 purpose_len;
-   size_t units_len, total_len;
-   png_size_tp params_len;
-   png_byte buf[10];
-   png_byte new_purpose[80];
-   int i;
-
-   png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
-
-   if (type >= PNG_EQUATION_LAST)
-      png_error(png_ptr, "Unrecognized equation type for pCAL chunk");
-
-   purpose_len = png_check_keyword(png_ptr, purpose, new_purpose);
-
-   if (purpose_len == 0)
-      png_error(png_ptr, "pCAL: invalid keyword");
-
-   ++purpose_len; /* terminator */
-
-   png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
-   units_len = strlen(units) + (nparams == 0 ? 0 : 1);
-   png_debug1(3, "pCAL units length = %d", (int)units_len);
-   total_len = purpose_len + units_len + 10;
-
-   params_len = (png_size_tp)png_malloc(png_ptr,
-       (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (size_t))));
-
-   /* Find the length of each parameter, making sure we don't count the
-    * null terminator for the last parameter.
-    */
-   for (i = 0; i < nparams; i++)
-   {
-      params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
-      png_debug2(3, "pCAL parameter %d length = %lu", i,
-          (unsigned long)params_len[i]);
-      total_len += params_len[i];
-   }
-
-   png_debug1(3, "pCAL total length = %d", (int)total_len);
-   png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
-   png_write_chunk_data(png_ptr, new_purpose, purpose_len);
-   png_save_int_32(buf, X0);
-   png_save_int_32(buf + 4, X1);
-   buf[8] = (png_byte)type;
-   buf[9] = (png_byte)nparams;
-   png_write_chunk_data(png_ptr, buf, 10);
-   png_write_chunk_data(png_ptr, (png_const_bytep)units, (size_t)units_len);
-
-   for (i = 0; i < nparams; i++)
-   {
-      png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
-   }
-
-   png_free(png_ptr, params_len);
-   png_write_chunk_end(png_ptr);
-}
-#endif
-
-#ifdef PNG_WRITE_sCAL_SUPPORTED
-/* Write the sCAL chunk */
-void /* PRIVATE */
-png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
-    png_const_charp height)
-{
-   png_byte buf[64];
-   size_t wlen, hlen, total_len;
-
-   png_debug(1, "in png_write_sCAL_s");
-
-   wlen = strlen(width);
-   hlen = strlen(height);
-   total_len = wlen + hlen + 2;
-
-   if (total_len > 64)
-   {
-      png_warning(png_ptr, "Can't write sCAL (buffer too small)");
-      return;
-   }
-
-   buf[0] = (png_byte)unit;
-   memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
-   memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
-
-   png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
-   png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
-}
-#endif
-
-#ifdef PNG_WRITE_pHYs_SUPPORTED
-/* Write the pHYs chunk */
-void /* PRIVATE */
-png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
-    png_uint_32 y_pixels_per_unit,
-    int unit_type)
-{
-   png_byte buf[9];
-
-   png_debug(1, "in png_write_pHYs");
-
-   if (unit_type >= PNG_RESOLUTION_LAST)
-      png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
-
-   png_save_uint_32(buf, x_pixels_per_unit);
-   png_save_uint_32(buf + 4, y_pixels_per_unit);
-   buf[8] = (png_byte)unit_type;
-
-   png_write_complete_chunk(png_ptr, png_pHYs, buf, 9);
-}
-#endif
-
-#ifdef PNG_WRITE_tIME_SUPPORTED
-/* Write the tIME chunk.  Use either png_convert_from_struct_tm()
- * or png_convert_from_time_t(), or fill in the structure yourself.
- */
-void /* PRIVATE */
-png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
-{
-   png_byte buf[7];
-
-   png_debug(1, "in png_write_tIME");
-
-   if (mod_time->month  > 12 || mod_time->month  < 1 ||
-       mod_time->day    > 31 || mod_time->day    < 1 ||
-       mod_time->hour   > 23 || mod_time->second > 60)
-   {
-      png_warning(png_ptr, "Invalid time specified for tIME chunk");
-      return;
-   }
-
-   png_save_uint_16(buf, mod_time->year);
-   buf[2] = mod_time->month;
-   buf[3] = mod_time->day;
-   buf[4] = mod_time->hour;
-   buf[5] = mod_time->minute;
-   buf[6] = mod_time->second;
-
-   png_write_complete_chunk(png_ptr, png_tIME, buf, 7);
-}
-#endif
-
-/* Initializes the row writing capability of libpng */
-void /* PRIVATE */
-png_write_start_row(png_structrp png_ptr)
-{
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-
-   /* Start of interlace block */
-   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
-
-   /* Offset to next interlace block */
-   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-
-   /* Start of interlace block in the y direction */
-   static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
-
-   /* Offset to next interlace block in the y direction */
-   static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-#endif
-
-   png_alloc_size_t buf_size;
-   int usr_pixel_depth;
-
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-   png_byte filters;
-#endif
-
-   png_debug(1, "in png_write_start_row");
-
-   usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
-   buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1;
-
-   /* 1.5.6: added to allow checking in the row write code. */
-   png_ptr->transformed_pixel_depth = png_ptr->pixel_depth;
-   png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
-
-   /* Set up row buffer */
-   png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
-
-   png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
-
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-   filters = png_ptr->do_filter;
-
-   if (png_ptr->height == 1)
-      filters &= 0xff & ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH);
-
-   if (png_ptr->width == 1)
-      filters &= 0xff & ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH);
-
-   if (filters == 0)
-      filters = PNG_FILTER_NONE;
-
-   png_ptr->do_filter = filters;
-
-   if (((filters & (PNG_FILTER_SUB | PNG_FILTER_UP | PNG_FILTER_AVG |
-       PNG_FILTER_PAETH)) != 0) && png_ptr->try_row == NULL)
-   {
-      int num_filters = 0;
-
-      png_ptr->try_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size));
-
-      if (filters & PNG_FILTER_SUB)
-         num_filters++;
-
-      if (filters & PNG_FILTER_UP)
-         num_filters++;
-
-      if (filters & PNG_FILTER_AVG)
-         num_filters++;
-
-      if (filters & PNG_FILTER_PAETH)
-         num_filters++;
-
-      if (num_filters > 1)
-         png_ptr->tst_row = png_voidcast(png_bytep, png_malloc(png_ptr,
-             buf_size));
-   }
-
-   /* We only need to keep the previous row if we are using one of the following
-    * filters.
-    */
-   if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0)
-      png_ptr->prev_row = png_voidcast(png_bytep,
-          png_calloc(png_ptr, buf_size));
-#endif /* WRITE_FILTER */
-
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-   /* If interlaced, we need to set up width and height of pass */
-   if (png_ptr->interlaced != 0)
-   {
-      if ((png_ptr->transformations & PNG_INTERLACE) == 0)
-      {
-         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
-             png_pass_ystart[0]) / png_pass_yinc[0];
-
-         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
-             png_pass_start[0]) / png_pass_inc[0];
-      }
-
-      else
-      {
-         png_ptr->num_rows = png_ptr->height;
-         png_ptr->usr_width = png_ptr->width;
-      }
-   }
-
-   else
-#endif
-   {
-      png_ptr->num_rows = png_ptr->height;
-      png_ptr->usr_width = png_ptr->width;
-   }
-}
-
-/* Internal use only.  Called when finished processing a row of data. */
-void /* PRIVATE */
-png_write_finish_row(png_structrp png_ptr)
-{
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-
-   /* Start of interlace block */
-   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
-
-   /* Offset to next interlace block */
-   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-
-   /* Start of interlace block in the y direction */
-   static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
-
-   /* Offset to next interlace block in the y direction */
-   static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-#endif
-
-   png_debug(1, "in png_write_finish_row");
-
-   /* Next row */
-   png_ptr->row_number++;
-
-   /* See if we are done */
-   if (png_ptr->row_number < png_ptr->num_rows)
-      return;
-
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-   /* If interlaced, go to next pass */
-   if (png_ptr->interlaced != 0)
-   {
-      png_ptr->row_number = 0;
-      if ((png_ptr->transformations & PNG_INTERLACE) != 0)
-      {
-         png_ptr->pass++;
-      }
-
-      else
-      {
-         /* Loop until we find a non-zero width or height pass */
-         do
-         {
-            png_ptr->pass++;
-
-            if (png_ptr->pass >= 7)
-               break;
-
-            png_ptr->usr_width = (png_ptr->width +
-                png_pass_inc[png_ptr->pass] - 1 -
-                png_pass_start[png_ptr->pass]) /
-                png_pass_inc[png_ptr->pass];
-
-            png_ptr->num_rows = (png_ptr->height +
-                png_pass_yinc[png_ptr->pass] - 1 -
-                png_pass_ystart[png_ptr->pass]) /
-                png_pass_yinc[png_ptr->pass];
-
-            if ((png_ptr->transformations & PNG_INTERLACE) != 0)
-               break;
-
-         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
-
-      }
-
-      /* Reset the row above the image for the next pass */
-      if (png_ptr->pass < 7)
-      {
-         if (png_ptr->prev_row != NULL)
-            memset(png_ptr->prev_row, 0,
-                PNG_ROWBYTES(png_ptr->usr_channels *
-                png_ptr->usr_bit_depth, png_ptr->width) + 1);
-
-         return;
-      }
-   }
-#endif
-
-   /* If we get here, we've just written the last row, so we need
-      to flush the compressor */
-   png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH);
-}
-
-#ifdef PNG_WRITE_INTERLACING_SUPPORTED
-/* Pick out the correct pixels for the interlace pass.
- * The basic idea here is to go through the row with a source
- * pointer and a destination pointer (sp and dp), and copy the
- * correct pixels for the pass.  As the row gets compacted,
- * sp will always be >= dp, so we should never overwrite anything.
- * See the default: case for the easiest code to understand.
- */
-void /* PRIVATE */
-png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
-{
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-
-   /* Start of interlace block */
-   static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
-
-   /* Offset to next interlace block */
-   static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-
-   png_debug(1, "in png_do_write_interlace");
-
-   /* We don't have to do anything on the last pass (6) */
-   if (pass < 6)
-   {
-      /* Each pixel depth is handled separately */
-      switch (row_info->pixel_depth)
-      {
-         case 1:
-         {
-            png_bytep sp;
-            png_bytep dp;
-            unsigned int shift;
-            int d;
-            int value;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            dp = row;
-            d = 0;
-            shift = 7;
-
-            for (i = png_pass_start[pass]; i < row_width;
-               i += png_pass_inc[pass])
-            {
-               sp = row + (size_t)(i >> 3);
-               value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
-               d |= (value << shift);
-
-               if (shift == 0)
-               {
-                  shift = 7;
-                  *dp++ = (png_byte)d;
-                  d = 0;
-               }
-
-               else
-                  shift--;
-
-            }
-            if (shift != 7)
-               *dp = (png_byte)d;
-
-            break;
-         }
-
-         case 2:
-         {
-            png_bytep sp;
-            png_bytep dp;
-            unsigned int shift;
-            int d;
-            int value;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            dp = row;
-            shift = 6;
-            d = 0;
-
-            for (i = png_pass_start[pass]; i < row_width;
-               i += png_pass_inc[pass])
-            {
-               sp = row + (size_t)(i >> 2);
-               value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
-               d |= (value << shift);
-
-               if (shift == 0)
-               {
-                  shift = 6;
-                  *dp++ = (png_byte)d;
-                  d = 0;
-               }
-
-               else
-                  shift -= 2;
-            }
-            if (shift != 6)
-               *dp = (png_byte)d;
-
-            break;
-         }
-
-         case 4:
-         {
-            png_bytep sp;
-            png_bytep dp;
-            unsigned int shift;
-            int d;
-            int value;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-
-            dp = row;
-            shift = 4;
-            d = 0;
-            for (i = png_pass_start[pass]; i < row_width;
-                i += png_pass_inc[pass])
-            {
-               sp = row + (size_t)(i >> 1);
-               value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
-               d |= (value << shift);
-
-               if (shift == 0)
-               {
-                  shift = 4;
-                  *dp++ = (png_byte)d;
-                  d = 0;
-               }
-
-               else
-                  shift -= 4;
-            }
-            if (shift != 4)
-               *dp = (png_byte)d;
-
-            break;
-         }
-
-         default:
-         {
-            png_bytep sp;
-            png_bytep dp;
-            png_uint_32 i;
-            png_uint_32 row_width = row_info->width;
-            size_t pixel_bytes;
-
-            /* Start at the beginning */
-            dp = row;
-
-            /* Find out how many bytes each pixel takes up */
-            pixel_bytes = (row_info->pixel_depth >> 3);
-
-            /* Loop through the row, only looking at the pixels that matter */
-            for (i = png_pass_start[pass]; i < row_width;
-               i += png_pass_inc[pass])
-            {
-               /* Find out where the original pixel is */
-               sp = row + (size_t)i * pixel_bytes;
-
-               /* Move the pixel */
-               if (dp != sp)
-                  memcpy(dp, sp, pixel_bytes);
-
-               /* Next pixel */
-               dp += pixel_bytes;
-            }
-            break;
-         }
-      }
-      /* Set new row width */
-      row_info->width = (row_info->width +
-          png_pass_inc[pass] - 1 -
-          png_pass_start[pass]) /
-          png_pass_inc[pass];
-
-      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
-          row_info->width);
-   }
-}
-#endif
-
-
-/* This filters the row, chooses which filter to use, if it has not already
- * been specified by the application, and then writes the row out with the
- * chosen filter.
- */
-static void /* PRIVATE */
-png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
-    size_t row_bytes);
-
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-static size_t /* PRIVATE */
-png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp,
-    size_t row_bytes, size_t lmins)
-{
-   png_bytep rp, dp, lp;
-   size_t i;
-   size_t sum = 0;
-   unsigned int v;
-
-   png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
-
-   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
-        i++, rp++, dp++)
-   {
-      v = *dp = *rp;
-#ifdef PNG_USE_ABS
-      sum += 128 - abs((int)v - 128);
-#else
-      sum += (v < 128) ? v : 256 - v;
-#endif
-   }
-
-   for (lp = png_ptr->row_buf + 1; i < row_bytes;
-      i++, rp++, lp++, dp++)
-   {
-      v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
-#ifdef PNG_USE_ABS
-      sum += 128 - abs((int)v - 128);
-#else
-      sum += (v < 128) ? v : 256 - v;
-#endif
-
-      if (sum > lmins)  /* We are already worse, don't continue. */
-        break;
-   }
-
-   return (sum);
-}
-
-static void /* PRIVATE */
-png_setup_sub_row_only(png_structrp png_ptr, png_uint_32 bpp,
-    size_t row_bytes)
-{
-   png_bytep rp, dp, lp;
-   size_t i;
-
-   png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
-
-   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
-        i++, rp++, dp++)
-   {
-      *dp = *rp;
-   }
-
-   for (lp = png_ptr->row_buf + 1; i < row_bytes;
-      i++, rp++, lp++, dp++)
-   {
-      *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
-   }
-}
-
-static size_t /* PRIVATE */
-png_setup_up_row(png_structrp png_ptr, size_t row_bytes, size_t lmins)
-{
-   png_bytep rp, dp, pp;
-   size_t i;
-   size_t sum = 0;
-   unsigned int v;
-
-   png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
-
-   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
-       pp = png_ptr->prev_row + 1; i < row_bytes;
-       i++, rp++, pp++, dp++)
-   {
-      v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
-#ifdef PNG_USE_ABS
-      sum += 128 - abs((int)v - 128);
-#else
-      sum += (v < 128) ? v : 256 - v;
-#endif
-
-      if (sum > lmins)  /* We are already worse, don't continue. */
-        break;
-   }
-
-   return (sum);
-}
-static void /* PRIVATE */
-png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes)
-{
-   png_bytep rp, dp, pp;
-   size_t i;
-
-   png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
-
-   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
-       pp = png_ptr->prev_row + 1; i < row_bytes;
-       i++, rp++, pp++, dp++)
-   {
-      *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
-   }
-}
-
-static size_t /* PRIVATE */
-png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp,
-    size_t row_bytes, size_t lmins)
-{
-   png_bytep rp, dp, pp, lp;
-   png_uint_32 i;
-   size_t sum = 0;
-   unsigned int v;
-
-   png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
-
-   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
-       pp = png_ptr->prev_row + 1; i < bpp; i++)
-   {
-      v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
-
-#ifdef PNG_USE_ABS
-      sum += 128 - abs((int)v - 128);
-#else
-      sum += (v < 128) ? v : 256 - v;
-#endif
-   }
-
-   for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
-   {
-      v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
-          & 0xff);
-
-#ifdef PNG_USE_ABS
-      sum += 128 - abs((int)v - 128);
-#else
-      sum += (v < 128) ? v : 256 - v;
-#endif
-
-      if (sum > lmins)  /* We are already worse, don't continue. */
-        break;
-   }
-
-   return (sum);
-}
-static void /* PRIVATE */
-png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp,
-    size_t row_bytes)
-{
-   png_bytep rp, dp, pp, lp;
-   png_uint_32 i;
-
-   png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
-
-   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
-       pp = png_ptr->prev_row + 1; i < bpp; i++)
-   {
-      *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
-   }
-
-   for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
-   {
-      *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
-          & 0xff);
-   }
-}
-
-static size_t /* PRIVATE */
-png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp,
-    size_t row_bytes, size_t lmins)
-{
-   png_bytep rp, dp, pp, cp, lp;
-   size_t i;
-   size_t sum = 0;
-   unsigned int v;
-
-   png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
-
-   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
-       pp = png_ptr->prev_row + 1; i < bpp; i++)
-   {
-      v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
-
-#ifdef PNG_USE_ABS
-      sum += 128 - abs((int)v - 128);
-#else
-      sum += (v < 128) ? v : 256 - v;
-#endif
-   }
-
-   for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
-        i++)
-   {
-      int a, b, c, pa, pb, pc, p;
-
-      b = *pp++;
-      c = *cp++;
-      a = *lp++;
-
-      p = b - c;
-      pc = a - c;
-
-#ifdef PNG_USE_ABS
-      pa = abs(p);
-      pb = abs(pc);
-      pc = abs(p + pc);
-#else
-      pa = p < 0 ? -p : p;
-      pb = pc < 0 ? -pc : pc;
-      pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-#endif
-
-      p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
-
-      v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
-
-#ifdef PNG_USE_ABS
-      sum += 128 - abs((int)v - 128);
-#else
-      sum += (v < 128) ? v : 256 - v;
-#endif
-
-      if (sum > lmins)  /* We are already worse, don't continue. */
-        break;
-   }
-
-   return (sum);
-}
-static void /* PRIVATE */
-png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp,
-    size_t row_bytes)
-{
-   png_bytep rp, dp, pp, cp, lp;
-   size_t i;
-
-   png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
-
-   for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
-       pp = png_ptr->prev_row + 1; i < bpp; i++)
-   {
-      *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
-   }
-
-   for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
-        i++)
-   {
-      int a, b, c, pa, pb, pc, p;
-
-      b = *pp++;
-      c = *cp++;
-      a = *lp++;
-
-      p = b - c;
-      pc = a - c;
-
-#ifdef PNG_USE_ABS
-      pa = abs(p);
-      pb = abs(pc);
-      pc = abs(p + pc);
-#else
-      pa = p < 0 ? -p : p;
-      pb = pc < 0 ? -pc : pc;
-      pc = (p + pc) < 0 ? -(p + pc) : p + pc;
-#endif
-
-      p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
-
-      *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
-   }
-}
-#endif /* WRITE_FILTER */
-
-void /* PRIVATE */
-png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
-{
-#ifndef PNG_WRITE_FILTER_SUPPORTED
-   png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1);
-#else
-   unsigned int filter_to_do = png_ptr->do_filter;
-   png_bytep row_buf;
-   png_bytep best_row;
-   png_uint_32 bpp;
-   size_t mins;
-   size_t row_bytes = row_info->rowbytes;
-
-   png_debug(1, "in png_write_find_filter");
-
-   /* Find out how many bytes offset each pixel is */
-   bpp = (row_info->pixel_depth + 7) >> 3;
-
-   row_buf = png_ptr->row_buf;
-   mins = PNG_SIZE_MAX - 256/* so we can detect potential overflow of the
-                               running sum */;
-
-   /* The prediction method we use is to find which method provides the
-    * smallest value when summing the absolute values of the distances
-    * from zero, using anything >= 128 as negative numbers.  This is known
-    * as the "minimum sum of absolute differences" heuristic.  Other
-    * heuristics are the "weighted minimum sum of absolute differences"
-    * (experimental and can in theory improve compression), and the "zlib
-    * predictive" method (not implemented yet), which does test compressions
-    * of lines using different filter methods, and then chooses the
-    * (series of) filter(s) that give minimum compressed data size (VERY
-    * computationally expensive).
-    *
-    * GRR 980525:  consider also
-    *
-    *   (1) minimum sum of absolute differences from running average (i.e.,
-    *       keep running sum of non-absolute differences & count of bytes)
-    *       [track dispersion, too?  restart average if dispersion too large?]
-    *
-    *  (1b) minimum sum of absolute differences from sliding average, probably
-    *       with window size <= deflate window (usually 32K)
-    *
-    *   (2) minimum sum of squared differences from zero or running average
-    *       (i.e., ~ root-mean-square approach)
-    */
-
-
-   /* We don't need to test the 'no filter' case if this is the only filter
-    * that has been chosen, as it doesn't actually do anything to the data.
-    */
-   best_row = png_ptr->row_buf;
-
-   if (PNG_SIZE_MAX/128 <= row_bytes)
-   {
-      /* Overflow can occur in the calculation, just select the lowest set
-       * filter.
-       */
-      filter_to_do &= 0U-filter_to_do;
-   }
-   else if ((filter_to_do & PNG_FILTER_NONE) != 0 &&
-         filter_to_do != PNG_FILTER_NONE)
-   {
-      /* Overflow not possible and multiple filters in the list, including the
-       * 'none' filter.
-       */
-      png_bytep rp;
-      size_t sum = 0;
-      size_t i;
-      unsigned int v;
-
-      {
-         for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
-         {
-            v = *rp;
-#ifdef PNG_USE_ABS
-            sum += 128 - abs((int)v - 128);
-#else
-            sum += (v < 128) ? v : 256 - v;
-#endif
-         }
-      }
-
-      mins = sum;
-   }
-
-   /* Sub filter */
-   if (filter_to_do == PNG_FILTER_SUB)
-   /* It's the only filter so no testing is needed */
-   {
-      png_setup_sub_row_only(png_ptr, bpp, row_bytes);
-      best_row = png_ptr->try_row;
-   }
-
-   else if ((filter_to_do & PNG_FILTER_SUB) != 0)
-   {
-      size_t sum;
-      size_t lmins = mins;
-
-      sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins);
-
-      if (sum < mins)
-      {
-         mins = sum;
-         best_row = png_ptr->try_row;
-         if (png_ptr->tst_row != NULL)
-         {
-            png_ptr->try_row = png_ptr->tst_row;
-            png_ptr->tst_row = best_row;
-         }
-      }
-   }
-
-   /* Up filter */
-   if (filter_to_do == PNG_FILTER_UP)
-   {
-      png_setup_up_row_only(png_ptr, row_bytes);
-      best_row = png_ptr->try_row;
-   }
-
-   else if ((filter_to_do & PNG_FILTER_UP) != 0)
-   {
-      size_t sum;
-      size_t lmins = mins;
-
-      sum = png_setup_up_row(png_ptr, row_bytes, lmins);
-
-      if (sum < mins)
-      {
-         mins = sum;
-         best_row = png_ptr->try_row;
-         if (png_ptr->tst_row != NULL)
-         {
-            png_ptr->try_row = png_ptr->tst_row;
-            png_ptr->tst_row = best_row;
-         }
-      }
-   }
-
-   /* Avg filter */
-   if (filter_to_do == PNG_FILTER_AVG)
-   {
-      png_setup_avg_row_only(png_ptr, bpp, row_bytes);
-      best_row = png_ptr->try_row;
-   }
-
-   else if ((filter_to_do & PNG_FILTER_AVG) != 0)
-   {
-      size_t sum;
-      size_t lmins = mins;
-
-      sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins);
-
-      if (sum < mins)
-      {
-         mins = sum;
-         best_row = png_ptr->try_row;
-         if (png_ptr->tst_row != NULL)
-         {
-            png_ptr->try_row = png_ptr->tst_row;
-            png_ptr->tst_row = best_row;
-         }
-      }
-   }
-
-   /* Paeth filter */
-   if (filter_to_do == PNG_FILTER_PAETH)
-   {
-      png_setup_paeth_row_only(png_ptr, bpp, row_bytes);
-      best_row = png_ptr->try_row;
-   }
-
-   else if ((filter_to_do & PNG_FILTER_PAETH) != 0)
-   {
-      size_t sum;
-      size_t lmins = mins;
-
-      sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins);
-
-      if (sum < mins)
-      {
-         best_row = png_ptr->try_row;
-         if (png_ptr->tst_row != NULL)
-         {
-            png_ptr->try_row = png_ptr->tst_row;
-            png_ptr->tst_row = best_row;
-         }
-      }
-   }
-
-   /* Do the actual writing of the filtered row data from the chosen filter. */
-   png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
-
-#endif /* WRITE_FILTER */
-}
-
-
-/* Do the actual writing of a previously filtered row. */
-static void
-png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
-    size_t full_row_length/*includes filter byte*/)
-{
-   png_debug(1, "in png_write_filtered_row");
-
-   png_debug1(2, "filter = %d", filtered_row[0]);
-
-   png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
-
-#ifdef PNG_WRITE_FILTER_SUPPORTED
-   /* Swap the current and previous rows */
-   if (png_ptr->prev_row != NULL)
-   {
-      png_bytep tptr;
-
-      tptr = png_ptr->prev_row;
-      png_ptr->prev_row = png_ptr->row_buf;
-      png_ptr->row_buf = tptr;
-   }
-#endif /* WRITE_FILTER */
-
-   /* Finish row - updates counters and flushes zlib if last row */
-   png_write_finish_row(png_ptr);
-
-#ifdef PNG_WRITE_FLUSH_SUPPORTED
-   png_ptr->flush_rows++;
-
-   if (png_ptr->flush_dist > 0 &&
-       png_ptr->flush_rows >= png_ptr->flush_dist)
-   {
-      png_write_flush(png_ptr);
-   }
-#endif /* WRITE_FLUSH */
-}
-#endif /* WRITE */