[master] Imported from libpng-1.6.10.tar
diff --git a/ANNOUNCE b/ANNOUNCE
index ecc043d..9f19880 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,5 +1,5 @@
 
-Libpng 1.6.9 - February 6, 2014
+Libpng 1.6.10 - March 6, 2014
 
 This is a public release of libpng, intended for use in production codes.
 
@@ -8,56 +8,80 @@
 Source files with LF line endings (for Unix/Linux) and with a
 "configure" script
 
-   libpng-1.6.9.tar.xz (LZMA-compressed, recommended)
-   libpng-1.6.9.tar.gz
+   libpng-1.6.10.tar.xz (LZMA-compressed, recommended)
+   libpng-1.6.10.tar.gz
 
 Source files with CRLF line endings (for Windows), without the
 "configure" script
 
-   lpng169.7z  (LZMA-compressed, recommended)
-   lpng169.zip
+   lpng1610.7z  (LZMA-compressed, recommended)
+   lpng1610.zip
 
 Other information:
 
-   libpng-1.6.9-README.txt
-   libpng-1.6.9-LICENSE.txt
-   Gnupg/*.asc (PGP armored detached signatures)
+   libpng-1.6.10-README.txt
+   libpng-1.6.10-LICENSE.txt
+   libpng-1.6.10-*.asc (armored detached GPG signatures)
 
-Changes since the last public release (1.6.8):
-  Bookkeeping: Moved functions around (no changes). Moved transform
-    function definitions before the place where they are called so that
-    they can be masde static. Move the intrapixel functions and the
-    grayscale palette builder out of the png?tran.c files. The latter
-    isn't a transform function and is no longer used internally, and the
-    former MNG specific functions are better placed in pngread/pngwrite.c
-  Made transform implementation functions static. This makes the internal
-    functions called by png_do_{read|write}_transformations static. On an
-    x86-64 DLL build (Gentoo Linux) this reduces the size of the text
-    segment of the DLL by 1208 bytes, about 0.6%. It also simplifies
-    maintenance by removing the declarations from pngpriv.h and allowing
-    easier changes to the internal interfaces.
-  Rebuilt configure scripts with automake-1.14.1 and autoconf-2.69
-    in the tar distributions.
-  Added checks for libpng 1.5 to pngvalid.c.  This supports the use of
-    this version of pngvalid in libpng 1.5
-  Merged with pngvalid.c from libpng-1.7 changes to create a single
-    pngvalid.c
-  Removed #error macro from contrib/tools/pngfix.c (Thomas Klausner).
-  Merged pngrio.c, pngtrans.c, pngwio.c, and pngerror.c with libpng-1.7.0
-  Merged libpng-1.7.0 changes to make no-interlace configurations work
-    with test programs.
-  Revised pngvalid.c to support libpng 1.5, which does not support the
-    PNG_MAXIMUM_INFLATE_WINDOW option, so #define it out when appropriate in
-    pngvalid.c
-  Allow unversioned links created on install to be disabled in configure.
-    In configure builds 'make install' changes/adds links like png.h
-    and libpng.a to point to the newly installed, versioned, files (e.g.
-    libpng17/png.h and libpng17.a). Three new configure options and some
-    rearrangement of Makefile.am allow creation of these links to be disabled.
-  Removed potentially misleading warning from png_check_IHDR().
-  Updated scripts/makefile.* to use CPPFLAGS (Cosmin).
-  Added clang attribute support (Cosmin).
-  Quiet an uninitialized memory warning from VC2013 in png_get_png().
+Changes since the last public release (1.6.9):
+  Backported changes from libpng-1.7.0beta30 and beta31:
+  Fixed a large number of instances where PNGCBAPI was omitted from
+    function definitions.
+  Added pngimage test program for png_read_png() and png_write_png()
+    with two new test scripts.
+  Removed dependence on !PNG_READ_EXPAND_SUPPORTED for calling
+    png_set_packing() in png_read_png().
+  Fixed combination of ~alpha with shift. On read invert alpha, processing
+    occurred after shift processing, which causes the final values to be
+    outside the range that should be produced by the shift. Reversing the
+    order on read makes the two transforms work together correctly and mirrors
+    the order used on write.
+  Do not read invalid sBIT chunks. Previously libpng only checked sBIT
+    values on write, so a malicious PNG writer could therefore cause
+    the read code to return an invalid sBIT chunk, which might lead to
+    application errors or crashes.  Such chunks are now skipped (with
+    chunk_benign_error).
+  Make png_read_png() and png_write_png() prototypes in png.h depend
+    upon PNG_READ_SUPPORTED and PNG_WRITE_SUPPORTED.
+  Support builds with unsupported PNG_TRANSFORM_* values.  All of the
+    PNG_TRANSFORM_* values are always defined in png.h and, because they
+    are used for both read and write in some cases, it is not reliable
+    to #if out ones that are totally unsupported. This change adds error
+    detection in png_read_image() and png_write_image() to do a
+    png_app_error() if the app requests something that cannot be done
+    and it adds corresponding code to pngimage.c to handle such options
+    by not attempting to test them.
+  Moved redefines of png_error(), png_warning(), png_chunk_error(),
+    and png_chunk_warning() from pngpriv.h to png.h to make them visible
+    to libpng-calling applications.
+  Moved OS dependent code from arm/arm_init.c, to allow the included
+    implementation of the ARM NEON discovery function to be set at
+    build-time and provide sample implementations from the current code in the
+    contrib/arm-neon subdirectory. The __linux__ code has also been changed to
+    compile and link on Android by using /proc/cpuinfo, and the old linux code
+    is in contrib/arm-neon/linux-auxv.c.  The new code avoids POSIX and Linux
+    dependencies apart from opening /proc/cpuinfo and is C90 compliant.
+  Check for info_ptr == NULL early in png_read_end() so we don't need to
+    run all the png_handle_*() and depend on them to return if info_ptr == NULL.
+    This improves the performance of png_read_end(png_ptr, NULL) and makes
+    it more robust against future programming errors.
+  Check for __has_extension before using it in pngconf.h, to
+    support older Clang versions (Jeremy Sequoia).
+  Treat CRC error handling with png_set_crc_action(), instead of with
+    png_set_benign_errors(), which has been the case since libpng-1.6.0beta18.
+  Use a user warning handler in contrib/gregbook/readpng2.c instead of default,
+    so warnings will be put on stderr even if libpng has CONSOLE_IO disabled.
+  Added png_ptr->process_mode = PNG_READ_IDAT_MODE in png_push_read_chunk
+    after recognizing the IDAT chunk, which avoids an infinite loop while
+    reading a datastream whose first IDAT chunk is of zero-length.
+    This fixes CERT VU#684412 and CVE-2014-0333.
+  Don't recognize known sRGB profiles as sRGB if they have been hacked,
+    but don't reject them and don't issue a copyright violation warning.
+  Moved some documentation from png.h to libpng.3 and libpng-manual.txt
+  Minor editing of contrib/arm-neon/README and contrib/examples/*.c
+  Fixed typos in the manual and in scripts/pnglibconf.dfa (CFLAGS -> CPPFLAGS
+    and PNG_USR_CONFIG -> PNG_USER_CONFIG).
+  Un-deprecated png_data_freer().
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
@@ -66,3 +90,4 @@
 or to glennrp at users.sourceforge.net
 
 Glenn R-P
+#endif
diff --git a/CHANGES b/CHANGES
index 99c954d..b3e09f8 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4754,7 +4754,7 @@
 Version 1.6.9beta01 [December 26, 2013]
   Bookkeeping: Moved functions around (no changes). Moved transform
     function definitions before the place where they are called so that
-    they can be masde static. Move the intrapixel functions and the
+    they can be made static. Move the intrapixel functions and the
     grayscale palette builder out of the png?tran.c files. The latter
     isn't a transform function and is no longer used internally, and the
     former MNG specific functions are better placed in pngread/pngwrite.c
@@ -4800,6 +4800,80 @@
 
 Version 1.6.9 [February 6, 2014]
 
+Version 1.6.10beta01 [February 9, 2014]
+  Backported changes from libpng-1.7.0beta30 and beta31:
+  Fixed a large number of instances where PNGCBAPI was omitted from
+    function definitions.
+  Added pngimage test program for png_read_png() and png_write_png()
+    with two new test scripts.
+  Removed dependence on !PNG_READ_EXPAND_SUPPORTED for calling
+    png_set_packing() in png_read_png().
+  Fixed combination of ~alpha with shift. On read invert alpha, processing
+    occurred after shift processing, which causes the final values to be
+    outside the range that should be produced by the shift. Reversing the
+    order on read makes the two transforms work together correctly and mirrors
+    the order used on write.
+  Do not read invalid sBIT chunks. Previously libpng only checked sBIT
+    values on write, so a malicious PNG writer could therefore cause
+    the read code to return an invalid sBIT chunk, which might lead to
+    application errors or crashes.  Such chunks are now skipped (with
+    chunk_benign_error).
+  Make png_read_png() and png_write_png() prototypes in png.h depend
+    upon PNG_READ_SUPPORTED and PNG_WRITE_SUPPORTED.
+  Support builds with unsupported PNG_TRANSFORM_* values.  All of the
+    PNG_TRANSFORM_* values are always defined in png.h and, because they
+    are used for both read and write in some cases, it is not reliable
+    to #if out ones that are totally unsupported. This change adds error
+    detection in png_read_image() and png_write_image() to do a
+    png_app_error() if the app requests something that cannot be done
+    and it adds corresponding code to pngimage.c to handle such options
+    by not attempting to test them.
+
+Version 1.6.10beta02 [February 23, 2014]
+  Moved redefines of png_error(), png_warning(), png_chunk_error(),
+    and png_chunk_warning() from pngpriv.h to png.h to make them visible
+    to libpng-calling applications.
+  Moved OS dependent code from arm/arm_init.c, to allow the included
+    implementation of the ARM NEON discovery function to be set at
+    build-time and provide sample implementations from the current code in the
+    contrib/arm-neon subdirectory. The __linux__ code has also been changed to
+    compile and link on Android by using /proc/cpuinfo, and the old linux code
+    is in contrib/arm-neon/linux-auxv.c.  The new code avoids POSIX and Linux
+    dependencies apart from opening /proc/cpuinfo and is C90 compliant.
+  Check for info_ptr == NULL early in png_read_end() so we don't need to
+    run all the png_handle_*() and depend on them to return if info_ptr == NULL.
+    This improves the performance of png_read_end(png_ptr, NULL) and makes
+    it more robust against future programming errors.
+  Check for __has_extension before using it in pngconf.h, to
+    support older Clang versions (Jeremy Sequoia).
+  Treat CRC error handling with png_set_crc_action(), instead of with
+    png_set_benign_errors(), which has been the case since libpng-1.6.0beta18.
+  Use a user warning handler in contrib/gregbook/readpng2.c instead of default,
+    so warnings will be put on stderr even if libpng has CONSOLE_IO disabled.
+  Added png_ptr->process_mode = PNG_READ_IDAT_MODE in png_push_read_chunk
+    after recognizing the IDAT chunk, which avoids an infinite loop while
+    reading a datastream whose first IDAT chunk is of zero-length.
+    This fixes CERT VU#684412 and CVE-2014-0333.
+  Don't recognize known sRGB profiles as sRGB if they have been hacked,
+    but don't reject them and don't issue a copyright violation warning.
+
+Version 1.6.10beta03 [February 25, 2014]
+  Moved some documentation from png.h to libpng.3 and libpng-manual.txt
+  Minor editing of contrib/arm-neon/README and contrib/examples/*.c
+
+Version 1.6.10rc01 [February 27, 2014]
+  Fixed typos in the manual and in scripts/pnglibconf.dfa (CFLAGS -> CPPFLAGS
+    and PNG_USR_CONFIG -> PNG_USER_CONFIG).
+
+Version 1.6.10rc02 [February 28, 2014]
+  Removed unreachable return statement after png_chunk_error()
+    in pngrutil.c
+
+Version 1.6.10rc03 [March 4, 2014]
+  Un-deprecated png_data_freer().
+
+Version 1.6.10 [March 6, 2014]
+
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
 https://lists.sourceforge.net/lists/listinfo/png-mng-implement
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ce5ca69..34d62b5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,7 +16,7 @@
 
 set(PNGLIB_MAJOR 1)
 set(PNGLIB_MINOR 6)
-set(PNGLIB_RELEASE 9)
+set(PNGLIB_RELEASE 10)
 set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR})
 set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE})
 
@@ -252,7 +252,7 @@
 # SET UP LINKS
 if(PNG_SHARED)
   set_target_properties(${PNG_LIB_NAME} PROPERTIES
-#   VERSION 16.${PNGLIB_RELEASE}.1.6.9
+#   VERSION 16.${PNGLIB_RELEASE}.1.6.10
     VERSION 16.${PNGLIB_RELEASE}.0
     SOVERSION 16
     CLEAN_DIRECT_OUTPUT 1)
diff --git a/LICENSE b/LICENSE
index cfab9c6..94f5e95 100644
--- a/LICENSE
+++ b/LICENSE
@@ -10,7 +10,7 @@
 
 This code is released under the libpng license.
 
-libpng versions 1.2.6, August 15, 2004, through 1.6.9, February 6, 2014, are
+libpng versions 1.2.6, August 15, 2004, through 1.6.10, March 6, 2014, are
 Copyright (c) 2004, 2006-2014 Glenn Randers-Pehrson, and are
 distributed according to the same disclaimer and license as libpng-1.2.5
 with the following individual added to the list of Contributing Authors
@@ -108,4 +108,4 @@
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-February 6, 2014
+March 6, 2014
diff --git a/Makefile.am b/Makefile.am
index e69519d..052e596 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -7,7 +7,7 @@
 ACLOCAL_AMFLAGS = -I scripts
 
 # test programs - run on make check, make distcheck
-check_PROGRAMS= pngtest pngunknown pngstest pngvalid
+check_PROGRAMS= pngtest pngunknown pngstest pngvalid pngimage
 
 # Utilities - installed
 bin_PROGRAMS= pngfix png-fix-itxt
@@ -34,6 +34,9 @@
 pngunknown_SOURCES = contrib/libtests/pngunknown.c
 pngunknown_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
 
+pngimage_SOURCES = contrib/libtests/pngimage.c
+pngimage_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
+
 pngfix_SOURCES = contrib/tools/pngfix.c
 pngfix_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la
 
@@ -59,7 +62,8 @@
    tests/pngstest-4a16 tests/pngstest-6a08 tests/pngstest-6a16\
    tests/pngstest-error tests/pngunknown-IDAT\
    tests/pngunknown-discard tests/pngunknown-if-safe tests/pngunknown-sAPI\
-   tests/pngunknown-sTER tests/pngunknown-save tests/pngunknown-vpAg
+   tests/pngunknown-sTER tests/pngunknown-save tests/pngunknown-vpAg\
+   tests/pngimage-quick tests/pngimage-full
 
 # These tests are expected, and required, to fail:
 XFAIL_TESTS = tests/pngstest-error
@@ -212,6 +216,7 @@
 contrib/libtests/makepng.o: pnglibconf.h
 contrib/libtests/pngstest.o: pnglibconf.h
 contrib/libtests/pngunknown.o: pnglibconf.h
+contrib/libtests/pngimage.o: pnglibconf.h
 contrib/libtests/pngvalid.o: pnglibconf.h
 contrib/libtests/readpng.o: pnglibconf.h
 contrib/libtests/tarith.o: pnglibconf.h
diff --git a/README b/README
index 1aefa24..57f287b 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-README for libpng version 1.6.9 - February 6, 2014 (shared library 16.0)
+README for libpng version 1.6.10 - March 6, 2014 (shared library 16.0)
 See the note about version numbers near the top of png.h
 
 See INSTALL for instructions on how to install libpng.
diff --git a/TODO b/TODO
index 6e1f028..63613b8 100644
--- a/TODO
+++ b/TODO
@@ -10,6 +10,7 @@
 Improved dithering.
 Multi-lingual error and warning message support.
 Complete sRGB transformation (presently it simply uses gamma=0.45455).
+Make profile checking optional via a png_set_something() call.
 Man pages for function calls.
 Better documentation.
 Better filter selection
diff --git a/arm/arm_init.c b/arm/arm_init.c
index 271c612..952b802 100644
--- a/arm/arm_init.c
+++ b/arm/arm_init.c
@@ -1,9 +1,9 @@
 
 /* arm_init.c - NEON optimised filter functions
  *
- * Copyright (c) 2013 Glenn Randers-Pehrson
+ * Copyright (c) 2014 Glenn Randers-Pehrson
  * Written by Mans Rullgard, 2011.
- * Last changed in libpng 1.6.6 [September 16, 2013]
+ * Last changed in libpng 1.6.10 [March 6, 2014]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -19,132 +19,33 @@
 #ifdef PNG_READ_SUPPORTED
 #if PNG_ARM_NEON_OPT > 0
 #ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */
-#include <signal.h> /* for sig_atomic_t */
-
-#ifdef __ANDROID__
-/* Linux provides access to information about CPU capabilites via
- * /proc/self/auxv, however Android blocks this while still claiming to be
- * Linux.  The Andoid NDK, however, provides appropriate support.
+/* 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
+ * presense of the required support, therefore run-time detectioon is extremely
+ * OS specific.
  *
- * Documentation: http://www.kandroid.org/ndk/docs/CPU-ARM-NEON.html
+ * 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.
  */
-#include <cpu-features.h>
+#ifndef PNG_ARM_NEON_FILE
+#  ifdef __linux__
+#     define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
+#  endif
+#endif
 
-static int
-png_have_neon(png_structp png_ptr)
-{
-   /* This is a whole lot easier than the mess below, however it is probably
-    * implemented as below, therefore it is better to cache the result (these
-    * function calls may be slow!)
-    */
-   PNG_UNUSED(png_ptr)
-   return android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM &&
-      (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
-}
-#elif defined(__linux__)
-/* The generic __linux__ implementation requires reading /proc/self/auxv and
- * looking at each element for one that records NEON capabilities.
- */
-#include <unistd.h> /* for POSIX 1003.1 */
-#include <errno.h>  /* for EINTR */
+#ifdef PNG_ARM_NEON_FILE
 
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <elf.h>
-#include <asm/hwcap.h>
+#include <signal.h> /* for sig_atomic_t */
+static int png_have_neon(png_structp png_ptr);
+#include PNG_ARM_NEON_FILE
 
-/* A read call may be interrupted, in which case it returns -1 and sets errno to
- * EINTR if nothing was done, otherwise (if something was done) a partial read
- * may result.
- */
-static size_t
-safe_read(png_structp png_ptr, int fd, void *buffer_in, size_t nbytes)
-{
-   size_t ntotal = 0;
-   char *buffer = png_voidcast(char*, buffer_in);
-
-   while (nbytes > 0)
-   {
-      unsigned int nread;
-      int iread;
-
-      /* Passing nread > INT_MAX to read is implementation defined in POSIX
-       * 1003.1, therefore despite the unsigned argument portable code must
-       * limit the value to INT_MAX!
-       */
-      if (nbytes > INT_MAX)
-         nread = INT_MAX;
-
-      else
-         nread = (unsigned int)/*SAFE*/nbytes;
-
-      iread = read(fd, buffer, nread);
-
-      if (iread == -1)
-      {
-         /* This is the devil in the details, a read can terminate early with 0
-          * bytes read because of EINTR, yet it still returns -1 otherwise end
-          * of file cannot be distinguished.
-          */
-         if (errno != EINTR)
-         {
-            png_warning(png_ptr, "/proc read failed");
-            return 0; /* I.e., a permanent failure */
-         }
-      }
-
-      else if (iread < 0)
-      {
-         /* Not a valid 'read' result: */
-         png_warning(png_ptr, "OS /proc read bug");
-         return 0;
-      }
-
-      else if (iread > 0)
-      {
-         /* Continue reading until a permanent failure, or EOF */
-         buffer += iread;
-         nbytes -= (unsigned int)/*SAFE*/iread;
-         ntotal += (unsigned int)/*SAFE*/iread;
-      }
-
-      else
-         return ntotal;
-   }
-
-   return ntotal; /* nbytes == 0 */
-}
-
-static int
-png_have_neon(png_structp png_ptr)
-{
-   int fd = open("/proc/self/auxv", O_RDONLY);
-   Elf32_auxv_t aux;
-
-   /* Failsafe: failure to open means no NEON */
-   if (fd == -1)
-   {
-      png_warning(png_ptr, "/proc/self/auxv open failed");
-      return 0;
-   }
-
-   while (safe_read(png_ptr, fd, &aux, sizeof aux) == sizeof aux)
-   {
-      if (aux.a_type == AT_HWCAP && (aux.a_un.a_val & HWCAP_NEON) != 0)
-      {
-         close(fd);
-         return 1;
-      }
-   }
-
-   close(fd);
-   return 0;
-}
-#else
-   /* We don't know how to do a run-time check on this system */
-#  error "no support for run-time ARM NEON checks"
-#endif /* OS checks */
+#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
diff --git a/configure.ac b/configure.ac
index 8061aba..a1ec129 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,7 +18,7 @@
 
 dnl Version number stuff here:
 
-AC_INIT([libpng],[1.6.9],[png-mng-implement@lists.sourceforge.net])
+AC_INIT([libpng],[1.6.10],[png-mng-implement@lists.sourceforge.net])
 AC_CONFIG_MACRO_DIR([scripts])
 
 # libpng does not follow GNU file name conventions (hence 'foreign')
@@ -39,10 +39,10 @@
 dnl AM_PREREQ([1.11.2])
 dnl stop configure from automagically running automake
 
-PNGLIB_VERSION=1.6.9
+PNGLIB_VERSION=1.6.10
 PNGLIB_MAJOR=1
 PNGLIB_MINOR=6
-PNGLIB_RELEASE=9
+PNGLIB_RELEASE=10
 
 dnl End of version number stuff
 
diff --git a/contrib/arm-neon/README b/contrib/arm-neon/README
new file mode 100644
index 0000000..535c8d3
--- /dev/null
+++ b/contrib/arm-neon/README
@@ -0,0 +1,83 @@
+OPERATING SYSTEM SPECIFIC ARM NEON DETECTION
+--------------------------------------------
+
+Detection of the ability to exexcute ARM NEON on an ARM processor requires
+operating system support.  (The information is not available in user mode.)
+
+HOW TO USE THIS
+---------------
+
+This directory contains C code fragments that can be included in arm/arm_init.c
+by setting the macro PNG_ARM_NEON_FILE to the file name in "" or <> at build
+time.  This setting is not recorded in pnglibconf.h and can be changed simply by
+rebuilding arm/arm_init.o with the required macro definition.
+
+For any of this code to be used the ARM NEON code must be enabled and run time
+checks must be supported.  I.e.:
+
+#if PNG_ARM_NEON_OPT > 0
+#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
+
+This is done in a 'configure' build by passing configure the argument:
+
+   --enable-arm-neon=check
+
+Apart from the basic Linux implementation in contrib/arm-neon/linux.c this code
+is unsupported.  That means that it is not even compiled on a regular basis and
+may be broken in any given minor release.
+
+FILE FORMAT
+-----------
+
+Each file documents its testing status as of the last time it was tested (which
+may have been a long time ago):
+
+STATUS: one of:
+   SUPPORTED: This indicates that the file is included in the regularly
+         performed test builds and bugs are fixed when discovered.
+   COMPILED: This indicates that the code did compile at least once.  See the
+         more detailed description for the extent to which the result was
+         successful.
+   TESTED: This means the code was fully compiled into the libpng test programs
+         and these were run at least once.
+
+BUG REPORTS: an email address to which to send reports of problems
+
+The file is a fragment of C code. It should not define any 'extern' symbols;
+everything should be static.  It must define the function:
+
+static int png_have_neon(png_structp png_ptr);
+
+That function must return 1 if ARM NEON instructions are supported, 0 if not.
+It must not execute png_error unless it detects a bug.  A png_error will prevent
+the reading of the PNG and in the future, writing too.
+
+BUG REPORTS
+-----------
+
+If you mail a bug report for any file that is not SUPPORTED there may only be
+limited response.  Consider fixing it and sending a patch to fix the problem -
+this is more likely to result in action.
+
+CONTRIBUTIONS
+-------------
+
+You may send contributions of new implementations to
+png-mng-implement@sourceforge.net.  Please write code in strict C90 C where
+possible.  Obviously OS dependencies are to be expected.  If you submit code you
+must have the authors permission and it must have a license that is acceptable
+to the current maintainer; in particular that license must permit modification
+and redistribution.
+
+Please try to make the contribution a single file and give the file a clear and
+unambiguous name that identifies the target OS.  If multiple files really are
+required put them all in a sub-directory.
+
+You must also be prepared to handle bug reports from users of the code, either
+by joining the png-mng-implement mailing list or by providing an email for the
+"BUG REPORTS" entry or both.  Please make sure that the header of the file
+contains the STATUS and BUG REPORTS fields as above.
+
+Please list the OS requirements as precisely as possible.  Ideally you should
+also list the environment in which the code has been tested and certainly list
+any environments where you suspect it might not work.
diff --git a/contrib/arm-neon/android-ndk.c b/contrib/arm-neon/android-ndk.c
new file mode 100644
index 0000000..7240123
--- /dev/null
+++ b/contrib/arm-neon/android-ndk.c
@@ -0,0 +1,39 @@
+/* contrib/arm-neon/android-ndk.c
+ *
+ * Copyright (c) 2014 Glenn Randers-Pehrson
+ * Written by John Bowler, 2014.
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * SEE contrib/arm-neon/README before reporting bugs
+ *
+ * STATUS: COMPILED, UNTESTED
+ * BUG REPORTS: png-mng-implement@sourceforge.net
+ *
+ * png_have_neon implemented for the Android NDK, see:
+ *
+ * Documentation:
+ *    http://www.kandroid.org/ndk/docs/CPU-ARM-NEON.html
+ *    http://code.google.com/p/android/issues/detail?id=49065
+ *
+ * NOTE: this requires that libpng is built against the Android NDK and linked
+ * with an implementation of the Android ARM 'cpu-features' library.  The code
+ * has been compiled only, not linked: no version of the library has been found,
+ * only the header files exist in the NDK.
+ */
+#include <cpu-features.h>
+
+static int
+png_have_neon(png_structp png_ptr)
+{
+   /* This is a whole lot easier than the linux code, however it is probably
+    * implemented as below, therefore it is better to cache the result (these
+    * function calls may be slow!)
+    */
+   PNG_UNUSED(png_ptr)
+   return android_getCpuFamily() == ANDROID_CPU_FAMILY_ARM &&
+      (android_getCpuFeatures() & ANDROID_CPU_ARM_FEATURE_NEON) != 0;
+}
diff --git a/contrib/arm-neon/linux-auxv.c b/contrib/arm-neon/linux-auxv.c
new file mode 100644
index 0000000..696e297
--- /dev/null
+++ b/contrib/arm-neon/linux-auxv.c
@@ -0,0 +1,120 @@
+/* contrib/arm-neon/linux-auxv.c
+ *
+ * Copyright (c) 2014 Glenn Randers-Pehrson
+ * Written by Mans Rullgard, 2011.
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ * 
+ * SEE contrib/arm-neon/README before reporting bugs
+ *
+ * STATUS: COMPILED, TESTED
+ * BUG REPORTS: png-mng-implement@sourceforge.net
+ *
+ * png_have_neon implemented for Linux versions which allow access to
+ * /proc/self/auxv.  This is probably faster, cleaner and safer than the code to
+ * read /proc/cpuinfo in contrib/arm-neon/linux, however it is yet another piece
+ * of potentially untested code and has more complex dependencies than the code
+ * to read cpuinfo.
+ *
+ * This generic __linux__ implementation requires reading /proc/self/auxv and
+ * looking at each element for one that records NEON capabilities.
+ */
+#include <unistd.h> /* for POSIX 1003.1 */
+#include <errno.h>  /* for EINTR */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <elf.h>
+#include <asm/hwcap.h>
+
+/* A read call may be interrupted, in which case it returns -1 and sets errno to
+ * EINTR if nothing was done, otherwise (if something was done) a partial read
+ * may result.
+ */
+static size_t
+safe_read(png_structp png_ptr, int fd, void *buffer_in, size_t nbytes)
+{
+   size_t ntotal = 0;
+   char *buffer = png_voidcast(char*, buffer_in);
+
+   while (nbytes > 0)
+   {
+      unsigned int nread;
+      int iread;
+
+      /* Passing nread > INT_MAX to read is implementation defined in POSIX
+       * 1003.1, therefore despite the unsigned argument portable code must
+       * limit the value to INT_MAX!
+       */
+      if (nbytes > INT_MAX)
+         nread = INT_MAX;
+
+      else
+         nread = (unsigned int)/*SAFE*/nbytes;
+
+      iread = read(fd, buffer, nread);
+
+      if (iread == -1)
+      {
+         /* This is the devil in the details, a read can terminate early with 0
+          * bytes read because of EINTR, yet it still returns -1 otherwise end
+          * of file cannot be distinguished.
+          */
+         if (errno != EINTR)
+         {
+            png_warning(png_ptr, "/proc read failed");
+            return 0; /* I.e., a permanent failure */
+         }
+      }
+
+      else if (iread < 0)
+      {
+         /* Not a valid 'read' result: */
+         png_warning(png_ptr, "OS /proc read bug");
+         return 0;
+      }
+
+      else if (iread > 0)
+      {
+         /* Continue reading until a permanent failure, or EOF */
+         buffer += iread;
+         nbytes -= (unsigned int)/*SAFE*/iread;
+         ntotal += (unsigned int)/*SAFE*/iread;
+      }
+
+      else
+         return ntotal;
+   }
+
+   return ntotal; /* nbytes == 0 */
+}
+
+static int
+png_have_neon(png_structp png_ptr)
+{
+   int fd = open("/proc/self/auxv", O_RDONLY);
+   Elf32_auxv_t aux;
+
+   /* Failsafe: failure to open means no NEON */
+   if (fd == -1)
+   {
+      png_warning(png_ptr, "/proc/self/auxv open failed");
+      return 0;
+   }
+
+   while (safe_read(png_ptr, fd, &aux, sizeof aux) == sizeof aux)
+   {
+      if (aux.a_type == AT_HWCAP && (aux.a_un.a_val & HWCAP_NEON) != 0)
+      {
+         close(fd);
+         return 1;
+      }
+   }
+
+   close(fd);
+   return 0;
+}
diff --git a/contrib/arm-neon/linux.c b/contrib/arm-neon/linux.c
new file mode 100644
index 0000000..182f376
--- /dev/null
+++ b/contrib/arm-neon/linux.c
@@ -0,0 +1,159 @@
+/* contrib/arm-neon/linux.c
+ *
+ * Copyright (c) 2014 Glenn Randers-Pehrson
+ * Written by John Bowler, 2014.
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * SEE contrib/arm-neon/README before reporting bugs
+ *
+ * STATUS: SUPPORTED
+ * BUG REPORTS: png-mng-implement@sourceforge.net
+ *
+ * png_have_neon implemented for Linux by reading the widely available
+ * pseudo-file /proc/cpuinfo.
+ *
+ * This code is strict ANSI-C and is probably moderately portable, it does
+ * however use <stdio.h> and assumes that /proc/cpuinfo is never localized.
+ */
+#include <stdio.h>
+
+static int
+png_have_neon(png_structp png_ptr)
+{
+   FILE *f = fopen("/proc/cpuinfo", "rb");
+
+   if (f != NULL)
+   {
+      /* This is a simple state machine which reads the input byte-by-byte until
+       * it gets a match on the 'neon' feature or reaches the end of the stream.
+       */
+      static const char ch_feature[] = { 70, 69, 65, 84, 85, 82, 69, 83 };
+      static const char ch_neon[] = { 78, 69, 79, 78 };
+
+      enum
+      {
+         StartLine, Feature, Colon, StartTag, Neon, HaveNeon, SkipTag, SkipLine
+      }  state;
+      int counter;
+
+      for (state=StartLine, counter=0;;)
+      {
+         int ch = fgetc(f);
+
+         if (ch == EOF)
+         {
+            /* EOF means error or end-of-file, return false; neon at EOF is
+             * assumed to be a mistake.
+             */
+            fclose(f);
+            return 0;
+         }
+
+         switch (state)
+         {
+            case StartLine:
+               /* Match spaces at the start of line */
+               if (ch <= 32) /* skip control characters and space */
+                  break;
+
+               counter=0;
+               state = Feature;
+               /* FALL THROUGH */
+
+            case Feature:
+               /* Match 'FEATURE', ASCII case insensitive. */
+               if ((ch & ~0x20) == ch_feature[counter])
+               {
+                  if (++counter == (sizeof ch_feature))
+                     state = Colon;
+                  break;
+               }
+               
+               /* did not match 'feature' */
+               state = SkipLine;
+               /* FALL THROUGH */
+
+            case SkipLine:
+            skipLine:
+               /* Skip everything until we see linefeed or carriage return */
+               if (ch != 10 && ch != 13)
+                  break;
+
+               state = StartLine;
+               break;
+
+            case Colon:
+               /* Match any number of space or tab followed by ':' */
+               if (ch == 32 || ch == 9)
+                  break;
+
+               if (ch == 58) /* i.e. ':' */
+               {
+                  state = StartTag;
+                  break;
+               }
+
+               /* Either a bad line format or a 'feature' prefix followed by
+                * other characters.
+                */
+               state = SkipLine;
+               goto skipLine;
+
+            case StartTag:
+               /* Skip space characters before a tag */
+               if (ch == 32 || ch == 9)
+                  break;
+
+               state = Neon;
+               counter = 0;
+               /* FALL THROUGH */
+
+            case Neon:
+               /* Look for 'neon' tag */
+               if ((ch & ~0x20) == ch_neon[counter])
+               {
+                  if (++counter == (sizeof ch_neon))
+                     state = HaveNeon;
+                  break;
+               }
+
+               state = SkipTag;
+               /* FALL THROUGH */
+
+            case SkipTag:
+               /* Skip non-space characters */
+               if (ch == 10 || ch == 13)
+                  state = StartLine;
+
+               else if (ch == 32 || ch == 9)
+                  state = StartTag;
+               break;
+
+            case HaveNeon:
+               /* Have seen a 'neon' prefix, but there must be a space or new
+                * line character to terminate it.
+                */
+               if (ch == 10 || ch == 13 || ch == 32 || ch == 9)
+               {
+                  fclose(f);
+                  return 1;
+               }
+
+               state = SkipTag;
+               break;
+
+            default:
+               png_error(png_ptr, "png_have_neon: internal error (bug)");
+         }
+      }
+   }
+
+   else
+      png_warning(png_ptr, "/proc/cpuinfo open failed");
+
+   return 0;
+}
diff --git a/contrib/examples/iccfrompng.c b/contrib/examples/iccfrompng.c
index 6767621..386e522 100644
--- a/contrib/examples/iccfrompng.c
+++ b/contrib/examples/iccfrompng.c
@@ -6,9 +6,9 @@
  * United States.
  *
  * Extract any icc profiles found in the given PNG files.  This is a simple
- * example of a program which extracts information from the header of a PNG file
+ * example of a program that extracts information from the header of a PNG file
  * without processing the image.  Notice that some header information may occur
- * after the image data, textual data and comments are an example; the approach
+ * after the image data. Textual data and comments are an example; the approach
  * in this file won't work reliably for such data because it only looks for the
  * information in the section of the file that preceeds the image data.
  *
diff --git a/contrib/examples/pngpixel.c b/contrib/examples/pngpixel.c
index 4104760..e0d43e3 100644
--- a/contrib/examples/pngpixel.c
+++ b/contrib/examples/pngpixel.c
@@ -8,7 +8,7 @@
  * Read a single pixel value from a PNG file.
  *
  * This code illustrates basic 'by-row' reading of a PNG file using libpng.
- * Rows are read until a particular pixel is found, the value of this pixel is
+ * Rows are read until a particular pixel is found; the value of this pixel is
  * then printed on stdout.
  *
  * The code illustrates how to do this on interlaced as well as non-interlaced
@@ -56,7 +56,7 @@
       case 8: return row[0];
       case 16: return (row[0] << 8) + row[1];
       default:
-         /* This should never happen, it indicates a bug in this program or in
+         /* This should never happen; it indicates a bug in this program or in
           * libpng itself:
           */
          fprintf(stderr, "pngpixel: invalid bit depth %u\n", bit_depth);
@@ -132,7 +132,7 @@
          return;
 
       default:
-         png_error(png_ptr, "invalid color type");
+         png_error(png_ptr, "pngpixel: invalid color type");
    }
 }
 
diff --git a/contrib/gregbook/readpng2.c b/contrib/gregbook/readpng2.c
index e179db7..e6a132e 100644
--- a/contrib/gregbook/readpng2.c
+++ b/contrib/gregbook/readpng2.c
@@ -69,6 +69,7 @@
                                  png_uint_32 row_num, int pass);
 static void readpng2_end_callback(png_structp png_ptr, png_infop info_ptr);
 static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg);
+static void readpng2_warning_handler(png_structp png_ptr, png_const_charp msg);
 
 
 
@@ -104,7 +105,7 @@
     /* could also replace libpng warning-handler (final NULL), but no need: */
 
     png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, mainprog_ptr,
-      readpng2_error_handler, NULL);
+      readpng2_error_handler, readpng2_warning_handler);
     if (!png_ptr)
         return 4;   /* out of memory */
 
@@ -467,7 +468,11 @@
 }
 
 
-
+static void readpng2_warning_handler(png_structp png_ptr, png_const_charp msg)
+{
+    fprintf(stderr, "readpng2 libpng warning: %s\n", msg);
+    fflush(stderr);
+}
 
 
 static void readpng2_error_handler(png_structp png_ptr, png_const_charp msg)
diff --git a/contrib/libtests/pngimage.c b/contrib/libtests/pngimage.c
new file mode 100644
index 0000000..372845e
--- /dev/null
+++ b/contrib/libtests/pngimage.c
@@ -0,0 +1,1618 @@
+/* pngimage.c
+ *
+ * Copyright (c) 2014 John Cunningham Bowler
+ *
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * Test the png_read_png and png_write_png interfaces.  Given a PNG file load it
+ * using png_read_png and then write with png_write_png.  Test all possible
+ * transforms.
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+
+#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
+#  include <config.h>
+#endif
+
+/* Define the following to use this test against your installed libpng, rather
+ * than the one being built here:
+ */
+#ifdef PNG_FREESTANDING_TESTS
+#  include <png.h>
+#else
+#  include "../../png.h"
+#endif
+
+#ifndef PNG_SETJMP_SUPPORTED
+#  include <setjmp.h> /* because png.h did *not* include this */
+#endif
+
+#if defined(PNG_INFO_IMAGE_SUPPORTED) && defined(PNG_SEQUENTIAL_READ_SUPPORTED)
+/* If a transform is valid on both read and write this implies that if the
+ * transform is applied to read it must also be applied on write to produce
+ * meaningful data.  This is because these transforms when performed on read
+ * produce data with a memory format that does not correspond to a PNG format.
+ *
+ * Most of these transforms are invertible; after applying the transform on
+ * write the result is the original PNG data that would have would have been
+ * read if no transform were applied.
+ *
+ * The exception is _SHIFT, which destroys the low order bits marked as not
+ * significant in a PNG with the sBIT chunk.
+ *
+ * The following table lists, for each transform, the conditions under which it
+ * is expected to do anything.  Conditions are defined as follows:
+ *
+ * 1) Color mask bits required - simply a mask to AND with color_type; one of
+ *    these must be present for the transform to fire, except that 0 means
+ *    'always'.
+ * 2) Color mask bits which must be absent - another mask - none of these must
+ *    be present.
+ * 3) Bit depths - a mask of component bit depths for the transform to fire.
+ * 4) 'read' - the transform works in png_read_png.
+ * 5) 'write' - the transform works in png_write_png.
+ * 6) PNG_INFO_chunk; a mask of the chunks that must be present for the
+ *    transform to fire.  All must be present - the requirement is that
+ *    png_get_valid() & mask == mask, so if mask is 0 there is no requirement.
+ *
+ * The condition refers to the original image state - if multiple transforms are
+ * used together it is possible to cause a transform that wouldn't fire on the
+ * original image to fire.
+ */
+static struct transform_info
+{
+   const char *name;
+   int         transform;
+   png_uint_32 valid_chunks;
+#     define CHUNK_NONE 0
+#     define CHUNK_sBIT PNG_INFO_sBIT
+#     define CHUNK_tRNS PNG_INFO_tRNS
+   png_byte    color_mask_required;
+   png_byte    color_mask_absent;
+#     define COLOR_MASK_X   0
+#     define COLOR_MASK_P   PNG_COLOR_MASK_PALETTE
+#     define COLOR_MASK_C   PNG_COLOR_MASK_COLOR
+#     define COLOR_MASK_A   PNG_COLOR_MASK_ALPHA
+#     define COLOR_MASK_ALL (PALETTE+COLOR+ALPHA)  /* absent = gray, no alpha */
+   png_byte    bit_depths;
+#     define BD_ALL  (1 + 2 + 4 + 8 + 16)
+#     define BD_PAL  (1 + 2 + 4 + 8)
+#     define BD_LOW  (1 + 2 + 4)
+#     define BD_16   16
+#     define BD_TRUE (8+16) /* i.e. true-color depths */
+   png_byte    when;
+#     define TRANSFORM_R  1
+#     define TRANSFORM_W  2
+#     define TRANSFORM_RW 3
+   png_byte    tested; /* the transform was tested somewhere */
+} transform_info[] =
+{
+   /* List ALL the PNG_TRANSFORM_ macros here.  Check for support using the READ
+    * macros; even if the transform is supported on write it cannot be tested
+    * without the read support.
+    */
+#  define T(name,chunk,cm_required,cm_absent,bd,when)\
+   {  #name, PNG_TRANSFORM_ ## name, CHUNK_ ## chunk,\
+      COLOR_MASK_ ## cm_required, COLOR_MASK_ ## cm_absent, BD_ ## bd,\
+      TRANSFORM_ ## when, 0/*!tested*/ }
+
+#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
+   T(STRIP_16,            NONE, X,   X,   16,  R),
+      /* drops the bottom 8 bits when bit depth is 16 */
+#endif
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+   T(STRIP_ALPHA,         NONE, A,   X,  ALL,  R),
+      /* removes the alpha channel if present */
+#endif
+#ifdef PNG_WRITE_PACK_SUPPORTED
+#  define TRANSFORM_RW_PACK TRANSFORM_RW
+#else
+#  define TRANSFORM_RW_PACK TRANSFORM_R
+#endif
+#ifdef PNG_READ_PACK_SUPPORTED
+   T(PACKING,             NONE, X,   X,  LOW, RW_PACK),
+      /* unpacks low-bit-depth components into 1 byte per component on read,
+       * reverses this on write.
+       */
+#endif
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
+#  define TRANSFORM_RW_PACKSWAP TRANSFORM_RW
+#else
+#  define TRANSFORM_RW_PACKSWAP TRANSFORM_R
+#endif
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+   T(PACKSWAP,            NONE, X,   X,  LOW, RW_PACKSWAP),
+      /* reverses the order of low-bit-depth components packed into a byte */
+#endif
+#ifdef PNG_READ_EXPAND_SUPPORTED
+   T(EXPAND,              NONE, P,   X,  ALL,  R),
+      /* expands PLTE PNG files to RGB (no tRNS) or RGBA (tRNS) *
+       * Note that the 'EXPAND' transform does lots of different things: */
+   T(EXPAND,              NONE, X,   C,  ALL,  R),
+      /* expands grayscale PNG files to RGB, or RGBA */
+   T(EXPAND,              tRNS, X,   A,  ALL,  R),
+      /* expands the tRNS chunk in files without alpha */
+#endif
+#ifdef PNG_WRITE_INVERT_SUPPORTED
+#  define TRANSFORM_RW_INVERT TRANSFORM_RW
+#else
+#  define TRANSFORM_RW_INVERT TRANSFORM_R
+#endif
+#ifdef PNG_READ_INVERT_SUPPORTED
+   T(INVERT_MONO,         NONE, X,   C,  ALL, RW_INVERT),
+      /* converts gray-scale components to 1..0 from 0..1 */
+#endif
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+#  define TRANSFORM_RW_SHIFT TRANSFORM_RW
+#else
+#  define TRANSFORM_RW_SHIFT TRANSFORM_R
+#endif
+#ifdef PNG_READ_SHIFT_SUPPORTED
+   T(SHIFT,               sBIT, X,   X,  ALL, RW_SHIFT),
+      /* reduces component values to the original range based on the sBIT chunk,
+       * this is only partially reversible - the low bits are lost and cannot be
+       * recovered on write.  In fact write code replicates the bits to generate
+       * new low-order bits.
+       */
+#endif
+#ifdef PNG_WRITE_BGR_SUPPORTED
+#  define TRANSFORM_RW_BGR TRANSFORM_RW
+#else
+#  define TRANSFORM_RW_BGR TRANSFORM_R
+#endif
+#ifdef PNG_READ_BGR_SUPPORTED
+   T(BGR,                 NONE, C,   P, TRUE, RW_BGR),
+      /* reverses the rgb component values of true-color pixels */
+#endif
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
+#  define TRANSFORM_RW_SWAP_ALPHA TRANSFORM_RW
+#else
+#  define TRANSFORM_RW_SWAP_ALPHA TRANSFORM_R
+#endif
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
+   T(SWAP_ALPHA,          NONE, A,   X, TRUE, RW_SWAP_ALPHA),
+      /* swaps the alpha channel of RGBA or GA pixels to the front - ARGB or
+       * AG, on write reverses the process.
+       */
+#endif
+#ifdef PNG_WRITE_SWAP_SUPPORTED
+#  define TRANSFORM_RW_SWAP TRANSFORM_RW
+#else
+#  define TRANSFORM_RW_SWAP TRANSFORM_R
+#endif
+#ifdef PNG_READ_SWAP_SUPPORTED
+   T(SWAP_ENDIAN,         NONE, X,   P,   16, RW_SWAP),
+      /* byte-swaps 16-bit component values */
+#endif
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+#  define TRANSFORM_RW_INVERT_ALPHA TRANSFORM_RW
+#else
+#  define TRANSFORM_RW_INVERT_ALPHA TRANSFORM_R
+#endif
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+   T(INVERT_ALPHA,        NONE, A,   X, TRUE, RW_INVERT_ALPHA),
+      /* converts an alpha channel from 0..1 to 1..0 */
+#endif
+#ifdef PNG_WRITE_FILLER_SUPPORTED
+   T(STRIP_FILLER_BEFORE, NONE, A,   P, TRUE,  W), /* 'A' for a filler! */
+      /* on write skips a leading filler channel; testing requires data with a
+       * filler channel so this is produced from RGBA or GA images by removing
+       * the 'alpha' flag from the color type in place.
+       */
+   T(STRIP_FILLER_AFTER,  NONE, A,   P, TRUE,  W),
+      /* on write strips a trailing filler channel */
+#endif
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+   T(GRAY_TO_RGB,         NONE, X,   C,  ALL,  R),
+      /* expands grayscale images to RGB, also causes the palette part of
+       * 'EXPAND' to happen.  Low bit depth grayscale images are expanded to
+       * 8-bits per component and no attempt is made to convert the image to a
+       * palette image.  While this transform is partially reversible
+       * png_write_png does not currently support this.
+       */
+   T(GRAY_TO_RGB,         NONE, P,   X,  ALL,  R),
+      /* The 'palette' side effect mentioned above; a bit bogus but this is the
+       * way the libpng code works.
+       */
+#endif
+#ifdef PNG_READ_EXPAND_16_SUPPORTED
+   T(EXPAND_16,           NONE, X,   X,  PAL,  R),
+      /* expands images to 16-bits per component, as a side effect expands
+       * palette images to RGB and expands the tRNS chunk if present, so it can
+       * modify 16-bit per component images as well:
+       */
+   T(EXPAND_16,           tRNS, X,   A,   16,  R),
+      /* side effect of EXPAND_16 - expands the tRNS chunk in an RGB or G 16-bit
+       * image.
+       */
+#endif
+#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
+   T(SCALE_16,            NONE, X,   X,   16,  R)
+      /* scales 16-bit components to 8-bits. */
+#endif
+
+#undef T
+};
+
+#define ARRAY_SIZE(a) ((sizeof a)/(sizeof a[0]))
+#define TTABLE_SIZE ARRAY_SIZE(transform_info)
+
+/* Some combinations of options that should be reversible are not; these cases
+ * are bugs.
+ */
+static int known_bad_combos[][2] =
+{
+   /* problem, antidote */
+   { PNG_TRANSFORM_SHIFT | PNG_TRANSFORM_INVERT_ALPHA, 0/*antidote*/ }
+};
+
+static int
+is_combo(int transforms)
+{
+   return transforms & (transforms-1); /* non-zero if more than one set bit */
+}
+
+static int
+first_transform(int transforms)
+{
+   return transforms & -transforms; /* lowest set bit */
+}
+
+static int
+is_bad_combo(int transforms)
+{
+   unsigned int i;
+
+   for (i=0; i<ARRAY_SIZE(known_bad_combos); ++i)
+   {
+      int combo = known_bad_combos[i][0];
+
+      if ((combo & transforms) == combo &&
+         (transforms & known_bad_combos[i][1]) == 0)
+         return 1;
+   }
+
+   return 0; /* combo is ok */
+}
+
+static const char *
+transform_name(int t)
+   /* The name, if 't' has multiple bits set the name of the lowest set bit is
+    * returned.
+    */
+{
+   unsigned int i;
+
+   t &= -t; /* first set bit */
+
+   for (i=0; i<TTABLE_SIZE; ++i)
+   {
+      if ((transform_info[i].transform & t) != 0)
+         return transform_info[i].name;
+   }
+
+   return "invalid transform";
+}
+
+/* Variables calculated by validate_T below and used to record all the supported
+ * transforms.  Need (unsigned int) here because of the places where these
+ * values are used (unsigned compares in the 'exhaustive' iterator.)
+ */
+static unsigned int read_transforms, write_transforms, rw_transforms;
+
+static void
+validate_T(void)
+   /* Validate the above table - this just builds the above values */
+{
+   unsigned int i;
+
+   for (i=0; i<TTABLE_SIZE; ++i)
+   {
+      if (transform_info[i].when & TRANSFORM_R)
+         read_transforms |= transform_info[i].transform;
+
+      if (transform_info[i].when & TRANSFORM_W)
+         write_transforms |= transform_info[i].transform;
+   }
+
+   /* Reversible transforms are those which are supported on both read and
+    * write.
+    */
+   rw_transforms = read_transforms & write_transforms;
+}
+
+/* FILE DATA HANDLING
+ *    The original file is cached in memory.  During write the output file is
+ *    written to memory.
+ *
+ *    In both cases the file data is held in a linked list of buffers - not all
+ *    of these are in use at any time.
+ */
+struct buffer_list
+{
+   struct buffer_list *next;         /* next buffer in list */
+   png_byte            buffer[1024]; /* the actual buffer */
+};
+
+struct buffer
+{
+   struct buffer_list  *last;       /* last buffer in use */
+   size_t               end_count;  /* bytes in the last buffer */
+   struct buffer_list  *current;    /* current buffer being read */
+   size_t               read_count; /* count of bytes read from current */
+   struct buffer_list   first;      /* the very first buffer */
+};
+
+static void
+buffer_init(struct buffer *buffer)
+   /* Call this only once for a given buffer */
+{
+   buffer->first.next = NULL;
+   buffer->last = NULL;
+   buffer->current = NULL;
+}
+
+#ifdef PNG_WRITE_SUPPORTED
+static void
+buffer_start_write(struct buffer *buffer)
+{
+   buffer->last = &buffer->first;
+   buffer->end_count = 0;
+   buffer->current = NULL;
+}
+#endif
+
+static void
+buffer_start_read(struct buffer *buffer)
+{
+   buffer->current = &buffer->first;
+   buffer->read_count = 0;
+}
+
+#ifdef ENOMEM /* required by POSIX 1003.1 */
+#  define MEMORY ENOMEM
+#else
+#  define MEMORY ERANGE /* required by ANSI-C */
+#endif
+static struct buffer *
+get_buffer(png_structp pp)
+   /* Used from libpng callbacks to get the current buffer */
+{
+   return (struct buffer*)png_get_io_ptr(pp);
+}
+
+#define NEW(type) ((type *)malloc(sizeof (type)))
+
+static struct buffer_list *
+buffer_extend(struct buffer_list *current)
+{
+   struct buffer_list *add;
+
+   assert(current->next == NULL);
+
+   add = NEW(struct buffer_list);
+   if (add == NULL)
+      return NULL;
+
+   add->next = NULL;
+   current->next = add;
+
+   return add;
+}
+
+/* Load a buffer from a file; does the equivalent of buffer_start_write.  On a
+ * read error returns an errno value, else returns 0.
+ */
+static int
+buffer_from_file(struct buffer *buffer, FILE *fp)
+{
+   struct buffer_list *last = &buffer->first;
+   size_t count = 0;
+
+   for (;;)
+   {
+      size_t r = fread(last->buffer+count, 1/*size*/,
+         (sizeof last->buffer)-count, fp);
+
+      if (r > 0)
+      {
+         count += r;
+
+         if (count >= sizeof last->buffer)
+         {
+            assert(count == sizeof last->buffer);
+            count = 0;
+
+            if (last->next == NULL)
+            {
+               last = buffer_extend(last);
+               if (last == NULL)
+                  return MEMORY;
+            }
+
+            else
+               last = last->next;
+         }
+      }
+
+      else /* fread failed - probably end of file */
+      {
+         if (feof(fp))
+         {
+            buffer->last = last;
+            buffer->end_count = count;
+            return 0; /* no error */
+         }
+
+         /* Some kind of funky error; errno should be non-zero */
+         return errno == 0 ? ERANGE : errno;
+      }
+   }
+}
+
+/* This structure is used to control the test of a single file. */
+typedef enum
+{
+   VERBOSE,        /* switches on all messages */
+   INFORMATION,
+   WARNINGS,       /* switches on warnings */
+   LIBPNG_WARNING,
+   APP_WARNING,
+   ERRORS,         /* just errors */
+   APP_FAIL,       /* continuable error - no need to longjmp */
+   LIBPNG_ERROR,   /* this and higher cause a longjmp */
+   LIBPNG_BUG,     /* erroneous behavior in libpng */
+   APP_ERROR,      /* such as out-of-memory in a callback */
+   QUIET,          /* no normal messages */
+   USER_ERROR,     /* such as file-not-found */
+   INTERNAL_ERROR
+} error_level;
+#define LEVEL_MASK      0xf   /* where the level is in 'options' */
+
+#define EXHAUSTIVE      0x010 /* Test all combinations of active options */
+#define STRICT          0x020 /* Fail on warnings as well as errors */
+#define LOG             0x040 /* Log pass/fail to stdout */
+#define CONTINUE        0x080 /* Continue on APP_FAIL errors */
+#define SKIP_BUGS       0x100 /* Skip over known bugs */
+#define LOG_SKIPPED     0x200 /* Log skipped bugs */
+#define FIND_BAD_COMBOS 0x400 /* Attempt to deduce bad combos */
+
+/* Result masks apply to the result bits in the 'results' field below; these
+ * bits are simple 1U<<error_level.  A pass requires either nothing worse than
+ * warnings (--relaxes) or nothing worse than information (--strict)
+ */
+#define RESULT_STRICT(r)   (((r) & ~((1U<<WARNINGS)-1)) == 0)
+#define RESULT_RELAXED(r)  (((r) & ~((1U<<ERRORS)-1)) == 0)
+
+struct display
+{
+   jmp_buf        error_return;      /* Where to go to on error */
+
+   const char    *filename;          /* The name of the original file */
+   const char    *operation;         /* Operation being performed */
+   int            transforms;        /* Transform used in operation */
+   png_uint_32    options;           /* See display_log below */
+   png_uint_32    results;           /* A mask of errors seen */
+
+
+   png_structp    original_pp;       /* used on the original read */
+   png_infop      original_ip;       /* set by the original read */
+
+   png_size_t     original_rowbytes; /* of the original rows: */
+   png_bytepp     original_rows;     /* from the original read */
+
+   /* Original chunks valid */
+   png_uint_32    chunks;
+
+   /* Original IHDR information */
+   png_uint_32    width;
+   png_uint_32    height;
+   int            bit_depth;
+   int            color_type;
+   int            interlace_method;
+   int            compression_method;
+   int            filter_method;
+
+   /* Derived information for the original image. */
+   int            active_transforms;  /* transforms that do something on read */
+   int            ignored_transforms; /* transforms that should do nothing */
+
+   /* Used on a read, both the original read and when validating a written
+    * image.
+    */
+   png_structp    read_pp;
+   png_infop      read_ip;
+
+#  ifdef PNG_WRITE_SUPPORTED
+      /* Used to write a new image (the original info_ptr is used) */
+      png_structp   write_pp;
+      struct buffer written_file;   /* where the file gets written */
+#  endif
+
+   struct buffer  original_file;     /* Data read from the original file */
+};
+
+static void
+display_init(struct display *dp)
+   /* Call this only once right at the start to initialize the control
+    * structure, the (struct buffer) lists are maintained across calls - the
+    * memory is not freed.
+    */
+{
+   memset(dp, 0, sizeof *dp);
+   dp->options = WARNINGS; /* default to !verbose, !quiet */
+   dp->filename = NULL;
+   dp->operation = NULL;
+   dp->original_pp = NULL;
+   dp->original_ip = NULL;
+   dp->original_rows = NULL;
+   dp->read_pp = NULL;
+   dp->read_ip = NULL;
+   buffer_init(&dp->original_file);
+
+#  ifdef PNG_WRITE_SUPPORTED
+      dp->write_pp = NULL;
+      buffer_init(&dp->written_file);
+#  endif
+}
+
+static void
+display_clean_read(struct display *dp)
+{
+   if (dp->read_pp != NULL)
+      png_destroy_read_struct(&dp->read_pp, &dp->read_ip, NULL);
+}
+
+#ifdef PNG_WRITE_SUPPORTED
+static void
+display_clean_write(struct display *dp)
+{
+      if (dp->write_pp != NULL)
+         png_destroy_write_struct(&dp->write_pp, NULL);
+}
+#endif
+
+static void
+display_clean(struct display *dp)
+{
+#  ifdef PNG_WRITE_SUPPORTED
+      display_clean_write(dp);
+#  endif
+   display_clean_read(dp);
+
+   dp->original_rowbytes = 0;
+   dp->original_rows = NULL;
+   dp->chunks = 0;
+
+   png_destroy_read_struct(&dp->original_pp, &dp->original_ip, NULL);
+   /* leave the filename for error detection */
+   dp->results = 0; /* reset for next time */
+}
+
+static struct display *
+get_dp(png_structp pp)
+   /* The display pointer is always stored in the png_struct error pointer */
+{
+   struct display *dp = (struct display*)png_get_error_ptr(pp);
+
+   if (dp == NULL)
+   {
+      fprintf(stderr, "pngimage: internal error (no display)\n");
+      exit(99); /* prevents a crash */
+   }
+
+   return dp;
+}
+
+/* error handling */
+#ifdef __GNUC__
+#  define VGATTR __attribute__((__format__ (__printf__,3,4)))
+   /* Required to quiet GNUC warnings when the compiler sees a stdarg function
+    * that calls one of the stdio v APIs.
+    */
+#else
+#  define VGATTR
+#endif
+static void VGATTR
+display_log(struct display *dp, error_level level, const char *fmt, ...)
+   /* 'level' is as above, fmt is a stdio style format string.  This routine
+    * does not return if level is above LIBPNG_WARNING
+    */
+{
+   dp->results |= 1U << level;
+
+   if (level > (error_level)(dp->options & LEVEL_MASK))
+   {
+      const char *lp;
+      va_list ap;
+
+      switch (level)
+      {
+         case INFORMATION:    lp = "information"; break;
+         case LIBPNG_WARNING: lp = "warning(libpng)"; break;
+         case APP_WARNING:    lp = "warning(pngimage)"; break;
+         case APP_FAIL:       lp = "error(continuable)"; break;
+         case LIBPNG_ERROR:   lp = "error(libpng)"; break;
+         case LIBPNG_BUG:     lp = "bug(libpng)"; break;
+         case APP_ERROR:      lp = "error(pngimage)"; break;
+         case USER_ERROR:     lp = "error(user)"; break;
+
+         case INTERNAL_ERROR: /* anything unexpected is an internal error: */
+         case VERBOSE: case WARNINGS: case ERRORS: case QUIET:
+         default:             lp = "bug(pngimage)"; break;
+      }
+
+      fprintf(stderr, "%s: %s: %s",
+         dp->filename != NULL ? dp->filename : "<stdin>", lp, dp->operation);
+
+      if (dp->transforms != 0)
+      {
+         int tr = dp->transforms;
+
+         if (is_combo(tr))
+            fprintf(stderr, "(0x%x)", tr);
+
+         else
+            fprintf(stderr, "(%s)", transform_name(tr));
+      }
+
+      fprintf(stderr, ": ");
+
+      va_start(ap, fmt);
+      vfprintf(stderr, fmt, ap);
+      va_end(ap);
+
+      fputc('\n', stderr);
+   }
+   /* else do not output any message */
+
+   /* Errors cause this routine to exit to the fail code */
+   if (level > APP_FAIL || (level > ERRORS && !(dp->options & CONTINUE)))
+      longjmp(dp->error_return, level);
+}
+
+/* error handler callbacks for libpng */
+static void PNGCBAPI
+display_warning(png_structp pp, png_const_charp warning)
+{
+   display_log(get_dp(pp), LIBPNG_WARNING, "%s", warning);
+}
+
+static void PNGCBAPI
+display_error(png_structp pp, png_const_charp error)
+{
+   struct display *dp = get_dp(pp);
+
+   display_log(dp, LIBPNG_ERROR, "%s", error);
+}
+
+static void
+display_cache_file(struct display *dp, const char *filename)
+   /* Does the initial cache of the file. */
+{
+   FILE *fp;
+   int ret;
+
+   dp->filename = filename;
+
+   if (filename != NULL)
+   {
+      fp = fopen(filename, "rb");
+      if (fp == NULL)
+         display_log(dp, USER_ERROR, "open failed: %s", strerror(errno));
+   }
+
+   else
+      fp = stdin;
+
+   ret = buffer_from_file(&dp->original_file, fp);
+
+   fclose(fp);
+
+   if (ret != 0)
+      display_log(dp, APP_ERROR, "read failed: %s", strerror(ret));
+}
+
+static void
+buffer_read(struct display *dp, struct buffer *bp, png_bytep data,
+   png_size_t size)
+{
+   struct buffer_list *last = bp->current;
+   size_t read_count = bp->read_count;
+
+   while (size > 0)
+   {
+      size_t avail;
+
+      if (last == NULL ||
+         (last == bp->last && read_count >= bp->end_count))
+      {
+         display_log(dp, USER_ERROR, "file truncated (%lu bytes)",
+            (unsigned long)size);
+         /*NOTREACHED*/
+         break;
+      }
+
+      else if (read_count >= sizeof last->buffer)
+      {
+         /* Move to the next buffer: */
+         last = last->next;
+         read_count = 0;
+         bp->current = last; /* Avoid update outside the loop */
+
+         /* And do a sanity check (the EOF case is caught above) */
+         if (last == NULL)
+         {
+            display_log(dp, INTERNAL_ERROR, "damaged buffer list");
+            /*NOTREACHED*/
+            break;
+         }
+      }
+
+      avail = (sizeof last->buffer) - read_count;
+      if (avail > size)
+         avail = size;
+
+      memcpy(data, last->buffer + read_count, avail);
+      read_count += avail;
+      size -= avail;
+      data += avail;
+   }
+
+   bp->read_count = read_count;
+}
+
+static void PNGCBAPI
+read_function(png_structp pp, png_bytep data, png_size_t size)
+{
+   buffer_read(get_dp(pp), get_buffer(pp), data, size);
+}
+
+static void
+read_png(struct display *dp, struct buffer *bp, const char *operation,
+   int transforms)
+{
+   png_structp pp;
+   png_infop   ip;
+
+   /* This cleans out any previous read and sets operation and transforms to
+    * empty.
+    */
+   display_clean_read(dp);
+
+   if (operation != NULL) /* else this is a verify and do not overwrite info */
+   {
+      dp->operation = operation;
+      dp->transforms = transforms;
+   }
+
+   dp->read_pp = pp = png_create_read_struct(PNG_LIBPNG_VER_STRING, dp,
+      display_error, display_warning);
+   if (pp == NULL)
+      display_log(dp, LIBPNG_ERROR, "failed to create read struct");
+
+   /* The png_read_png API requires us to make the info struct, but it does the
+    * call to png_read_info.
+    */
+   dp->read_ip = ip = png_create_info_struct(pp);
+   if (ip == NULL)
+      display_log(dp, LIBPNG_ERROR, "failed to create info struct");
+
+#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
+      /* Remove the user limits, if any */
+      png_set_user_limits(pp, 0x7fffffff, 0x7fffffff);
+#  endif
+
+   /* Set the IO handling */
+   buffer_start_read(bp);
+   png_set_read_fn(pp, bp, read_function);
+
+   png_read_png(pp, ip, transforms, NULL/*params*/);
+
+#if 0 /* crazy debugging */
+   {
+      png_bytep pr = png_get_rows(pp, ip)[0];
+      size_t rb = png_get_rowbytes(pp, ip);
+      size_t cb;
+      char c = ' ';
+
+      fprintf(stderr, "%.4x %2d (%3lu bytes):", transforms, png_get_bit_depth(pp,ip), (unsigned long)rb);
+
+      for (cb=0; cb<rb; ++cb)
+         fputc(c, stderr), fprintf(stderr, "%.2x", pr[cb]), c='.';
+
+      fputc('\n', stderr);
+   }
+#endif
+}
+
+static void
+update_display(struct display *dp)
+   /* called once after the first read to update all the info, original_pp and
+    * original_ip must have been filled in.
+    */
+{
+   png_structp pp;
+   png_infop   ip;
+
+   /* Now perform the initial read with a 0 tranform. */
+   read_png(dp, &dp->original_file, "original read", 0/*no transform*/);
+
+   /* Move the result to the 'original' fields */
+   dp->original_pp = pp = dp->read_pp, dp->read_pp = NULL;
+   dp->original_ip = ip = dp->read_ip, dp->read_ip = NULL;
+
+   dp->original_rowbytes = png_get_rowbytes(pp, ip);
+   if (dp->original_rowbytes == 0)
+      display_log(dp, LIBPNG_BUG, "png_get_rowbytes returned 0");
+
+   dp->chunks = png_get_valid(pp, ip, 0xffffffff);
+   if ((dp->chunks & PNG_INFO_IDAT) == 0) /* set by png_read_png */
+      display_log(dp, LIBPNG_BUG, "png_read_png did not set IDAT flag");
+
+   dp->original_rows = png_get_rows(pp, ip);
+   if (dp->original_rows == NULL)
+      display_log(dp, LIBPNG_BUG, "png_read_png did not create row buffers");
+
+   if (!png_get_IHDR(pp, ip,
+      &dp->width, &dp->height, &dp->bit_depth, &dp->color_type,
+      &dp->interlace_method, &dp->compression_method, &dp->filter_method))
+      display_log(dp, LIBPNG_BUG, "png_get_IHDR failed");
+
+   /* 'active' transforms are discovered based on the original image format;
+    * running one active transform can activate others.  At present the code
+    * does not attempt to determine the closure.
+    */
+   {
+      png_uint_32 chunks = dp->chunks;
+      int active = 0, inactive = 0;
+      int ct = dp->color_type;
+      int bd = dp->bit_depth;
+      unsigned int i;
+
+      for (i=0; i<TTABLE_SIZE; ++i)
+      {
+         int transform = transform_info[i].transform;
+
+         if ((transform_info[i].valid_chunks == 0 ||
+               (transform_info[i].valid_chunks & chunks) != 0) &&
+            (transform_info[i].color_mask_required & ct) == 
+               transform_info[i].color_mask_required &&
+            (transform_info[i].color_mask_absent & ct) == 0 &&
+            (transform_info[i].bit_depths & bd) != 0 &&
+            (transform_info[i].when & TRANSFORM_R) != 0)
+            active |= transform;
+
+         else if ((transform_info[i].when & TRANSFORM_R) != 0)
+            inactive |= transform;
+      }
+
+      /* Some transforms appear multiple times in the table; the 'active' status
+       * is the logical OR of these and the inactive status must be adjusted to
+       * take this into account.
+       */
+      inactive &= ~active;
+
+      dp->active_transforms = active;
+      dp->ignored_transforms = inactive; /* excluding write-only transforms */
+
+      if (active == 0)
+         display_log(dp, INTERNAL_ERROR, "bad transform table");
+   }
+}
+
+static int
+compare_read(struct display *dp, int applied_transforms)
+{
+   /* Compare the png_info from read_ip with original_info */
+   size_t rowbytes;
+   png_uint_32 width, height;
+   int bit_depth, color_type;
+   int interlace_method, compression_method, filter_method;
+   const char *e = NULL;
+
+   png_get_IHDR(dp->read_pp, dp->read_ip, &width, &height, &bit_depth,
+      &color_type, &interlace_method, &compression_method, &filter_method);
+
+#  define C(item) if (item != dp->item) \
+      display_log(dp, APP_WARNING, "IHDR " #item "(%lu) changed to %lu",\
+         (unsigned long)dp->item, (unsigned long)item), e = #item
+
+   /* The IHDR should be identical: */
+   C(width);
+   C(height);
+   C(bit_depth);
+   C(color_type);
+   C(interlace_method);
+   C(compression_method);
+   C(filter_method);
+
+   /* 'e' remains set to the name of the last thing changed: */
+   if (e)
+      display_log(dp, APP_ERROR, "IHDR changed (%s)", e);
+
+   /* All the chunks from the original PNG should be preserved in the output PNG
+    * because the PNG format has not been changed.
+    */
+   {
+      unsigned long chunks =
+         png_get_valid(dp->read_pp, dp->read_ip, 0xffffffff);
+      
+      if (chunks != dp->chunks)
+         display_log(dp, APP_FAIL, "PNG chunks changed from 0x%lx to 0x%lx",
+            (unsigned long)dp->chunks, chunks);
+   }
+
+   /* rowbytes should be the same */
+   rowbytes = png_get_rowbytes(dp->read_pp, dp->read_ip);
+
+   /* NOTE: on 64-bit systems this may trash the top bits of rowbytes,
+    * which could lead to weird error messages.
+    */
+   if (rowbytes != dp->original_rowbytes)
+      display_log(dp, APP_ERROR, "PNG rowbytes changed from %lu to %lu",
+         (unsigned long)dp->original_rowbytes, (unsigned long)rowbytes);
+
+   /* The rows should be the same too, unless the applied transforms includes
+    * the shift transform, in which case low bits may have been lost.
+    */
+   {
+      png_bytepp rows = png_get_rows(dp->read_pp, dp->read_ip);
+      unsigned int mask;  /* mask (if not zero) for the final byte */
+
+      if (bit_depth < 8)
+      {
+         /* Need the stray bits at the end, this depends only on the low bits
+          * of the image width; overflow does not matter.  If the width is an
+          * exact multiple of 8 bits this gives a mask of 0, not 0xff.
+          */
+         mask = 0xff & (0xff00 >> ((bit_depth * width) & 7));
+      }
+
+      else
+         mask = 0;
+
+      if (rows == NULL)
+         display_log(dp, LIBPNG_BUG, "png_get_rows returned NULL");
+
+      if ((applied_transforms & PNG_TRANSFORM_SHIFT) == 0 ||
+         (dp->active_transforms & PNG_TRANSFORM_SHIFT) == 0 ||
+         color_type == PNG_COLOR_TYPE_PALETTE)
+      {
+         unsigned long y;
+
+         for (y=0; y<height; ++y)
+         {
+            png_bytep row = rows[y];
+            png_bytep orig = dp->original_rows[y];
+
+            if (memcmp(row, orig, rowbytes-(mask != 0)) != 0 || (mask != 0 &&
+               ((row[rowbytes-1] & mask) != (orig[rowbytes-1] & mask))))
+            {
+               size_t x;
+
+               /* Find the first error */
+               for (x=0; x<rowbytes-1; ++x) if (row[x] != orig[x])
+                  break;
+
+               display_log(dp, APP_FAIL,
+                  "byte(%lu,%lu) changed 0x%.2x -> 0x%.2x",
+                  (unsigned long)x, (unsigned long)y, orig[x], row[x]);
+               return 0; /* don't keep reporting failed rows on 'continue' */
+            }
+         }
+      }
+
+      else
+      {
+         unsigned long y;
+         int bpp;   /* bits-per-pixel then bytes-per-pixel */
+         /* components are up to 8 bytes in size */
+         png_byte sig_bits[8];
+         png_color_8p sBIT;
+
+         if (png_get_sBIT(dp->read_pp, dp->read_ip, &sBIT) != PNG_INFO_sBIT)
+            display_log(dp, INTERNAL_ERROR,
+               "active shift transform but no sBIT in file");
+
+         switch (color_type)
+         {
+            case PNG_COLOR_TYPE_GRAY:
+               sig_bits[0] = sBIT->gray;
+               bpp = bit_depth;
+               break;
+
+            case PNG_COLOR_TYPE_GA:
+               sig_bits[0] = sBIT->gray;
+               sig_bits[1] = sBIT->alpha;
+               bpp = 2 * bit_depth;
+               break;
+
+            case PNG_COLOR_TYPE_RGB:
+               sig_bits[0] = sBIT->red;
+               sig_bits[1] = sBIT->green;
+               sig_bits[2] = sBIT->blue;
+               bpp = 3 * bit_depth;
+               break;
+
+            case PNG_COLOR_TYPE_RGBA:
+               sig_bits[0] = sBIT->red;
+               sig_bits[1] = sBIT->green;
+               sig_bits[2] = sBIT->blue;
+               sig_bits[3] = sBIT->alpha;
+               bpp = 4 * bit_depth;
+               break;
+
+            default:
+               display_log(dp, LIBPNG_ERROR, "invalid colour type %d",
+                  color_type);
+               /*NOTREACHED*/
+               bpp = 0;
+               break;
+         }
+
+         {
+            int b;
+
+            for (b=0; 8*b<bpp; ++b)
+            {
+               /* libpng should catch this; if not there is a security issue
+                * because an app (like this one) may overflow an array. In fact
+                * libpng doesn't catch this at present.
+                */
+               if (sig_bits[b] == 0 || sig_bits[b] > bit_depth/*!palette*/)
+                  display_log(dp, LIBPNG_BUG,
+                     "invalid sBIT[%u]  value %d returned for PNG bit depth %d",
+                     b, sig_bits[b], bit_depth);
+            }
+         }
+
+         if (bpp < 8 && bpp != bit_depth)
+         {
+            /* sanity check; this is a grayscale PNG; something is wrong in the
+             * code above.
+             */
+            display_log(dp, INTERNAL_ERROR, "invalid bpp %u for bit_depth %u",
+               bpp, bit_depth);
+         }
+
+         switch (bit_depth)
+         {
+            int b;
+
+            case 16: /* Two bytes per component, bit-endian */
+               for (b = (bpp >> 4); b > 0; )
+               {
+                  unsigned int sig = (unsigned int)(0xffff0000 >> sig_bits[b]);
+
+                  sig_bits[2*b+1] = (png_byte)sig;
+                  sig_bits[2*b+0] = (png_byte)(sig >> 8); /* big-endian */
+               }
+               break;
+
+            case 8: /* One byte per component */
+               for (b=0; b*8 < bpp; ++b)
+                  sig_bits[b] = (png_byte)(0xff00 >> sig_bits[b]);
+               break;
+
+            case 1: /* allowed, but dumb */
+               /* Value is 1 */
+               sig_bits[0] = 0xff;
+               break;
+
+            case 2: /* Replicate 4 times */
+               /* Value is 1 or 2 */
+               b = 0x3 & ((0x3<<2) >> sig_bits[0]);
+               b |= b << 2;
+               b |= b << 4;
+               sig_bits[0] = (png_byte)b;
+               break;
+
+            case 4: /* Relicate twice */
+               /* Value is 1, 2, 3 or 4 */
+               b = 0xf & ((0xf << 4) >> sig_bits[0]);
+               b |= b << 4;
+               sig_bits[0] = (png_byte)b;
+               break;
+
+            default:
+               display_log(dp, LIBPNG_BUG, "invalid bit depth %d", bit_depth);
+               break;
+         }
+
+         /* Convert bpp to bytes; this gives '1' for low-bit depth grayscale,
+          * where there are multiple pixels per byte.
+          */
+         bpp = (bpp+7) >> 3;
+
+         /* The mask can be combined with sig_bits[0] */
+         if (mask != 0)
+         {
+            mask &= sig_bits[0];
+
+            if (bpp != 1 || mask == 0)
+               display_log(dp, INTERNAL_ERROR, "mask calculation error %u, %u",
+                  bpp, mask);
+         }
+
+         for (y=0; y<height; ++y)
+         {
+            png_bytep row = rows[y];
+            png_bytep orig = dp->original_rows[y];
+            unsigned long x;
+
+            for (x=0; x<(width-(mask!=0)); ++x)
+            {
+               int b;
+
+               for (b=0; b<bpp; ++b)
+               {
+                  if ((*row++ & sig_bits[b]) != (*orig++ & sig_bits[b]))
+                  {
+                     display_log(dp, APP_FAIL,
+                        "significant bits at (%lu[%u],%lu) changed %.2x->%.2x",
+                        x, b, y, orig[-1], row[-1]);
+                     return 0;
+                  }
+               }
+            }
+
+            if (mask != 0 && (*row & mask) != (*orig & mask))
+            {
+               display_log(dp, APP_FAIL,
+                  "significant bits at (%lu[end],%lu) changed", x, y);
+               return 0;
+            }
+         } /* for y */
+      }
+   }
+
+   return 1; /* compare succeeded */
+}
+
+#ifdef PNG_WRITE_SUPPORTED
+static void
+buffer_write(struct display *dp, struct buffer *buffer, png_bytep data,
+   png_size_t size)
+   /* Generic write function used both from the write callback provided to
+    * libpng and from the generic read code.
+    */
+{
+   /* Write the data into the buffer, adding buffers as required */
+   struct buffer_list *last = buffer->last;
+   size_t end_count = buffer->end_count;
+
+   while (size > 0)
+   {
+      size_t avail;
+
+      if (end_count >= sizeof last->buffer)
+      {
+         if (last->next == NULL)
+         {
+            last = buffer_extend(last);
+
+            if (last == NULL)
+               display_log(dp, APP_ERROR, "out of memory saving file");
+         }
+
+         else
+            last = last->next;
+
+         buffer->last = last; /* avoid the need to rewrite every time */
+         end_count = 0;
+      }
+
+      avail = (sizeof last->buffer) - end_count;
+      if (avail > size)
+         avail = size;
+
+      memcpy(last->buffer + end_count, data, avail);
+      end_count += avail;
+      size -= avail;
+      data += avail;
+   }
+
+   buffer->end_count = end_count;
+}
+
+static void PNGCBAPI
+write_function(png_structp pp, png_bytep data, png_size_t size)
+{
+   buffer_write(get_dp(pp), get_buffer(pp), data, size);
+}
+
+static void
+write_png(struct display *dp, png_infop ip, int transforms)
+{
+   display_clean_write(dp); /* safety */
+
+   buffer_start_write(&dp->written_file);
+   dp->operation = "write";
+   dp->transforms = transforms;
+
+   dp->write_pp = png_create_write_struct(PNG_LIBPNG_VER_STRING, dp,
+      display_error, display_warning);
+
+   if (dp->write_pp == NULL)
+      display_log(dp, APP_ERROR, "failed to create write png_struct");
+
+   png_set_write_fn(dp->write_pp, &dp->written_file, write_function,
+      NULL/*flush*/);
+
+#  ifdef PNG_SET_USER_LIMITS_SUPPORTED
+      /* Remove the user limits, if any */
+      png_set_user_limits(dp->write_pp, 0x7fffffff, 0x7fffffff);
+#  endif
+
+   /* Certain transforms require the png_info to be zapped to allow the
+    * transform to work correctly.
+    */
+   if (transforms & (PNG_TRANSFORM_PACKING|
+                     PNG_TRANSFORM_STRIP_FILLER|
+                     PNG_TRANSFORM_STRIP_FILLER_BEFORE))
+   {
+      int ct = dp->color_type;
+
+      if (transforms & (PNG_TRANSFORM_STRIP_FILLER|
+                        PNG_TRANSFORM_STRIP_FILLER_BEFORE))
+         ct &= ~PNG_COLOR_MASK_ALPHA;
+
+      png_set_IHDR(dp->write_pp, ip, dp->width, dp->height, dp->bit_depth, ct,
+         dp->interlace_method, dp->compression_method, dp->filter_method);
+   }
+
+   png_write_png(dp->write_pp, ip, transforms, NULL/*params*/);
+
+   /* Clean it on the way out - if control returns to the caller then the
+    * written_file contains the required data.
+    */
+   display_clean_write(dp);
+}
+#endif /* WRITE_SUPPORTED */
+
+static int
+skip_transform(struct display *dp, int tr)
+   /* Helper to test for a bad combo and log it if it is skipped */
+{
+   if ((dp->options & SKIP_BUGS) != 0 && is_bad_combo(tr))
+   {
+      /* Log this to stdout if logging is on, otherwise just do an information
+       * display_log.
+       */
+      if ((dp->options & LOG_SKIPPED) != 0)
+      {
+         printf("SKIP: %s transforms ", dp->filename);
+
+         while (tr != 0)
+         {
+            int next = first_transform(tr);
+            tr &= ~next;
+
+            printf("%s", transform_name(next));
+            if (tr != 0)
+               putchar('+');
+         }
+
+         putchar('\n');
+      }
+
+      else
+         display_log(dp, INFORMATION, "%s: skipped known bad combo 0x%x",
+            dp->filename, tr);
+
+      return 1; /* skip */
+   }
+
+   return 0; /* don't skip */
+}
+
+static void
+test_one_file(struct display *dp, const char *filename)
+{
+   /* First cache the file and update the display original file
+    * information for the new file.
+    */
+   dp->operation = "cache file";
+   dp->transforms = 0;
+   display_cache_file(dp, filename);
+   update_display(dp);
+
+   /* First test: if there are options that should be ignored for this file
+    * verify that they really are ignored.
+    */
+   if (dp->ignored_transforms != 0)
+   {
+      read_png(dp, &dp->original_file, "ignored transforms",
+         dp->ignored_transforms);
+
+      /* The result should be identical to the original_rows */
+      if (!compare_read(dp, 0/*transforms applied*/))
+         return; /* no point testing more */
+   }
+
+#ifdef PNG_WRITE_SUPPORTED
+   /* Second test: write the original PNG data out to a new file (to test the
+    * write side) then read the result back in and make sure that it hasn't
+    * changed.
+    */
+   dp->operation = "write";
+   write_png(dp, dp->original_ip, 0/*transforms*/);
+   read_png(dp, &dp->written_file, NULL, 0/*transforms*/);
+   if (!compare_read(dp, 0/*transforms applied*/))
+      return;
+#endif
+
+   /* Third test: the active options.  Test each in turn, or, with the
+    * EXHAUSTIVE option, test all possible combinations.
+    */
+   {
+      /* Use unsigned int here because the code below to increment through all
+       * the possibilities exhaustively has to use a compare and that must be
+       * unsigned, because some transforms are negative on a 16-bit system.
+       */
+      unsigned int active = dp->active_transforms;
+      const int exhaustive = (dp->options & EXHAUSTIVE) != 0;
+      unsigned int current = first_transform(active);
+      unsigned int bad_transforms = 0;
+      unsigned int bad_combo = ~0U;    /* bitwise AND of failing transforms */
+      unsigned int bad_combo_list = 0; /* bitwise OR of failures */
+
+      for (;;)
+      {
+         read_png(dp, &dp->original_file, "active transforms", current);
+
+         /* If this involved any irreversible transformations then if we write
+          * it out with just the reversible transformations and read it in again
+          * with the same transforms we should get the same thing.  At present
+          * this isn't done - it just seems like a waste of time and it would
+          * require two sets of read png_struct/png_info.
+          *
+          * If there were no irreversible transformations then if we write it
+          * out and read it back in again (without the reversible transforms)
+          * we should get back to the place where we started.
+          */
+#ifdef PNG_WRITE_SUPPORTED
+         if ((current & write_transforms) == current)
+         {
+            /* All transforms reversible: write the PNG with the transformations
+             * reversed, then read it back in with no transformations.  The
+             * result should be the same as the original apart from the loss of
+             * low order bits because of the SHIFT/sBIT transform.
+             */
+            dp->operation = "reversible transforms";
+            write_png(dp, dp->read_ip, current);
+
+            /* And if this is read back in, because all the transformations were
+             * reversible, the result should be the same.
+             */
+            read_png(dp, &dp->written_file, NULL, 0);
+            if (!compare_read(dp, current/*for the SHIFT/sBIT transform*/))
+            {
+               /* This set of transforms failed.  If a single bit is set - if
+                * there is just one transform - don't include this in further
+                * 'exhaustive' tests.  Notice that each transform is tested on
+                * its own before testing combos in the exhaustive case.
+                */
+               if (is_combo(current))
+               {
+                  bad_combo &= current;
+                  bad_combo_list |= current;
+               }
+
+               else
+                  bad_transforms |= current;
+            }
+         }
+#endif
+
+         /* Now move to the next transform */
+         if (exhaustive) /* all combinations */
+         {
+            unsigned int next = current;
+
+            do
+            {
+               if (next == read_transforms) /* Everything tested */
+                  goto combo;
+
+               ++next;
+            }  /* skip known bad combos if the relevant option is set; skip
+                * combos involving known bad single transforms in all cases.
+                */
+            while (  (next & read_transforms) <= current
+                  || (next & active) == 0 /* skip cases that do nothing */
+                  || (next & bad_transforms) != 0
+                  || skip_transform(dp, next));
+
+            assert((next & read_transforms) == next);
+            current = next;
+         }
+
+         else /* one at a time */
+         {
+            active &= ~current;
+
+            if (active == 0)
+               goto combo;
+
+            current = first_transform(active);
+         }
+      }
+
+combo:
+      if (dp->options & FIND_BAD_COMBOS)
+      {
+         /* bad_combos identifies the combos that occur in all failing cases;
+          * bad_combo_list identifies transforms that do not prevent the
+          * failure.
+          */
+         if (bad_combo != ~0U)
+            printf("%s[0x%x]: PROBLEM: 0x%x[0x%x] ANTIDOTE: 0x%x\n",
+               dp->filename, active, bad_combo, bad_combo_list,
+               rw_transforms & ~bad_combo_list);
+
+         else
+            printf("%s: no %sbad combos found\n", dp->filename,
+               (dp->options & SKIP_BUGS) ? "additional " : "");
+      }
+   }
+}
+
+static int
+do_test(struct display *dp, const char *file)
+   /* Exists solely to isolate the setjmp clobbers */
+{
+   int ret = setjmp(dp->error_return);
+
+   if (ret == 0)
+   {
+      test_one_file(dp, file);
+      return 0;
+   }
+
+   else if (ret < ERRORS) /* shouldn't longjmp on warnings */
+      display_log(dp, INTERNAL_ERROR, "unexpected return code %d", ret);
+
+   return ret;
+}
+
+int
+main(const int argc, const char * const * const argv)
+{
+   /* For each file on the command line test it with a range of transforms */
+   int option_end, ilog = 0;
+   struct display d;
+
+   validate_T();
+   display_init(&d);
+
+   for (option_end=1; option_end<argc; ++option_end)
+   {
+      const char *name = argv[option_end];
+
+      if (strcmp(name, "--verbose") == 0)
+         d.options = (d.options & ~LEVEL_MASK) | VERBOSE;
+
+      else if (strcmp(name, "--warnings") == 0)
+         d.options = (d.options & ~LEVEL_MASK) | WARNINGS;
+
+      else if (strcmp(name, "--errors") == 0)
+         d.options = (d.options & ~LEVEL_MASK) | ERRORS;
+
+      else if (strcmp(name, "--quiet") == 0)
+         d.options = (d.options & ~LEVEL_MASK) | QUIET;
+
+      else if (strcmp(name, "--exhaustive") == 0)
+         d.options |= EXHAUSTIVE;
+
+      else if (strcmp(name, "--fast") == 0)
+         d.options &= ~EXHAUSTIVE;
+
+      else if (strcmp(name, "--strict") == 0)
+         d.options |= STRICT;
+
+      else if (strcmp(name, "--relaxed") == 0)
+         d.options &= ~STRICT;
+
+      else if (strcmp(name, "--log") == 0)
+      {
+         ilog = option_end; /* prevent display */
+         d.options |= LOG;
+      }
+
+      else if (strcmp(name, "--nolog") == 0)
+         d.options &= ~LOG;
+
+      else if (strcmp(name, "--continue") == 0)
+         d.options |= CONTINUE;
+
+      else if (strcmp(name, "--stop") == 0)
+         d.options &= ~CONTINUE;
+
+      else if (strcmp(name, "--skip-bugs") == 0)
+         d.options |= SKIP_BUGS;
+
+      else if (strcmp(name, "--test-all") == 0)
+         d.options &= ~SKIP_BUGS;
+
+      else if (strcmp(name, "--log-skipped") == 0)
+         d.options |= LOG_SKIPPED;
+
+      else if (strcmp(name, "--nolog-skipped") == 0)
+         d.options &= ~LOG_SKIPPED;
+
+      else if (strcmp(name, "--find-bad-combos") == 0)
+         d.options |= FIND_BAD_COMBOS;
+
+      else if (strcmp(name, "--nofind-bad-combos") == 0)
+         d.options &= ~FIND_BAD_COMBOS;
+
+      else if (name[0] == '-' && name[1] == '-')
+      {
+         fprintf(stderr, "pngimage: %s: unknown option\n", name);
+         return 99;
+      }
+
+      else
+         break; /* Not an option */
+   }
+
+   {
+      int i;
+      int errors = 0;
+
+      for (i=option_end; i<argc; ++i)
+      {
+         {
+            int ret = do_test(&d, argv[i]);
+
+            if (ret > QUIET) /* abort on user or internal error */
+               return 99;
+         }
+
+         /* Here on any return, including failures, except user/internal issues
+          */
+         {
+            const int pass = (d.options & STRICT) ?
+               RESULT_STRICT(d.results) : RESULT_RELAXED(d.results);
+
+            if (!pass)
+               ++errors;
+
+            if (d.options & LOG)
+            {
+               int j;
+
+               printf("%s: pngimage ", pass ? "PASS" : "FAIL");
+
+               for (j=1; j<option_end; ++j) if (j != ilog)
+                  printf("%s ", argv[j]);
+
+               printf("%s\n", d.filename);
+            }
+         }
+
+         display_clean(&d);
+      }
+
+      return errors != 0;
+   }
+}
+#else /* !PNG_INFO_IMAGE_SUPPORTED || !PNG_READ_SUPPORTED */
+int
+main(void)
+{
+   fprintf(stderr, "pngimage: no support for png_read/write_image\n");
+   return 77;
+}
+#endif
diff --git a/contrib/libtests/pngunknown.c b/contrib/libtests/pngunknown.c
index a21c9d7..b8c4899 100644
--- a/contrib/libtests/pngunknown.c
+++ b/contrib/libtests/pngunknown.c
@@ -1,8 +1,8 @@
 
 /* pngunknown.c - test the read side unknown chunk handling
  *
- * Last changed in libpng 1.6.0 [February 14, 2013]
- * Copyright (c) 2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ * Copyright (c) 2014 Glenn Randers-Pehrson
  * Written by John Cunningham Bowler
  *
  * This code is released under the libpng license.
@@ -439,7 +439,7 @@
 }
 
 /* libpng error and warning callbacks */
-PNG_FUNCTION(void, error, (png_structp png_ptr, const char *message),
+PNG_FUNCTION(void, (PNGCBAPI error), (png_structp png_ptr, const char *message),
    static PNG_NORETURN)
 {
    display *d = (display*)png_get_error_ptr(png_ptr);
@@ -448,7 +448,7 @@
    display_exit(d);
 }
 
-static void
+static void PNGCBAPI
 warning(png_structp png_ptr, const char *message)
 {
    display *d = (display*)png_get_error_ptr(png_ptr);
@@ -490,7 +490,7 @@
 }
 
 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
-static int
+static int PNGCBAPI
 read_callback(png_structp pp, png_unknown_chunkp pc)
 {
    /* This function mimics the behavior of png_set_keep_unknown_chunks by
diff --git a/contrib/libtests/pngvalid.c b/contrib/libtests/pngvalid.c
index 7347c1b..788b693 100644
--- a/contrib/libtests/pngvalid.c
+++ b/contrib/libtests/pngvalid.c
@@ -1,7 +1,7 @@
 
 /* pngvalid.c - validate libpng by constructing then reading png files.
  *
- * Last changed in libpng 1.5.18 [February 6, 2014]
+ * Last changed in libpng 1.6.10 [March 6, 2014]
  * Copyright (c) 2014 Glenn Randers-Pehrson
  * Written by John Cunningham Bowler
  *
@@ -122,11 +122,6 @@
 #  endif
 #endif
 
-/* Fixups for various minimal builds */
-#ifndef PNG_ERROR_TEXT_SUPPORTED
-#  define png_error(a,b) png_err(a)
-#endif
-
 /***************************** EXCEPTION HANDLING *****************************/
 #ifdef PNG_FREESTANDING_TESTS
 #  include <cexcept.h>
@@ -926,7 +921,7 @@
 #endif /* PNG_READ_SUPPORTED */
 
 /* Functions to use as PNG callbacks. */
-static void
+static void PNGCBAPI
 store_error(png_structp ppIn, png_const_charp message) /* PNG_NORETURN */
 {
    png_const_structp pp = ppIn;
@@ -942,7 +937,7 @@
    }
 }
 
-static void
+static void PNGCBAPI
 store_warning(png_structp ppIn, png_const_charp message)
 {
    png_const_structp pp = ppIn;
@@ -1093,7 +1088,7 @@
 }
 #endif /* PNG_READ_SUPPORTED */
 
-static void
+static void PNGCBAPI
 store_write(png_structp ppIn, png_bytep pb, png_size_t st)
 {
    png_const_structp pp = ppIn;
@@ -1121,7 +1116,7 @@
    }
 }
 
-static void
+static void PNGCBAPI
 store_flush(png_structp ppIn)
 {
    UNUSED(ppIn) /*DOES NOTHING*/
@@ -1215,7 +1210,7 @@
    }
 }
 
-static void
+static void PNGCBAPI
 store_read(png_structp ppIn, png_bytep pb, png_size_t st)
 {
    png_const_structp pp = ppIn;
@@ -1408,7 +1403,7 @@
 }
 
 /* The memory callbacks: */
-static png_voidp
+static png_voidp PNGCBAPI
 store_malloc(png_structp ppIn, png_alloc_size_t cb)
 {
    png_const_structp pp = ppIn;
@@ -1457,7 +1452,7 @@
    return new;
 }
 
-static void
+static void PNGCBAPI
 store_free(png_structp ppIn, png_voidp memory)
 {
    png_const_structp pp = ppIn;
@@ -2676,7 +2671,7 @@
 }
 
 /* The callback: */
-static void
+static void PNGCBAPI
 modifier_read(png_structp ppIn, png_bytep pb, png_size_t st)
 {
    png_const_structp pp = ppIn;
@@ -4680,7 +4675,7 @@
    standard_info_part2(dp, pp, pi, nImages);
 }
 
-static void
+static void PNGCBAPI
 standard_info(png_structp pp, png_infop pi)
 {
    standard_display *dp = voidcast(standard_display*,
@@ -4692,7 +4687,7 @@
    standard_info_imp(dp, pp, pi, 1 /*only one image*/);
 }
 
-static void
+static void PNGCBAPI
 progressive_row(png_structp ppIn, png_bytep new_row, png_uint_32 y, int pass)
 {
    png_const_structp pp = ppIn;
@@ -5006,7 +5001,7 @@
    dp->ps->validated = 1;
 }
 
-static void
+static void PNGCBAPI
 standard_end(png_structp ppIn, png_infop pi)
 {
    png_const_structp pp = ppIn;
@@ -5841,7 +5836,7 @@
    }
 }
 
-static void
+static void PNGCBAPI
 transform_info(png_structp pp, png_infop pi)
 {
    transform_info_imp(voidcast(transform_display*, png_get_progressive_ptr(pp)),
@@ -6048,7 +6043,7 @@
    dp->this.ps->validated = 1;
 }
 
-static void
+static void PNGCBAPI
 transform_end(png_structp ppIn, png_infop pi)
 {
    png_const_structp pp = ppIn;
@@ -7865,7 +7860,7 @@
    standard_info_part2(&dp->this, pp, pi, 1 /*images*/);
 }
 
-static void
+static void PNGCBAPI
 gamma_info(png_structp pp, png_infop pi)
 {
    gamma_info_imp(voidcast(gamma_display*, png_get_progressive_ptr(pp)), pp,
@@ -8829,7 +8824,7 @@
    dp->this.ps->validated = 1;
 }
 
-static void
+static void PNGCBAPI
 gamma_end(png_structp ppIn, png_infop pi)
 {
    png_const_structp pp = ppIn;
diff --git a/contrib/pngminim/decoder/pngusr.h b/contrib/pngminim/decoder/pngusr.h
index 841da0c..cbd7890 100644
--- a/contrib/pngminim/decoder/pngusr.h
+++ b/contrib/pngminim/decoder/pngusr.h
@@ -18,7 +18,6 @@
  * affect the API (so are not recorded in pnglibconf.h)
  */
 
-#define PNG_NO_WARNINGS
 #define PNG_ALIGN_TYPE PNG_ALIGN_NONE
 
 #endif /* MINRDPNGCONF_H */
diff --git a/contrib/pngminim/encoder/pngusr.h b/contrib/pngminim/encoder/pngusr.h
index a050ef3..997d44f 100644
--- a/contrib/pngminim/encoder/pngusr.h
+++ b/contrib/pngminim/encoder/pngusr.h
@@ -18,7 +18,6 @@
  * affect the API (so are not recorded in pnglibconf.h)
  */
 
-#define PNG_NO_WARNINGS
 #define PNG_ALIGN_TYPE PNG_ALIGN_NONE
 
 #endif /* MINWRPNGCONF_H */
diff --git a/contrib/pngminim/preader/pngusr.h b/contrib/pngminim/preader/pngusr.h
index d848634..80db3bb 100644
--- a/contrib/pngminim/preader/pngusr.h
+++ b/contrib/pngminim/preader/pngusr.h
@@ -18,7 +18,6 @@
  * affect the API (so are not recorded in pnglibconf.h)
  */
 
-#define PNG_NO_WARNINGS
 #define PNG_ALIGN_TYPE PNG_ALIGN_NONE
 
 #endif /* MINPRDPNGCONF_H */
diff --git a/contrib/tools/pngfix.c b/contrib/tools/pngfix.c
index 08b23e7..3b64627 100644
--- a/contrib/tools/pngfix.c
+++ b/contrib/tools/pngfix.c
@@ -2,7 +2,7 @@
  *
  * Copyright (c) 2014 John Cunningham Bowler
  *
- * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Last changed in libpng 1.6.10 [March 6, 2014]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -3159,13 +3159,13 @@
 /* This returns a file* from a png_struct in an implementation specific way. */
 static struct file *get_control(png_const_structrp png_ptr);
 
-static void
+static void PNGCBAPI
 error_handler(png_structp png_ptr, png_const_charp message)
 {
    stop(get_control(png_ptr),  LIBPNG_ERROR_CODE, message);
 }
 
-static void
+static void PNGCBAPI
 warning_handler(png_structp png_ptr, png_const_charp message)
 {
    struct file *file = get_control(png_ptr);
@@ -3177,7 +3177,7 @@
 /* Read callback - this is where the work gets done to check the stream before
  * passing it to libpng
  */
-static void
+static void PNGCBAPI
 read_callback(png_structp png_ptr, png_bytep buffer, size_t count)
    /* Return 'count' bytes to libpng in 'buffer' */
 {
diff --git a/libpng-manual.txt b/libpng-manual.txt
index c854b4c..73e09ab 100644
--- a/libpng-manual.txt
+++ b/libpng-manual.txt
@@ -1,6 +1,6 @@
 libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.6.9 - February 6, 2014
+ libpng version 1.6.10 - March 6, 2014
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
  Copyright (c) 1998-2014 Glenn Randers-Pehrson
@@ -11,7 +11,7 @@
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.6.9 - February 6, 2014
+ libpng versions 0.97, January 1998, through 1.6.10 - March 6, 2014
  Updated and distributed by Glenn Randers-Pehrson
  Copyright (c) 1998-2014 Glenn Randers-Pehrson
 
@@ -274,10 +274,10 @@
 contrib/pngminim/*.  See the "$(PNGCONF):" target in the makefile and
 pngusr.dfa in these directories.
 
-C. Configuration using PNG_USR_CONFIG
+C. Configuration using PNG_USER_CONFIG
 
-If -DPNG_USR_CONFIG is added to the CFLAGS when pnglibconf.h is built the file
-pngusr.h will automatically be included before the options in
+If -DPNG_USER_CONFIG is added to the CPPFLAGS when pnglibconf.h is built,
+the file pngusr.h will automatically be included before the options in
 scripts/pnglibconf.dfa are processed.  Your pngusr.h file should contain only
 macro definitions turning features on or off or setting settings.
 
@@ -712,12 +712,12 @@
 case the required information is missing from the file.  By default libpng
 assumes that the PNG data matches your system, to keep this default call:
 
-   png_set_gamma(png_ptr, screen_gamma, 1/screen_gamma/*file gamma*/);
+   png_set_gamma(png_ptr, screen_gamma, output_gamma);
 
 or you can use the fixed point equivalent:
 
    png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma,
-      PNG_FP_1/screen_gamma);
+      PNG_FP_1*output_gamma);
 
 If you don't know the gamma for your system it is probably 2.2 - a good
 approximation to the IEC standard for display systems (sRGB).  If images are
@@ -745,6 +745,70 @@
 uses linear values for this reason, often with higher precision component values
 to preserve overall accuracy.
 
+
+The output_gamma value expresses how to decode the output values, not how
+they are encoded.  The values used correspond to the normal numbers used to
+describe the overall gamma of a computer display system; for example 2.2 for
+an sRGB conformant system.  The values are scaled by 100000 in the _fixed
+version of the API (so 220000 for sRGB.)
+
+The inverse of the value is always used to provide a default for the PNG file
+encoding if it has no gAMA chunk and if png_set_gamma() has not been called
+to override the PNG gamma information.
+
+When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode
+opaque pixels however pixels with lower alpha values are not encoded,
+regardless of the output gamma setting.
+
+When the standard Porter Duff handling is requested with mode 1 the output
+encoding is set to be linear and the output_gamma value is only relevant
+as a default for input data that has no gamma information.  The linear output
+encoding will be overridden if png_set_gamma() is called - the results may be
+highly unexpected!
+
+The following numbers are derived from the sRGB standard and the research
+behind it.  sRGB is defined to be approximated by a PNG gAMA chunk value of
+0.45455 (1/2.2) for PNG.  The value implicitly includes any viewing
+correction required to take account of any differences in the color
+environment of the original scene and the intended display environment; the
+value expresses how to *decode* the image for display, not how the original
+data was *encoded*.
+
+sRGB provides a peg for the PNG standard by defining a viewing environment.
+sRGB itself, and earlier TV standards, actually use a more complex transform
+(a linear portion then a gamma 2.4 power law) than PNG can express.  (PNG is
+limited to simple power laws.)  By saying that an image for direct display on
+an sRGB conformant system should be stored with a gAMA chunk value of 45455
+(11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification
+makes it possible to derive values for other display systems and
+environments.
+
+The Mac value is deduced from the sRGB based on an assumption that the actual
+extra viewing correction used in early Mac display systems was implemented as
+a power 1.45 lookup table.
+
+Any system where a programmable lookup table is used or where the behavior of
+the final display device characteristics can be changed requires system
+specific code to obtain the current characteristic.  However this can be
+difficult and most PNG gamma correction only requires an approximate value.
+
+By default, if png_set_alpha_mode() is not called, libpng assumes that all
+values are unencoded, linear, values and that the output device also has a
+linear characteristic.  This is only very rarely correct - it is invariably
+better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the
+default if you don't know what the right answer is!
+
+The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS
+10.6) which used a correction table to implement a somewhat lower gamma on an
+otherwise sRGB system.
+
+Both these values are reserved (not simple gamma values) in order to allow
+more precise correction internally in the future.
+
+NOTE: the values can be passed to either the fixed or floating
+point APIs, but the floating point API will also accept floating point
+values.
+
 The second thing you may need to tell libpng about is how your system handles
 alpha channel information.  Some, but not all, PNG files contain an alpha
 channel.  To display these files correctly you need to compose the data onto a
@@ -769,11 +833,11 @@
 
 The mode is as follows:
 
-    PNG_ALPHA_PNG: The data is encoded according to the PNG specification.  Red,
-green and blue, or gray, components are gamma encoded color
-values and are not premultiplied by the alpha value.  The
-alpha value is a linear measure of the contribution of the
-pixel to the corresponding final output pixel.
+    PNG_ALPHA_PNG: The data is encoded according to the PNG
+specification.  Red, green and blue, or gray, components are
+gamma encoded color values and are not premultiplied by the
+alpha value.  The alpha value is a linear measure of the
+contribution of the pixel to the corresponding final output pixel.
 
 You should normally use this format if you intend to perform
 color correction on the color values; most, maybe all, color
@@ -790,11 +854,35 @@
 
 The remaining modes assume you don't need to do any further color correction or
 that if you do, your color correction software knows all about alpha (it
-probably doesn't!)
+probably doesn't!).  They 'associate' the alpha with the color information by
+storing color channel values that have been scaled by the alpha.  The
+advantage is that the color channels can be resampled (the image can be
+scaled) in this form.  The disadvantage is that normal practice is to store
+linear, not (gamma) encoded, values and this requires 16-bit channels for
+still images rather than the 8-bit channels that are just about sufficient if
+gamma encoding is used.  In addition all non-transparent pixel values,
+including completely opaque ones, must be gamma encoded to produce the final
+image.  These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
+described below (the latter being the two common names for associated alpha
+color channels). Note that PNG files always contain non-associated color
+channels; png_set_alpha_mode() with one of the modes causes the decoder to
+convert the pixels to an associated form before returning them to your
+application. 
 
-    PNG_ALPHA_STANDARD:  The data libpng produces
-is encoded in the standard way
-assumed by most correctly written graphics software.
+Since it is not necessary to perform arithmetic on opaque color values so
+long as they are not to be resampled and are in the final color space it is
+possible to optimize the handling of alpha by storing the opaque pixels in
+the PNG format (adjusted for the output color space) while storing partially
+opaque pixels in the standard, linear, format.  The accuracy required for
+standard alpha composition is relatively low, because the pixels are
+isolated, therefore typically the accuracy loss in storing 8-bit linear
+values is acceptable.  (This is not true if the alpha channel is used to
+simulate transparency over large areas - use 16 bits or the PNG mode in
+this case!)  This is the 'OPTIMIZED' mode.  For this mode a pixel is
+treated as opaque only if the alpha value is equal to the maximum value.
+
+    PNG_ALPHA_STANDARD:  The data libpng produces is encoded in the
+standard way assumed by most correctly written graphics software.
 The gamma encoding will be removed by libpng and the
 linear component values will be pre-multiplied by the
 alpha channel.
@@ -823,9 +911,8 @@
 supports it, use png_set_expand_16() to force all
 components to 16 bits.
 
-    PNG_ALPHA_OPTIMIZED: This mode is the same
-as PNG_ALPHA_STANDARD except that
-completely opaque pixels are gamma encoded according to
+    PNG_ALPHA_OPTIMIZED: This mode is the same as PNG_ALPHA_STANDARD
+except that completely opaque pixels are gamma encoded according to
 the screen_gamma value.  Pixels with alpha less than 1.0
 will still have linear components.
 
@@ -844,18 +931,16 @@
 You can also try this format if your software is broken;
 it might look better.
 
-    PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD;
-however, all component values,
-including the alpha channel are gamma encoded.  This is
-an appropriate format to try if your software, or more
-likely hardware, is totally broken, i.e., if it performs
-linear arithmetic directly on gamma encoded values.
-
-In most cases of broken software or hardware the bug in the final display
-manifests as a subtle halo around composited parts of the image.  You may not
-even perceive this as a halo; the composited part of the image may simply appear
-separate from the background, as though it had been cut out of paper and pasted
-on afterward.
+    PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD; however, all component
+values, including the alpha channel are gamma encoded.  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.  In most cases of broken software or hardware the bug in the
+final display manifests as a subtle halo around composited parts of the
+image.  You may not even perceive this as a halo; the composited part of
+the image may simply appear separate from the background, as though it had
+been cut out of paper and pasted on afterward.
 
 If you don't have to deal with bugs in software or hardware, or if you can fix
 them, there are three recommended ways of using png_set_alpha_mode():
@@ -886,6 +971,89 @@
 mode is libpng-specific you also need to write your own composition
 software.
 
+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 preceeded 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 ouput 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.
+
 If you don't need, or can't handle, the alpha channel you can call
 png_set_background() to remove it by compositing against a fixed color.  Don't
 call png_set_strip_alpha() to do this - it will leave spurious pixel values in
@@ -1216,7 +1384,7 @@
 
     png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
 
-    file_srgb_intent - the rendering intent (PNG_INFO_sRGB)
+    srgb_intent -    the rendering intent (PNG_INFO_sRGB)
                      The presence of the sRGB chunk
                      means that the pixel data is in the
                      sRGB color space.  This chunk also
@@ -2166,10 +2334,15 @@
 Finishing a sequential read
 
 After you are finished reading the image through the
-low-level interface, you can finish reading the file.  If you are
-interested in comments or time, which may be stored either before or
-after the image data, you should pass the separate png_info struct if
-you want to keep the comments from before and after the image
+low-level interface, you can finish reading the file.
+
+If you want to use a different crc action for handling CRC errors in
+chunks after the image data, you can call png_set_crc_action()
+again at this point.
+
+If you are interested in comments or time, which may be stored either
+before or after the image data, you should pass the separate png_info
+struct if you want to keep the comments from before and after the image
 separate.
 
     png_infop end_info = png_create_info_struct(png_ptr);
@@ -2185,6 +2358,9 @@
 
 If you are not interested, you should still call png_read_end()
 but you can pass NULL, avoiding the need to create an end_info structure.
+If you do this, libpng will not process any chunks after IDAT other than
+skipping over them and perhaps (depending on whether you have called
+png_set_crc_action) checking their CRCs while looking for the IEND chunk.
 
    png_read_end(png_ptr, (png_infop)NULL);
 
@@ -4941,7 +5117,7 @@
 build of pnglibconf.h and it is never included in an application build.
 
 The rarely used alternative of adding a list of feature macros to the
-CFLAGS setting in the build also still works; however, the macros will be
+CPPFLAGS setting in the build also still works; however, the macros will be
 copied to pnglibconf.h and this may produce macro redefinition warnings
 when the individual C files are compiled.
 
@@ -4998,7 +5174,6 @@
    png_info_init_3()
    png_convert_to_rfc1123() which has been replaced
      with png_convert_to_rfc1123_buffer()
-   png_data_freer()
    png_malloc_default()
    png_free_default()
    png_reset_zstream()
@@ -5174,6 +5349,9 @@
     body;
  }
 
+The return type and decorations are placed on a separate line
+ahead of the function name, as illustrated above.
+
 The prototypes for all exported functions appear in png.h,
 above the comment that says
 
@@ -5238,13 +5416,13 @@
 
 XVI. Y2K Compliance in libpng
 
-February 6, 2014
+March 6, 2014
 
 Since the PNG Development group is an ad-hoc body, we can't make
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.6.9 are Y2K compliant.  It is my belief that earlier
+upward through 1.6.10 are Y2K compliant.  It is my belief that earlier
 versions were also Y2K compliant.
 
 Libpng only has two year fields.  One is a 2-byte unsigned integer
diff --git a/libpng.3 b/libpng.3
index f80ca41..db4990f 100644
--- a/libpng.3
+++ b/libpng.3
@@ -1,6 +1,6 @@
-.TH LIBPNG 3 "February 6, 2014"
+.TH LIBPNG 3 "March 6, 2014"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.6.9
+libpng \- Portable Network Graphics (PNG) Reference Library 1.6.10
 .SH SYNOPSIS
 \fB
 #include <png.h>\fP
@@ -504,7 +504,7 @@
 .SH LIBPNG.TXT
 libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.6.9 - February 6, 2014
+ libpng version 1.6.10 - March 6, 2014
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
  Copyright (c) 1998-2014 Glenn Randers-Pehrson
@@ -515,7 +515,7 @@
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.6.9 - February 6, 2014
+ libpng versions 0.97, January 1998, through 1.6.10 - March 6, 2014
  Updated and distributed by Glenn Randers-Pehrson
  Copyright (c) 1998-2014 Glenn Randers-Pehrson
 
@@ -778,10 +778,10 @@
 contrib/pngminim/*.  See the "$(PNGCONF):" target in the makefile and
 pngusr.dfa in these directories.
 
-C. Configuration using PNG_USR_CONFIG
+C. Configuration using PNG_USER_CONFIG
 
-If \-DPNG_USR_CONFIG is added to the CFLAGS when pnglibconf.h is built the file
-pngusr.h will automatically be included before the options in
+If \-DPNG_USER_CONFIG is added to the CPPFLAGS when pnglibconf.h is built,
+the file pngusr.h will automatically be included before the options in
 scripts/pnglibconf.dfa are processed.  Your pngusr.h file should contain only
 macro definitions turning features on or off or setting settings.
 
@@ -1216,12 +1216,12 @@
 case the required information is missing from the file.  By default libpng
 assumes that the PNG data matches your system, to keep this default call:
 
-   png_set_gamma(png_ptr, screen_gamma, 1/screen_gamma/*file gamma*/);
+   png_set_gamma(png_ptr, screen_gamma, output_gamma);
 
 or you can use the fixed point equivalent:
 
    png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma,
-      PNG_FP_1/screen_gamma);
+      PNG_FP_1*output_gamma);
 
 If you don't know the gamma for your system it is probably 2.2 - a good
 approximation to the IEC standard for display systems (sRGB).  If images are
@@ -1249,6 +1249,70 @@
 uses linear values for this reason, often with higher precision component values
 to preserve overall accuracy.
 
+
+The output_gamma value expresses how to decode the output values, not how
+they are encoded.  The values used correspond to the normal numbers used to
+describe the overall gamma of a computer display system; for example 2.2 for
+an sRGB conformant system.  The values are scaled by 100000 in the _fixed
+version of the API (so 220000 for sRGB.)
+
+The inverse of the value is always used to provide a default for the PNG file
+encoding if it has no gAMA chunk and if png_set_gamma() has not been called
+to override the PNG gamma information.
+
+When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode
+opaque pixels however pixels with lower alpha values are not encoded,
+regardless of the output gamma setting.
+
+When the standard Porter Duff handling is requested with mode 1 the output
+encoding is set to be linear and the output_gamma value is only relevant
+as a default for input data that has no gamma information.  The linear output
+encoding will be overridden if png_set_gamma() is called - the results may be
+highly unexpected!
+
+The following numbers are derived from the sRGB standard and the research
+behind it.  sRGB is defined to be approximated by a PNG gAMA chunk value of
+0.45455 (1/2.2) for PNG.  The value implicitly includes any viewing
+correction required to take account of any differences in the color
+environment of the original scene and the intended display environment; the
+value expresses how to *decode* the image for display, not how the original
+data was *encoded*.
+
+sRGB provides a peg for the PNG standard by defining a viewing environment.
+sRGB itself, and earlier TV standards, actually use a more complex transform
+(a linear portion then a gamma 2.4 power law) than PNG can express.  (PNG is
+limited to simple power laws.)  By saying that an image for direct display on
+an sRGB conformant system should be stored with a gAMA chunk value of 45455
+(11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification
+makes it possible to derive values for other display systems and
+environments.
+
+The Mac value is deduced from the sRGB based on an assumption that the actual
+extra viewing correction used in early Mac display systems was implemented as
+a power 1.45 lookup table.
+
+Any system where a programmable lookup table is used or where the behavior of
+the final display device characteristics can be changed requires system
+specific code to obtain the current characteristic.  However this can be
+difficult and most PNG gamma correction only requires an approximate value.
+
+By default, if png_set_alpha_mode() is not called, libpng assumes that all
+values are unencoded, linear, values and that the output device also has a
+linear characteristic.  This is only very rarely correct - it is invariably
+better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the
+default if you don't know what the right answer is!
+
+The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS
+10.6) which used a correction table to implement a somewhat lower gamma on an
+otherwise sRGB system.
+
+Both these values are reserved (not simple gamma values) in order to allow
+more precise correction internally in the future.
+
+NOTE: the values can be passed to either the fixed or floating
+point APIs, but the floating point API will also accept floating point
+values.
+
 The second thing you may need to tell libpng about is how your system handles
 alpha channel information.  Some, but not all, PNG files contain an alpha
 channel.  To display these files correctly you need to compose the data onto a
@@ -1273,11 +1337,11 @@
 
 The mode is as follows:
 
-    PNG_ALPHA_PNG: The data is encoded according to the PNG specification.  Red,
-green and blue, or gray, components are gamma encoded color
-values and are not premultiplied by the alpha value.  The
-alpha value is a linear measure of the contribution of the
-pixel to the corresponding final output pixel.
+    PNG_ALPHA_PNG: The data is encoded according to the PNG
+specification.  Red, green and blue, or gray, components are
+gamma encoded color values and are not premultiplied by the
+alpha value.  The alpha value is a linear measure of the
+contribution of the pixel to the corresponding final output pixel.
 
 You should normally use this format if you intend to perform
 color correction on the color values; most, maybe all, color
@@ -1294,11 +1358,35 @@
 
 The remaining modes assume you don't need to do any further color correction or
 that if you do, your color correction software knows all about alpha (it
-probably doesn't!)
+probably doesn't!).  They 'associate' the alpha with the color information by
+storing color channel values that have been scaled by the alpha.  The
+advantage is that the color channels can be resampled (the image can be
+scaled) in this form.  The disadvantage is that normal practice is to store
+linear, not (gamma) encoded, values and this requires 16-bit channels for
+still images rather than the 8-bit channels that are just about sufficient if
+gamma encoding is used.  In addition all non-transparent pixel values,
+including completely opaque ones, must be gamma encoded to produce the final
+image.  These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
+described below (the latter being the two common names for associated alpha
+color channels). Note that PNG files always contain non-associated color
+channels; png_set_alpha_mode() with one of the modes causes the decoder to
+convert the pixels to an associated form before returning them to your
+application. 
 
-    PNG_ALPHA_STANDARD:  The data libpng produces
-is encoded in the standard way
-assumed by most correctly written graphics software.
+Since it is not necessary to perform arithmetic on opaque color values so
+long as they are not to be resampled and are in the final color space it is
+possible to optimize the handling of alpha by storing the opaque pixels in
+the PNG format (adjusted for the output color space) while storing partially
+opaque pixels in the standard, linear, format.  The accuracy required for
+standard alpha composition is relatively low, because the pixels are
+isolated, therefore typically the accuracy loss in storing 8-bit linear
+values is acceptable.  (This is not true if the alpha channel is used to
+simulate transparency over large areas - use 16 bits or the PNG mode in
+this case!)  This is the 'OPTIMIZED' mode.  For this mode a pixel is
+treated as opaque only if the alpha value is equal to the maximum value.
+
+    PNG_ALPHA_STANDARD:  The data libpng produces is encoded in the
+standard way assumed by most correctly written graphics software.
 The gamma encoding will be removed by libpng and the
 linear component values will be pre-multiplied by the
 alpha channel.
@@ -1327,9 +1415,8 @@
 supports it, use png_set_expand_16() to force all
 components to 16 bits.
 
-    PNG_ALPHA_OPTIMIZED: This mode is the same
-as PNG_ALPHA_STANDARD except that
-completely opaque pixels are gamma encoded according to
+    PNG_ALPHA_OPTIMIZED: This mode is the same as PNG_ALPHA_STANDARD
+except that completely opaque pixels are gamma encoded according to
 the screen_gamma value.  Pixels with alpha less than 1.0
 will still have linear components.
 
@@ -1348,18 +1435,16 @@
 You can also try this format if your software is broken;
 it might look better.
 
-    PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD;
-however, all component values,
-including the alpha channel are gamma encoded.  This is
-an appropriate format to try if your software, or more
-likely hardware, is totally broken, i.e., if it performs
-linear arithmetic directly on gamma encoded values.
-
-In most cases of broken software or hardware the bug in the final display
-manifests as a subtle halo around composited parts of the image.  You may not
-even perceive this as a halo; the composited part of the image may simply appear
-separate from the background, as though it had been cut out of paper and pasted
-on afterward.
+    PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD; however, all component
+values, including the alpha channel are gamma encoded.  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.  In most cases of broken software or hardware the bug in the
+final display manifests as a subtle halo around composited parts of the
+image.  You may not even perceive this as a halo; the composited part of
+the image may simply appear separate from the background, as though it had
+been cut out of paper and pasted on afterward.
 
 If you don't have to deal with bugs in software or hardware, or if you can fix
 them, there are three recommended ways of using png_set_alpha_mode():
@@ -1390,6 +1475,89 @@
 mode is libpng-specific you also need to write your own composition
 software.
 
+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 preceeded 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 ouput 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.
+
 If you don't need, or can't handle, the alpha channel you can call
 png_set_background() to remove it by compositing against a fixed color.  Don't
 call png_set_strip_alpha() to do this - it will leave spurious pixel values in
@@ -1720,7 +1888,7 @@
 
     png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
 
-    file_srgb_intent - the rendering intent (PNG_INFO_sRGB)
+    srgb_intent -    the rendering intent (PNG_INFO_sRGB)
                      The presence of the sRGB chunk
                      means that the pixel data is in the
                      sRGB color space.  This chunk also
@@ -2670,10 +2838,15 @@
 .SS Finishing a sequential read
 
 After you are finished reading the image through the
-low-level interface, you can finish reading the file.  If you are
-interested in comments or time, which may be stored either before or
-after the image data, you should pass the separate png_info struct if
-you want to keep the comments from before and after the image
+low-level interface, you can finish reading the file.
+
+If you want to use a different crc action for handling CRC errors in
+chunks after the image data, you can call png_set_crc_action()
+again at this point.
+
+If you are interested in comments or time, which may be stored either
+before or after the image data, you should pass the separate png_info
+struct if you want to keep the comments from before and after the image
 separate.
 
     png_infop end_info = png_create_info_struct(png_ptr);
@@ -2689,6 +2862,9 @@
 
 If you are not interested, you should still call png_read_end()
 but you can pass NULL, avoiding the need to create an end_info structure.
+If you do this, libpng will not process any chunks after IDAT other than
+skipping over them and perhaps (depending on whether you have called
+png_set_crc_action) checking their CRCs while looking for the IEND chunk.
 
    png_read_end(png_ptr, (png_infop)NULL);
 
@@ -5446,7 +5622,7 @@
 build of pnglibconf.h and it is never included in an application build.
 
 The rarely used alternative of adding a list of feature macros to the
-CFLAGS setting in the build also still works; however, the macros will be
+CPPFLAGS setting in the build also still works; however, the macros will be
 copied to pnglibconf.h and this may produce macro redefinition warnings
 when the individual C files are compiled.
 
@@ -5503,7 +5679,6 @@
    png_info_init_3()
    png_convert_to_rfc1123() which has been replaced
      with png_convert_to_rfc1123_buffer()
-   png_data_freer()
    png_malloc_default()
    png_free_default()
    png_reset_zstream()
@@ -5679,6 +5854,9 @@
     body;
  }
 
+The return type and decorations are placed on a separate line
+ahead of the function name, as illustrated above.
+
 The prototypes for all exported functions appear in png.h,
 above the comment that says
 
@@ -5743,13 +5921,13 @@
 
 .SH XVI. Y2K Compliance in libpng
 
-February 6, 2014
+March 6, 2014
 
 Since the PNG Development group is an ad-hoc body, we can't make
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.6.9 are Y2K compliant.  It is my belief that earlier
+upward through 1.6.10 are Y2K compliant.  It is my belief that earlier
 versions were also Y2K compliant.
 
 Libpng only has two year fields.  One is a 2-byte unsigned integer
@@ -5980,6 +6158,9 @@
  1.6.9beta01-04      16    10609  16.so.16.9[.0]
  1.6.9rc01-02        16    10609  16.so.16.9[.0]
  1.6.9               16    10609  16.so.16.9[.0]
+ 1.6.10beta01-03     16    10610  16.so.16.10[.0]
+ 1.6.10rc01-04       16    10610  16.so.16.10[.0]
+ 1.6.10              16    10610  16.so.16.10[.0]
 
 Henceforth the source version will match the shared-library minor
 and patch numbers; the shared-library major version number will be
@@ -6036,7 +6217,7 @@
 
 Thanks to Frank J. T. Wojcik for helping with the documentation.
 
-Libpng version 1.6.9 - February 6, 2014:
+Libpng version 1.6.10 - March 6, 2014:
 Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
 Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net).
 
@@ -6059,7 +6240,7 @@
 
 This code is released under the libpng license.
 
-libpng versions 1.2.6, August 15, 2004, through 1.6.9, February 6, 2014, are
+libpng versions 1.2.6, August 15, 2004, through 1.6.10, March 6, 2014, are
 Copyright (c) 2004,2006-2007 Glenn Randers-Pehrson, and are
 distributed according to the same disclaimer and license as libpng-1.2.5
 with the following individual added to the list of Contributing Authors
@@ -6158,7 +6339,7 @@
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-February 6, 2014
+March 6, 2014
 
 .\" end of man page
 
diff --git a/libpngpf.3 b/libpngpf.3
index ef0fb86..844a9fc 100644
--- a/libpngpf.3
+++ b/libpngpf.3
@@ -1,6 +1,6 @@
-.TH LIBPNGPF 3 "February 6, 2014"
+.TH LIBPNGPF 3 "March 6, 2014"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.6.9
+libpng \- Portable Network Graphics (PNG) Reference Library 1.6.10
 (private functions)
 .SH SYNOPSIS
 \fB#include \fI"pngpriv.h"
diff --git a/png.5 b/png.5
index 096ccc2..3beacfa 100644
--- a/png.5
+++ b/png.5
@@ -1,4 +1,4 @@
-.TH PNG 5 "February 6, 2014"
+.TH PNG 5 "March 6, 2014"
 .SH NAME
 png \- Portable Network Graphics (PNG) format
 .SH DESCRIPTION
diff --git a/png.c b/png.c
index 3db9ad4..0cb4a1d 100644
--- a/png.c
+++ b/png.c
@@ -14,7 +14,7 @@
 #include "pngpriv.h"
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_9 Your_png_h_is_not_version_1_6_9;
+typedef png_libpng_version_1_6_10 Your_png_h_is_not_version_1_6_10;
 
 /* 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
@@ -773,13 +773,13 @@
 #else
 #  ifdef __STDC__
    return PNG_STRING_NEWLINE \
-     "libpng version 1.6.9 - February 6, 2014" PNG_STRING_NEWLINE \
+     "libpng version 1.6.10 - March 6, 2014" PNG_STRING_NEWLINE \
      "Copyright (c) 1998-2014 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
      "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
      "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
      PNG_STRING_NEWLINE;
 #  else
-      return "libpng version 1.6.9 - February 6, 2014\
+      return "libpng version 1.6.10 - March 6, 2014\
       Copyright (c) 1998-2014 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
@@ -1742,7 +1742,8 @@
       (it >= 97 && it <= 122);
 }
 
-static int is_ICC_signature(png_alloc_size_t it)
+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) &&
@@ -2295,15 +2296,16 @@
             }
          }
 
-#        if PNG_sRGB_PROFILE_CHECKS > 0
-            /* The signature matched, but the profile had been changed in some
-             * way.  This is an apparent violation of the ICC terms of use and,
-             * anyway, probably indicates a data error or uninformed hacking.
-             */
-            if (png_sRGB_checks[i].have_md5)
-               png_benign_error(png_ptr,
-                  "copyright violation: edited ICC profile ignored");
-#        endif
+# 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
       }
    }
 
diff --git a/png.h b/png.h
index b572dc7..16d3299 100644
--- a/png.h
+++ b/png.h
@@ -1,8 +1,8 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.6.9 - February 6, 2014
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * libpng version 1.6.10 - March 6, 2014
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -11,7 +11,7 @@
  * Authors and maintainers:
  *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *   libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.6.9 - February 6, 2014: Glenn
+ *   libpng versions 0.97, January 1998, through 1.6.10 - March 6, 2014: Glenn
  *   See also "Contributing Authors", below.
  *
  * Note about libpng version numbers:
@@ -192,6 +192,9 @@
  *    1.6.9beta01-04          16    10609  16.so.16.9[.0]
  *    1.6.9rc01-02            16    10609  16.so.16.9[.0]
  *    1.6.9                   16    10609  16.so.16.9[.0]
+ *    1.6.10beta01-03         16    10610  16.so.16.10[.0]
+ *    1.6.10betarc01-04       16    10610  16.so.16.10[.0]
+ *    1.6.10beta              16    10610  16.so.16.10[.0]
  *
  *   Henceforth the source version will match the shared-library major
  *   and minor numbers; the shared-library major version number will be
@@ -223,7 +226,7 @@
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.2.6, August 15, 2004, through 1.6.9, February 6, 2014, are
+ * libpng versions 1.2.6, August 15, 2004, through 1.6.10, March 6, 2014, are
  * Copyright (c) 2004, 2006-2013 Glenn Randers-Pehrson, and are
  * distributed according to the same disclaimer and license as libpng-1.2.5
  * with the following individual added to the list of Contributing Authors:
@@ -335,13 +338,13 @@
  * Y2K compliance in libpng:
  * =========================
  *
- *    February 6, 2014
+ *    March 6, 2014
  *
  *    Since the PNG Development group is an ad-hoc body, we can't make
  *    an official declaration.
  *
  *    This is your unofficial assurance that libpng from version 0.71 and
- *    upward through 1.6.9 are Y2K compliant.  It is my belief that
+ *    upward through 1.6.10 are Y2K compliant.  It is my belief that
  *    earlier versions were also Y2K compliant.
  *
  *    Libpng only has two year fields.  One is a 2-byte unsigned integer
@@ -401,9 +404,9 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.9"
+#define PNG_LIBPNG_VER_STRING "1.6.10"
 #define PNG_HEADER_VERSION_STRING \
-     " libpng version 1.6.9 - February 6, 2014\n"
+     " libpng version 1.6.10 - March 6, 2014\n"
 
 #define PNG_LIBPNG_VER_SONUM   16
 #define PNG_LIBPNG_VER_DLLNUM  16
@@ -411,7 +414,7 @@
 /* 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 9
+#define PNG_LIBPNG_VER_RELEASE 10
 
 /* This should match the numeric part of the final component of
  * PNG_LIBPNG_VER_STRING, omitting any leading zero:
@@ -442,7 +445,7 @@
  * version 1.0.0 was mis-numbered 100 instead of 10000).  From
  * version 1.0.1 it's    xxyyzz, where x=major, y=minor, z=release
  */
-#define PNG_LIBPNG_VER 10609 /* 1.6.9 */
+#define PNG_LIBPNG_VER 10610 /* 1.6.10 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
@@ -547,7 +550,7 @@
 /* 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_9;
+typedef char* png_libpng_version_1_6_10;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
@@ -1209,9 +1212,9 @@
 #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 when an alpha channel, or tRNS chunk in a palette
- * file, is present.
+/* 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
@@ -1219,33 +1222,19 @@
  *
  * 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.  The gamma encoded color channels must be
- * scaled according to the contribution and to do this it is necessary to undo
+ * 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 reencode
  * 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.  The
- * advantage is that the color channels can be resampled (the image can be
- * scaled) in this form.  The disadvantage is that normal practice is to store
- * linear, not (gamma) encoded, values and this requires 16-bit channels for
- * still images rather than the 8-bit channels that are just about sufficient if
- * gamma encoding is used.  In addition all non-transparent pixel values,
- * including completely opaque ones, must be gamma encoded to produce the final
- * image.  This is the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' mode (the
- * latter being the two common names for associated alpha color channels.)
+ * 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).
  *
- * Since it is not necessary to perform arithmetic on opaque color values so
- * long as they are not to be resampled and are in the final color space it is
- * possible to optimize the handling of alpha by storing the opaque pixels in
- * the PNG format (adjusted for the output color space) while storing partially
- * opaque pixels in the standard, linear, format.  The accuracy required for
- * standard alpha composition is relatively low, because the pixels are
- * isolated, therefore typically the accuracy loss in storing 8-bit linear
- * values is acceptable.  (This is not true if the alpha channel is used to
- * simulate transparency over large areas - use 16 bits or the PNG mode in
- * this case!)  This is the 'OPTIMIZED' mode.  For this mode a pixel is
- * treated as opaque only if the alpha value is equal to the maximum value.
+ * 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
@@ -1272,68 +1261,7 @@
 
 #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.  The values used
- * correspond to the normal numbers used to describe the overall gamma of a
- * computer display system; for example 2.2 for an sRGB conformant system.  The
- * values are scaled by 100000 in the _fixed version of the API (so 220000 for
- * sRGB.)
- *
- * The inverse of the value is always used to provide a default for the PNG file
- * encoding if it has no gAMA chunk and if png_set_gamma() has not been called
- * to override the PNG gamma information.
- *
- * When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode
- * opaque pixels however pixels with lower alpha values are not encoded,
- * regardless of the output gamma setting.
- *
- * When the standard Porter Duff handling is requested with mode 1 the output
- * encoding is set to be linear and the output_gamma value is only relevant
- * as a default for input data that has no gamma information.  The linear output
- * encoding will be overridden if png_set_gamma() is called - the results may be
- * highly unexpected!
- *
- * The following numbers are derived from the sRGB standard and the research
- * behind it.  sRGB is defined to be approximated by a PNG gAMA chunk value of
- * 0.45455 (1/2.2) for PNG.  The value implicitly includes any viewing
- * correction required to take account of any differences in the color
- * environment of the original scene and the intended display environment; the
- * value expresses how to *decode* the image for display, not how the original
- * data was *encoded*.
- *
- * sRGB provides a peg for the PNG standard by defining a viewing environment.
- * sRGB itself, and earlier TV standards, actually use a more complex transform
- * (a linear portion then a gamma 2.4 power law) than PNG can express.  (PNG is
- * limited to simple power laws.)  By saying that an image for direct display on
- * an sRGB conformant system should be stored with a gAMA chunk value of 45455
- * (11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification
- * makes it possible to derive values for other display systems and
- * environments.
- *
- * The Mac value is deduced from the sRGB based on an assumption that the actual
- * extra viewing correction used in early Mac display systems was implemented as
- * a power 1.45 lookup table.
- *
- * Any system where a programmable lookup table is used or where the behavior of
- * the final display device characteristics can be changed requires system
- * specific code to obtain the current characteristic.  However this can be
- * difficult and most PNG gamma correction only requires an approximate value.
- *
- * By default, if png_set_alpha_mode() is not called, libpng assumes that all
- * values are unencoded, linear, values and that the output device also has a
- * linear characteristic.  This is only very rarely correct - it is invariably
- * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the
- * default if you don't know what the right answer is!
- *
- * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS
- * 10.6) which used a correction table to implement a somewhat lower gamma on an
- * otherwise sRGB system.
- *
- * Both these values are reserved (not simple gamma values) in order to allow
- * more precise correction internally in the future.
- *
- * NOTE: the following values can be passed to either the fixed or floating
- * point APIs, but the floating point API will also accept floating point
- * values.
+ * 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 */
@@ -1956,8 +1884,8 @@
  * 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_EXPORTA(99, void, png_data_freer, (png_const_structrp png_ptr,
-    png_inforp info_ptr, int freer, png_uint_32 mask), PNG_DEPRECATED);
+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
@@ -1999,6 +1927,8 @@
 #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
@@ -2009,6 +1939,9 @@
 /* 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
@@ -2519,11 +2452,15 @@
 
 #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));
diff --git a/pngconf.h b/pngconf.h
index 7ce5c65..afc0ead 100644
--- a/pngconf.h
+++ b/pngconf.h
@@ -1,7 +1,7 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.6.9 - February 6, 2014
+ * libpng version 1.6.10 - March 6, 2014
  *
  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
@@ -376,9 +376,11 @@
 #      define PNG_DEPRECATED __attribute__((__deprecated__))
 #    endif
 #    if !defined(PNG_PRIVATE)
-#      if __has_extension(attribute_unavailable_with_message)
-#        define PNG_PRIVATE __attribute__((__unavailable__(\
-           "This function is not exported by libpng.")))
+#      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
diff --git a/pngerror.c b/pngerror.c
index 3faf273..5876b47 100644
--- a/pngerror.c
+++ b/pngerror.c
@@ -1,8 +1,8 @@
 
 /* pngerror.c - stub functions for i/o and memory allocation
  *
- * Last changed in libpng 1.6.8 [December 19, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -876,8 +876,8 @@
     * possible to implement without setjmp support just so long as there is some
     * way to handle the error return here:
     */
-PNG_FUNCTION(void /* PRIVATE */,
-png_safe_error,(png_structp png_nonconst_ptr, png_const_charp error_message),
+PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
+png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
    PNG_NORETURN)
 {
    const png_const_structrp png_ptr = png_nonconst_ptr;
@@ -912,7 +912,7 @@
 }
 
 #ifdef PNG_WARNINGS_SUPPORTED
-void /* PRIVATE */
+void /* PRIVATE */ PNGCBAPI
 png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
 {
    const png_const_structrp png_ptr = png_nonconst_ptr;
diff --git a/pngpread.c b/pngpread.c
index 94856e9..6c8404e 100644
--- a/pngpread.c
+++ b/pngpread.c
@@ -1,8 +1,8 @@
 
 /* pngpread.c - read a png file in push mode
  *
- * Last changed in libpng 1.6.8 [December 19, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -234,6 +234,7 @@
          png_error(png_ptr, "Missing PLTE before IDAT");
 
       png_ptr->mode |= PNG_HAVE_IDAT;
+      png_ptr->process_mode = PNG_READ_IDAT_MODE;
 
       if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
          if (png_ptr->push_length == 0)
diff --git a/pngpriv.h b/pngpriv.h
index a9aa1a2..a3fd1a4 100644
--- a/pngpriv.h
+++ b/pngpriv.h
@@ -6,7 +6,7 @@
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
- * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Last changed in libpng 1.6.10 [March 6, 2014]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -254,6 +254,11 @@
       extern PNG_FUNCTION(type, name, args, PNG_EMPTY attributes)
 #endif
 
+#ifndef PNG_INTERNAL_CALLBACK
+#  define PNG_INTERNAL_CALLBACK(type, name, args, attributes)\
+      extern 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
@@ -373,8 +378,6 @@
 #ifdef PNG_WARNINGS_SUPPORTED
 #  define PNG_WARNING_PARAMETERS(p) png_warning_parameters p;
 #else
-#  define png_warning(s1,s2) ((void)(s1))
-#  define png_chunk_warning(s1,s2) ((void)(s1))
 #  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)
@@ -382,8 +385,6 @@
 #  define PNG_WARNING_PARAMETERS(p)
 #endif
 #ifndef PNG_ERROR_TEXT_SUPPORTED
-#  define png_error(s1,s2) png_err(s1)
-#  define png_chunk_error(s1,s2) png_err(s1)
 #  define png_fixed_error(s1,s2) png_err(s1)
 #endif
 
@@ -1883,11 +1884,11 @@
  * 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_FUNCTION(void,png_safe_error,(png_structp png_ptr,
+PNG_INTERNAL_CALLBACK(void,png_safe_error,(png_structp png_ptr,
    png_const_charp error_message),PNG_NORETURN);
 
 #ifdef PNG_WARNINGS_SUPPORTED
-PNG_INTERNAL_FUNCTION(void,png_safe_warning,(png_structp png_ptr,
+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*/
diff --git a/pngread.c b/pngread.c
index 9ff639d..cd9ab58 100644
--- a/pngread.c
+++ b/pngread.c
@@ -1,7 +1,7 @@
 
 /* pngread.c - read a PNG file
  *
- * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Last changed in libpng 1.6.10 [March 6, 2014]
  * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -781,11 +781,14 @@
       png_uint_32 length = png_read_chunk_header(png_ptr);
       png_uint_32 chunk_name = png_ptr->chunk_name;
 
-      if (chunk_name == png_IHDR)
+      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 (chunk_name == png_IEND)
-         png_handle_IEND(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)
@@ -1001,8 +1004,6 @@
                            int transforms,
                            voidp params)
 {
-   int row;
-
    if (png_ptr == NULL || info_ptr == NULL)
       return;
 
@@ -1014,120 +1015,149 @@
       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.
+    */
 
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
    /* Tell libpng to strip 16-bit/color files down to 8 bits per color.
     */
    if (transforms & PNG_TRANSFORM_SCALE_16)
-   {
      /* 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
 
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
    /* 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)
+#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
 
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
    /* Strip alpha bytes from the input data without combining with
     * the background (not recommended).
     */
    if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
+#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
 
-#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
    /* 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)
+#ifdef PNG_READ_PACK_SUPPORTED
       png_set_packing(png_ptr);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
 #endif
 
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
    /* 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)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
       png_set_packswap(png_ptr);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
 #endif
 
-#ifdef PNG_READ_EXPAND_SUPPORTED
    /* 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)
-      if ((png_ptr->bit_depth < 8) ||
-          (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
-          (info_ptr->valid & PNG_INFO_tRNS))
-         png_set_expand(png_ptr);
+#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.
     */
 
-#ifdef PNG_READ_INVERT_SUPPORTED
    /* Invert monochrome files to have 0 as white and 1 as black
     */
    if (transforms & PNG_TRANSFORM_INVERT_MONO)
+#ifdef PNG_READ_INVERT_SUPPORTED
       png_set_invert_mono(png_ptr);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
 #endif
 
-#ifdef PNG_READ_SHIFT_SUPPORTED
    /* 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) && (info_ptr->valid & PNG_INFO_sBIT))
-      png_set_shift(png_ptr, &info_ptr->sig_bit);
+   if (transforms & PNG_TRANSFORM_SHIFT)
+#ifdef PNG_READ_SHIFT_SUPPORTED
+      if (info_ptr->valid & PNG_INFO_sBIT)
+         png_set_shift(png_ptr, &info_ptr->sig_bit);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
 #endif
 
-#ifdef PNG_READ_BGR_SUPPORTED
    /* Flip the RGB pixels to BGR (or RGBA to BGRA) */
    if (transforms & PNG_TRANSFORM_BGR)
+#ifdef PNG_READ_BGR_SUPPORTED
       png_set_bgr(png_ptr);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
 #endif
 
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
    /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+#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
 
-#ifdef PNG_READ_SWAP_SUPPORTED
    /* Swap bytes of 16-bit files to least significant byte first */
    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+#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 */
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
    /* Invert the alpha channel from opacity to transparency */
    if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+#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 */
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
    /* Expand grayscale image to RGB */
    if (transforms & PNG_TRANSFORM_GRAY_TO_RGB)
+#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 */
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
    if (transforms & PNG_TRANSFORM_EXPAND_16)
+#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 */
@@ -1150,16 +1180,17 @@
    {
       png_uint_32 iptr;
 
-      info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
-          info_ptr->height * (sizeof (png_bytep)));
+      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 (row = 0; row < (int)info_ptr->height; row++)
-         info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
-            png_get_rowbytes(png_ptr, info_ptr));
+      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);
@@ -1168,9 +1199,7 @@
    /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
    png_read_end(png_ptr, info_ptr);
 
-   PNG_UNUSED(transforms)   /* Quiet compiler warnings */
    PNG_UNUSED(params)
-
 }
 #endif /* PNG_INFO_IMAGE_SUPPORTED */
 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
diff --git a/pngrtran.c b/pngrtran.c
index f0c0164..5395396 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -1,7 +1,7 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Last changed in libpng 1.6.10 [March 6, 2014]
  * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -1363,12 +1363,12 @@
     * 12) PNG_EXPAND_16
     * 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
     * 14) PNG_INVERT_MONO
-    * 15) PNG_SHIFT
-    * 16) PNG_PACK
-    * 17) PNG_BGR
-    * 18) PNG_PACKSWAP
-    * 19) PNG_FILLER (includes PNG_ADD_ALPHA)
-    * 20) PNG_INVERT_ALPHA
+    * 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]
@@ -4907,6 +4907,11 @@
       png_do_invert(row_info, png_ptr->row_buf + 1);
 #endif
 
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+   if (png_ptr->transformations & PNG_INVERT_ALPHA)
+      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
+#endif
+
 #ifdef PNG_READ_SHIFT_SUPPORTED
    if (png_ptr->transformations & PNG_SHIFT)
       png_do_unshift(row_info, png_ptr->row_buf + 1,
@@ -4941,11 +4946,6 @@
           (png_uint_32)png_ptr->filler, png_ptr->flags);
 #endif
 
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-   if (png_ptr->transformations & PNG_INVERT_ALPHA)
-      png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
    if (png_ptr->transformations & PNG_SWAP_ALPHA)
       png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
diff --git a/pngrutil.c b/pngrutil.c
index 062f287..98e9524 100644
--- a/pngrutil.c
+++ b/pngrutil.c
@@ -1,8 +1,8 @@
 
 /* pngrutil.c - utilities to read a PNG file
  *
- * Last changed in libpng 1.6.8 [December 19, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.10 [March 6, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
  *
@@ -227,10 +227,7 @@
       }
 
       else
-      {
-         png_chunk_benign_error(png_ptr, "CRC error");
-         return (0);
-      }
+         png_chunk_error(png_ptr, "CRC error");
 
       return (1);
    }
@@ -314,16 +311,11 @@
 
       else if (warn < 2) /* else silent */
       {
-#ifdef PNG_WARNINGS_SUPPORTED
          if (warn)
              png_chunk_warning(png_ptr, "insufficient memory to read chunk");
+
          else
-#endif
-         {
-#ifdef PNG_ERROR_TEXT_SUPPORTED
              png_chunk_error(png_ptr, "insufficient memory to read chunk");
-#endif
-         }
       }
    }
 
@@ -986,22 +978,15 @@
       if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
       {
          if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
-         {
-            png_chunk_benign_error(png_ptr, "CRC error");
-         }
+            return;
 
          else
-         {
-            png_chunk_warning(png_ptr, "CRC error");
-            return;
-         }
+            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))
-      {
          png_chunk_warning(png_ptr, "CRC error");
-      }
    }
 #endif
 
@@ -1112,13 +1097,12 @@
 void /* PRIVATE */
 png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
 {
-   unsigned int truelen;
+   unsigned int truelen, i;
+   png_byte sample_depth;
    png_byte buf[4];
 
    png_debug(1, "in png_handle_sBIT");
 
-   buf[0] = buf[1] = buf[2] = buf[3] = 0;
-
    if (!(png_ptr->mode & PNG_HAVE_IHDR))
       png_chunk_error(png_ptr, "missing IHDR");
 
@@ -1137,10 +1121,16 @@
    }
 
    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)
    {
@@ -1149,11 +1139,19 @@
       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))
       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)
    {
       png_ptr->sig_bit.red = buf[0];
@@ -1423,7 +1421,7 @@
                               (sizeof local_buffer), &length,
                               profile + (sizeof profile_header), &size, 0);
 
-                           /* Still expect a a buffer error because we expect
+                           /* Still expect a buffer error because we expect
                             * there to be some tag data!
                             */
                            if (size == 0)
diff --git a/pngtest.c b/pngtest.c
index 2c69f33..3b1f055 100644
--- a/pngtest.c
+++ b/pngtest.c
@@ -667,8 +667,8 @@
    return 1; /* handled */
 }
 
-static int PNGCBAPI read_user_chunk_callback(png_struct *png_ptr,
-   png_unknown_chunkp chunk)
+static int PNGCBAPI
+read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
 {
    struct user_chunk_data *my_user_chunk_data =
       (struct user_chunk_data*)png_get_user_chunk_ptr(png_ptr);
@@ -1991,4 +1991,4 @@
 #endif
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_9 Your_png_h_is_not_version_1_6_9;
+typedef png_libpng_version_1_6_10 Your_png_h_is_not_version_1_6_10;
diff --git a/pngwrite.c b/pngwrite.c
index c3cb607..cff7864 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -1,7 +1,7 @@
 
 /* pngwrite.c - general routines to write a PNG file
  *
- * Last changed in libpng 1.6.9 [February 6, 2014]
+ * Last changed in libpng 1.6.10 [March 6, 2014]
  * Copyright (c) 1998-2014 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -1546,81 +1546,117 @@
    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 ------- */
 
-#ifdef PNG_WRITE_INVERT_SUPPORTED
    /* Invert monochrome pixels */
    if (transforms & PNG_TRANSFORM_INVERT_MONO)
+#ifdef PNG_WRITE_INVERT_SUPPORTED
       png_set_invert_mono(png_ptr);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
 #endif
 
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
    /* Shift the pixels up to a legal bit depth and fill in
     * as appropriate to correctly scale the image.
     */
-   if ((transforms & PNG_TRANSFORM_SHIFT)
-       && (info_ptr->valid & PNG_INFO_sBIT))
-      png_set_shift(png_ptr, &info_ptr->sig_bit);
+   if (transforms & PNG_TRANSFORM_SHIFT)
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+      if (info_ptr->valid & PNG_INFO_sBIT)
+         png_set_shift(png_ptr, &info_ptr->sig_bit);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
 #endif
 
-#ifdef PNG_WRITE_PACK_SUPPORTED
    /* Pack pixels into bytes */
    if (transforms & PNG_TRANSFORM_PACKING)
-       png_set_packing(png_ptr);
+#ifdef PNG_WRITE_PACK_SUPPORTED
+      png_set_packing(png_ptr);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
 #endif
 
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
    /* Swap location of alpha bytes from ARGB to RGBA */
    if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+#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))
+   {
 #ifdef PNG_WRITE_FILLER_SUPPORTED
-   /* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */
-   if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
-      png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+      if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
+      {
+         if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
+            png_app_error(png_ptr,
+               "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
 
-   else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
-      png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+         /* 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)
+         png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported");
 #endif
+   }
 
-#ifdef PNG_WRITE_BGR_SUPPORTED
    /* Flip BGR pixels to RGB */
    if (transforms & PNG_TRANSFORM_BGR)
+#ifdef PNG_WRITE_BGR_SUPPORTED
       png_set_bgr(png_ptr);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
 #endif
 
-#ifdef PNG_WRITE_SWAP_SUPPORTED
    /* Swap bytes of 16-bit files to most significant byte first */
    if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+#ifdef PNG_WRITE_SWAP_SUPPORTED
       png_set_swap(png_ptr);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
 #endif
 
-#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
    /* Swap bits of 1, 2, 4 bit packed pixel formats */
    if (transforms & PNG_TRANSFORM_PACKSWAP)
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
       png_set_packswap(png_ptr);
+#else
+      png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
 #endif
 
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
    /* Invert the alpha channel from opacity to transparency */
    if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+#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 */
-   if (info_ptr->valid & PNG_INFO_IDAT)
-       png_write_image(png_ptr, info_ptr->row_pointers);
+   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(transforms)   /* Quiet compiler warnings */
    PNG_UNUSED(params)
 }
 #endif
diff --git a/pngwutil.c b/pngwutil.c
index 49e6a2d..755bbdb 100644
--- a/pngwutil.c
+++ b/pngwutil.c
@@ -2309,7 +2309,8 @@
  * been specified by the application, and then writes the row out with the
  * chosen filter.
  */
-static void png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
+static void
+png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
    png_size_t row_bytes);
 
 #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
diff --git a/projects/vstudio/readme.txt b/projects/vstudio/readme.txt
index d88d98c..2ee18ff 100644
--- a/projects/vstudio/readme.txt
+++ b/projects/vstudio/readme.txt
@@ -1,7 +1,7 @@
 
 VisualStudio instructions
 
-libpng version 1.6.9 - February 6, 2014
+libpng version 1.6.10 - March 6, 2014
 
 Copyright (c) 1998-2010 Glenn Randers-Pehrson
 
diff --git a/projects/vstudio/zlib.props b/projects/vstudio/zlib.props
index 9d894dd..8438f36 100644
--- a/projects/vstudio/zlib.props
+++ b/projects/vstudio/zlib.props
@@ -2,7 +2,7 @@
 <!--
  * zlib.props - location of zlib source
  *
- * libpng version 1.6.9 - February 6, 2014
+ * libpng version 1.6.10 - March 6, 2014
  *
  * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  *
diff --git a/scripts/README.txt b/scripts/README.txt
index f0b7267..c468d97 100644
--- a/scripts/README.txt
+++ b/scripts/README.txt
@@ -1,9 +1,9 @@
 
-Makefiles for  libpng version 1.6.9 - February 6, 2014
+Makefiles for  libpng version 1.6.10 - March 6, 2014
 
 pnglibconf.h.prebuilt       =>  Stores configuration settings
  makefile.linux    =>  Linux/ELF makefile
-                       (gcc, creates libpng16.so.16.1.6.9)
+                       (gcc, creates libpng16.so.16.1.6.10)
  makefile.gcc      =>  Generic makefile (gcc, creates static libpng.a)
  makefile.knr      =>  Archaic UNIX Makefile that converts files with
                        ansi2knr (Requires ansi2knr.c from
@@ -20,7 +20,7 @@
  makefile.dec      =>  DEC Alpha UNIX makefile
  makefile.dj2      =>  DJGPP 2 makefile
  makefile.elf      =>  Linux/ELF makefile symbol versioning,
-                       (gcc, creates libpng16.so.16.1.6.9)
+                       (gcc, creates libpng16.so.16.1.6.10)
  makefile.freebsd  =>  FreeBSD makefile
  makefile.gcc      =>  Generic gcc makefile
  makefile.hpgcc    =>  HPUX makefile using gcc
@@ -35,12 +35,12 @@
  makefile.os2      =>  OS/2 Makefile (gcc and emx, requires libpng.def)
  makefile.sco      =>  For SCO OSr5  ELF and Unixware 7 with Native cc
  makefile.sggcc    =>  Silicon Graphics (gcc,
-                       creates libpng16.so.16.1.6.9)
+                       creates libpng16.so.16.1.6.10)
  makefile.sgi      =>  Silicon Graphics IRIX makefile (cc, creates static lib)
  makefile.solaris  =>  Solaris 2.X makefile (gcc,
-                       creates libpng16.so.16.1.6.9)
+                       creates libpng16.so.16.1.6.10)
  makefile.so9      =>  Solaris 9 makefile (gcc,
-                       creates libpng16.so.16.1.6.9)
+                       creates libpng16.so.16.1.6.10)
  makefile.std      =>  Generic UNIX makefile (cc, creates static libpng.a)
  makefile.sunos    =>  Sun makefile
  makefile.32sunu   =>  Sun Ultra 32-bit makefile
diff --git a/scripts/def.dfn b/scripts/def.dfn
index 40f7654..c4b5a38 100644
--- a/scripts/def.dfn
+++ b/scripts/def.dfn
@@ -21,7 +21,7 @@
 PNG_DFN "OS2 CODE PRELOAD MOVEABLE DISCARDABLE"
 PNG_DFN ""
 PNG_DFN "EXPORTS"
-PNG_DFN ";Version 1.6.9"
+PNG_DFN ";Version 1.6.10"
 
 #define PNG_EXPORTA(ordinal, type, name, args, attributes)\
         PNG_DFN "@" SYMBOL_PREFIX "@@" name "@"
diff --git a/scripts/dfn.awk b/scripts/dfn.awk
index 89b92d5..afa498c 100644
--- a/scripts/dfn.awk
+++ b/scripts/dfn.awk
Binary files differ
diff --git a/scripts/intprefix.dfn b/scripts/intprefix.dfn
index 790bdfe..fa59f88 100644
--- a/scripts/intprefix.dfn
+++ b/scripts/intprefix.dfn
@@ -15,5 +15,8 @@
 #define PNG_INTERNAL_FUNCTION(type, name, args, attributes)\
         PNG_DFN "@" name "@"
 
+#define PNG_INTERNAL_CALLBACK(type, name, args, attributes)\
+        PNG_DFN "@" name "@"
+
 #define PNGPREFIX_H /* self generation */
 #include "../pngpriv.h"
diff --git a/scripts/libpng-config-head.in b/scripts/libpng-config-head.in
index 51b861e..462de74 100755
--- a/scripts/libpng-config-head.in
+++ b/scripts/libpng-config-head.in
@@ -11,7 +11,7 @@
 
 # Modeled after libxml-config.
 
-version=1.6.9
+version=1.6.10
 prefix=""
 libdir=""
 libs=""
diff --git a/scripts/libpng.pc.in b/scripts/libpng.pc.in
index 9395df4..1ae258b 100644
--- a/scripts/libpng.pc.in
+++ b/scripts/libpng.pc.in
@@ -5,6 +5,6 @@
 
 Name: libpng
 Description: Loads and saves PNG files
-Version: 1.6.9
+Version: 1.6.10
 Libs: -L${libdir} -lpng16
 Cflags: -I${includedir}
diff --git a/scripts/makefile.cegcc b/scripts/makefile.cegcc
index f2179b7..e2ff273 100644
--- a/scripts/makefile.cegcc
+++ b/scripts/makefile.cegcc
@@ -23,7 +23,7 @@
 
 VERMAJ = 1
 VERMIN = 6
-VERMIC = 9
+VERMIC = 10
 VER = $(VERMAJ).$(VERMIN).$(VERMIC)
 NAME = libpng
 PACKAGE = $(NAME)-$(VER)
diff --git a/scripts/makefile.linux b/scripts/makefile.linux
index 5727249..73a30c8 100644
--- a/scripts/makefile.linux
+++ b/scripts/makefile.linux
@@ -10,7 +10,7 @@
 # Library name:
 LIBNAME = libpng16
 PNGMAJ = 16
-RELEASE = 9
+RELEASE = 10
 
 # Shared library names:
 LIBSO=$(LIBNAME).so
diff --git a/scripts/makefile.msys b/scripts/makefile.msys
index 0a5727f..69fbb4d 100644
--- a/scripts/makefile.msys
+++ b/scripts/makefile.msys
@@ -18,7 +18,7 @@
 # Library name:
 LIBNAME = libpng16
 PNGMAJ = 16
-RELEASE = 9
+RELEASE = 10
 
 # Shared library names:
 LIBSO=$(LIBNAME).dll
diff --git a/scripts/makefile.ne12bsd b/scripts/makefile.ne12bsd
index 649acdd..783e5d5 100644
--- a/scripts/makefile.ne12bsd
+++ b/scripts/makefile.ne12bsd
@@ -17,7 +17,7 @@
 
 LIB=	png16
 SHLIB_MAJOR=	0
-SHLIB_MINOR=	1.6.9
+SHLIB_MINOR=	1.6.10
 SRCS=	png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \
 	pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \
 	pngwtran.c pngmem.c pngerror.c pngpread.c
diff --git a/scripts/makefile.netbsd b/scripts/makefile.netbsd
index a16dae8..af4eb93 100644
--- a/scripts/makefile.netbsd
+++ b/scripts/makefile.netbsd
@@ -17,7 +17,7 @@
 
 LIB=	png
 SHLIB_MAJOR=	16
-SHLIB_MINOR=	1.6.9
+SHLIB_MINOR=	1.6.10
 SRCS=	png.c pngset.c pngget.c pngrutil.c pngtrans.c pngwutil.c \
 	pngread.c pngrio.c pngwio.c pngwrite.c pngrtran.c \
 	pngwtran.c pngmem.c pngerror.c pngpread.c
diff --git a/scripts/makefile.openbsd b/scripts/makefile.openbsd
index 69b1ecc..c61fa2e 100644
--- a/scripts/makefile.openbsd
+++ b/scripts/makefile.openbsd
@@ -11,7 +11,7 @@
 MANDIR= ${PREFIX}/man/cat
 
 SHLIB_MAJOR=	16
-SHLIB_MINOR=	1.6.9
+SHLIB_MINOR=	1.6.10
 
 LIB=	png
 SRCS=	png.c pngerror.c pngget.c pngmem.c pngpread.c \
diff --git a/scripts/pnglibconf.dfa b/scripts/pnglibconf.dfa
index b173bb1..4d4ea8a 100755
--- a/scripts/pnglibconf.dfa
+++ b/scripts/pnglibconf.dfa
@@ -164,7 +164,7 @@
 
 # NONE
 
-# Note that PNG_USR_CONFIG only has an effect when building
+# Note that PNG_USER_CONFIG only has an effect when building
 # pnglibconf.h
 
 setting USER_CONFIG
@@ -578,8 +578,9 @@
 option COLORSPACE enables GAMMA disabled
 
 # When an ICC profile is read, or png_set, it will be checked for a match
-# against known sRGB profiles if the sRGB handling is enabled.  This
-# setting controls how much work is done during the check:
+# against known sRGB profiles if the sRGB handling is enabled.  The
+# PNG_sRGB_PROFILE_CHECKS setting controls how much work is done during the
+# check:
 #
 # 0: Just validate the profile MD5 signature if present, otherwise use
 #    the checks in option 1.
diff --git a/scripts/pnglibconf.h.prebuilt b/scripts/pnglibconf.h.prebuilt
index 8ad56db..9d4ef5a 100644
--- a/scripts/pnglibconf.h.prebuilt
+++ b/scripts/pnglibconf.h.prebuilt
@@ -1,8 +1,8 @@
-/* libpng 1.6.9 STANDARD API DEFINITION */
+/* libpng 1.6.10 STANDARD API DEFINITION */
 
 /* pnglibconf.h - library build configuration */
 
-/* Libpng version 1.6.9 - February 6, 2014 */
+/* Libpng version 1.6.10 - March 6, 2014 */
 
 /* Copyright (c) 1998-2013 Glenn Randers-Pehrson */
 
diff --git a/scripts/symbols.def b/scripts/symbols.def
index 61e4769..f509932 100644
--- a/scripts/symbols.def
+++ b/scripts/symbols.def
@@ -1,4 +1,4 @@
-;Version 1.6.9
+;Version 1.6.10
 ;--------------------------------------------------------------
 ; LIBPNG symbol list as a Win32 DEF file
 ; Contains all the symbols that can be exported from libpng
diff --git a/tests/pngimage-full b/tests/pngimage-full
new file mode 100755
index 0000000..f5eb989
--- /dev/null
+++ b/tests/pngimage-full
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec ./pngimage --exhaustive --log "${srcdir}/contrib/pngsuite/"*.png
diff --git a/tests/pngimage-quick b/tests/pngimage-quick
new file mode 100755
index 0000000..2d4b5db
--- /dev/null
+++ b/tests/pngimage-quick
@@ -0,0 +1,2 @@
+#!/bin/sh
+exec ./pngimage --log "${srcdir}/contrib/pngsuite/"*.png