DO NOT MERGE Update libpng to 1.6.20 am: cf8a579007 am: a0b5142c6c am: 34dcc2af83  -s ours am: 3aec76d873  -s ours am: 9cac6eee10 am: c34faaeec7 am: 8ecc2c0512  -s ours am: 89d19aa8f1 am: 9a9e74b2ec am: 0f95eaef8e
am: fd18529232  -s ours

* commit 'fd1852923233f8430da35126201245bcc06ac4e6':
  DO NOT MERGE Update libpng to 1.6.20

Change-Id: I4d46b6b8fcc4bcf613b4d454e92c0cd4356784dc
diff --git a/ANNOUNCE b/ANNOUNCE
index 4dae783..c5ba025 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,47 +1,72 @@
-Libpng 1.6.20 - December 3, 2015
+Libpng 1.6.22beta03 - February 19, 2016
 
-This is a public release of libpng, intended for use in production codes.
+This is not intended to be a public release.  It will be replaced
+within a few weeks by a public version or by another test version.
 
 Files available for download:
 
 Source files with LF line endings (for Unix/Linux) and with a
 "configure" script
 
-   libpng-1.6.20.tar.xz (LZMA-compressed, recommended)
-   libpng-1.6.20.tar.gz
+   1.6.22beta03.tar.xz (LZMA-compressed, recommended)
+   1.6.22beta03.tar.gz
 
 Source files with CRLF line endings (for Windows), without the
 "configure" script
 
-   /scratch/glennrp/Libpng16/lpng1620.7z  (LZMA-compressed, recommended)
-   /scratch/glennrp/Libpng16/lpng1620.zip
+   lp1622b03.7z  (LZMA-compressed, recommended)
+   lp1622b03.zip
 
 Other information:
 
-   libpng-1.6.20-README.txt
-   libpng-1.6.20-LICENSE.txt
-   libpng-1.6.20-*.asc (armored detached GPG signatures)
+   1.6.22beta03-README.txt
+   1.6.22beta03-LICENSE.txt
+   libpng-1.6.22beta03-*.asc (armored detached GPG signatures)
 
-Changes since the last public release (1.6.19):
-  Avoid potential pointer overflow/underflow in png_handle_sPLT() and
-    png_handle_pCAL() (Bug report by John Regehr).
-  Fixed incorrect implementation of png_set_PLTE() that uses png_ptr
-    not info_ptr, that left png_set_PLTE() open to the CVE-2015-8126
-    vulnerability.
-  Backported tests from libpng-1.7.0beta69.
-  Fixed an error in handling of bad zlib CMINFO field in pngfix, found by
-    American Fuzzy Lop, reported by Brian Carpenter.  inflate() doesn't
-    immediately fault a bad CMINFO field; instead a 'too far back' error
-    happens later (at least some times).  pngfix failed to limit CMINFO to
-    the allowed values but then assumed that window_bits was in range,
-    triggering an assert. The bug is mostly harmless; the PNG file cannot
-    be fixed.
-  In libpng 1.6 zlib initialization was changed to use the window size
-    in the zlib stream, not a fixed value. This causes some invalid images,
-    where CINFO is too large, to display 'correctly' if the rest of the
-    data is valid.  This provides a workaround for zlib versions where the
-    error arises (ones that support the API change to use the window size
-    in the stream).
+Changes since the last public release (1.6.21):
+
+Version 1.6.22beta01 [January 23, 2016]
+  Changed PNG_USE_MKSTEMP to __COVERITY__ to select alternate
+    "tmpfile()" implementation in contrib/libtests/pngstest.c
+  Fixed NO_STDIO build of pngunknown.c to skip calling png_init_io()
+    if there is no stdio.h support.
+  Added a png_image_write_to_memory() API and a number of assist macros
+    to allow an application that uses the simplified API write to bypass
+    stdio and write directly to memory.
+  Added some warnings (png.h) and some check code to detect *possible*
+    overflow in the ROW_STRIDE and simplified image SIZE macros.  This
+    disallows image width/height/format that *might* overflow.  This is
+    a quiet API change that limits in-memory image size (uncompressed) to
+    less than 4GByte and image row size (stride) to less than 2GByte.
+  Revised workaround for false-positive Coverity issue in pngvalid.c.
+
+Version 1.6.22beta02 [February 8, 2016]
+  Only use exit(77) in configure builds.
+  Corrected error in PNG_IMAGE_PNG_SIZE_MAX. This new macro underreported
+    the palette size because it failed to take into account that the memory
+    palette has to be expanded to full RGB when it is written to PNG.
+  Updated CMakeLists.txt, added supporting scripts/gen*.cmake.in
+    and test.cmake.in (Roger Leigh).
+  Relaxed limit checks on gamma values in pngrtran.c. As suggested in
+    the comments gamma values outside the range currently permitted
+    by png_set_alpha_mode are useful for HDR data encoding.  These values
+    are already permitted by png_set_gamma so it is reasonable caution to
+    extend the png_set_alpha_mode range as HDR imaging systems are starting
+    to emerge.
+
+Version 1.6.22beta03 [February 19, 2016]
+  Added a common-law trademark notice and export control information
+    to the LICENSE file, png.h, and the man page.
+  Restored "& 0xff" in png_save_uint_16() and png_save_uint_32() that
+    were accidentally removed from libpng-1.6.17. 
+  Changed PNG_INFO_cHNK and PNG_FREE_cHNK from 0xnnnn to 0xnnnnU in png.h
+    (Robert C. Seacord).
+  Removed dubious "#if INT_MAX" test from png.h that was added to
+    libpng-1.6.19beta02 (John Bowler).
+  Add ${INCLUDES} in scripts/genout.cmake.in (Bug report by Nixon Kwok).
+  Updated LICENSE to say files in the contrib directory are not
+    necessarily under the libpng license, and that some makefiles have
+    other copyright owners.
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/Android.mk b/Android.mk
index 959b73c..14aba91 100644
--- a/Android.mk
+++ b/Android.mk
@@ -4,21 +4,21 @@
 # and the host (as a static library for tools to use).
 
 common_SRC_FILES := \
-	png.c \
-	pngerror.c \
-	pngget.c \
-	pngmem.c \
-	pngpread.c \
-	pngread.c \
-	pngrio.c \
-	pngrtran.c \
-	pngrutil.c \
-	pngset.c \
-	pngtrans.c \
-	pngwio.c \
-	pngwrite.c \
-	pngwtran.c \
-	pngwutil.c \
+    png.c \
+    pngerror.c \
+    pngget.c \
+    pngmem.c \
+    pngpread.c \
+    pngread.c \
+    pngrio.c \
+    pngrtran.c \
+    pngrutil.c \
+    pngset.c \
+    pngtrans.c \
+    pngwio.c \
+    pngwrite.c \
+    pngwtran.c \
+    pngwutil.c \
 
 ifeq ($(ARCH_ARM_HAVE_NEON),true)
 my_cflags_arm := -DPNG_ARM_NEON_OPT=2
@@ -26,44 +26,77 @@
 
 my_cflags_arm64 := -DPNG_ARM_NEON_OPT=2
 
-# BUG: http://llvm.org/PR19472 - SLP vectorization (on ARM at least) crashes
-# when we can't lower a vectorized bswap.
-my_cflags_arm += -fno-slp-vectorize
-
 my_src_files_arm := \
-			arm/arm_init.c \
-			arm/filter_neon.S \
-			arm/filter_neon_intrinsics.c
+    arm/arm_init.c \
+    arm/filter_neon.S \
+    arm/filter_neon_intrinsics.c
 
+my_cflags_intel := -DPNG_INTEL_SSE_OPT=1
 
-common_CFLAGS := -std=gnu89 #-fvisibility=hidden ## -fomit-frame-pointer
+my_src_files_intel := \
+    contrib/intel/intel_init.c \
+    contrib/intel/filter_sse2_intrinsics.c
+
+common_CFLAGS := -std=gnu89 -Wno-unused-parameter #-fvisibility=hidden ## -fomit-frame-pointer
 
 # For the host
 # =====================================================
 
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES := $(common_SRC_FILES)
+LOCAL_SRC_FILES_x86 += $(my_src_files_intel)
+LOCAL_SRC_FILES_x86_64 += $(my_src_files_intel)
 LOCAL_CFLAGS += $(common_CFLAGS)
+LOCAL_CFLAGS_x86 += $(my_cflags_intel)
+LOCAL_CFLAGS_x86_64 += $(my_cflags_intel)
 LOCAL_ASFLAGS += $(common_ASFLAGS)
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
 LOCAL_STATIC_LIBRARIES := libz
 LOCAL_MODULE:= libpng
+LOCAL_MODULE_HOST_OS := darwin linux windows
 include $(BUILD_HOST_STATIC_LIBRARY)
 
 
-# For the device (static)
+# For the device (static) for NDK
 # =====================================================
 
 include $(CLEAR_VARS)
 LOCAL_CLANG := true
 LOCAL_SRC_FILES := $(common_SRC_FILES)
+LOCAL_SRC_FILES_arm := $(my_src_files_arm)
+LOCAL_SRC_FILES_arm64 := $(my_src_files_arm)
+LOCAL_SRC_FILES_x86 += $(my_src_files_intel)
+LOCAL_SRC_FILES_x86_64 += $(my_src_files_intel)
 LOCAL_CFLAGS += $(common_CFLAGS) -ftrapv
 LOCAL_CFLAGS_arm := $(my_cflags_arm)
-LOCAL_ASFLAGS += $(common_ASFLAGS)
-LOCAL_SRC_FILES_arm := $(my_src_files_arm)
 LOCAL_CFLAGS_arm64 := $(my_cflags_arm64)
+LOCAL_CFLAGS_x86 += $(my_cflags_intel)
+LOCAL_CFLAGS_x86_64 += $(my_cflags_intel)
+LOCAL_ASFLAGS += $(common_ASFLAGS)
+LOCAL_SANITIZE := never
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+LOCAL_SHARED_LIBRARIES := libz
+LOCAL_MODULE:= libpng_ndk
+LOCAL_SDK_VERSION := 14
+include $(BUILD_STATIC_LIBRARY)
+
+# For the device (static) for platform (retains fortify support)
+# =====================================================
+
+include $(CLEAR_VARS)
+LOCAL_CLANG := true
+LOCAL_SRC_FILES := $(common_SRC_FILES)
+LOCAL_SRC_FILES_arm := $(my_src_files_arm)
 LOCAL_SRC_FILES_arm64 := $(my_src_files_arm)
-LOCAL_ADDRESS_SANITIZER := false
+LOCAL_SRC_FILES_x86 += $(my_src_files_intel)
+LOCAL_SRC_FILES_x86_64 += $(my_src_files_intel)
+LOCAL_CFLAGS += $(common_CFLAGS) -ftrapv
+LOCAL_CFLAGS_arm := $(my_cflags_arm)
+LOCAL_CFLAGS_arm64 := $(my_cflags_arm64)
+LOCAL_CFLAGS_x86 += $(my_cflags_intel)
+LOCAL_CFLAGS_x86_64 += $(my_cflags_intel)
+LOCAL_ASFLAGS += $(common_ASFLAGS)
+LOCAL_SANITIZE := never
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
 LOCAL_SHARED_LIBRARIES := libz
 LOCAL_MODULE:= libpng
@@ -75,12 +108,16 @@
 include $(CLEAR_VARS)
 LOCAL_CLANG := true
 LOCAL_SRC_FILES := $(common_SRC_FILES)
+LOCAL_SRC_FILES_arm := $(my_src_files_arm)
+LOCAL_SRC_FILES_arm64 := $(my_src_files_arm)
+LOCAL_SRC_FILES_x86 += $(my_src_files_intel)
+LOCAL_SRC_FILES_x86_64 += $(my_src_files_intel)
 LOCAL_CFLAGS += $(common_CFLAGS) -ftrapv
 LOCAL_CFLAGS_arm := $(my_cflags_arm)
-LOCAL_ASFLAGS += $(common_ASFLAGS)
-LOCAL_SRC_FILES_arm := $(my_src_files_arm)
 LOCAL_CFLAGS_arm64 := $(my_cflags_arm64)
-LOCAL_SRC_FILES_arm64 := $(my_src_files_arm)
+LOCAL_CFLAGS_x86 += $(my_cflags_intel)
+LOCAL_CFLAGS_x86_64 += $(my_cflags_intel)
+LOCAL_ASFLAGS += $(common_ASFLAGS)
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
 LOCAL_SHARED_LIBRARIES := libz
 LOCAL_MODULE:= libpng
diff --git a/CHANGES b/CHANGES
index 28094fd..f9c8cf2 100644
--- a/CHANGES
+++ b/CHANGES
@@ -5421,7 +5421,7 @@
 Version 1.6.20beta02 [November 23, 2015]
   Fixed incorrect implementation of png_set_PLTE() that uses png_ptr
     not info_ptr, that left png_set_PLTE() open to the CVE-2015-8126
-    vulnerability.
+    vulnerability.  Fixes CVE-2015-8472.
 
 Version 1.6.20beta03 [November 24, 2015]
   Backported tests from libpng-1.7.0beta69.
@@ -5446,6 +5446,87 @@
 Version 1.6.20 [December 3, 2015]
   No changes.
 
+Version 1.6.21beta01 [December 11, 2015]
+  Fixed syntax "$(command)" in tests/pngstest that some shells other than
+    bash could not parse (Bug report by Nelson Beebe). Use `command` instead.
+
+Version 1.6.21beta02 [December 14, 2015]
+  Moved png_check_keyword() from pngwutil.c to pngset.c
+  Removed LE/BE dependencies in pngvalid, to 'fix' the current problem
+    in the BigEndian tests by not testing it, making the BE code the same 
+    as the LE version.
+  Fixes to pngvalid for various reduced build configurations (eliminate unused
+    statics) and a fix for the case in rgb_to_gray when the digitize option
+    reduces graylo to 0, producing a large error.
+
+Version 1.6.21beta03 [December 18, 2015]
+  Widened the 'limit' check on the internally calculated error limits in
+    the 'DIGITIZE' case (the code used prior to 1.7 for rgb_to_gray error
+    checks) and changed the check to only operate in non-release builds
+    (base build type not RC or RELEASE.)
+  Fixed undefined behavior in pngvalid.c, undefined because
+    (png_byte) << shift is undefined if it changes the signed bit
+    (because png_byte is promoted to int). The libpng exported functions
+    png_get_uint_32 and png_get_uint_16 handle this. (Bug reported by
+    David Drysdale as a result of reports from UBSAN in clang 3.8).
+  This changes pngvalid to use BE random numbers; this used to produce
+    errors but these should not be fixed as a result of the previous changes.
+
+Version 1.6.21rc01 [January 4, 2016]
+  In projects/vstudio, combined readme.txt and WARNING into README.txt
+
+Version 1.6.21rc02 [January 7, 2016]
+  Relocated assert() in contrib/tools/pngfix.c, bug found by American
+    Fuzzy Lop, reported by Brian Carpenter.
+  Marked 'limit' UNUSED in transform_range_check().  This only affects
+    release builds.
+
+Version 1.6.21 [January 15, 2016]
+  Worked around a false-positive Coverity issue in pngvalid.c.
+
+Version 1.6.22beta01 [January 23, 2016]
+  Changed PNG_USE_MKSTEMP to __COVERITY__ to select alternate
+    "tmpfile()" implementation in contrib/libtests/pngstest.c
+  Fixed NO_STDIO build of pngunknown.c to skip calling png_init_io()
+    if there is no stdio.h support.
+  Added a png_image_write_to_memory() API and a number of assist macros
+    to allow an application that uses the simplified API write to bypass
+    stdio and write directly to memory.
+  Added some warnings (png.h) and some check code to detect *possible*
+    overflow in the ROW_STRIDE and simplified image SIZE macros.  This
+    disallows image width/height/format that *might* overflow.  This is
+    a quiet API change that limits in-memory image size (uncompressed) to
+    less than 4GByte and image row size (stride) to less than 2GByte.
+  Revised workaround for false-positive Coverity issue in pngvalid.c.
+
+Version 1.6.22beta02 [February 8, 2016]
+  Only use exit(77) in configure builds.
+  Corrected error in PNG_IMAGE_PNG_SIZE_MAX. This new macro underreported
+    the palette size because it failed to take into account that the memory
+    palette has to be expanded to full RGB when it is written to PNG.
+  Updated CMakeLists.txt, added supporting scripts/gen*.cmake.in
+    and test.cmake.in (Roger Leigh).
+  Relaxed limit checks on gamma values in pngrtran.c. As suggested in
+    the comments gamma values outside the range currently permitted
+    by png_set_alpha_mode are useful for HDR data encoding.  These values
+    are already permitted by png_set_gamma so it is reasonable caution to
+    extend the png_set_alpha_mode range as HDR imaging systems are starting
+    to emerge.
+
+Version 1.6.22beta03 [February 19, 2016]
+  Added a common-law trademark notice and export control information
+    to the LICENSE file, png.h, and the man page.
+  Restored "& 0xff" in png_save_uint_16() and png_save_uint_32() that
+    were accidentally removed from libpng-1.6.17. 
+  Changed PNG_INFO_cHNK and PNG_FREE_cHNK from 0xnnnn to 0xnnnnU in png.h
+    (Robert C. Seacord).
+  Removed dubious "#if INT_MAX" test from png.h that was added to
+    libpng-1.6.19beta02 (John Bowler).
+  Add ${INCLUDES} in scripts/genout.cmake.in (Bug report by Nixon Kwok).
+  Updated LICENSE to say files in the contrib directory are not
+    necessarily under the libpng license, and that some makefiles have
+    other copyright owners.
+
 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 7bc49c5..3afe215 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,13 +1,32 @@
 # CMakeLists.txt
 
-# Copyright (C) 2007-2015 Glenn Randers-Pehrson
+# Copyright (C) 2007,2009-2016 Glenn Randers-Pehrson
+# Written by Christian Ehrlicher, 2007
+# Revised by Roger Lowman, 2009-2010
+# Revised by Clifford Yapp, 2011-2012
+# Revised by Roger Leigh, 2016
 
 # This code is released under the libpng license.
 # For conditions of distribution and use, see the disclaimer
 # and license in png.h
 
-cmake_minimum_required(VERSION 2.4.4)
-set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
+cmake_minimum_required(VERSION 2.8.3)
+cmake_policy(VERSION 2.8.3)
+
+# Set MacOSX @rpath usage globally.
+if (POLICY CMP0020)
+  cmake_policy(SET CMP0020 NEW)
+endif(POLICY CMP0020)
+if (POLICY CMP0042)
+  cmake_policy(SET CMP0042 NEW)
+endif(POLICY CMP0042)
+# Use new variable expansion policy.
+if (POLICY CMP0053)
+  cmake_policy(SET CMP0053 NEW)
+endif(POLICY CMP0053)
+if (POLICY CMP0054)
+  cmake_policy(SET CMP0054 NEW)
+endif(POLICY CMP0054)
 
 set(CMAKE_CONFIGURATION_TYPES "Release;Debug;MinSizeRel;RelWithDebInfo")
 
@@ -16,7 +35,7 @@
 
 set(PNGLIB_MAJOR 1)
 set(PNGLIB_MINOR 6)
-set(PNGLIB_RELEASE 20)
+set(PNGLIB_RELEASE 22)
 set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR})
 set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE})
 
@@ -47,32 +66,284 @@
 option(PNG_DEBUG     "Build with debug output" OFF)
 option(PNGARG        "Disable ANSI-C prototypes" OFF)
 
+set(PNG_PREFIX "" CACHE STRING "Prefix to add to the API function names")
+set(DFA_XTRA "" CACHE FILEPATH "File containing extra configuration settings")
+
 # SET LIBNAME
 set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR})
 
 # to distinguish between debug and release lib
 set(CMAKE_DEBUG_POSTFIX "d")
 
-# Use the prebuilt pnglibconf.h file from the scripts folder
-# TODO: fix this by building with awk; without this no cmake build can be
-# configured directly (to do so indirectly use your local awk to build a
-# pnglibconf.h in the build directory.)
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt
-               ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h)
+include(CheckCSourceCompiles)
+option(ld-version-script "Enable linker version script" ON)
+if(ld-version-script AND NOT APPLE)
+  # Check if LD supports linker scripts.
+  file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map" "VERS_1 {
+        global: sym;
+        local: *;
+};
+
+VERS_2 {
+        global: sym2;
+                main;
+} VERS_1;
+")
+  set(CMAKE_REQUIRED_FLAGS_SAVE ${CMAKE_REQUIRED_FLAGS})
+  set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/conftest.map'")
+  check_c_source_compiles("void sym(void) {}
+void sym2(void) {}
+int main(void) {return 0;}
+" HAVE_LD_VERSION_SCRIPT)
+  if(NOT HAVE_LD_VERSION_SCRIPT)
+    set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE} "-Wl,-M -Wl,${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
+  check_c_source_compiles("void sym(void) {}
+void sym2(void) {}
+int main(void) {return 0;}
+" HAVE_SOLARIS_LD_VERSION_SCRIPT)
+  endif()
+  set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS_SAVE})
+  file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map")
+endif()
+
+# Find symbol prefix.  Likely obsolete and unnecessary with recent
+# toolchains (it's not done in many other projects).
+function(symbol_prefix)
+  set(SYMBOL_PREFIX)
+
+  execute_process(COMMAND "${CMAKE_C_COMPILER}" "-E" "-"
+                  INPUT_FILE /dev/null
+                  OUTPUT_VARIABLE OUT
+                  RESULT_VARIABLE STATUS)
+
+  if(CPP_FAIL)
+    message(WARNING "Failed to run the C preprocessor")
+  endif()
+
+  string(REPLACE "\n" ";" OUT "${OUT}")
+  foreach(line ${OUT})
+    string(REGEX MATCH "^PREFIX=" found_match "${line}")
+    if(found_match)
+      STRING(REGEX REPLACE "^PREFIX=(.*\)" "\\1" prefix "${line}")
+      string(REGEX MATCH "__USER_LABEL_PREFIX__" found_match "${prefix}")
+      if(found_match)
+        STRING(REGEX REPLACE "(.*)__USER_LABEL_PREFIX__(.*)" "\\1\\2" prefix "${prefix}")
+      endif()
+      set(SYMBOL_PREFIX "${prefix}")
+    endif()
+  endforeach()
+
+    message(STATUS "Symbol prefix: ${SYMBOL_PREFIX}")
+    set(SYMBOL_PREFIX "${SYMBOL_PREFIX}" PARENT_SCOPE)
+endfunction()
+
+if(UNIX)
+  symbol_prefix()
+endif()
+
+find_program(AWK NAMES gawk awk)
+
 include_directories(${CMAKE_CURRENT_BINARY_DIR})
 
+if(NOT AWK)
+  # No awk available to generate sources; use pre-built pnglibconf.h
+  configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt
+                 ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h)
+  add_custom_target(genfiles) # Dummy
+else()
+  include(CMakeParseArguments)
+  # Generate .chk from .out with awk
+  # generate_chk(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]])
+  function(generate_chk)
+    set(options)
+    set(oneValueArgs INPUT OUTPUT)
+    set(multiValueArgs DEPENDS)
+    cmake_parse_arguments(_GC "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+    if (NOT _GC_INPUT)
+      message(FATAL_ERROR "Invalid arguments.  generate_out requires input.")
+    endif()
+    if (NOT _GC_OUTPUT)
+      message(FATAL_ERROR "Invalid arguments.  generate_out requires output.")
+    endif()
+
+    add_custom_command(OUTPUT "${_GC_OUTPUT}"
+                       COMMAND "${CMAKE_COMMAND}"
+                               "-DINPUT=${_GC_INPUT}"
+                               "-DOUTPUT=${_GC_OUTPUT}"
+                               -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/genchk.cmake"
+                       DEPENDS "${_GC_INPUT}" ${_GC_DEPENDS}
+                       WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+  endfunction()
+
+  # Generate .out from .c with awk
+  # generate_out(INPUT inputfile OUTPUT outputfile [DEPENDS dep1 [dep2...]])
+  function(generate_out)
+    set(options)
+    set(oneValueArgs INPUT OUTPUT)
+    set(multiValueArgs DEPENDS)
+    cmake_parse_arguments(_GO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+    if (NOT _GO_INPUT)
+      message(FATAL_ERROR "Invalid arguments.  generate_out requires input.")
+    endif()
+    if (NOT _GO_OUTPUT)
+      message(FATAL_ERROR "Invalid arguments.  generate_out requires output.")
+    endif()
+
+    add_custom_command(OUTPUT "${_GO_OUTPUT}"
+                       COMMAND "${CMAKE_COMMAND}"
+                               "-DINPUT=${_GO_INPUT}"
+                               "-DOUTPUT=${_GO_OUTPUT}"
+                               -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/genout.cmake"
+                       DEPENDS "${_GO_INPUT}" ${_GO_DEPENDS}
+                       WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+  endfunction()
+
+  # Generate specific source file with awk
+  # generate_source(OUTPUT outputfile [DEPENDS dep1 [dep2...]])
+  function(generate_source)
+    set(options)
+    set(oneValueArgs OUTPUT)
+    set(multiValueArgs DEPENDS)
+    cmake_parse_arguments(_GSO "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+    if (NOT _GSO_OUTPUT)
+      message(FATAL_ERROR "Invalid arguments.  generate_source requires output.")
+    endif()
+
+    add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${_GSO_OUTPUT}"
+                       COMMAND "${CMAKE_COMMAND}"
+                               "-DOUTPUT=${_GSO_OUTPUT}"
+                               -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake"
+                       DEPENDS ${_GSO_DEPENDS}
+                       WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+  endfunction()
+
+  # Copy file
+  function(generate_copy source destination)
+    add_custom_command(OUTPUT "${destination}"
+                       COMMAND "${CMAKE_COMMAND}" -E remove "${destination}"
+                       COMMAND "${CMAKE_COMMAND}" -E copy "${source}"
+                                                          "${destination}"
+                       DEPENDS "${source}")
+  endfunction()
+
+  # Generate scripts/pnglibconf.h
+  generate_source(OUTPUT "scripts/pnglibconf.c"
+                  DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa"
+                          "${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk"
+                          "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h")
+
+  # Generate pnglibconf.c
+  generate_source(OUTPUT "pnglibconf.c"
+                  DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.dfa"
+                          "${CMAKE_CURRENT_SOURCE_DIR}/scripts/options.awk"
+                          "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h")
+
+  if(PNG_PREFIX)
+    set(PNGLIBCONF_H_EXTRA_DEPENDS
+        "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
+        "${CMAKE_CURRENT_SOURCE_DIR}/scripts/macro.lst")
+    set(PNGPREFIX_H_EXTRA_DEPENDS
+        "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out")
+  endif()
+
+  generate_out(INPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c"
+               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out")
+
+  # Generate pnglibconf.h
+  generate_source(OUTPUT "pnglibconf.h"
+                  DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
+                          ${PNGLIBCONF_H_EXTRA_DEPENDS})
+
+  generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/intprefix.c"
+               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out"
+               DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
+
+  generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/prefix.c"
+               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
+               DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
+                       "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
+                       "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out")
+
+  # Generate pngprefix.h
+  generate_source(OUTPUT "pngprefix.h"
+                  DEPENDS ${PNGPREFIX_H_EXTRA_DEPENDS})
+
+  generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/sym.c"
+               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
+               DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
+
+  generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.c"
+               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
+               DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
+                       "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
+                       "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt")
+
+  generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/vers.c"
+               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
+               DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h"
+                       "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h"
+                       "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h")
+
+  generate_chk(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
+               OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk"
+               DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/scripts/checksym.awk"
+                       "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.def")
+
+  add_custom_target(symbol-check DEPENDS
+                    "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk")
+
+  generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
+                "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
+  generate_copy("${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out"
+                "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
+
+  add_custom_target(genvers DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers")
+  add_custom_target(gensym DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym")
+
+  add_custom_target("genprebuilt"
+                    COMMAND "${CMAKE_COMMAND}"
+                            "-DOUTPUT=scripts/pnglibconf.h.prebuilt"
+                            -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake"
+                    WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
+
+  # A single target handles generation of all generated files.  If
+  # they are dependend upon separately by multiple targets, this
+  # confuses parallel make (it would require a separate top-level
+  # target for each file to track the dependencies properly).
+  add_custom_target(genfiles DEPENDS
+    "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym"
+    "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers"
+    "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c"
+    "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
+    "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out"
+    "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h"
+    "${CMAKE_CURRENT_BINARY_DIR}/scripts/intprefix.out"
+    "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf.c"
+    "${CMAKE_CURRENT_BINARY_DIR}/scripts/prefix.out"
+    "${CMAKE_CURRENT_BINARY_DIR}/scripts/sym.out"
+    "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.chk"
+    "${CMAKE_CURRENT_BINARY_DIR}/scripts/symbols.out"
+    "${CMAKE_CURRENT_BINARY_DIR}/scripts/vers.out")
+endif(NOT AWK)
+
 # OUR SOURCES
 set(libpng_public_hdrs
   png.h
   pngconf.h
-  ${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h
+  "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h"
 )
-set(libpng_sources
-  ${libpng_public_hdrs}
+set(libpng_private_hdrs
+  pngpriv.h
   pngdebug.h
   pnginfo.h
-  pngpriv.h
   pngstruct.h
+)
+if(AWK)
+  list(APPEND libpng_private_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h")
+endif()
+set(libpng_sources
+  ${libpng_public_hdrs}
+  ${libpng_private_hdrs}
   png.c
   pngerror.c
   pngget.c
@@ -98,7 +369,18 @@
 set(pngstest_sources
   contrib/libtests/pngstest.c
 )
-# SOME NEEDED DEFINITIONS
+set(pngunknown_sources
+  contrib/libtests/pngunknown.c
+)
+set(pngimage_sources
+  contrib/libtests/pngimage.c
+)
+set(pngfix_sources
+  contrib/tools/pngfix.c
+)
+set(png_fix_itxt_sources
+  contrib/tools/png-fix-itxt.c
+)
 
 if(MSVC)
   add_definitions(-D_CRT_SECURE_NO_DEPRECATE)
@@ -114,33 +396,59 @@
 unset(PNG_LIB_TARGETS)
 
 if(PNG_SHARED)
-  add_library(${PNG_LIB_NAME} SHARED ${libpng_sources})
-  set(PNG_LIB_TARGETS ${PNG_LIB_NAME})
+  add_library(png SHARED ${libpng_sources})
+  set(PNG_LIB_TARGETS png)
+  set_target_properties(png PROPERTIES OUTPUT_NAME ${PNG_LIB_NAME})
+  add_dependencies(png genfiles)
   if(MSVC)
     # msvc does not append 'lib' - do it here to have consistent name
-    set_target_properties(${PNG_LIB_NAME} PROPERTIES PREFIX "lib")
-    set_target_properties(${PNG_LIB_NAME} PROPERTIES IMPORT_PREFIX "lib")
+    set_target_properties(png PROPERTIES PREFIX "lib")
+    set_target_properties(png PROPERTIES IMPORT_PREFIX "lib")
   endif()
-  target_link_libraries(${PNG_LIB_NAME} ${ZLIB_LIBRARY} ${M_LIBRARY})
+  target_link_libraries(png ${ZLIB_LIBRARY} ${M_LIBRARY})
+
+  if(UNIX AND AWK)
+    if(HAVE_LD_VERSION_SCRIPT)
+      set_target_properties(png PROPERTIES LINK_FLAGS
+        "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'")
+    elseif(HAVE_SOLARIS_LD_VERSION_SCRIPT)
+      set_target_properties(png PROPERTIES LINK_FLAGS
+        "-Wl,-M -Wl,'${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'")
+    endif()
+  endif()
 endif()
 
 if(PNG_STATIC)
   # does not work without changing name
-  set(PNG_LIB_NAME_STATIC ${PNG_LIB_NAME}_static)
-  add_library(${PNG_LIB_NAME_STATIC} STATIC ${libpng_sources})
-  list(APPEND PNG_LIB_TARGETS ${PNG_LIB_NAME_STATIC})
+  set(PNG_LIB_NAME_STATIC png_static)
+  add_library(png_static STATIC ${libpng_sources})
+  add_dependencies(png_static genfiles)
+  # MSVC doesn't use a different file extension for shared vs. static
+  # libs.  We are able to change OUTPUT_NAME to remove the _static
+  # for all other platforms.
+  if(NOT MSVC)
+    set_target_properties(png_static PROPERTIES
+      OUTPUT_NAME "${PNG_LIB_NAME}"
+      CLEAN_DIRECT_OUTPUT 1)
+  else()
+    set_target_properties(png_static PROPERTIES
+      OUTPUT_NAME "${PNG_LIB_NAME}_static"
+      CLEAN_DIRECT_OUTPUT 1)
+  endif()
+  list(APPEND PNG_LIB_TARGETS png_static)
   if(MSVC)
     # msvc does not append 'lib' - do it here to have consistent name
-    set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES PREFIX "lib")
+    set_target_properties(png_static PROPERTIES PREFIX "lib")
   endif()
-  target_link_libraries(${PNG_LIB_NAME_STATIC} ${ZLIB_LIBRARY} ${M_LIBRARY})
+  target_link_libraries(png_static ${ZLIB_LIBRARY} ${M_LIBRARY})
 endif()
 
 if(PNG_FRAMEWORK)
-  set(PNG_LIB_NAME_FRAMEWORK ${PNG_LIB_NAME}_framework)
-  add_library(${PNG_LIB_NAME_FRAMEWORK} SHARED ${libpng_sources})
-  list(APPEND PNG_LIB_TARGETS ${PNG_LIB_NAME_FRAMEWORK})
-  set_target_properties(${PNG_LIB_NAME_FRAMEWORK} PROPERTIES
+  set(PNG_LIB_NAME_FRAMEWORK png_framework)
+  add_library(png_framework SHARED ${libpng_sources})
+  add_dependencies(png_framework genfiles)
+  list(APPEND PNG_LIB_TARGETS png_framework)
+  set_target_properties(png_framework PROPERTIES
     FRAMEWORK TRUE
     FRAMEWORK_VERSION ${PNGLIB_VERSION}
     MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${PNGLIB_MAJOR}.${PNGLIB_MINOR}
@@ -149,7 +457,7 @@
     XCODE_ATTRIBUTE_INSTALL_PATH "@rpath"
     PUBLIC_HEADER "${libpng_public_hdrs}"
     OUTPUT_NAME png)
-  target_link_libraries(${PNG_LIB_NAME_FRAMEWORK} ${ZLIB_LIBRARY} ${M_LIBRARY})
+  target_link_libraries(png_framework ${ZLIB_LIBRARY} ${M_LIBRARY})
 endif()
 
 if(NOT PNG_LIB_TARGETS)
@@ -160,52 +468,170 @@
 endif()
 
 if(PNG_SHARED AND WIN32)
-  set_target_properties(${PNG_LIB_NAME} PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL)
+  set_target_properties(png PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL)
 endif()
 
+function(png_add_test)
+  set(options)
+  set(oneValueArgs NAME COMMAND)
+  set(multiValueArgs OPTIONS FILES)
+  cmake_parse_arguments(_PAT "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+  if (NOT _PAT_NAME)
+    message(FATAL_ERROR "Invalid arguments.  png_add_test requires name.")
+  endif()
+  if (NOT _PAT_COMMAND)
+    message(FATAL_ERROR "Invalid arguments.  png_add_test requires command.")
+  endif()
+
+  set(TEST_OPTIONS "${_PAT_OPTIONS}")
+  set(TEST_FILES "${_PAT_FILES}")
+
+  configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/test.cmake.in"
+                 "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake" @ONLY)
+  if(CMAKE_MAJOR_VERSION GREATER 2) # have generator expressions
+    add_test(NAME "${_PAT_NAME}"
+             COMMAND "${CMAKE_COMMAND}"
+             "-DLIBPNG=$<TARGET_FILE:png>"
+             "-DTEST_COMMAND=$<TARGET_FILE:${_PAT_COMMAND}>"
+             -P "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake")
+  else() # old 2.x add_test; limited and won't work well on Windows
+    # Note LIBPNG is a dummy value as there are no generator expressions
+    add_test("${_PAT_NAME}" "${CMAKE_COMMAND}"
+             "-DLIBPNG=${CMAKE_CURRENT_BINARY_DIR}/libpng.so"
+             "-DTEST_COMMAND=./${_PAT_COMMAND}"
+             -P "${CMAKE_CURRENT_BINARY_DIR}/tests/${_PAT_NAME}.cmake")
+  endif()
+endfunction()
+
 if(PNG_TESTS AND PNG_SHARED)
-  # does not work with msvc due to png_lib_ver issue
+  # Find test PNG files by globbing, but sort lists to ensure
+  # consistency between different filesystems.
+  file(GLOB PNGSUITE_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/*.png")
+  list(SORT PNGSUITE_PNGS)
+  file(GLOB TEST_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/*.png")
+  list(SORT TEST_PNGS)
+
+  set(PNGTEST_PNG "${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png")
+
   add_executable(pngtest ${pngtest_sources})
-  target_link_libraries(pngtest ${PNG_LIB_NAME})
-  add_test(pngtest ./pngtest ${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png)
-  #
+  target_link_libraries(pngtest png)
+
+  png_add_test(NAME pngtest COMMAND pngtest FILES "${PNGTEST_PNG}")
+
   add_executable(pngvalid ${pngvalid_sources})
-  target_link_libraries(pngvalid ${PNG_LIB_NAME})
-  add_test(pngvalid ./pngvalid)
+  target_link_libraries(pngvalid png)
+
+  png_add_test(NAME pngvalid-gamma-16-to-8
+               COMMAND pngvalid OPTIONS --gamma-16-to-8)
+  png_add_test(NAME pngvalid-gamma-alpha-mode
+               COMMAND pngvalid OPTIONS --gamma-alpha-mode)
+  png_add_test(NAME pngvalid-gamma-background
+               COMMAND pngvalid OPTIONS --gamma-background)
+  png_add_test(NAME pngvalid-gamma-expand16-alpha-mode
+               COMMAND pngvalid OPTIONS --gamma-alpha-mode --expand16)
+  png_add_test(NAME pngvalid-gamma-expand16-background
+               COMMAND pngvalid OPTIONS --gamma-background --expand16)
+  png_add_test(NAME pngvalid-gamma-expand16-transform
+               COMMAND pngvalid OPTIONS --gamma-transform --expand16)
+  png_add_test(NAME pngvalid-gamma-sbit
+               COMMAND pngvalid OPTIONS --gamma-sbit)
+  png_add_test(NAME pngvalid-gamma-threshold
+               COMMAND pngvalid OPTIONS --gamma-threshold)
+  png_add_test(NAME pngvalid-gamma-transform
+               COMMAND pngvalid OPTIONS --gamma-transform)
+  png_add_test(NAME pngvalid-progressive-interlace-standard
+               COMMAND pngvalid OPTIONS --standard --progressive-read --interlace)
+  png_add_test(NAME pngvalid-progressive-size
+               COMMAND pngvalid OPTIONS --size --progressive-read)
+  png_add_test(NAME pngvalid-progressive-standard
+               COMMAND pngvalid OPTIONS --standard --progressive-read)
+  png_add_test(NAME pngvalid-standard
+               COMMAND pngvalid OPTIONS --standard)
+  png_add_test(NAME pngvalid-transform
+               COMMAND pngvalid OPTIONS --transform)
+
   add_executable(pngstest ${pngstest_sources})
-  target_link_libraries(pngstest ${PNG_LIB_NAME})
-  add_test(pngstest ./pngstest
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn0g01.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn0g02.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn0g04.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn0g08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn0g16.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn2c08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn2c16.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn3p01.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn3p02.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn3p04.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn3p08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn4a08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn4a16.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn6a08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/basn6a16.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbbn0g01.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbbn0g02.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbbn0g04.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbbn2c16.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbbn3p08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbgn2c16.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbgn3p08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbrn2c08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbwn0g16.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbwn3p08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftbyn3p08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftp0n0g08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftp0n2c08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftp0n3p08.png
-    ${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/ftp1n3p08.png
-  )
+  target_link_libraries(pngstest png)
+
+  foreach(gamma_type 1.8 linear none sRGB)
+    foreach(alpha_type none alpha)
+      set(PNGSTEST_FILES)
+      foreach(test_png ${TEST_PNGS})
+        string(REGEX MATCH ".*-linear[-.].*" TEST_PNG_LINEAR "${test_png}")
+        string(REGEX MATCH ".*-sRGB[-.].*" TEST_PNG_SRGB "${test_png}")
+        string(REGEX MATCH ".*-1.8[-.].*" TEST_PNG_G18 "${test_png}")
+        string(REGEX MATCH ".*-alpha-.*" TEST_PNG_ALPHA "${test_png}")
+
+        set(TEST_PNG_VALID TRUE)
+
+        if(TEST_PNG_ALPHA)
+          if (NOT "${alpha_type}" STREQUAL "alpha")
+            set(TEST_PNG_VALID FALSE)
+          endif()
+        else()
+          if ("${alpha_type}" STREQUAL "alpha")
+            set(TEST_PNG_VALID FALSE)
+          endif()
+        endif()
+
+        if(TEST_PNG_LINEAR)
+          if(NOT "${gamma_type}" STREQUAL "linear")
+            set(TEST_PNG_VALID FALSE)
+          endif()
+        elseif(TEST_PNG_SRGB)
+          if(NOT "${gamma_type}" STREQUAL "sRGB")
+            set(TEST_PNG_VALID FALSE)
+          endif()
+        elseif(TEST_PNG_G18)
+          if(NOT "${gamma_type}" STREQUAL "1.8")
+            set(TEST_PNG_VALID FALSE)
+          endif()
+        else()
+          if(NOT "${gamma_type}" STREQUAL "none")
+            set(TEST_PNG_VALID FALSE)
+          endif()
+        endif()
+
+        if(TEST_PNG_VALID)
+          list(APPEND PNGSTEST_FILES "${test_png}")
+        endif()
+      endforeach()
+      # Should already be sorted, but sort anyway to be certain.
+      list(SORT PNGSTEST_FILES)
+      png_add_test(NAME pngstest-${gamma_type}-${alpha_type}
+                   COMMAND pngstest
+                   OPTIONS --tmpfile "${gamma_type}-${alpha_type}-" --log
+                   FILES ${PNGSTEST_FILES})
+    endforeach()
+  endforeach()
+
+  add_executable(pngunknown ${pngunknown_sources})
+  target_link_libraries(pngunknown png)
+
+  png_add_test(NAME pngunknown-discard COMMAND pngunknown OPTIONS --strict default=discard FILES "${PNGTEST_PNG}")
+  png_add_test(NAME pngunknown-IDAT COMMAND pngunknown OPTIONS --strict default=discard IDAT=save FILES "${PNGTEST_PNG}")
+  png_add_test(NAME pngunknown-if-safe COMMAND pngunknown OPTIONS --strict default=if-safe FILES "${PNGTEST_PNG}")
+  png_add_test(NAME pngunknown-sAPI COMMAND pngunknown OPTIONS --strict bKGD=save cHRM=save gAMA=save all=discard iCCP=save sBIT=save sRGB=save FILES "${PNGTEST_PNG}")
+  png_add_test(NAME pngunknown-save COMMAND pngunknown OPTIONS --strict default=save FILES "${PNGTEST_PNG}")
+  png_add_test(NAME pngunknown-sTER COMMAND pngunknown OPTIONS --strict sTER=if-safe FILES "${PNGTEST_PNG}")
+  png_add_test(NAME pngunknown-vpAg COMMAND pngunknown OPTIONS --strict vpAg=if-safe FILES "${PNGTEST_PNG}")
+
+  add_executable(pngimage ${pngimage_sources})
+  target_link_libraries(pngimage png)
+
+  png_add_test(NAME pngimage-quick COMMAND pngimage OPTIONS --list-combos --log FILES ${PNGSUITE_PNGS})
+  png_add_test(NAME pngimage-full COMMAND pngimage OPTIONS --exhaustive --list-combos --log FILES ${PNGSUITE_PNGS})
+endif()
+
+if(PNG_SHARED)
+  add_executable(pngfix ${pngfix_sources})
+  target_link_libraries(pngfix png)
+  set(PNG_BIN_TARGETS pngfix)
+
+  add_executable(png-fix-itxt ${png_fix_itxt_sources})
+  target_link_libraries(png-fix-itxt ${ZLIB_LIBRARY} ${M_LIBRARY})
+  list(APPEND PNG_BIN_TARGETS png-fix-itxt)
 endif()
 
 # Ensure the CMAKE_LIBRARY_OUTPUT_DIRECTORY is set
@@ -234,6 +660,15 @@
   endif(WIN32 AND NOT CYGWIN AND NOT MSYS)
 endmacro()
 
+# Create source generation scripts.
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genchk.cmake.in
+               ${CMAKE_CURRENT_BINARY_DIR}/scripts/genchk.cmake @ONLY)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/genout.cmake.in
+               ${CMAKE_CURRENT_BINARY_DIR}/scripts/genout.cmake @ONLY)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/gensrc.cmake.in
+               ${CMAKE_CURRENT_BINARY_DIR}/scripts/gensrc.cmake @ONLY)
+
+
 # libpng is a library so default to 'lib'
 if(NOT DEFINED CMAKE_INSTALL_LIBDIR)
   set(CMAKE_INSTALL_LIBDIR lib)
@@ -260,22 +695,12 @@
 
 # SET UP LINKS
 if(PNG_SHARED)
-  set_target_properties(${PNG_LIB_NAME} PROPERTIES
-#   VERSION 16.${PNGLIB_RELEASE}.1.6.20
+  set_target_properties(png PROPERTIES
+#   VERSION 16.${PNGLIB_RELEASE}.1.6.22beta03
     VERSION 16.${PNGLIB_RELEASE}.0
     SOVERSION 16
     CLEAN_DIRECT_OUTPUT 1)
 endif()
-if(PNG_STATIC)
-  # MSVC doesn't use a different file extension for shared vs. static
-  # libs.  We are able to change OUTPUT_NAME to remove the _static
-  # for all other platforms.
-  if(NOT MSVC)
-    set_target_properties(${PNG_LIB_NAME_STATIC} PROPERTIES
-      OUTPUT_NAME ${PNG_LIB_NAME}
-      CLEAN_DIRECT_OUTPUT 1)
-  endif()
-endif()
 
 # If CMake > 2.4.x, we set a variable used below to export
 # targets to an export file.
@@ -298,14 +723,14 @@
   if(PNG_SHARED)
     # Create a symlink for libpng.dll.a => libpng16.dll.a on Cygwin
     if(CYGWIN OR MINGW)
-       get_target_property(BUILD_TARGET_LOCATION ${PNG_LIB_NAME} LOCATION_${CMAKE_BUILD_TYPE})
+       get_target_property(BUILD_TARGET_LOCATION png LOCATION_${CMAKE_BUILD_TYPE})
        CREATE_SYMLINK(${BUILD_TARGET_LOCATION} libpng${CMAKE_IMPORT_LIBRARY_SUFFIX})
        install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_IMPORT_LIBRARY_SUFFIX}
          DESTINATION ${CMAKE_INSTALL_LIBDIR})
     endif(CYGWIN OR MINGW)
 
     if(NOT WIN32)
-      get_target_property(BUILD_TARGET_LOCATION ${PNG_LIB_NAME} LOCATION_${CMAKE_BUILD_TYPE})
+      get_target_property(BUILD_TARGET_LOCATION png LOCATION_${CMAKE_BUILD_TYPE})
       CREATE_SYMLINK(${BUILD_TARGET_LOCATION} libpng${CMAKE_SHARED_LIBRARY_SUFFIX})
       install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_SHARED_LIBRARY_SUFFIX}
          DESTINATION ${CMAKE_INSTALL_LIBDIR})
@@ -314,7 +739,7 @@
 
   if(PNG_STATIC)
     if(NOT WIN32 OR CYGWIN OR MINGW)
-      get_target_property(BUILD_TARGET_LOCATION ${PNG_LIB_NAME_STATIC} LOCATION_${CMAKE_BUILD_TYPE})
+      get_target_property(BUILD_TARGET_LOCATION png_static LOCATION_${CMAKE_BUILD_TYPE})
       CREATE_SYMLINK(${BUILD_TARGET_LOCATION} libpng${CMAKE_STATIC_LIBRARY_SUFFIX})
       install(FILES ${CMAKE_CURRENT_BINARY_DIR}/libpng${CMAKE_STATIC_LIBRARY_SUFFIX}
          DESTINATION ${CMAKE_INSTALL_LIBDIR})
@@ -334,6 +759,11 @@
   endif(NOT WIN32 OR CYGWIN OR MINGW)
 endif()
 
+if(NOT SKIP_INSTALL_PROGRAMS AND NOT SKIP_INSTALL_ALL )
+  install(TARGETS ${PNG_BIN_TARGETS}
+      RUNTIME DESTINATION bin)
+endif()
+
 if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL )
   # Install man pages
   if(NOT PNG_MAN_DIR)
diff --git a/LICENSE b/LICENSE
index 82dbe11..d2bb706 100644
--- a/LICENSE
+++ b/LICENSE
@@ -10,8 +10,8 @@
 
 This code is released under the libpng license.
 
-libpng versions 1.0.7, July 1, 2000, through 1.6.20, December 3, 2015, are
-Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are
+libpng versions 1.0.7, July 1, 2000, through 1.6.22beta03, February 19, 2016, are
+Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
 derived from libpng-1.0.6, and are distributed according to the same
 disclaimer and license as libpng-1.0.6 with the following individuals
 added to the list of Contributing Authors:
@@ -32,6 +32,10 @@
    risk of satisfactory quality, performance, accuracy, and effort is with
    the user.
 
+Some files in the "contrib" directory and some configure-generated
+files that are distributed with libpng have other copyright owners and
+are released under other open source licenses.
+
 libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
 Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
 libpng-0.96, and are distributed according to the same disclaimer and
@@ -55,6 +59,9 @@
    Greg Roelofs
    Tom Tanner
 
+Some files in the "scripts" directory have other copyright owners
+but are released under this license.
+
 libpng versions 0.5, May 1995, through 0.88, January 1996, are
 Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
 
@@ -95,18 +102,29 @@
 
 END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
 
-A "png_get_copyright" function is available, for convenient use in "about"
-boxes and the like:
+TRADEMARK:
 
-   printf("%s", png_get_copyright(NULL));
+The name "libpng" has not been registered by the Copyright owner
+as a trademark in any jurisdiction.  However, because libpng has
+been distributed and maintained world-wide, continually since 1995,
+the Copyright owner claims "common-law trademark protection" in any
+jurisdiction where common-law trademark is recognized.
 
-Also, the PNG logo (in PNG format, of course) is supplied in the
-files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
+OSI CERTIFICATION:
 
 Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
 a certification mark of the Open Source Initiative. OSI has not addressed
 the additional disclaimers inserted at version 1.0.7.
 
+EXPORT CONTROL:
+
+The Copyright owner believes that the Export Control Classification
+Number (ECCN) for libpng is EAR99, which means not subject to export
+controls or International Traffic in Arms Regulations (ITAR) because
+it is open source, publicly available software, that does not contain
+any encryption software.  See the EAR, paragraphs 734.3(b)(3) and
+734.7(b).
+
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-December 3, 2015
+February 19, 2016
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index 11f6ffe..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,112 +0,0 @@
-
-This copy of the libpng notices is provided for your convenience.  In case of
-any discrepancy between this copy and the notices in the file png.h that is
-included in the libpng distribution, the latter shall prevail.
-
-COPYRIGHT NOTICE, DISCLAIMER, and LICENSE:
-
-If you modify libpng you may insert additional notices immediately following
-this sentence.
-
-This code is released under the libpng license.
-
-libpng versions 1.0.7, July 1, 2000, through 1.6.19, November 12, 2015, are
-Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are
-derived from libpng-1.0.6, and are distributed according to the same
-disclaimer and license as libpng-1.0.6 with the following individuals
-added to the list of Contributing Authors:
-
-   Simon-Pierre Cadieux
-   Eric S. Raymond
-   Mans Rullgard
-   Cosmin Truta
-   Gilles Vollant
-   James Yu
-
-and with the following additions to the disclaimer:
-
-   There is no warranty against interference with your enjoyment of the
-   library or against infringement.  There is no warranty that our
-   efforts or the library will fulfill any of your particular purposes
-   or needs.  This library is provided with all faults, and the entire
-   risk of satisfactory quality, performance, accuracy, and effort is with
-   the user.
-
-libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
-Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
-libpng-0.96, and are distributed according to the same disclaimer and
-license as libpng-0.96, with the following individuals added to the list
-of Contributing Authors:
-
-   Tom Lane
-   Glenn Randers-Pehrson
-   Willem van Schaik
-
-libpng versions 0.89, June 1996, through 0.96, May 1997, are
-Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
-and are distributed according to the same disclaimer and license as
-libpng-0.88, with the following individuals added to the list of
-Contributing Authors:
-
-   John Bowler
-   Kevin Bracey
-   Sam Bushell
-   Magnus Holmgren
-   Greg Roelofs
-   Tom Tanner
-
-libpng versions 0.5, May 1995, through 0.88, January 1996, are
-Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
-
-For the purposes of this copyright and license, "Contributing Authors"
-is defined as the following set of individuals:
-
-   Andreas Dilger
-   Dave Martindale
-   Guy Eric Schalnat
-   Paul Schmidt
-   Tim Wegner
-
-The PNG Reference Library is supplied "AS IS".  The Contributing Authors
-and Group 42, Inc. disclaim all warranties, expressed or implied,
-including, without limitation, the warranties of merchantability and of
-fitness for any purpose.  The Contributing Authors and Group 42, Inc.
-assume no liability for direct, indirect, incidental, special, exemplary,
-or consequential damages, which may result from the use of the PNG
-Reference Library, even if advised of the possibility of such damage.
-
-Permission is hereby granted to use, copy, modify, and distribute this
-source code, or portions hereof, for any purpose, without fee, subject
-to the following restrictions:
-
-  1. The origin of this source code must not be misrepresented.
-
-  2. Altered versions must be plainly marked as such and must not
-     be misrepresented as being the original source.
-
-  3. This Copyright notice may not be removed or altered from any
-     source or altered source distribution.
-
-The Contributing Authors and Group 42, Inc. specifically permit, without
-fee, and encourage the use of this source code as a component to
-supporting the PNG file format in commercial products.  If you use this
-source code in a product, acknowledgment is not required but would be
-appreciated.
-
-END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
-
-A "png_get_copyright" function is available, for convenient use in "about"
-boxes and the like:
-
-   printf("%s", png_get_copyright(NULL));
-
-Also, the PNG logo (in PNG format, of course) is supplied in the
-files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
-
-Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
-a certification mark of the Open Source Initiative. OSI has not addressed
-the additional disclaimers inserted at version 1.0.7.
-
-Glenn Randers-Pehrson
-glennrp at users.sourceforge.net
-November 12, 2015
diff --git a/README b/README
index 59f1f91..4c5b0ec 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-README for libpng version 1.6.20 - December 3, 2015 (shared library 16.0)
+README for libpng version 1.6.22beta03 - February 8, 2016 (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/README.android b/README.android
index b582ca5..190d454 100644
--- a/README.android
+++ b/README.android
@@ -1,4 +1,4 @@
-Any Android specific modifications to upstream libpng (1.6.20) should
+Any Android specific modifications to upstream libpng (1.6.22beta) should
 be listed here:
 
 (1) Android has added the following files.
@@ -15,5 +15,3 @@
 (3) Removed contrib/testpngs/
     There is no reason to check in all of these files if we won't
     be using them.
-
-(4) PNG_INDEX_SUPPORTED optimizations.
diff --git a/README.version b/README.version
index 58890dd..f59dc45 100644
--- a/README.version
+++ b/README.version
@@ -1,3 +1,3 @@
-URL: http://prdownloads.sourceforge.net/libpng/libpng-1.6.20.tar.gz?download
-Version: 1.6.20
+URL: https://sourceforge.net/projects/libpng/files/libpng16/1.6.22beta02/libpng-1.6.22beta02.tar.gz/download
+Version: 1.6.22beta
 BugComponent: 87896
diff --git a/configure.ac b/configure.ac
index 845ae1c..10538fc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -18,7 +18,7 @@
 
 dnl Version number stuff here:
 
-AC_INIT([libpng],[1.6.20],[png-mng-implement@lists.sourceforge.net])
+AC_INIT([libpng],[1.6.22beta03],[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.20
+PNGLIB_VERSION=1.6.22beta03
 PNGLIB_MAJOR=1
 PNGLIB_MINOR=6
-PNGLIB_RELEASE=20
+PNGLIB_RELEASE=22
 
 dnl End of version number stuff
 
diff --git a/contrib/intel/INSTALL b/contrib/intel/INSTALL
new file mode 100644
index 0000000..abcfae8
--- /dev/null
+++ b/contrib/intel/INSTALL
@@ -0,0 +1,5 @@
+
+Copyright (c) 2016 Google, Inc.
+
+To enable SSE support, manually edit configure.ac and Makefile.am, following
+the instructions in the configure.ac.patch and Makefile.am.patch files. 
diff --git a/contrib/intel/Makefile.am.patch b/contrib/intel/Makefile.am.patch
new file mode 100644
index 0000000..3921f27
--- /dev/null
+++ b/contrib/intel/Makefile.am.patch
@@ -0,0 +1,17 @@
+
+#
+# Copyright (c) 2016 Google, Inc.
+#
+# This code is released under the libpng license.
+# For conditions of distribution and use, see the disclaimer
+# and license in png.h
+#
+
+# In order to compile Intel SSE optimizations for libpng, please add
+# the following code to Makefile.am directly beneath the
+# "if PNG_ARM_NEON ... endif" statement.
+
+if PNG_INTEL_SSE
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += contrib/intel/intel_init.c\
+    contrib/intel/filter_sse2_intrinsics.c
+endif
diff --git a/contrib/intel/configure.ac.patch b/contrib/intel/configure.ac.patch
new file mode 100644
index 0000000..fec6549
--- /dev/null
+++ b/contrib/intel/configure.ac.patch
@@ -0,0 +1,46 @@
+#
+# Copyright (c) 2016 Google, Inc.
+#
+# This code is released under the libpng license.
+# For conditions of distribution and use, see the disclaimer
+# and license in png.h
+#
+
+# In order to compile Intel SSE optimizations for libpng, please add
+# the following code to configure.ac under HOST SPECIFIC OPTIONS
+# directly beneath the section for ARM.
+
+# INTEL
+# ===
+#
+# INTEL SSE (SIMD) support.
+
+AC_ARG_ENABLE([intel-sse],
+   AS_HELP_STRING([[[--enable-intel-sse]]],
+      [Enable Intel SSE optimizations: =no/off, yes/on:]
+      [no/off: disable the optimizations;]
+      [yes/on: enable the optimizations.]
+      [If not specified: determined by the compiler.]),
+   [case "$enableval" in
+      no|off)
+         # disable the default enabling:
+         AC_DEFINE([PNG_INTEL_SSE_OPT], [0],
+                   [Disable Intel SSE optimizations])
+         # Prevent inclusion of the assembler files below:
+         enable_intel_sse=no;;
+      yes|on)
+         AC_DEFINE([PNG_INTEL_SSE_OPT], [1],
+                   [Enable Intel SSE optimizations]);;
+      *)
+         AC_MSG_ERROR([--enable-intel-sse=${enable_intel_sse}: invalid value])
+   esac])
+
+# Add Intel specific files to all builds where the host_cpu is Intel ('x86*')
+# or where Intel optimizations were explicitly requested (this allows a
+# fallback if a future host CPU does not match 'x86*')
+AM_CONDITIONAL([PNG_INTEL_SSE],
+   [test "$enable_intel_sse" != 'no' &&
+    case "$host_cpu" in
+      i?86|x86_64) :;;
+      *)    test "$enable_intel_sse" != '';;
+    esac])
diff --git a/contrib/intel/filter_sse2_intrinsics.c b/contrib/intel/filter_sse2_intrinsics.c
new file mode 100644
index 0000000..b4ca61f
--- /dev/null
+++ b/contrib/intel/filter_sse2_intrinsics.c
@@ -0,0 +1,287 @@
+
+/* filter_sse2_intrinsics.c - SSE2 optimized filter functions
+ *
+ * Copyright (c) 2016 Google, Inc.
+ *
+ * Last changed in libpng 1.6.22 [(PENDING RELEASE)]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#include "../../pngpriv.h"
+
+#ifdef PNG_READ_SUPPORTED
+
+#if PNG_INTEL_SSE_IMPLEMENTATION > 0
+
+#include <immintrin.h>
+
+// Functions in this file look at most 3 pixels (a,b,c) to predict the 4th (d).
+// They're positioned like this:
+//    prev:  c b
+//    row:   a d
+// The Sub filter predicts d=a, Avg d=(a+b)/2, and Paeth predicts d to be
+// whichever of a, b, or c is closest to p=a+b-c.
+
+static __m128i load3(const void* p) {
+   png_uint_32 packed;
+   memcpy(&packed, p, 3);
+   return _mm_cvtsi32_si128(packed);
+}
+
+static __m128i load4(const void* p) {
+   return _mm_cvtsi32_si128(*(const int*)p);
+}
+
+static void store3(void* p, __m128i v) {
+   png_uint_32 packed = _mm_cvtsi128_si32(v);
+   memcpy(p, &packed, 3);
+}
+
+static void store4(void* p, __m128i v) {
+   *(int*)p = _mm_cvtsi128_si32(v);
+}
+
+void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row,
+   png_const_bytep prev)
+{
+   // The Sub filter predicts each pixel as the previous pixel, a.
+   // There is no pixel to the left of the first pixel.  It's encoded directly.
+   // That works with our main loop if we just say that left pixel was zero.
+   __m128i a, d = _mm_setzero_si128();
+
+   int rb = row_info->rowbytes;
+   while (rb > 0) {
+      a = d; d = load3(row);
+      d = _mm_add_epi8(d, a);
+      store3(row, d);
+
+      row += 3;
+      rb  -= 3;
+   }
+}
+
+void png_read_filter_row_sub4_sse2(png_row_infop row_info, png_bytep row,
+   png_const_bytep prev)
+{
+   // The Sub filter predicts each pixel as the previous pixel, a.
+   // There is no pixel to the left of the first pixel.  It's encoded directly.
+   // That works with our main loop if we just say that left pixel was zero.
+   __m128i a, d = _mm_setzero_si128();
+
+   int rb = row_info->rowbytes;
+   while (rb > 0) {
+      a = d; d = load4(row);
+      d = _mm_add_epi8(d, a);
+      store4(row, d);
+
+      row += 4;
+      rb  -= 4;
+   }
+}
+
+void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row,
+   png_const_bytep prev)
+{
+   // The Avg filter predicts each pixel as the (truncated) average of a and b.
+   // There's no pixel to the left of the first pixel.  Luckily, it's
+   // predicted to be half of the pixel above it.  So again, this works
+   // perfectly with our loop if we make sure a starts at zero.
+   const __m128i zero = _mm_setzero_si128();
+   __m128i    b;
+   __m128i a, d = zero;
+
+   int rb = row_info->rowbytes;
+   while (rb > 0) {
+             b = load3(prev);
+      a = d; d = load3(row );
+
+      // PNG requires a truncating average, so we can't just use _mm_avg_epu8...
+      __m128i avg = _mm_avg_epu8(a,b);
+      // ...but we can fix it up by subtracting off 1 if it rounded up.
+      avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
+                                            _mm_set1_epi8(1)));
+
+      d = _mm_add_epi8(d, avg);
+      store3(row, d);
+
+      prev += 3;
+      row  += 3;
+      rb   -= 3;
+   }
+}
+
+void png_read_filter_row_avg4_sse2(png_row_infop row_info, png_bytep row,
+   png_const_bytep prev)
+{
+   // The Avg filter predicts each pixel as the (truncated) average of a and b.
+   // There's no pixel to the left of the first pixel.  Luckily, it's
+   // predicted to be half of the pixel above it.  So again, this works
+   // perfectly with our loop if we make sure a starts at zero.
+   const __m128i zero = _mm_setzero_si128();
+   __m128i    b;
+   __m128i a, d = zero;
+
+   int rb = row_info->rowbytes;
+   while (rb > 0) {
+             b = load4(prev);
+      a = d; d = load4(row );
+
+      // PNG requires a truncating average, so we can't just use _mm_avg_epu8...
+      __m128i avg = _mm_avg_epu8(a,b);
+      // ...but we can fix it up by subtracting off 1 if it rounded up.
+      avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
+                                            _mm_set1_epi8(1)));
+
+      d = _mm_add_epi8(d, avg);
+      store4(row, d);
+
+      prev += 4;
+      row  += 4;
+      rb   -= 4;
+   }
+}
+
+// Returns |x| for 16-bit lanes.
+static __m128i abs_i16(__m128i x) {
+#if PNG_INTEL_SSE_IMPLEMENTATION >= 2
+   return _mm_abs_epi16(x);
+#else
+   // Read this all as, return x<0 ? -x : x.
+   // To negate two's complement, you flip all the bits then add 1.
+   __m128i is_negative = _mm_cmplt_epi16(x, _mm_setzero_si128());
+
+   // Flip negative lanes.
+   x = _mm_xor_si128(x, is_negative);
+
+   // +1 to negative lanes, else +0.
+   x = _mm_add_epi16(x, _mm_srli_epi16(is_negative, 15));
+   return x;
+#endif
+}
+
+// Bytewise c ? t : e.
+static __m128i if_then_else(__m128i c, __m128i t, __m128i e) {
+#if PNG_INTEL_SSE_IMPLEMENTATION >= 3
+   return _mm_blendv_epi8(e,t,c);
+#else
+   return _mm_or_si128(_mm_and_si128(c, t), _mm_andnot_si128(c, e));
+#endif
+}
+
+void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row,
+   png_const_bytep prev)
+{
+   // Paeth tries to predict pixel d using the pixel to the left of it, a,
+   // and two pixels from the previous row, b and c:
+   //   prev: c b
+   //   row:  a d
+   // The Paeth function predicts d to be whichever of a, b, or c is nearest to
+   // p=a+b-c.
+
+   // The first pixel has no left context, and so uses an Up filter, p = b.
+   // This works naturally with our main loop's p = a+b-c if we force a and c
+   // to zero.
+   // Here we zero b and d, which become c and a respectively at the start of
+   // the loop.
+   const __m128i zero = _mm_setzero_si128();
+   __m128i c, b = zero,
+           a, d = zero;
+
+   int rb = row_info->rowbytes;
+   while (rb > 0) {
+      // It's easiest to do this math (particularly, deal with pc) with 16-bit
+      // intermediates.
+      c = b; b = _mm_unpacklo_epi8(load3(prev), zero);
+      a = d; d = _mm_unpacklo_epi8(load3(row ), zero);
+
+      // (p-a) == (a+b-c - a) == (b-c)
+      __m128i pa = _mm_sub_epi16(b,c);
+
+      // (p-b) == (a+b-c - b) == (a-c)
+      __m128i pb = _mm_sub_epi16(a,c);
+
+      // (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c)
+      __m128i pc = _mm_add_epi16(pa,pb);
+
+      pa = abs_i16(pa);  // |p-a|
+      pb = abs_i16(pb);  // |p-b|
+      pc = abs_i16(pc);  // |p-c|
+
+      __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
+
+      // Paeth breaks ties favoring a over b over c.
+      __m128i nearest  = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
+                         if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
+                                                                     c));
+
+      // Note `_epi8`: we need addition to wrap modulo 255.
+      d = _mm_add_epi8(d, nearest);
+      store3(row, _mm_packus_epi16(d,d));
+
+      prev += 3;
+      row  += 3;
+      rb   -= 3;
+   }
+}
+
+void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row,
+   png_const_bytep prev)
+{
+   // Paeth tries to predict pixel d using the pixel to the left of it, a,
+   // and two pixels from the previous row, b and c:
+   //   prev: c b
+   //   row:  a d
+   // The Paeth function predicts d to be whichever of a, b, or c is nearest to
+   // p=a+b-c.
+
+   // The first pixel has no left context, and so uses an Up filter, p = b.
+   // This works naturally with our main loop's p = a+b-c if we force a and c
+   // to zero.
+   // Here we zero b and d, which become c and a respectively at the start of
+   // the loop.
+   const __m128i zero = _mm_setzero_si128();
+   __m128i c, b = zero,
+           a, d = zero;
+
+   int rb = row_info->rowbytes;
+   while (rb > 0) {
+      // It's easiest to do this math (particularly, deal with pc) with 16-bit
+      // intermediates.
+      c = b; b = _mm_unpacklo_epi8(load4(prev), zero);
+      a = d; d = _mm_unpacklo_epi8(load4(row ), zero);
+
+      // (p-a) == (a+b-c - a) == (b-c)
+      __m128i pa = _mm_sub_epi16(b,c);
+
+      // (p-b) == (a+b-c - b) == (a-c)
+      __m128i pb = _mm_sub_epi16(a,c);
+
+      // (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c)
+      __m128i pc = _mm_add_epi16(pa,pb);
+
+      pa = abs_i16(pa);  // |p-a|
+      pb = abs_i16(pb);  // |p-b|
+      pc = abs_i16(pc);  // |p-c|
+
+      __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
+
+      // Paeth breaks ties favoring a over b over c.
+      __m128i nearest  = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
+                         if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
+                                                                     c));
+
+      // Note `_epi8`: we need addition to wrap modulo 255.
+      d = _mm_add_epi8(d, nearest);
+      store4(row, _mm_packus_epi16(d,d));
+
+      prev += 4;
+      row  += 4;
+      rb   -= 4;
+   }
+}
+
+#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */
+#endif /* READ */
diff --git a/contrib/intel/intel_init.c b/contrib/intel/intel_init.c
new file mode 100644
index 0000000..80fcfc2
--- /dev/null
+++ b/contrib/intel/intel_init.c
@@ -0,0 +1,47 @@
+
+/* intel_init.c - SSE2 optimized filter functions
+ *
+ * Copyright (c) 2016 Google, Inc.
+ *
+ * Last changed in libpng 1.6.22 [(PENDING RELEASE)]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#include "../../pngpriv.h"
+
+#ifdef PNG_READ_SUPPORTED
+#if PNG_INTEL_SSE_IMPLEMENTATION > 0
+
+void
+png_init_filter_functions_sse2(png_structp pp, unsigned int bpp)
+{
+   // The techniques used to implement each of these filters in SSE operate on
+   // one pixel at a time.
+   // So they generally speed up 3bpp images about 3x, 4bpp images about 4x.
+   // They can scale up to 6 and 8 bpp images and down to 2 bpp images, 
+   // but they'd not likely have any benefit for 1bpp images.
+   // Most of these can be implemented using only MMX and 64-bit registers,
+   // but they end up a bit slower than using the equally-ubiquitous SSE2.
+   if (bpp == 3)
+   {
+      pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_sse2;
+      pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_sse2;
+      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
+         png_read_filter_row_paeth3_sse2;
+   }
+   else if (bpp == 4)
+   {
+      pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_sse2;
+      pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_sse2;
+      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
+          png_read_filter_row_paeth4_sse2;
+   }
+
+   // No need optimize PNG_FILTER_VALUE_UP.  The compiler should autovectorize.
+}
+
+#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */
+#endif /* PNG_READ_SUPPORTED */
diff --git a/contrib/libtests/makepng.c b/contrib/libtests/makepng.c
index 60d96d1..9dff048 100644
--- a/contrib/libtests/makepng.c
+++ b/contrib/libtests/makepng.c
@@ -3,7 +3,7 @@
 /* Copyright: */
 #define COPYRIGHT "\251 2013,2015 John Cunningham Bowler"
 /*
- * Last changed in libpng 1.7.0 [(PENDING RELEASE)]
+ * Last changed in libpng 1.6.20 [November 24, 2015]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
diff --git a/contrib/libtests/pngimage.c b/contrib/libtests/pngimage.c
index 442b2f4..6413573 100644
--- a/contrib/libtests/pngimage.c
+++ b/contrib/libtests/pngimage.c
@@ -1,8 +1,8 @@
 /* pngimage.c
  *
- * Copyright (c) 2015 John Cunningham Bowler
+ * Copyright (c) 2015,2016 John Cunningham Bowler
  *
- * Last changed in libpng 1.6.20 [December 3, 2015]
+ * Last changed in libpng 1.6.22 [(PENDING RELEASE)]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -36,6 +36,15 @@
 #  include <setjmp.h> /* because png.h did *not* include this */
 #endif
 
+/* 1.6.1 added support for the configure test harness, which uses 77 to indicate
+ * a skipped test, in earlier versions we need to succeed on a skipped test, so:
+ */
+#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H)
+#  define SKIP 77
+#else
+#  define SKIP 0
+#endif
+
 #if defined(PNG_INFO_IMAGE_SUPPORTED) && defined(PNG_SEQUENTIAL_READ_SUPPORTED)\
     && (defined(PNG_READ_PNG_SUPPORTED) || PNG_LIBPNG_VER < 10700)
 /* If a transform is valid on both read and write this implies that if the
@@ -1682,6 +1691,6 @@
 main(void)
 {
    fprintf(stderr, "pngimage: no support for png_read/write_image\n");
-   return 77;
+   return SKIP;
 }
 #endif
diff --git a/contrib/libtests/pngstest.c b/contrib/libtests/pngstest.c
index 3374c72..b70bebc 100644
--- a/contrib/libtests/pngstest.c
+++ b/contrib/libtests/pngstest.c
@@ -1,9 +1,9 @@
 /*-
  * pngstest.c
  *
- * Copyright (c) 2013-2015 John Cunningham Bowler
+ * Copyright (c) 2013-2016 John Cunningham Bowler
  *
- * Last changed in libpng 1.6.19 [(PENDING RELEASE)]
+ * Last changed in libpng 1.6.22 [(PENDING RELEASE)]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -26,6 +26,15 @@
 #  include <config.h>
 #endif
 
+/* 1.6.1 added support for the configure test harness, which uses 77 to indicate
+ * a skipped test, in earlier versions we need to succeed on a skipped test, so:
+ */
+#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H)
+#  define SKIP 77
+#else
+#  define SKIP 0
+#endif
+
 /* Define the following to use this test against your installed libpng, rather
  * than the one being built here:
  */
@@ -99,10 +108,18 @@
    seed[1] = u1;
 }
 
+static png_uint_32 color_seed[2];
+
+static void
+reseed(void)
+{
+   color_seed[0] = 0x12345678U;
+   color_seed[1] = 0x9abcdefU;
+}
+
 static void
 random_color(png_colorp color)
 {
-   static png_uint_32 color_seed[2] = { 0x12345678, 0x9abcdef };
    make_random_bytes(color_seed, color, sizeof *color);
 }
 
@@ -307,7 +324,7 @@
 }
 #endif /* unused */
 
-#define READ_FILE 1      /* else memory */
+#define USE_FILE 1       /* else memory */
 #define USE_STDIO 2      /* else use file name */
 #define STRICT 4         /* fail on warnings too */
 #define VERBOSE 8
@@ -316,16 +333,19 @@
 #define ACCUMULATE 64
 #define FAST_WRITE 128
 #define sRGB_16BIT 256
+#define NO_RESEED  512   /* do not reseed on each new file */
+#define GBG_ERROR 1024   /* do not ignore the gamma+background_rgb_to_gray
+                          * libpng warning. */
 
 static void
 print_opts(png_uint_32 opts)
 {
-   if (opts & READ_FILE)
+   if (opts & USE_FILE)
       printf(" --file");
    if (opts & USE_STDIO)
       printf(" --stdio");
-   if (opts & STRICT)
-      printf(" --strict");
+   if (!(opts & STRICT))
+      printf(" --nostrict");
    if (opts & VERBOSE)
       printf(" --verbose");
    if (opts & KEEP_TMPFILES)
@@ -338,6 +358,12 @@
       printf(" --slow");
    if (opts & sRGB_16BIT)
       printf(" --sRGB-16bit");
+   if (opts & NO_RESEED)
+      printf(" --noreseed");
+#if PNG_LIBPNG_VER < 10700 /* else on by default */
+   if (opts & GBG_ERROR)
+      printf(" --fault-gbg-warning");
+#endif
 }
 
 #define FORMAT_NO_CHANGE 0x80000000 /* additional flag */
@@ -741,8 +767,15 @@
       return logerror(image, image->file_name, ": opaque not NULL", "");
    }
 
-   else if (image->image.warning_or_error != 0 && (image->opts & STRICT) != 0)
-      return logerror(image, image->file_name, " --strict", "");
+   /* Separate out the gamma+background_rgb_to_gray warning because it may
+    * produce opaque component errors:
+    */
+   else if (image->image.warning_or_error != 0 &&
+            (strcmp(image->image.message,
+               "libpng does not support gamma+background+rgb_to_gray") == 0 ?
+                  (image->opts & GBG_ERROR) != 0 : (image->opts & STRICT) != 0))
+      return logerror(image, image->file_name, (image->opts & GBG_ERROR) != 0 ?
+                      " --fault-gbg-warning" : " --strict", "");
 
    else
       return 1;
@@ -3008,14 +3041,14 @@
 static int
 read_one_file(Image *image)
 {
-   if (!(image->opts & READ_FILE) || (image->opts & USE_STDIO))
+   if (!(image->opts & USE_FILE) || (image->opts & USE_STDIO))
    {
       /* memory or stdio. */
       FILE *f = fopen(image->file_name, "rb");
 
       if (f != NULL)
       {
-         if (image->opts & READ_FILE)
+         if (image->opts & USE_FILE)
             image->input_file = f;
 
          else /* memory */
@@ -3096,7 +3129,8 @@
 
    if (image->opts & USE_STDIO)
    {
-#ifndef PNG_USE_MKSTEMP
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
+#ifndef __COVERITY__
       FILE *f = tmpfile();
 #else
       /* Experimental. Coverity says tmpfile() is insecure because it
@@ -3158,10 +3192,14 @@
 
       else
          return logerror(image, "tmpfile", ": open: ", strerror(errno));
+#else /* SIMPLIFIED_WRITE_STDIO */
+      return logerror(image, "tmpfile", ": open: unsupported", "");
+#endif /* SIMPLIFIED_WRITE_STDIO */
    }
 
-   else
+   else if (image->opts & USE_FILE)
    {
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
       static int counter = 0;
       char name[32];
 
@@ -3181,6 +3219,51 @@
 
       else
          return logerror(image, name, ": write failed", "");
+#else /* SIMPLIFIED_WRITE_STDIO */
+      return logerror(image, "stdio", ": open: unsupported", "");
+#endif /* SIMPLIFIED_WRITE_STDIO */
+   }
+
+   else /* use memory */
+   {
+      png_alloc_size_t size;
+
+      if (png_image_write_get_memory_size(image->image, size, convert_to_8bit,
+               image->buffer+16, (png_int_32)image->stride, image->colormap))
+      {
+         /* This is non-fatal but ignoring it was causing serious problems in
+          * the macro to be ignored:
+          */
+         if (size > PNG_IMAGE_PNG_SIZE_MAX(image->image))
+            return logerror(image, "memory", ": PNG_IMAGE_SIZE_MAX wrong", "");
+
+         initimage(output, image->opts, "memory", image->stride_extra);
+         output->input_memory = malloc(size);
+
+         if (output->input_memory != NULL)
+         {
+            output->input_memory_size = size;
+
+            if (png_image_write_to_memory(&image->image, output->input_memory,
+                  &output->input_memory_size, convert_to_8bit, image->buffer+16,
+                  (png_int_32)image->stride, image->colormap))
+            {
+               /* This is also non-fatal but it safes safer to error out anyway:
+                */
+               if (size != output->input_memory_size)
+                  return logerror(image, "memory", ": memory size wrong", "");
+            }
+
+            else
+               return logerror(image, "memory", ": write failed", "");
+         }
+
+         else
+            return logerror(image, "memory", ": out of memory", "");
+      }
+
+      else
+         return logerror(image, "memory", ": get size:", "");
    }
 
    /* 'output' has an initialized temporary image, read this back in and compare
@@ -3356,6 +3439,8 @@
    int result;
    Image image;
 
+   if (!(opts & NO_RESEED))
+      reseed(); /* ensure that the random numbers don't depend on file order */
    newimage(&image);
    initimage(&image, opts, file_name, stride_extra);
    result = read_one_file(&image);
@@ -3393,7 +3478,7 @@
 int
 main(int argc, char **argv)
 {
-   png_uint_32 opts = FAST_WRITE;
+   png_uint_32 opts = FAST_WRITE | STRICT;
    format_list formats;
    const char *touch = NULL;
    int log_pass = 0;
@@ -3402,11 +3487,17 @@
    int retval = 0;
    int c;
 
+#if PNG_LIBPNG_VER >= 10700
+      /* This error should not exist in 1.7 or later: */
+      opts |= GBG_ERROR;
+#endif
+
    init_sRGB_to_d();
 #if 0
    init_error_via_linear();
 #endif
    format_init(&formats);
+   reseed(); /* initialize random number seeds */
 
    for (c=1; c<argc; ++c)
    {
@@ -3421,17 +3512,17 @@
       }
       else if (strcmp(arg, "--file") == 0)
 #        ifdef PNG_STDIO_SUPPORTED
-            opts |= READ_FILE;
+            opts |= USE_FILE;
 #        else
-            return 77; /* skipped: no support */
+            return SKIP; /* skipped: no support */
 #        endif
       else if (strcmp(arg, "--memory") == 0)
-         opts &= ~READ_FILE;
+         opts &= ~USE_FILE;
       else if (strcmp(arg, "--stdio") == 0)
 #        ifdef PNG_STDIO_SUPPORTED
             opts |= USE_STDIO;
 #        else
-            return 77; /* skipped: no support */
+            return SKIP; /* skipped: no support */
 #        endif
       else if (strcmp(arg, "--name") == 0)
          opts &= ~USE_STDIO;
@@ -3457,10 +3548,16 @@
          opts &= ~KEEP_GOING;
       else if (strcmp(arg, "--strict") == 0)
          opts |= STRICT;
+      else if (strcmp(arg, "--nostrict") == 0)
+         opts &= ~STRICT;
       else if (strcmp(arg, "--sRGB-16bit") == 0)
          opts |= sRGB_16BIT;
       else if (strcmp(arg, "--linear-16bit") == 0)
          opts &= ~sRGB_16BIT;
+      else if (strcmp(arg, "--noreseed") == 0)
+         opts |= NO_RESEED;
+      else if (strcmp(arg, "--fault-gbg-warning") == 0)
+         opts |= GBG_ERROR;
       else if (strcmp(arg, "--tmpfile") == 0)
       {
          if (c+1 < argc)
@@ -3717,6 +3814,6 @@
 {
    fprintf(stderr, "pngstest: no read support in libpng, test skipped\n");
    /* So the test is skipped: */
-   return 77;
+   return SKIP;
 }
 #endif /* PNG_SIMPLIFIED_READ_SUPPORTED */
diff --git a/contrib/libtests/pngunknown.c b/contrib/libtests/pngunknown.c
index 0d52ff8..b5ab04a 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.10 [March 6, 2014]
- * Copyright (c) 2014 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.22 [(PENDING RELEASE)]
+ * Copyright (c) 2015,2016 Glenn Randers-Pehrson
  * Written by John Cunningham Bowler
  *
  * This code is released under the libpng license.
@@ -30,10 +30,21 @@
 #  include "../../png.h"
 #endif
 
+/* 1.6.1 added support for the configure test harness, which uses 77 to indicate
+ * a skipped test, in earlier versions we need to succeed on a skipped test, so:
+ */
+#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H)
+#  define SKIP 77
+#else
+#  define SKIP 0
+#endif
+
+
 /* Since this program tests the ability to change the unknown chunk handling
  * these must be defined:
  */
 #if defined(PNG_SET_UNKNOWN_CHUNKS_SUPPORTED) &&\
+   defined(PNG_STDIO_SUPPORTED) &&\
    defined(PNG_READ_SUPPORTED)
 
 /* One of these must be defined to allow us to find out what happened.  It is
@@ -615,7 +626,7 @@
 
    return flags;
 }
-#else
+#else /* SAVE_UNKNOWN_CHUNKS */
 static png_uint_32
 get_unknown(display *d, png_infop info_ptr, int after_IDAT)
    /* Otherwise this will return the cached values set by any user callback */
@@ -634,8 +645,8 @@
        * a check to ensure the logic is correct.
        */
 #     error No store support and no user chunk support, this will not work
-#  endif
-#endif
+#  endif /* READ_USER_CHUNKS */
+#endif /* SAVE_UNKNOWN_CHUNKS */
 
 static int
 check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/,
@@ -1001,6 +1012,20 @@
 
    def = check(fp, argc, argv, flags[1], d, set_callback);
 
+   /* If IDAT is being handled as unknown the image read is skipped and all the
+    * IDATs after the first end up in the end info struct, so in this case add
+    * IDAT to the list of unknowns.  (Do this after 'check' above sets the
+    * chunk_info 'keep' fields.)
+    *
+    * Note that the flag setting has to be in the 'known' field to avoid
+    * triggering the consistency check below and the flag must only be set if
+    * there are multiple IDATs, so if the check above did find an unknown IDAT
+    * after IDAT.
+    */
+   if (chunk_info[0/*IDAT*/].keep != PNG_HANDLE_CHUNK_AS_DEFAULT &&
+       (flags[1][3] & PNG_INFO_IDAT) != 0)
+      flags[0][2] |= PNG_INFO_IDAT;
+
    /* Chunks should either be known or unknown, never both and this should apply
     * whether the chunk is before or after the IDAT (actually, the app can
     * probably change this by swapping the handling after the image, but this
@@ -1245,7 +1270,7 @@
    fprintf(stderr,
       " test ignored: no support to find out about unknown chunks\n");
    /* So the test is skipped: */
-   return 77;
+   return SKIP;
 }
 #endif /* READ_USER_CHUNKS || SAVE_UNKNOWN_CHUNKS */
 
@@ -1256,6 +1281,6 @@
    fprintf(stderr,
       " test ignored: no support to modify unknown chunk handling\n");
    /* So the test is skipped: */
-   return 77;
+   return SKIP;
 }
 #endif /* SET_UNKNOWN_CHUNKS && READ*/
diff --git a/contrib/libtests/pngvalid.c b/contrib/libtests/pngvalid.c
index bdd3c91..c82c269 100644
--- a/contrib/libtests/pngvalid.c
+++ b/contrib/libtests/pngvalid.c
@@ -1,8 +1,8 @@
 
 /* pngvalid.c - validate libpng by constructing then reading png files.
  *
- * Last changed in libpng 1.5.25 [December 3, 2015]
- * Copyright (c) 2014-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.22 [(PENDING RELEASE)]
+ * Copyright (c) 2014-2016 Glenn Randers-Pehrson
  * Written by John Cunningham Bowler
  *
  * This code is released under the libpng license.
@@ -62,10 +62,10 @@
 /* 1.6.1 added support for the configure test harness, which uses 77 to indicate
  * a skipped test, in earlier versions we need to succeed on a skipped test, so:
  */
-#if PNG_LIBPNG_VER < 10601
-#  define SKIP 0
-#else
+#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H)
 #  define SKIP 77
+#else
+#  define SKIP 0
 #endif
 
 /* pngvalid requires write support and one of the fixed or floating point APIs.
@@ -116,6 +116,16 @@
 #  define png_const_structp png_structp
 #endif
 
+#ifndef RELEASE_BUILD
+   /* RELEASE_BUILD is true for releases and release candidates: */
+#  define RELEASE_BUILD (PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC)
+#endif
+#if RELEASE_BUILD
+#   define debugonly(something)
+#else /* !RELEASE_BUILD */
+#   define debugonly(something) something
+#endif /* !RELEASE_BUILD */
+
 #include <float.h>  /* For floating point constants */
 #include <stdlib.h> /* For malloc */
 #include <string.h> /* For memcpy, memset */
@@ -276,7 +286,8 @@
    make_random_bytes(seed, bytes, 4);
 }
 
-#if defined PNG_READ_SUPPORTED || defined PNG_WRITE_tRNS_SUPPORTED
+#if defined PNG_READ_SUPPORTED || defined PNG_WRITE_tRNS_SUPPORTED ||\
+    defined PNG_WRITE_FILTER_SUPPORTED
 static void
 randomize(void *pv, size_t size)
 {
@@ -284,19 +295,56 @@
    make_random_bytes(random_seed, pv, size);
 }
 
-#define RANDOMIZE(this) randomize(&(this), sizeof (this))
-#endif /* READ || WRITE_tRNS */
+#define R8(this) randomize(&(this), sizeof (this))
 
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
+static void r16(png_uint_16p p16, size_t count)
+{
+   size_t i;
+
+   for (i=0; i<count; ++i)
+   {
+      unsigned char b2[2];
+      randomize(b2, sizeof b2);
+      *p16++ = png_get_uint_16(b2);
+   }
+}
+
+#define R16(this) r16(&(this), (sizeof (this))/(sizeof (png_uint_16)))
+#define R16_1(this) r16(&(this), (size_t) 1U)
+
+#if defined PNG_READ_RGB_TO_GRAY_SUPPORTED ||\
+    defined PNG_READ_FILLER_SUPPORTED
+static void r32(png_uint_32p p32, size_t count)
+{
+   size_t i;
+
+   for (i=0; i<count; ++i)
+   {
+      unsigned char b4[4];
+      randomize(b4, sizeof b4);
+      *p32++ = png_get_uint_32(b4);
+   }
+}
+
+#define R32(this) r32(&(this), (sizeof (this))/(sizeof (png_uint_32)))
+#define R32_1(this) r32(&(this), (size_t) 1U)
+
+#endif /* READ_FILLER || READ_RGB_TO_GRAY */
+
+#endif /* READ || WRITE_tRNS || WRITE_FILTER */
+
+#if defined PNG_READ_TRANSFORMS_SUPPORTED ||\
+    defined PNG_WRITE_FILTER_SUPPORTED
 static unsigned int
 random_mod(unsigned int max)
 {
-   unsigned int x;
+   png_uint_16 x;
 
-   RANDOMIZE(x);
+   R16_1(x);
 
    return x % max; /* 0 .. max-1 */
 }
+#endif /* READ_TRANSFORMS || WRITE_FILTER */
 
 #if (defined PNG_READ_RGB_TO_GRAY_SUPPORTED) ||\
     (defined PNG_READ_FILLER_SUPPORTED)
@@ -305,12 +353,11 @@
 {
    unsigned char x;
 
-   RANDOMIZE(x);
+   R8(x);
 
    return x & 1;
 }
-#endif
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ_RGB_TO_GRAY || READ_FILLER */
 
 /* A numeric ID based on PNG file characteristics.  The 'do_interlace' field
  * simply records whether pngvalid did the interlace itself or whether it
@@ -1974,6 +2021,8 @@
     * internal check on pngvalid to ensure that the calculated error limits are
     * not ridiculous; without this it is too easy to make a mistake in pngvalid
     * that allows any value through.
+    *
+    * NOTE: this is not checked in release builds.
     */
    double                   limit;    /* limit on error values, normally 4E-3 */
 
@@ -3278,12 +3327,14 @@
    png_color_16 tRNS;
    const png_uint_16 mask = (png_uint_16)((1U << bit_depth)-1);
 
-   RANDOMIZE(tRNS);
+   R8(tRNS); /* makes unset fields random */
 
    if (colour_type & 2/*RGB*/)
    {
       if (bit_depth == 8)
       {
+         R16(tRNS.red);
+         R16(tRNS.green);
          tRNS.blue = tRNS.red ^ tRNS.green;
          tRNS.red &= mask;
          tRNS.green &= mask;
@@ -3292,13 +3343,17 @@
 
       else /* bit_depth == 16 */
       {
+         R16(tRNS.red);
          tRNS.green = (png_uint_16)(tRNS.red * 257);
          tRNS.blue = (png_uint_16)(tRNS.green * 17);
       }
    }
 
    else
+   {
+      R16(tRNS.gray);
       tRNS.gray &= mask;
+   }
 
    png_set_tRNS(pp, pi, NULL, 0, &tRNS);
 }
@@ -3649,6 +3704,28 @@
  * layout details.  See make_size_images below for a way to make images
  * that test odd sizes along with the libpng interlace handling.
  */
+#ifdef PNG_WRITE_FILTER_SUPPORTED
+static void
+choose_random_filter(png_structp pp, int start)
+{
+   /* Choose filters randomly except that on the very first row ensure that
+    * there is at least one previous row filter.
+    */
+   int filters = PNG_ALL_FILTERS & random_mod(256U);
+
+   /* There may be no filters; skip the setting. */
+   if (filters != 0)
+   {
+      if (start && filters < PNG_FILTER_UP)
+         filters |= PNG_FILTER_UP;
+
+      png_set_filter(pp, 0/*method*/, filters);
+   }
+}
+#else /* !WRITE_FILTER */
+#  define choose_random_filter(pp, start) ((void)0)
+#endif /* !WRITE_FILTER */
+
 static void
 make_transform_image(png_store* const ps, png_byte const colour_type,
     png_byte const bit_depth, unsigned int palette_number,
@@ -3767,6 +3844,7 @@
                   }
 #              endif /* do_own_interlace */
 
+               choose_random_filter(pp, pass == 0 && y == 0);
                png_write_row(pp, buffer);
             }
          }
@@ -3943,9 +4021,6 @@
          int npasses = npasses_from_interlace_type(pp, interlace_type);
          png_uint_32 y;
          int pass;
-#        ifdef PNG_WRITE_FILTER_SUPPORTED
-            int nfilter = PNG_FILTER_VALUE_LAST;
-#        endif
          png_byte image[16][SIZE_ROWMAX];
 
          /* To help consistent error detection make the parts of this buffer
@@ -4008,15 +4083,19 @@
                 * does accept a filter number (per the spec) as well as a bit
                 * mask.
                 *
-                * The apparent wackiness of decrementing nfilter rather than
-                * incrementing is so that Paeth gets used in all images bigger
-                * than 1 row - it's the tricky one.
+                * The code now uses filters at random, except that on the first
+                * row of an image it ensures that a previous row filter is in
+                * the set so that libpng allocates the row buffer.
                 */
-               png_set_filter(pp, 0/*method*/,
-                  nfilter >= PNG_FILTER_VALUE_LAST ? PNG_ALL_FILTERS : nfilter);
+               {
+                  int filters = 8 << random_mod(PNG_FILTER_VALUE_LAST);
 
-               if (nfilter-- == 0)
-                  nfilter = PNG_FILTER_VALUE_LAST-1;
+                  if (pass == 0 && y == 0 &&
+                      (filters < PNG_FILTER_UP || w == 1U))
+                     filters |= PNG_FILTER_UP;
+
+                  png_set_filter(pp, 0/*method*/, filters);
+               }
 #           endif
 
                png_write_row(pp, row);
@@ -4244,62 +4323,71 @@
 #undef exception__env
 
       /* And clear these flags */
-      ps->expect_error = 0;
       ps->expect_warning = 0;
 
-      /* Now write the whole image, just to make sure that the detected, or
-       * undetected, errro has not created problems inside libpng.
-       */
-      if (png_get_rowbytes(pp, pi) !=
-          transform_rowsize(pp, colour_type, bit_depth))
-         png_error(pp, "row size incorrect");
+      if (ps->expect_error)
+         ps->expect_error = 0;
 
       else
       {
-         int npasses = set_write_interlace_handling(pp, interlace_type);
-         int pass;
+         /* Now write the whole image, just to make sure that the detected, or
+          * undetected, errro has not created problems inside libpng.  This
+          * doesn't work if there was a png_error in png_write_info because that
+          * can abort before PLTE was written.
+          */
+         if (png_get_rowbytes(pp, pi) !=
+             transform_rowsize(pp, colour_type, bit_depth))
+            png_error(pp, "row size incorrect");
 
-         if (npasses != npasses_from_interlace_type(pp, interlace_type))
-            png_error(pp, "write: png_set_interlace_handling failed");
-
-         for (pass=0; pass<npasses; ++pass)
+         else
          {
-            png_uint_32 y;
+            int npasses = set_write_interlace_handling(pp, interlace_type);
+            int pass;
 
-            for (y=0; y<h; ++y)
+            if (npasses != npasses_from_interlace_type(pp, interlace_type))
+               png_error(pp, "write: png_set_interlace_handling failed");
+
+            for (pass=0; pass<npasses; ++pass)
             {
-               png_byte buffer[TRANSFORM_ROWMAX];
+               png_uint_32 y;
 
-               transform_row(pp, buffer, colour_type, bit_depth, y);
+               for (y=0; y<h; ++y)
+               {
+                  png_byte buffer[TRANSFORM_ROWMAX];
 
-#              if do_own_interlace
-                  /* If do_own_interlace *and* the image is interlaced we need a
-                   * reduced interlace row; this may be reduced to empty.
-                   */
-                  if (interlace_type == PNG_INTERLACE_ADAM7)
-                  {
-                     /* The row must not be written if it doesn't exist, notice
-                      * that there are two conditions here, either the row isn't
-                      * ever in the pass or the row would be but isn't wide
-                      * enough to contribute any pixels.  In fact the wPass test
-                      * can be used to skip the whole y loop in this case.
+                  transform_row(pp, buffer, colour_type, bit_depth, y);
+
+#                 if do_own_interlace
+                     /* If do_own_interlace *and* the image is interlaced we
+                      * need a reduced interlace row; this may be reduced to
+                      * empty.
                       */
-                     if (PNG_ROW_IN_INTERLACE_PASS(y, pass) &&
-                         PNG_PASS_COLS(w, pass) > 0)
-                        interlace_row(buffer, buffer,
-                              bit_size(pp, colour_type, bit_depth), w, pass,
-                              0/*data always bigendian*/);
-                     else
-                        continue;
-                  }
-#              endif /* do_own_interlace */
+                     if (interlace_type == PNG_INTERLACE_ADAM7)
+                     {
+                        /* The row must not be written if it doesn't exist,
+                         * notice that there are two conditions here, either the
+                         * row isn't ever in the pass or the row would be but
+                         * isn't wide enough to contribute any pixels.  In fact
+                         * the wPass test can be used to skip the whole y loop
+                         * in this case.
+                         */
+                        if (PNG_ROW_IN_INTERLACE_PASS(y, pass) &&
+                            PNG_PASS_COLS(w, pass) > 0)
+                           interlace_row(buffer, buffer,
+                                 bit_size(pp, colour_type, bit_depth), w, pass,
+                                 0/*data always bigendian*/);
+                        else
+                           continue;
+                     }
+#                 endif /* do_own_interlace */
 
-               png_write_row(pp, buffer);
+                  png_write_row(pp, buffer);
+               }
             }
-         }
-      }
+         } /* image writing */
 
-      png_write_end(pp, pi);
+         png_write_end(pp, pi);
+      }
 
       /* The following deletes the file that was just written. */
       store_write_reset(ps);
@@ -6257,7 +6345,7 @@
    unsigned int max = (1U<<sample_depth)-1;
    double in_min = ceil((in-err)*max - digitization_error);
    double in_max = floor((in+err)*max + digitization_error);
-   if (err > limit || !(out >= in_min && out <= in_max))
+   if (debugonly(err > limit ||) !(out >= in_min && out <= in_max))
    {
       char message[256];
       size_t pos;
@@ -6283,6 +6371,8 @@
 
       png_error(pp, message);
    }
+
+   UNUSED(limit)
 }
 
 static void
@@ -7213,7 +7303,7 @@
       png_uint_32 ru;
       double total;
 
-      RANDOMIZE(ru);
+      R32_1(ru);
       data.green_coefficient = total = (ru & 0xffff) / 65535.;
       ru >>= 16;
       data.red_coefficient = (1 - total) * (ru & 0xffff) / 65535.;
@@ -7274,14 +7364,12 @@
           * When DIGITIZE is set because a pre-1.7 version of libpng is being
           * tested allow a bigger slack.
           *
-          * NOTE: this magic number was determined by experiment to be about
-          * 1.263.  There's no great merit to the value below, however it only
-          * affects the limit used for checking for internal calculation errors,
-          * not the actual limit imposed by pngvalid on the output errors.
+          * NOTE: this number only affects the internal limit check in pngvalid,
+          * it has no effect on the limits applied to the libpng values.
           */
          that->pm->limit += pow(
 #        if DIGITIZE
-            1.3
+            2.0
 #        else
             1.0
 #        endif
@@ -7443,7 +7531,7 @@
       /* Image now has RGB channels... */
 #  if DIGITIZE
       {
-         const png_modifier *pm = display->pm;
+         png_modifier *pm = display->pm;
          const unsigned int sample_depth = that->sample_depth;
          const unsigned int calc_depth = (pm->assume_16_bit_calculations ? 16 :
             sample_depth);
@@ -7592,9 +7680,11 @@
          else
          {
             err = fabs(grayhi-gray);
+
             if (fabs(gray - graylo) > err)
                err = fabs(graylo-gray);
 
+#if !RELEASE_BUILD
             /* Check that this worked: */
             if (err > pm->limit)
             {
@@ -7605,11 +7695,13 @@
                pos = safecatd(buffer, sizeof buffer, pos, err, 6);
                pos = safecat(buffer, sizeof buffer, pos, " exceeds limit ");
                pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6);
-               png_error(pp, buffer);
+               png_warning(pp, buffer);
+               pm->limit = err;
             }
+#endif /* !RELEASE_BUILD */
          }
       }
-#  else  /* DIGITIZE */
+#  else  /* !DIGITIZE */
       {
          double r = that->redf;
          double re = that->rede;
@@ -7668,7 +7760,7 @@
              * lookups in the calculation and each introduces a quantization
              * error defined by the table size.
              */
-            const png_modifier *pm = display->pm;
+            png_modifier *pm = display->pm;
             double in_qe = (that->sample_depth > 8 ? .5/65535 : .5/255);
             double out_qe = (that->sample_depth > 8 ? .5/65535 :
                (pm->assume_16_bit_calculations ? .5/(1<<display->max_gamma_8) :
@@ -7718,6 +7810,7 @@
             else
                err -= in_qe;
 
+#if !RELEASE_BUILD
             /* Validate that the error is within limits (this has caused
              * problems before, it's much easier to detect them here.)
              */
@@ -7730,8 +7823,10 @@
                pos = safecatd(buffer, sizeof buffer, pos, err, 6);
                pos = safecat(buffer, sizeof buffer, pos, " exceeds limit ");
                pos = safecatd(buffer, sizeof buffer, pos, pm->limit, 6);
-               png_error(pp, buffer);
+               png_warning(pp, buffer);
+               pm->limit = err;
             }
+#endif /* !RELEASE_BUILD */
          }
       }
 #  endif /* !DIGITIZE */
@@ -7802,7 +7897,7 @@
     * so we need to know what that is!  The background colour is stored in the
     * transform_display.
     */
-   RANDOMIZE(random_bytes);
+   R8(random_bytes);
 
    /* Read the random value, for colour type 3 the background colour is actually
     * expressed as a 24bit rgb, not an index.
@@ -7830,7 +7925,7 @@
    /* Extract the background colour from this image_pixel, but make sure the
     * unused fields of 'back' are garbage.
     */
-   RANDOMIZE(back);
+   R8(back);
 
    if (colour_type & PNG_COLOR_MASK_COLOR)
    {
@@ -8136,7 +8231,7 @@
     * filler.  The 'filler' value has all 32 bits set, but only bit_depth
     * will be used.  At this point we don't know bit_depth.
     */
-   RANDOMIZE(data.filler);
+   R32(data.filler);
    data.flags = random_choice();
 
    png_set_filler(pp, data.filler, data.flags);
@@ -8209,7 +8304,7 @@
     * filler.  The 'filler' value has all 32 bits set, but only bit_depth
     * will be used.  At this point we don't know bit_depth.
     */
-   RANDOMIZE(data.filler);
+   R32(data.filler);
    data.flags = random_choice();
 
    png_set_add_alpha(pp, data.filler, data.flags);
@@ -11296,6 +11391,9 @@
 
       else if (strcmp(*argv, "-w") == 0 ||
                strcmp(*argv, "--strict") == 0)
+         pm.this.treat_warnings_as_errors = 1; /* NOTE: this is the default! */
+
+      else if (strcmp(*argv, "--nostrict") == 0)
          pm.this.treat_warnings_as_errors = 0;
 
       else if (strcmp(*argv, "--speed") == 0)
diff --git a/contrib/tools/pngfix.c b/contrib/tools/pngfix.c
index 7fde31c..b2043e3 100644
--- a/contrib/tools/pngfix.c
+++ b/contrib/tools/pngfix.c
@@ -1,8 +1,8 @@
 /* pngfix.c
  *
- * Copyright (c) 2014-2015 John Cunningham Bowler
+ * Copyright (c) 2014-2016 John Cunningham Bowler
  *
- * Last changed in libpng 1.6.20 [December 3, 2015]
+ * Last changed in libpng 1.6.21 [January 15, 2016]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -319,13 +319,13 @@
       a_digits = uarb_mult_digit(acc, a_digits, num, n_digits,
          (png_uint_16)(val & 0xffff));
 
-      /* Because n_digits and val are >0 the following must be true: */
-      assert(a_digits > 0);
-
       val >>= 16;
       if (val > 0)
          a_digits = uarb_mult_digit(acc+1, a_digits-1, num, n_digits,
             (png_uint_16)val) + 1;
+
+      /* Because n_digits and val are >0 the following must be true: */
+      assert(a_digits > 0);
    }
 
    return a_digits;
diff --git a/libpng-manual.txt b/libpng-manual.txt
index 87eeb2b..9261e01 100644
--- a/libpng-manual.txt
+++ b/libpng-manual.txt
@@ -1,9 +1,9 @@
 libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.6.20 - December 3, 2015
+ libpng version 1.6.22beta03 - February 19, 2016
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
- Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ Copyright (c) 1998-2016 Glenn Randers-Pehrson
 
  This document is released under the libpng license.
  For conditions of distribution and use, see the disclaimer
@@ -11,9 +11,9 @@
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.6.20 - December 3, 2015
+ libpng versions 0.97, January 1998, through 1.6.22beta03 - February 19, 2016
  Updated and distributed by Glenn Randers-Pehrson
- Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ Copyright (c) 1998-2016 Glenn Randers-Pehrson
 
  libpng 1.0 beta 6 - version 0.96 - May 28, 1997
  Updated and distributed by Andreas Dilger
@@ -4103,6 +4103,13 @@
 
       Write the image to the named file.
 
+   int png_image_write_to_memory (png_imagep image, void *memory,
+      png_alloc_size_t * PNG_RESTRICT memory_bytes,
+      int convert_to_8_bit, const void *buffer, ptrdiff_t row_stride,
+      const void *colormap));
+
+      Write the image to memory.
+
    int png_image_write_to_stdio(png_imagep image, FILE *file,
       int convert_to_8_bit, const void *buffer,
       png_int_32 row_stride, const void *colormap)
@@ -4775,7 +4782,8 @@
 the 1.4.5 API and the 1.5.0 API; however, the ability to directly access
 members of the main libpng control structures, png_struct and png_info,
 deprecated in earlier versions of libpng, has been completely removed from
-libpng 1.5.
+libpng 1.5, and new private "pngstruct.h", "pnginfo.h", and "pngdebug.h"
+header files were created.
 
 We no longer include zlib.h in png.h.  The include statement has been moved
 to pngstruct.h, where it is not accessible by applications. Applications that
@@ -5015,6 +5023,7 @@
      png_image_free()
    write functions
      png_image_write_to_file()
+     png_image_write_to_memory()
      png_image_write_to_stdio()
 
 Starting with libpng-1.6.0, you can configure libpng to prefix all exported
@@ -5078,6 +5087,10 @@
 and is interpreted by libpng to convey a one-tracer-curve gray profile or a
 three-tracer-curve RGB profile as appropriate.
 
+Libpng 1.5.x erroneously used /MD for Debug DLL builds; if you used the debug
+builds in your app and you changed your app to use /MD you will need to
+change it back to /MDd for libpng 1.6.x.
+
 Prior to libpng-1.6.0 a warning would be issued if the iTXt chunk contained
 an empty language field or an empty translated keyword.  Both of these
 are allowed by the PNG specification, so these warnings are no longer issued.
@@ -5324,7 +5337,7 @@
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.6.20 are Y2K compliant.  It is my belief that earlier
+upward through 1.6.22beta03 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 357d0ec..561e464 100644
--- a/libpng.3
+++ b/libpng.3
@@ -1,6 +1,6 @@
-.TH LIBPNG 3 "December 3, 2015"
+.TH LIBPNG 3 "February 19, 2016"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.6.20
+libpng \- Portable Network Graphics (PNG) Reference Library 1.6.22beta03
 .SH SYNOPSIS
 \fB
 #include <png.h>\fP
@@ -229,6 +229,8 @@
 
 \fBint png_image_write_to_file (png_imagep \fP\fIimage\fP\fB, const char \fP\fI*file\fP\fB, int \fP\fIconvert_to_8bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, void \fI*colormap\fP\fB);\fP
 
+\fBint png_image_write_to_memory (png_imagep \fP\fIimage\fP\fB, void \fP\fI*memory\fP\fB, png_alloc_size_t * PNG_RESTRICT \fP\fImemory_bytes\fP\fB, int \fP\fIconvert_to_8_bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, const void \fI*colormap)\fP\fB);\fP
+
 \fBint png_image_write_to_stdio (png_imagep \fP\fIimage\fP\fB, FILE \fP\fI*file\fP\fB, int \fP\fIconvert_to_8_bit\fP\fB, const void \fP\fI*buffer\fP\fB, png_int_32 \fP\fIrow_stride\fP\fB, void \fI*colormap)\fP\fB);\fP
 
 \fBvoid png_info_init_3 (png_infopp \fP\fIinfo_ptr\fP\fB, png_size_t \fIpng_info_struct_size\fP\fB);\fP
@@ -508,10 +510,10 @@
 .SH LIBPNG.TXT
 libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.6.20 - December 3, 2015
+ libpng version 1.6.22beta03 - February 19, 2016
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
- Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ Copyright (c) 1998-2016 Glenn Randers-Pehrson
 
  This document is released under the libpng license.
  For conditions of distribution and use, see the disclaimer
@@ -519,9 +521,9 @@
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.6.20 - December 3, 2015
+ libpng versions 0.97, January 1998, through 1.6.22beta03 - February 19, 2016
  Updated and distributed by Glenn Randers-Pehrson
- Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ Copyright (c) 1998-2016 Glenn Randers-Pehrson
 
  libpng 1.0 beta 6 - version 0.96 - May 28, 1997
  Updated and distributed by Andreas Dilger
@@ -4611,6 +4613,13 @@
 
       Write the image to the named file.
 
+   int png_image_write_to_memory (png_imagep image, void *memory,
+      png_alloc_size_t * PNG_RESTRICT memory_bytes,
+      int convert_to_8_bit, const void *buffer, ptrdiff_t row_stride,
+      const void *colormap));
+
+      Write the image to memory.
+
    int png_image_write_to_stdio(png_imagep image, FILE *file,
       int convert_to_8_bit, const void *buffer,
       png_int_32 row_stride, const void *colormap)
@@ -5283,7 +5292,8 @@
 the 1.4.5 API and the 1.5.0 API; however, the ability to directly access
 members of the main libpng control structures, png_struct and png_info,
 deprecated in earlier versions of libpng, has been completely removed from
-libpng 1.5.
+libpng 1.5, and new private "pngstruct.h", "pnginfo.h", and "pngdebug.h"
+header files were created.
 
 We no longer include zlib.h in png.h.  The include statement has been moved
 to pngstruct.h, where it is not accessible by applications. Applications that
@@ -5523,6 +5533,7 @@
      png_image_free()
    write functions
      png_image_write_to_file()
+     png_image_write_to_memory()
      png_image_write_to_stdio()
 
 Starting with libpng-1.6.0, you can configure libpng to prefix all exported
@@ -5586,6 +5597,10 @@
 and is interpreted by libpng to convey a one-tracer-curve gray profile or a
 three-tracer-curve RGB profile as appropriate.
 
+Libpng 1.5.x erroneously used /MD for Debug DLL builds; if you used the debug
+builds in your app and you changed your app to use /MD you will need to
+change it back to /MDd for libpng 1.6.x.
+
 Prior to libpng-1.6.0 a warning would be issued if the iTXt chunk contained
 an empty language field or an empty translated keyword.  Both of these
 are allowed by the PNG specification, so these warnings are no longer issued.
@@ -5832,7 +5847,7 @@
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.6.20 are Y2K compliant.  It is my belief that earlier
+upward through 1.6.22beta03 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
@@ -5934,7 +5949,7 @@
  ...
  1.5.23                  15    10523  15.so.15.23[.0]
  ...
- 1.6.20                  16    10620  16.so.16.20[.0]
+ 1.6.22                  16    10622  16.so.16.22[.0]
 
 Henceforth the source version will match the shared-library minor
 and patch numbers; the shared-library major version number will be
@@ -5990,7 +6005,7 @@
 
 Thanks to Frank J. T. Wojcik for helping with the documentation.
 
-Libpng version 1.6.20 - December 3, 2015:
+Libpng version 1.6.22beta03 - February 19, 2016:
 Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
 Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net).
 
@@ -6015,8 +6030,8 @@
 
 This code is released under the libpng license.
 
-libpng versions 1.0.7, July 1, 2000, through 1.6.20, December 3, 2015, are
-Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are
+libpng versions 1.0.7, July 1, 2000, through 1.6.22beta03, February 19, 2016, are
+Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
 derived from libpng-1.0.6, and are distributed according to the same
 disclaimer and license as libpng-1.0.6 with the following individuals
 added to the list of Contributing Authors:
@@ -6037,6 +6052,10 @@
    risk of satisfactory quality, performance, accuracy, and effort is with
    the user.
 
+Some files in the "contrib" directory and some configure-generated
+files that are distributed with libpng have other copyright owners and
+are released under other open source licenses.
+
 libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
 Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
 libpng-0.96, and are distributed according to the same disclaimer and
@@ -6060,6 +6079,9 @@
    Greg Roelofs
    Tom Tanner
 
+Some files in the "scripts" directory have other copyright owners
+but are released under this license.
+
 libpng versions 0.5, May 1995, through 0.88, January 1996, are
 Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
 
@@ -6100,6 +6122,29 @@
 
 END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
 
+TRADEMARK:
+
+The name "libpng" has not been registered by the Copyright owner
+as a trademark in any jurisdiction.  However, because libpng has
+been distributed and maintained world-wide, continually since 1995,
+the Copyright owner claims "common-law trademark protection" in any
+jurisdiction where common-law trademark is recognized.
+
+OSI CERTIFICATION:
+
+Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
+a certification mark of the Open Source Initiative. OSI has not addressed
+the additional disclaimers inserted at version 1.0.7.
+
+EXPORT CONTROL:
+
+The Copyright owner believes that the Export Control Classification
+Number (ECCN) for libpng is EAR99, which means not subject to export
+controls or International Traffic in Arms Regulations (ITAR) because
+it is open source, publicly available software, that does not contain
+any encryption software.  See the EAR, paragraphs 734.3(b)(3) and
+734.7(b).
+
 A "png_get_copyright" function is available, for convenient use in "about"
 boxes and the like:
 
@@ -6108,13 +6153,9 @@
 Also, the PNG logo (in PNG format, of course) is supplied in the
 files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
 
-Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
-a certification mark of the Open Source Initiative. OSI has not addressed
-the additional disclaimers inserted at version 1.0.7.
-
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-December 3, 2015
+February 19, 2016
 
 .\" end of man page
 
diff --git a/libpngpf.3 b/libpngpf.3
index 4da0843..5173d8a 100644
--- a/libpngpf.3
+++ b/libpngpf.3
@@ -1,6 +1,6 @@
-.TH LIBPNGPF 3 "December 3, 2015"
+.TH LIBPNGPF 3 "February 8, 2016"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.6.20
+libpng \- Portable Network Graphics (PNG) Reference Library 1.6.22beta03
 (private functions)
 .SH SYNOPSIS
 \fB#include \fI"pngpriv.h"
diff --git a/png.5 b/png.5
index 76a327b..f1e6c3a 100644
--- a/png.5
+++ b/png.5
@@ -1,4 +1,4 @@
-.TH PNG 5 "December 3, 2015"
+.TH PNG 5 "February 8, 2016"
 .SH NAME
 png \- Portable Network Graphics (PNG) format
 .SH DESCRIPTION
diff --git a/png.c b/png.c
index c183e3f..ea5b94c 100644
--- a/png.c
+++ b/png.c
@@ -2,7 +2,7 @@
 /* png.c - location for general purpose libpng functions
  *
  * Last changed in libpng 1.6.19 [November 12, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
@@ -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_20 Your_png_h_is_not_version_1_6_20;
+typedef png_libpng_version_1_6_22beta03 Your_png_h_is_not_version_1_6_22beta03;
 
 /* 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
@@ -775,14 +775,15 @@
 #else
 #  ifdef __STDC__
    return PNG_STRING_NEWLINE \
-      "libpng version 1.6.20 - December 3, 2015" PNG_STRING_NEWLINE \
-      "Copyright (c) 1998-2015 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+      "libpng version 1.6.22beta03 - February 8, 2016" PNG_STRING_NEWLINE \
+      "Copyright (c) 1998-2002,2004,2006-2016 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.20 - December 3, 2015\
-      Copyright (c) 1998-2015 Glenn Randers-Pehrson\
+   return "libpng version 1.6.22beta03 - February 8, 2016\
+      Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
 #  endif
diff --git a/png.h b/png.h
index 3ac3ee9..62a7cb7 100644
--- a/png.h
+++ b/png.h
@@ -1,9 +1,9 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.6.20, December 3, 2015
+ * libpng version 1.6.22beta03, February 19, 2016
  *
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2016 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.)
  *
@@ -12,7 +12,7 @@
  * Authors and maintainers:
  *   libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
  *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
- *   libpng versions 0.97, January 1998, through 1.6.20, December 3, 2015:
+ *   libpng versions 0.97, January 1998, through 1.6.22beta03, February 19, 2016:
  *     Glenn Randers-Pehrson.
  *   See also "Contributing Authors", below.
  */
@@ -25,8 +25,12 @@
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.0.7, July 1, 2000, through 1.6.20, December 3, 2015, are
- * Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are
+ * Some files in the "contrib" directory and some configure-generated
+ * files that are distributed with libpng have other copyright owners and
+ * are released under other open source licenses.
+ *
+ * libpng versions 1.0.7, July 1, 2000, through 1.6.22beta03, February 19, 2016, are
+ * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
  * derived from libpng-1.0.6, and are distributed according to the same
  * disclaimer and license as libpng-1.0.6 with the following individuals
  * added to the list of Contributing Authors:
@@ -47,6 +51,10 @@
  *    risk of satisfactory quality, performance, accuracy, and effort is with
  *    the user.
  *
+ * Some files in the "contrib" directory have other copyright owners and
+ * are released under other open source licenses.
+ *
+ *
  * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
  * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
  * libpng-0.96, and are distributed according to the same disclaimer and
@@ -57,6 +65,9 @@
  *    Glenn Randers-Pehrson
  *    Willem van Schaik
  *
+ * Some files in the "scripts" directory have different copyright owners
+ * but are also released under this license.
+ *
  * libpng versions 0.89, June 1996, through 0.96, May 1997, are
  * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
  * and are distributed according to the same disclaimer and license as
@@ -70,6 +81,9 @@
  *    Greg Roelofs
  *    Tom Tanner
  *
+ * Some files in the "scripts" directory have other copyright owners
+ * but are released under this license.
+ *
  * libpng versions 0.5, May 1995, through 0.88, January 1996, are
  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
  *
@@ -109,6 +123,29 @@
  * appreciated.
  *
  * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
+ *
+ * TRADEMARK:
+ *
+ * The name "libpng" has not been registered by the Copyright owner
+ * as a trademark in any jurisdiction.  However, because libpng has
+ * been distributed and maintained world-wide, continually since 1995,
+ * the Copyright owner claims "common-law trademark protection" in any
+ * jurisdiction where common-law trademark is recognized.
+ *
+ * OSI CERTIFICATION:
+ *
+ * Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
+ * a certification mark of the Open Source Initiative. OSI has not addressed
+ * the additional disclaimers inserted at version 1.0.7.
+ *
+ * EXPORT CONTROL:
+ *
+ * The Copyright owner believes that the Export Control Classification
+ * Number (ECCN) for libpng is EAR99, which means not subject to export
+ * controls or International Traffic in Arms Regulations (ITAR) because
+ * it is open source, publicly available software, that does not contain
+ * any encryption software.  See the EAR, paragraphs 734.3(b)(3) and
+ * 734.7(b).
  */
 
 /*
@@ -122,12 +159,6 @@
  */
 
 /*
- * Libpng is OSI Certified Open Source Software.  OSI Certified Open Source is
- * a certification mark of the Open Source Initiative. OSI has not addressed
- * the additional disclaimers inserted at version 1.0.7.
- */
-
-/*
  * The contributing authors would like to thank all those who helped
  * with testing, bug fixes, and patience.  This wouldn't have been
  * possible without all of you.
@@ -186,7 +217,7 @@
  *    ...
  *    1.5.23                  15    10523  15.so.15.23[.0]
  *    ...
- *    1.6.20                  16    10620  16.so.16.20[.0]
+ *    1.6.22                  16    10622  16.so.16.22[.0]
  *
  *    Henceforth the source version will match the shared-library major
  *    and minor numbers; the shared-library major version number will be
@@ -214,13 +245,13 @@
  * Y2K compliance in libpng:
  * =========================
  *
- *    December 3, 2015
+ *    February 19, 2016
  *
  *    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.20 are Y2K compliant.  It is my belief that
+ *    upward through 1.6.22beta03 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
@@ -282,9 +313,9 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.20"
+#define PNG_LIBPNG_VER_STRING "1.6.22beta03"
 #define PNG_HEADER_VERSION_STRING \
-     " libpng version 1.6.20 - December 3, 2015\n"
+     " libpng version 1.6.22beta03 - February 19, 2016\n"
 
 #define PNG_LIBPNG_VER_SONUM   16
 #define PNG_LIBPNG_VER_DLLNUM  16
@@ -292,13 +323,13 @@
 /* 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 20
+#define PNG_LIBPNG_VER_RELEASE 22
 
 /* This should match the numeric part of the final component of
  * PNG_LIBPNG_VER_STRING, omitting any leading zero:
  */
 
-#define PNG_LIBPNG_VER_BUILD  0
+#define PNG_LIBPNG_VER_BUILD  03
 
 /* Release Status */
 #define PNG_LIBPNG_BUILD_ALPHA    1
@@ -315,7 +346,7 @@
 #define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with
                                        PNG_LIBPNG_BUILD_PRIVATE */
 
-#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
+#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA
 
 /* Careful here.  At one time, Guy wanted to use 082, but that would be octal.
  * We must not include leading zeros.
@@ -323,7 +354,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 10620 /* 1.6.20 */
+#define PNG_LIBPNG_VER 10622 /* 1.6.22 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
@@ -433,7 +464,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_20;
+typedef char* png_libpng_version_1_6_22beta03;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
@@ -734,24 +765,22 @@
  * data in the info_struct to be written into the output file.  The values
  * of the PNG_INFO_<chunk> defines should NOT be changed.
  */
-#define PNG_INFO_gAMA 0x0001
-#define PNG_INFO_sBIT 0x0002
-#define PNG_INFO_cHRM 0x0004
-#define PNG_INFO_PLTE 0x0008
-#define PNG_INFO_tRNS 0x0010
-#define PNG_INFO_bKGD 0x0020
-#define PNG_INFO_hIST 0x0040
-#define PNG_INFO_pHYs 0x0080
-#define PNG_INFO_oFFs 0x0100
-#define PNG_INFO_tIME 0x0200
-#define PNG_INFO_pCAL 0x0400
-#define PNG_INFO_sRGB 0x0800   /* GR-P, 0.96a */
-#define PNG_INFO_iCCP 0x1000   /* ESR, 1.0.6 */
-#define PNG_INFO_sPLT 0x2000   /* ESR, 1.0.6 */
-#define PNG_INFO_sCAL 0x4000   /* ESR, 1.0.6 */
-#if INT_MAX >= 0x8000 /* else this might break */
-#define PNG_INFO_IDAT 0x8000   /* ESR, 1.0.6 */
-#endif
+#define PNG_INFO_gAMA 0x0001U
+#define PNG_INFO_sBIT 0x0002U
+#define PNG_INFO_cHRM 0x0004U
+#define PNG_INFO_PLTE 0x0008U
+#define PNG_INFO_tRNS 0x0010U
+#define PNG_INFO_bKGD 0x0020U
+#define PNG_INFO_hIST 0x0040U
+#define PNG_INFO_pHYs 0x0080U
+#define PNG_INFO_oFFs 0x0100U
+#define PNG_INFO_tIME 0x0200U
+#define PNG_INFO_pCAL 0x0400U
+#define PNG_INFO_sRGB 0x0800U  /* GR-P, 0.96a */
+#define PNG_INFO_iCCP 0x1000U  /* ESR, 1.0.6 */
+#define PNG_INFO_sPLT 0x2000U  /* ESR, 1.0.6 */
+#define PNG_INFO_sCAL 0x4000U  /* ESR, 1.0.6 */
+#define PNG_INFO_IDAT 0x8000U  /* ESR, 1.0.6 */
 
 /* This is used for the transformation routines, as some of them
  * change these values for the row.  It also should enable using
@@ -786,10 +815,6 @@
 typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32,
     int));
 
-#ifdef PNG_INDEX_SUPPORTED
-typedef PNG_CALLBACK(void, *png_seek_ptr, (png_structp, png_uint_32));
-#endif
-
 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
 typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
 typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
@@ -1750,40 +1775,26 @@
 PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
     png_inforp info_ptr, int freer, png_uint_32 mask));
 
-#ifdef PNG_INDEX_SUPPORTED
-/* Build image index for partial image decoding. */
-PNG_EXPORT(300, void, png_build_index, (png_structp png_ptr));
-PNG_EXPORT(301, void, png_configure_decoder,
-    (png_structp png_ptr, int *row_offset, int pass));
-/* Set the data seek function with a user supplied one.
- * REQUIRED by partial image decode.
- */
-PNG_EXPORT(302, void, png_set_seek_fn, (png_structp png_ptr,
-   png_seek_ptr seek_data_fn));
-/* Update the decoder status to the given pass */
-PNG_EXPORT(303, void, png_set_interlaced_pass, (png_structp png_ptr, int pass));
-#endif
-
 /* Assignments for png_data_freer */
 #define PNG_DESTROY_WILL_FREE_DATA 1
 #define PNG_SET_WILL_FREE_DATA 1
 #define PNG_USER_WILL_FREE_DATA 2
 /* Flags for png_ptr->free_me and info_ptr->free_me */
-#define PNG_FREE_HIST 0x0008
-#define PNG_FREE_ICCP 0x0010
-#define PNG_FREE_SPLT 0x0020
-#define PNG_FREE_ROWS 0x0040
-#define PNG_FREE_PCAL 0x0080
-#define PNG_FREE_SCAL 0x0100
+#define PNG_FREE_HIST 0x0008U
+#define PNG_FREE_ICCP 0x0010U
+#define PNG_FREE_SPLT 0x0020U
+#define PNG_FREE_ROWS 0x0040U
+#define PNG_FREE_PCAL 0x0080U
+#define PNG_FREE_SCAL 0x0100U
 #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-#  define PNG_FREE_UNKN 0x0200
+#  define PNG_FREE_UNKN 0x0200U
 #endif
-/*      PNG_FREE_LIST 0x0400    removed in 1.6.0 because it is ignored */
-#define PNG_FREE_PLTE 0x1000
-#define PNG_FREE_TRNS 0x2000
-#define PNG_FREE_TEXT 0x4000
-#define PNG_FREE_ALL  0x7fff
-#define PNG_FREE_MUL  0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
+/*      PNG_FREE_LIST 0x0400U   removed in 1.6.0 because it is ignored */
+#define PNG_FREE_PLTE 0x1000U
+#define PNG_FREE_TRNS 0x2000U
+#define PNG_FREE_TEXT 0x4000U
+#define PNG_FREE_ALL  0x7fffU
+#define PNG_FREE_MUL  0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
 
 #ifdef PNG_USER_MEM_SUPPORTED
 PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr,
@@ -2907,12 +2918,19 @@
     * is the minimum 'row stride', the minimum count of components between each
     * row.  For a color-mapped image this is the minimum number of bytes in a
     * row.
+    *
+    * WARNING: this macro overflows for some images with more than one component
+    * and very large image widths.  libpng will refuse to process an image where
+    * this macro would overflow.
     */
 
 #define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
    (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
    /* Return the size, in bytes, of an image buffer given a png_image and a row
     * stride - the number of components to leave space for in each row.
+    *
+    * WARNING: this macro overflows a 32-bit integer for some large PNG images,
+    * libpng will refuse to process an image where such an overflow would occur.
     */
 
 #define PNG_IMAGE_SIZE(image)\
@@ -3033,7 +3051,6 @@
 #endif /* SIMPLIFIED_READ */
 
 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
-#ifdef PNG_STDIO_SUPPORTED
 /* WRITE APIS
  * ----------
  * For write you must initialize a png_image structure to describe the image to
@@ -3050,6 +3067,7 @@
  *    values do not correspond to the colors in sRGB.
  * colormap_entries: set to the number of entries in the color-map (0 to 256)
  */
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
 PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
    const char *file, int convert_to_8bit, const void *buffer,
    png_int_32 row_stride, const void *colormap));
@@ -3059,8 +3077,9 @@
    int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
    const void *colormap));
    /* Write the image to the given (FILE*). */
+#endif /* SIMPLIFIED_WRITE_STDIO */
 
-/* With both write APIs if image is in one of the linear formats with 16-bit
+/* With all write APIs if image is in one of the linear formats with 16-bit
  * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
  * gamma encoded according to the sRGB specification, otherwise a 16-bit linear
  * encoded PNG file is written.
@@ -3072,13 +3091,103 @@
  *
  * With all APIs row_stride is handled as in the read APIs - it is the spacing
  * from one row to the next in component sized units (1 or 2 bytes) and if
- * negative indicates a bottom-up row layout in the buffer.  If row_stride is zero,
- * libpng will calculate it for you from the image width and number of channels.
+ * negative indicates a bottom-up row layout in the buffer.  If row_stride is
+ * zero, libpng will calculate it for you from the image width and number of
+ * channels.
  *
- * Note that the write API does not support interlacing, sub-8-bit pixels, indexed
- * PNG (color_type 3) or most ancillary chunks.
+ * Note that the write API does not support interlacing, sub-8-bit pixels or
+ * most ancillary chunks.  If you need to write text chunks (e.g. for copyright
+ * notices) you need to use one of the other APIs.
  */
-#endif /* STDIO */
+
+PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
+   png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit,
+   const void *buffer, png_int_32 row_stride, const void *colormap));
+   /* Write the image to the given memory buffer.  The function both writes the
+    * whole PNG data stream to *memory and updates *memory_bytes with the count
+    * of bytes written.
+    *
+    * 'memory' may be NULL.  In this case *memory_bytes is not read however on
+    * success the number of bytes which would have been written will still be
+    * stored in *memory_bytes.  On failure *memory_bytes will contain 0.
+    *
+    * If 'memory' is not NULL it must point to memory[*memory_bytes] of
+    * writeable memory.
+    *
+    * If the function returns success memory[*memory_bytes] (if 'memory' is not
+    * NULL) contains the written PNG data.  *memory_bytes will always be less
+    * than or equal to the original value.
+    *
+    * If the function returns false and *memory_bytes was not changed an error
+    * occured during write.  If *memory_bytes was changed, or is not 0 if
+    * 'memory' was NULL, the write would have succeeded but for the memory
+    * buffer being too small.  *memory_bytes contains the required number of
+    * bytes and will be bigger that the original value.
+    */
+
+#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\
+   row_stride, colormap)\
+   png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\
+         row_stride, colormap)
+   /* Return the amount of memory in 'size' required to compress this image.
+    * The png_image structure 'image' must be filled in as in the above
+    * function and must not be changed before the actual write call, the buffer
+    * and all other parameters must also be identical to that in the final
+    * write call.  The 'size' variable need not be initialized.
+    *
+    * NOTE: the macro returns true/false, if false is returned 'size' will be
+    * set to zero and the write failed and probably will fail if tried again.
+    */
+
+/* You can pre-allocate the buffer by making sure it is of sufficient size
+ * regardless of the amount of compression achieved.  The buffer size will
+ * always be bigger than the original image and it will never be filled.  The
+ * following macros are provided to assist in allocating the buffer.
+ */
+#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height)
+   /* The number of uncompressed bytes in the PNG byte encoding of the image;
+    * uncompressing the PNG IDAT data will give this number of bytes.
+    *
+    * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this
+    * macro can because of the extra bytes used in the PNG byte encoding.  You
+    * need to avoid this macro if your image size approaches 2^30 in width or
+    * height.  The same goes for the remainder of these macros; they all produce
+    * bigger numbers than the actual in-memory image size.
+    */
+#ifndef PNG_ZLIB_MAX_SIZE
+#  define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U)
+   /* An upper bound on the number of compressed bytes given 'b' uncompressed
+    * bytes.  This is based on deflateBounds() in zlib; different
+    * implementations of zlib compression may conceivably produce more data so
+    * if your zlib implementation is not zlib itself redefine this macro
+    * appropriately.
+    */
+#endif
+
+#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\
+   PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image))
+   /* An upper bound on the size of the data in the PNG IDAT chunks. */
+
+#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\
+   ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\
+    (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\
+     12U+3U*(image).colormap_entries/*PLTE data*/+\
+     (((image).format&PNG_FORMAT_FLAG_ALPHA)?\
+      12U/*tRNS*/+(image).colormap_entries:0U):0U)+\
+    12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size))
+   /* A helper for the following macro; if your compiler cannot handle the
+    * following macro use this one with the result of
+    * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most
+    * compilers should handle this just fine.)
+    */
+
+#define PNG_IMAGE_PNG_SIZE_MAX(image)\
+   PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image))
+   /* An upper bound on the total length of the PNG data stream for 'image'.
+    * The result is of type png_alloc_size_t, on 32-bit systems this may
+    * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will
+    * run out of buffer space but return a corrected size which should work.
+    */
 #endif /* SIMPLIFIED_WRITE */
 /*******************************************************************************
  *  END OF SIMPLIFIED API
@@ -3136,7 +3245,7 @@
  * one to use is one more than this.)
  */
 #ifdef PNG_EXPORT_LAST_ORDINAL
-  PNG_EXPORT_LAST_ORDINAL(244);
+  PNG_EXPORT_LAST_ORDINAL(245);
 #endif
 
 #ifdef __cplusplus
diff --git a/pngconf.h b/pngconf.h
index 92f2500..c850f5d 100644
--- a/pngconf.h
+++ b/pngconf.h
@@ -1,9 +1,9 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.6.20, December 3, 2015
+ * libpng version 1.6.22beta03, February 8, 2016
  *
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
diff --git a/pngdebug.h b/pngdebug.h
index 6a01b10..15a7ed0 100644
--- a/pngdebug.h
+++ b/pngdebug.h
@@ -2,7 +2,7 @@
 /* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
  *
  * Last changed in libpng 1.6.8 [December 19, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2013 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.)
  *
diff --git a/pngerror.c b/pngerror.c
index bdb959e..6904bea 100644
--- a/pngerror.c
+++ b/pngerror.c
@@ -2,7 +2,7 @@
 /* pngerror.c - stub functions for i/o and memory allocation
  *
  * Last changed in libpng 1.6.15 [November 20, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-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.)
  *
diff --git a/pngget.c b/pngget.c
index 743a6a9..ca44982 100644
--- a/pngget.c
+++ b/pngget.c
@@ -2,7 +2,7 @@
 /* pngget.c - retrieval of values from info struct
  *
  * Last changed in libpng 1.6.17 [March 26, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
diff --git a/pnginfo.h b/pnginfo.h
index 4bd264b..361ed8b 100644
--- a/pnginfo.h
+++ b/pnginfo.h
@@ -2,7 +2,7 @@
 /* pnginfo.h - header file for PNG reference library
  *
  * Last changed in libpng 1.6.1 [March 28, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2013 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.)
  *
diff --git a/pnglibconf.h b/pnglibconf.h
index ff01a93..657452d 100644
--- a/pnglibconf.h
+++ b/pnglibconf.h
@@ -1,8 +1,8 @@
-/* libpng 1.6.19 STANDARD API DEFINITION */
+/* libpng 1.6.22beta03 STANDARD API DEFINITION */
 
 /* pnglibconf.h - library build configuration */
 
-/* Libpng version 1.6.19 - November 12, 2015 */
+/* Libpng version 1.6.22beta03 - February 8, 2016 */
 
 /* Copyright (c) 1998-2015 Glenn Randers-Pehrson */
 
@@ -40,7 +40,6 @@
 #define PNG_GET_PALETTE_MAX_SUPPORTED
 #define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
 #define PNG_INCH_CONVERSIONS_SUPPORTED
-#define PNG_INDEX_SUPPORTED
 #define PNG_INFO_IMAGE_SUPPORTED
 #define PNG_IO_STATE_SUPPORTED
 #define PNG_MNG_FEATURES_SUPPORTED
@@ -110,6 +109,7 @@
 #define PNG_SIMPLIFIED_READ_SUPPORTED
 #define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
 #define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
+#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
 #define PNG_SIMPLIFIED_WRITE_SUPPORTED
 #define PNG_STDIO_SUPPORTED
 #define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
@@ -121,7 +121,7 @@
 #define PNG_USER_MEM_SUPPORTED
 #define PNG_USER_TRANSFORM_INFO_SUPPORTED
 #define PNG_USER_TRANSFORM_PTR_SUPPORTED
-/* #undef PNG_WARNINGS_SUPPORTED */
+/*#undef PNG_WARNINGS_SUPPORTED*/
 #define PNG_WRITE_16BIT_SUPPORTED
 #define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
 #define PNG_WRITE_BGR_SUPPORTED
diff --git a/pngmem.c b/pngmem.c
index 45ac557..7bcfd00 100644
--- a/pngmem.c
+++ b/pngmem.c
@@ -2,7 +2,7 @@
 /* pngmem.c - stub functions for memory allocation
  *
  * Last changed in libpng 1.6.15 [November 20, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-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.)
  *
diff --git a/pngpread.c b/pngpread.c
index 89ffc40..0dc1e53 100644
--- a/pngpread.c
+++ b/pngpread.c
@@ -2,7 +2,7 @@
 /* pngpread.c - read a png file in push mode
  *
  * Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
diff --git a/pngpriv.h b/pngpriv.h
index bf7cc74..0ac16fa 100644
--- a/pngpriv.h
+++ b/pngpriv.h
@@ -1,8 +1,8 @@
 
 /* pngpriv.h - private declarations for use inside libpng
  *
- * Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.21 [(PENDING RELEASE)]
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
@@ -182,6 +182,42 @@
 #  endif
 #endif /* PNG_ARM_NEON_OPT > 0 */
 
+#ifndef PNG_INTEL_SSE_OPT
+#   ifdef PNG_INTEL_SSE
+      /* Only check for SSE if the build configuration has been modified to
+       * enable SSE optimizations.  This means that these optimizations will
+       * be off by default.  See contrib/intel for more details.
+       */
+#     if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
+       defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
+       (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
+#         define PNG_INTEL_SSE_OPT 1
+#      endif
+#   endif
+#endif
+
+#if PNG_INTEL_SSE_OPT > 0
+#   ifndef PNG_INTEL_SSE_IMPLEMENTATION
+#      if defined(__SSE4_1__) || defined(__AVX__)
+          /* We are not actually using AVX, but checking for AVX is the best
+             way we can detect SSE4.1 and SSSE3 on MSVC.
+          */
+#         define PNG_INTEL_SSE_IMPLEMENTATION 3
+#      elif defined(__SSSE3__)
+#         define PNG_INTEL_SSE_IMPLEMENTATION 2
+#      elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
+       (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
+#         define PNG_INTEL_SSE_IMPLEMENTATION 1
+#      else
+#         define PNG_INTEL_SSE_IMPLEMENTATION 0
+#      endif
+#   endif
+
+#   if PNG_INTEL_SSE_IMPLEMENTATION > 0
+#      define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2
+#   endif
+#endif
+
 /* Is this a build of a DLL where compilation of the object modules requires
  * different preprocessor settings to those required for a simple library?  If
  * so PNG_BUILD_DLL must be set.
@@ -1189,6 +1225,19 @@
 PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
 
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+
 /* Choose the best filter to use and filter the row data */
 PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
     png_row_infop row_info),PNG_EMPTY);
@@ -1915,14 +1964,12 @@
     */
 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
+   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
 #endif
 
-#ifdef PNG_INDEX_SUPPORTED
-PNG_INTERNAL_FUNCTION(void, png_seek_data, (png_structp png_ptr,
-   png_uint_32 length), PNG_EMPTY);
-PNG_INTERNAL_FUNCTION(int, png_opt_crc_finish,(png_structrp png_ptr,
-   png_uint_32 skip), PNG_EMPTY);
-#endif
+PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
+   png_const_charp key, png_bytep new_key), PNG_EMPTY);
 
 /* Maintainer: Put new private prototypes here ^ */
 
diff --git a/pngread.c b/pngread.c
index 7699608..614fcd1 100644
--- a/pngread.c
+++ b/pngread.c
@@ -2,7 +2,7 @@
 /* pngread.c - read a PNG file
  *
  * Last changed in libpng 1.6.17 [March 26, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
@@ -73,10 +73,6 @@
        * required.
        */
       png_set_read_fn(png_ptr, NULL, NULL);
-
-#ifdef PNG_INDEX_SUPPORTED
-      png_ptr->index = NULL;
-#endif
    }
 
    return png_ptr;
@@ -266,11 +262,6 @@
 
    if (png_ptr != NULL)
    {
-#ifdef PNG_INDEX_SUPPORTED
-      if (png_ptr->index) {
-         png_read_start_row(png_ptr);
-      }
-#endif
       if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
       {
          png_read_start_row(png_ptr);
@@ -281,12 +272,11 @@
             PNG_UNUSED(info_ptr)
 #        endif
       }
-#ifndef PNG_INDEX_SUPPORTED
+
       /* New in 1.6.0 this avoids the bug of doing the initializations twice */
       else
          png_app_error(png_ptr,
             "png_read_update_info/png_start_read_image: duplicate call");
-#endif
    }
 }
 
@@ -684,148 +674,6 @@
 }
 #endif /* SEQUENTIAL_READ */
 
-#ifdef PNG_INDEX_SUPPORTED
-#define IDAT_HEADER_SIZE 8
-
-/* Set the png read position to a new position based on idat_position and
- * offset.
- */
-void
-png_set_read_offset(png_structp png_ptr,
-      png_uint_32 idat_position, png_uint_32 bytes_left)
-{
-   png_seek_data(png_ptr, idat_position);
-   png_ptr->idat_size = png_read_chunk_header(png_ptr);
-
-   // We need to add back IDAT_HEADER_SIZE because in zlib's perspective,
-   // IDAT_HEADER in PNG is already stripped out.
-   png_seek_data(png_ptr, idat_position + IDAT_HEADER_SIZE + png_ptr->idat_size - bytes_left);
-   png_ptr->idat_size = bytes_left;
-}
-
-/* Configure png decoder to decode the pass starting from *row.
- * The requested row may be adjusted to align with an indexing row.
- * The actual row for the decoder to start its decoding will be returned in
- * *row.
- */
-void PNGAPI
-png_configure_decoder(png_structp png_ptr, int *row, int pass)
-{
-   png_indexp index = png_ptr->index;
-   int n = *row / index->step[pass];
-   png_line_indexp line_index = index->pass_line_index[pass][n];
-
-   // Adjust row to an indexing row.
-   *row = n * index->step[pass];
-   png_ptr->row_number = *row;
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   if (png_ptr->interlaced)
-      png_set_interlaced_pass(png_ptr, pass);
-#endif
-
-   long row_byte_length =
-      PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1;
-
-   inflateEnd(&png_ptr->zstream);
-   inflateCopy(&png_ptr->zstream, line_index->z_state);
-
-   // Set the png read position to line_index.
-   png_set_read_offset(png_ptr, line_index->stream_idat_position,
-         line_index->bytes_left_in_idat);
-   memcpy(png_ptr->prev_row, line_index->prev_row, row_byte_length);
-   png_ptr->zstream.avail_in = 0;
-}
-
-/* Build the line index and store the index in png_ptr->index.
- */
-void PNGAPI
-png_build_index(png_structp png_ptr)
-{
-   // number of rows in a 8x8 block for each interlaced pass.
-   int number_rows_in_pass[7] = {1, 1, 1, 2, 2, 4, 4};
-
-   int ret;
-   png_uint_32 i, j;
-   png_bytep rp;
-   int p, pass_number = 1;
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   pass_number = png_set_interlace_handling(png_ptr);
-#endif
-
-   if (png_ptr == NULL)
-      return;
-
-   png_read_start_row(png_ptr);
-
-#ifdef PNG_READ_INTERLACING_SUPPORTED
-   if (!png_ptr->interlaced)
-#endif
-   {
-      number_rows_in_pass[0] = 8;
-   }
-
-   // Allocate a buffer big enough for any transform.
-   rp = png_malloc(png_ptr, PNG_ROWBYTES(png_ptr->maximum_pixel_depth, png_ptr->width));
-
-   png_indexp index = png_malloc(png_ptr, sizeof(png_index));
-   png_ptr->index = index;
-
-   index->stream_idat_position = png_ptr->total_data_read - IDAT_HEADER_SIZE;
-
-   // Set the default size of index in each pass to 0,
-   // so that we can free index correctly in png_destroy_read_struct.
-   for (p = 0; p < 7; p++)
-      index->size[p] = 0;
-
-   for (p = 0; p < pass_number; p++)
-   {
-      // We adjust the index step in each pass to make sure each pass
-      // has roughly the same size of index.
-      // This way, we won't consume to much memory in recording index.
-      index->step[p] = INDEX_SAMPLE_SIZE * (8 / number_rows_in_pass[p]);
-      const png_uint_32 temp_size =
-         (png_ptr->height + index->step[p] - 1) / index->step[p];
-      index->pass_line_index[p] =
-         png_malloc(png_ptr, temp_size * sizeof(png_line_indexp));
-
-      // Get the row_byte_length seen by the filter. This value may be
-      // different from the row_byte_length of a bitmap in the case of
-      // color palette mode.
-      int row_byte_length =
-         PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1;
-
-      // Now, we record index for each indexing row.
-      for (i = 0; i < temp_size; i++)
-      {
-         png_line_indexp line_index = png_malloc(png_ptr, sizeof(png_line_index));
-         index->pass_line_index[p][i] = line_index;
-
-         line_index->z_state = png_malloc(png_ptr, sizeof(z_stream));
-         inflateCopy(line_index->z_state, &png_ptr->zstream);
-         line_index->prev_row = png_malloc(png_ptr, row_byte_length);
-         memcpy(line_index->prev_row, png_ptr->prev_row, row_byte_length);
-         line_index->stream_idat_position = index->stream_idat_position;
-         line_index->bytes_left_in_idat = png_ptr->idat_size + png_ptr->zstream.avail_in;
-
-         // increment the size now that we have the backing data structures.
-         // This prevents a crash in the event that png_read_row fails and
-         // we need to cleanup the partially constructed png_index_struct;
-         index->size[p] += 1;
-
-         // Skip the "step" number of rows to the next indexing row.
-         for (j = 0; j < index->step[p] &&
-               i * index->step[p] + j < png_ptr->height; j++)
-         {
-            png_read_row(png_ptr, rp, NULL);
-         }
-      }
-   }
-   png_free(png_ptr, rp);
-}
-#endif
-
 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
 /* Read the entire image.  If the image has an alpha channel or a tRNS
  * chunk, and you have called png_handle_alpha()[*], you will need to
@@ -1125,25 +973,6 @@
    png_ptr->chunk_list = NULL;
 #endif
 
-#ifdef PNG_INDEX_SUPPORTED
-   if (png_ptr->index) {
-      unsigned int i, p;
-      png_indexp index = png_ptr->index;
-      for (p = 0; p < 7; p++) {
-         for (i = 0; i < index->size[p]; i++) {
-            inflateEnd(index->pass_line_index[p][i]->z_state);
-            png_free(png_ptr, index->pass_line_index[p][i]->z_state);
-            png_free(png_ptr, index->pass_line_index[p][i]->prev_row);
-            png_free(png_ptr, index->pass_line_index[p][i]);
-         }
-         if (index->size[p] != 0) {
-            png_free(png_ptr, index->pass_line_index[p]);
-         }
-      }
-      png_free(png_ptr, index);
-   }
-#endif
-
    /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
     * callbacks are still set at this point.  They are required to complete the
     * destruction of the png_struct itself.
@@ -4242,58 +4071,84 @@
 {
    if (image != NULL && image->version == PNG_IMAGE_VERSION)
    {
-      png_uint_32 check;
+      /* Check for row_stride overflow.  This check is not performed on the
+       * original PNG format because it may not occur in the output PNG format
+       * and libpng deals with the issues of reading the original.
+       */
+      const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
 
-      if (row_stride == 0)
-         row_stride = PNG_IMAGE_ROW_STRIDE(*image);
-
-      if (row_stride < 0)
-         check = -row_stride;
-
-      else
-         check = row_stride;
-
-      if (image->opaque != NULL && buffer != NULL &&
-         check >= PNG_IMAGE_ROW_STRIDE(*image))
+      if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
       {
-         if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
-            (image->colormap_entries > 0 && colormap != NULL))
+         png_uint_32 check;
+         const png_uint_32 png_row_stride = image->width * channels;
+
+         if (row_stride == 0)
+            row_stride = (png_int_32)/*SAFE*/png_row_stride;
+
+         if (row_stride < 0)
+            check = -row_stride;
+
+         else
+            check = row_stride;
+
+         if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
          {
-            int result;
-            png_image_read_control display;
-
-            memset(&display, 0, (sizeof display));
-            display.image = image;
-            display.buffer = buffer;
-            display.row_stride = row_stride;
-            display.colormap = colormap;
-            display.background = background;
-            display.local_row = NULL;
-
-            /* Choose the correct 'end' routine; for the color-map case all the
-             * setup has already been done.
+            /* Now check for overflow of the image buffer calculation; this
+             * limits the whole image size to 32 bits for API compatibility with
+             * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
              */
-            if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
-               result =
-                  png_safe_execute(image, png_image_read_colormap, &display) &&
-                  png_safe_execute(image, png_image_read_colormapped, &display);
+            if (image->height <= 0xFFFFFFFF/png_row_stride)
+            {
+               if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
+                  (image->colormap_entries > 0 && colormap != NULL))
+               {
+                  int result;
+                  png_image_read_control display;
+
+                  memset(&display, 0, (sizeof display));
+                  display.image = image;
+                  display.buffer = buffer;
+                  display.row_stride = row_stride;
+                  display.colormap = colormap;
+                  display.background = background;
+                  display.local_row = NULL;
+
+                  /* Choose the correct 'end' routine; for the color-map case
+                   * all the setup has already been done.
+                   */
+                  if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
+                     result = png_safe_execute(image,
+                                    png_image_read_colormap, &display) &&
+                              png_safe_execute(image,
+                                    png_image_read_colormapped, &display);
+
+                  else
+                     result =
+                        png_safe_execute(image,
+                              png_image_read_direct, &display);
+
+                  png_image_free(image);
+                  return result;
+               }
+
+               else
+                  return png_image_error(image,
+                     "png_image_finish_read[color-map]: no color-map");
+            }
 
             else
-               result =
-                  png_safe_execute(image, png_image_read_direct, &display);
-
-            png_image_free(image);
-            return result;
+               return png_image_error(image,
+                  "png_image_finish_read: image too large");
          }
 
          else
             return png_image_error(image,
-               "png_image_finish_read[color-map]: no color-map");
+               "png_image_finish_read: invalid argument");
       }
 
       else
          return png_image_error(image,
-            "png_image_finish_read: invalid argument");
+            "png_image_finish_read: row_stride too large");
    }
 
    else if (image != NULL)
diff --git a/pngrio.c b/pngrio.c
index 23d72b1..5101d54 100644
--- a/pngrio.c
+++ b/pngrio.c
@@ -2,7 +2,7 @@
 /* pngrio.c - functions for data input
  *
  * Last changed in libpng 1.6.17 [March 26, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
@@ -38,22 +38,8 @@
 
    else
       png_error(png_ptr, "Call to NULL read function");
-#ifdef PNG_INDEX_SUPPORTED
-   png_ptr->total_data_read += length;
-#endif
 }
 
-#ifdef PNG_INDEX_SUPPORTED
-void /* PRIVATE */
-png_seek_data(png_structp png_ptr, png_uint_32 offset)
-{
-   if (png_ptr->seek_data_fn != NULL)
-      (*(png_ptr->seek_data_fn))(png_ptr, offset);
-   else
-      png_error(png_ptr, "Call to NULL seek function");
-}
-#endif
-
 #ifdef PNG_STDIO_SUPPORTED
 /* This is the function that does the actual reading of data.  If you are
  * not reading from a standard C stream, you should create a replacement
@@ -131,15 +117,4 @@
    png_ptr->output_flush_fn = NULL;
 #endif
 }
-
-#ifdef PNG_INDEX_SUPPORTED
-void PNGAPI
-png_set_seek_fn(png_structp png_ptr, png_seek_ptr seek_data_fn)
-{
-   if (png_ptr == NULL)
-      return;
-   png_ptr->seek_data_fn = seek_data_fn;
-}
-#endif
-
 #endif /* READ */
diff --git a/pngrtran.c b/pngrtran.c
index 608adef..8456714 100644
--- a/pngrtran.c
+++ b/pngrtran.c
@@ -1,8 +1,8 @@
 
 /* pngrtran.c - transforms the data in a row for PNG readers
  *
- * Last changed in libpng 1.6.19 [November 12, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.22 [(PENDING RELEASE)]
+ * Copyright (c) 1998-2002,2004,2006-2016 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.)
  *
@@ -99,7 +99,6 @@
 {
    if (png_ptr != NULL)
    {
-#ifndef PNG_INDEX_SUPPORTED
       if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
          png_app_error(png_ptr,
             "invalid after png_start_read_image or png_read_update_info");
@@ -114,9 +113,6 @@
 
          return 1; /* Ok */
       }
-#else
-      return 1;
-#endif
    }
 
    return 0; /* no png_error possible! */
@@ -293,9 +289,12 @@
     * is expected to be 1 or greater, but this range test allows for some
     * viewing correction values.  The intent is to weed out users of this API
     * who use the inverse of the gamma value accidentally!  Since some of these
-    * values are reasonable this may have to be changed.
+    * values are reasonable this may have to be changed:
+    *
+    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit
+    * gamma of 36, and its reciprocal.)
     */
-   if (output_gamma < 70000 || output_gamma > 300000)
+   if (output_gamma < 1000 || output_gamma > 10000000)
       png_error(png_ptr, "output gamma out of expected range");
 
    /* The default file gamma is the inverse of the output gamma; the output
diff --git a/pngrutil.c b/pngrutil.c
index 8382444..c9747fc 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.20 [December 3, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.20 [December 3, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
@@ -241,40 +241,6 @@
    return (0);
 }
 
-#ifdef PNG_INDEX_SUPPORTED
-/* If tile index is used to skip over data and decode a partial image
- * the crc value may be incorrect.
- * The crc will only be calculated for the partial data read,
- * not the entire data, which will result in an incorrect crc value.
- * This function treats a png_crc_error as a warning, as opposed to the
- * original function png_crc_finish, which will treat it as an error.
- */
-int /* PRIVATE */
-png_opt_crc_finish(png_structrp png_ptr, png_uint_32 skip)
-{
-   while (skip > 0)
-   {
-      png_uint_32 len;
-      png_byte tmpbuf[PNG_INFLATE_BUF_SIZE];
-
-      len = (sizeof tmpbuf);
-      if (len > skip)
-         len = skip;
-      skip -= len;
-
-      png_crc_read(png_ptr, tmpbuf, len);
-   }
-
-   if (png_crc_error(png_ptr))
-   {
-      png_chunk_warning(png_ptr, "CRC error");
-      return (1);
-   }
-
-   return (0);
-}
-#endif
-
 /* Compare the CRC stored in the PNG file with that calculated by libpng from
  * the data it has read thus far.
  */
@@ -4050,12 +4016,6 @@
 
          while (png_ptr->idat_size == 0)
          {
-#ifdef PNG_INDEX_SUPPORTED
-            if (png_ptr->index) {
-               png_opt_crc_finish(png_ptr, 0);
-               png_ptr->index->stream_idat_position = png_ptr->total_data_read;
-            } else
-#endif
             png_crc_finish(png_ptr, 0);
 
             png_ptr->idat_size = png_read_chunk_header(png_ptr);
@@ -4134,14 +4094,7 @@
          break;
       }
 
-      if (ret != Z_OK) {
-#ifdef PNG_INDEX_SUPPORTED
-        if (png_ptr->index) {
-          if (png_ptr->row_number != png_ptr->height - 1) {
-            png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : "Decompression error");
-          }
-        } else
-#endif
+      if (ret != Z_OK)
       {
          png_zstream_error(png_ptr, ret);
 
@@ -4154,7 +4107,6 @@
             return;
          }
       }
-    }
    } while (avail_out > 0);
 
    if (avail_out > 0)
@@ -4214,39 +4166,10 @@
        * crc_finish here.  If idat_size is non-zero we also need to read the
        * spurious bytes at the end of the chunk now.
        */
-#ifdef PNG_INDEX_SUPPORTED
-      if (png_ptr->index)
-      {
-        (void)png_opt_crc_finish(png_ptr, png_ptr->idat_size);
-        png_ptr->index->stream_idat_position = png_ptr->total_data_read;
-      }
-      else
-#endif
       (void)png_crc_finish(png_ptr, png_ptr->idat_size);
    }
 }
 
-#ifdef PNG_INDEX_SUPPORTED
-void /* PRIVATE */
-png_set_interlaced_pass(png_structp png_ptr, int pass)
-{
-   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
-   /* Start of interlace block */
-   PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
-   /* Offset to next interlace block */
-   PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
-   /* Start of interlace block in the y direction */
-   PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
-   /* Offset to next interlace block in the y direction */
-   PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-   png_ptr->pass = pass;
-   png_ptr->iwidth = (png_ptr->width +
-         png_pass_inc[png_ptr->pass] - 1 -
-         png_pass_start[png_ptr->pass]) /
-      png_pass_inc[png_ptr->pass];
-}
-#endif
-
 void /* PRIVATE */
 png_read_finish_row(png_structrp png_ptr)
 {
diff --git a/pngset.c b/pngset.c
index 8fd7965..2103fe6 100644
--- a/pngset.c
+++ b/pngset.c
@@ -1,7 +1,7 @@
 
 /* pngset.c - storage of image information into info struct
  *
- * Last changed in libpng 1.6.19 [November 12, 2015]
+ * Last changed in libpng 1.6.21 [(PENDING RELEASE)]
  * Copyright (c) 1998-2015 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.)
@@ -1644,4 +1644,88 @@
       png_ptr->num_palette_max = -1;
 }
 #endif
+
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \
+    defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
+/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+ * and if invalid, correct the keyword rather than discarding the entire
+ * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
+ * length, forbids leading or trailing whitespace, multiple internal spaces,
+ * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
+ *
+ * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
+ * trailing '\0').  If this routine returns 0 then there was no keyword, or a
+ * valid one could not be generated, and the caller must png_error.
+ */
+png_uint_32 /* PRIVATE */
+png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
+{
+   png_const_charp orig_key = key;
+   png_uint_32 key_len = 0;
+   int bad_character = 0;
+   int space = 1;
+
+   png_debug(1, "in png_check_keyword");
+
+   if (key == NULL)
+   {
+      *new_key = 0;
+      return 0;
+   }
+
+   while (*key && key_len < 79)
+   {
+      png_byte ch = (png_byte)*key++;
+
+      if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
+         *new_key++ = ch, ++key_len, space = 0;
+
+      else if (space == 0)
+      {
+         /* A space or an invalid character when one wasn't seen immediately
+          * before; output just a space.
+          */
+         *new_key++ = 32, ++key_len, space = 1;
+
+         /* If the character was not a space then it is invalid. */
+         if (ch != 32)
+            bad_character = ch;
+      }
+
+      else if (bad_character == 0)
+         bad_character = ch; /* just skip it, record the first error */
+   }
+
+   if (key_len > 0 && space != 0) /* trailing space */
+   {
+      --key_len, --new_key;
+      if (bad_character == 0)
+         bad_character = 32;
+   }
+
+   /* Terminate the keyword */
+   *new_key = 0;
+
+   if (key_len == 0)
+      return 0;
+
+#ifdef PNG_WARNINGS_SUPPORTED
+   /* Try to only output one warning per keyword: */
+   if (*key != 0) /* keyword too long */
+      png_warning(png_ptr, "keyword truncated");
+
+   else if (bad_character != 0)
+   {
+      PNG_WARNING_PARAMETERS(p)
+
+      png_warning_parameter(p, 1, orig_key);
+      png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
+
+      png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
+   }
+#endif /* WARNINGS */
+
+   return key_len;
+}
+#endif /* TEXT || pCAL || iCCP || sPLT */
 #endif /* READ || WRITE */
diff --git a/pngstruct.h b/pngstruct.h
index dd2e38e..c1f35ed 100644
--- a/pngstruct.h
+++ b/pngstruct.h
@@ -2,7 +2,7 @@
 /* pngstruct.h - header file for PNG reference library
  *
  * Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
@@ -140,50 +140,6 @@
 #define PNG_COLORSPACE_CANCEL(flags)        (0xffff ^ (flags))
 #endif /* COLORSPACE || GAMMA */
 
-#ifdef PNG_INDEX_SUPPORTED
-/* png_line_index_struct records an index point, where we impose an index point
- * to be located at the beginning of a line for simplifying the implementation.
- */
-typedef struct png_line_index_struct
-{
-   // state of the lz decoder
-   z_streamp   z_state;
-
-   // the IDAT header position of the chunk, which the index point is in
-   png_uint_32  stream_idat_position;
-
-   // we intend to record the offset of the index point in the chunk,
-   // but we record the number of remaining bytes in the chunk after the
-   // index point. That's because PNG processes a chunk this way.
-   png_uint_32  bytes_left_in_idat;
-
-   // decompressed data of the previous row
-   png_bytep   prev_row;
-} png_line_index;
-typedef png_line_index FAR * png_line_indexp;
-
-typedef struct png_index_struct
-{
-   // A temporary variable used when we build the index. The variable records
-   // the IDAT header position of the last chunk read in so far.
-   png_uint_32  stream_idat_position;
-
-   // line index information about each passes
-
-   // the number of index points in each pass
-   png_uint_32  size[7];
-
-   // the line span of two index points of each pass
-   png_uint_32  step[7];
-
-   // the index points of each pass
-   png_line_indexp  *pass_line_index[7];
-} png_index;
-typedef png_index FAR * png_indexp;
-
-#define INDEX_SAMPLE_SIZE 254
-#endif
-
 struct png_struct_def
 {
 #ifdef PNG_SETJMP_SUPPORTED
@@ -199,9 +155,6 @@
    png_voidp error_ptr;       /* user supplied struct for error functions */
    png_rw_ptr write_data_fn;  /* function for writing output data */
    png_rw_ptr read_data_fn;   /* function for reading input data */
-#ifdef PNG_INDEX_SUPPORTED
-   png_seek_ptr seek_data_fn; /* function for seeking input data */
-#endif
    png_voidp io_ptr;          /* ptr to application struct for I/O functions */
 
 #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
@@ -526,11 +479,5 @@
    png_colorspace   colorspace;
 #endif
 #endif
-
-#ifdef PNG_INDEX_SUPPORTED
-   png_indexp index;
-   png_uint_32 total_data_read;
-#endif
-
 };
 #endif /* PNGSTRUCT_H */
diff --git a/pngtest.c b/pngtest.c
index 5d50e66..40a73ff 100644
--- a/pngtest.c
+++ b/pngtest.c
@@ -2,7 +2,7 @@
 /* pngtest.c - a simple test program to test libpng
  *
  * Last changed in libpng 1.5.25 [December 3, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
@@ -43,6 +43,15 @@
 
 #include "png.h"
 
+/* 1.6.1 added support for the configure test harness, which uses 77 to indicate
+ * a skipped test, in earlier versions we need to succeed on a skipped test, so:
+ */
+#if PNG_LIBPNG_VER >= 10601 && defined(HAVE_CONFIG_H)
+#  define SKIP 77
+#else
+#  define SKIP 0
+#endif
+
 /* Known chunks that exist in pngtest.png must be supported or pngtest will fail
  * simply as a result of re-ordering them.  This may be fixed in 1.7
  *
@@ -2065,9 +2074,9 @@
    fprintf(STDERR,
       " test ignored because libpng was not built with read support\n");
    /* And skip this test */
-   return PNG_LIBPNG_VER < 10600 ? 0 : 77;
+   return SKIP;
 }
 #endif
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_20 Your_png_h_is_not_version_1_6_20;
+typedef png_libpng_version_1_6_22beta03 Your_png_h_is_not_version_1_6_22beta03;
diff --git a/pngtrans.c b/pngtrans.c
index 0c0d92d..7f8cc45 100644
--- a/pngtrans.c
+++ b/pngtrans.c
@@ -2,7 +2,7 @@
 /* pngtrans.c - transforms the data in a row (used by both readers and writers)
  *
  * Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
diff --git a/pngwio.c b/pngwio.c
index db76e6b..586c03b 100644
--- a/pngwio.c
+++ b/pngwio.c
@@ -2,7 +2,7 @@
 /* pngwio.c - functions for data output
  *
  * Last changed in libpng 1.6.15 [November 20, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-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.)
  *
diff --git a/pngwrite.c b/pngwrite.c
index 0d4ee9f..181a899 100644
--- a/pngwrite.c
+++ b/pngwrite.c
@@ -2,7 +2,7 @@
 /* pngwrite.c - general routines to write a PNG file
  *
  * Last changed in libpng 1.6.19 [November 12, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
@@ -12,9 +12,9 @@
  */
 
 #include "pngpriv.h"
-#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
 #  include <errno.h>
-#endif
+#endif /* SIMPLIFIED_WRITE_STDIO */
 
 #ifdef PNG_WRITE_SUPPORTED
 
@@ -1452,7 +1452,6 @@
 
 
 #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
-# ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
 /* Initialize the write structure - general purpose utility. */
 static int
 png_image_write_init(png_imagep image)
@@ -1504,6 +1503,10 @@
    png_const_voidp first_row;
    ptrdiff_t       row_bytes;
    png_voidp       local_row;
+   /* Byte count for memory writing */
+   png_bytep        memory;
+   png_alloc_size_t memory_bytes; /* not used for STDIO */
+   png_alloc_size_t output_bytes; /* running total */
 } png_image_write_control;
 
 /* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
@@ -1931,9 +1934,43 @@
       png_set_benign_errors(png_ptr, 0/*error*/);
 #   endif
 
-   /* Default the 'row_stride' parameter if required. */
-   if (display->row_stride == 0)
-      display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
+   /* Default the 'row_stride' parameter if required, also check the row stride
+    * and total image size to ensure that they are within the system limits.
+    */
+   {
+      const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
+
+      if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
+      {
+         png_uint_32 check;
+         const png_uint_32 png_row_stride = image->width * channels;
+
+         if (display->row_stride == 0)
+            display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
+
+         if (display->row_stride < 0)
+            check = -display->row_stride;
+
+         else
+            check = display->row_stride;
+
+         if (check >= png_row_stride)
+         {
+            /* Now check for overflow of the image buffer calculation; this
+             * limits the whole image size to 32 bits for API compatibility with
+             * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
+             */
+            if (image->height > 0xFFFFFFFF/png_row_stride)
+               png_error(image->opaque->png_ptr, "memory image too large");
+         }
+
+         else
+            png_error(image->opaque->png_ptr, "supplied row stride too small");
+      }
+
+      else
+         png_error(image->opaque->png_ptr, "image row stride too large");
+   }
 
    /* Set the required transforms then write the rows in the correct order. */
    if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
@@ -2110,6 +2147,122 @@
    return 1;
 }
 
+
+static void (PNGCBAPI
+image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data,
+   png_size_t size)
+{
+   png_image_write_control *display = png_voidcast(png_image_write_control*,
+      png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
+   const png_alloc_size_t ob = display->output_bytes;
+
+   /* Check for overflow; this should never happen: */
+   if (size <= ((png_alloc_size_t)-1) - ob)
+   {
+      /* I don't think libpng ever does this, but just in case: */
+      if (size > 0)
+      {
+         if (display->memory_bytes >= ob+size) /* writing */
+            memcpy(display->memory+ob, data, size);
+
+         /* Always update the size: */
+         display->output_bytes = ob+size;
+      }
+   }
+
+   else
+      png_error(png_ptr, "png_image_write_to_memory: PNG too big");
+}
+
+static void (PNGCBAPI
+image_memory_flush)(png_structp png_ptr)
+{
+   PNG_UNUSED(png_ptr)
+}
+
+static int
+png_image_write_memory(png_voidp argument)
+{
+   png_image_write_control *display = png_voidcast(png_image_write_control*,
+      argument);
+
+   /* The rest of the memory-specific init and write_main in an error protected
+    * environment.  This case needs to use callbacks for the write operations
+    * since libpng has no built in support for writing to memory.
+    */
+   png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/,
+         image_memory_write, image_memory_flush);
+
+   return png_image_write_main(display);
+}
+
+int PNGAPI
+png_image_write_to_memory(png_imagep image, void *memory,
+   png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
+   const void *buffer, png_int_32 row_stride, const void *colormap)
+{
+   /* Write the image to the given buffer, or count the bytes if it is NULL */
+   if (image != NULL && image->version == PNG_IMAGE_VERSION)
+   {
+      if (memory_bytes != NULL && buffer != NULL)
+      {
+         /* This is to give the caller an easier error detection in the NULL
+          * case and guard against uninitialized variable problems:
+          */
+         if (memory == NULL)
+            *memory_bytes = 0;
+
+         if (png_image_write_init(image) != 0)
+         {
+            png_image_write_control display;
+            int result;
+
+            memset(&display, 0, (sizeof display));
+            display.image = image;
+            display.buffer = buffer;
+            display.row_stride = row_stride;
+            display.colormap = colormap;
+            display.convert_to_8bit = convert_to_8bit;
+            display.memory = png_voidcast(png_bytep, memory);
+            display.memory_bytes = *memory_bytes;
+            display.output_bytes = 0;
+
+            result = png_safe_execute(image, png_image_write_memory, &display);
+            png_image_free(image);
+
+            /* write_memory returns true even if we ran out of buffer. */
+            if (result)
+            {
+               /* On out-of-buffer this function returns '0' but still updates
+                * memory_bytes:
+                */
+               if (memory != NULL && display.output_bytes > *memory_bytes)
+                  result = 0;
+
+               *memory_bytes = display.output_bytes;
+            }
+
+            return result;
+         }
+
+         else
+            return 0;
+      }
+
+      else
+         return png_image_error(image,
+            "png_image_write_to_memory: invalid argument");
+   }
+
+   else if (image != NULL)
+      return png_image_error(image,
+         "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
+
+   else
+      return 0;
+}
+
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
 int PNGAPI
 png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
    const void *buffer, png_int_32 row_stride, const void *colormap)
@@ -2117,7 +2270,7 @@
    /* Write the image to the given (FILE*). */
    if (image != NULL && image->version == PNG_IMAGE_VERSION)
    {
-      if (file != NULL)
+      if (file != NULL && buffer != NULL)
       {
          if (png_image_write_init(image) != 0)
          {
@@ -2167,7 +2320,7 @@
    /* Write the image to the named file. */
    if (image != NULL && image->version == PNG_IMAGE_VERSION)
    {
-      if (file_name != NULL)
+      if (file_name != NULL && buffer != NULL)
       {
          FILE *fp = fopen(file_name, "wb");
 
@@ -2225,6 +2378,6 @@
    else
       return 0;
 }
-# endif /* STDIO */
+#endif /* SIMPLIFIED_WRITE_STDIO */
 #endif /* SIMPLIFIED_WRITE */
 #endif /* WRITE */
diff --git a/pngwtran.c b/pngwtran.c
index 5dc9491..038a2ef 100644
--- a/pngwtran.c
+++ b/pngwtran.c
@@ -2,7 +2,7 @@
 /* pngwtran.c - transforms the data in a row for PNG writers
  *
  * Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
diff --git a/pngwutil.c b/pngwutil.c
index 0ee102b..aa5bda3 100644
--- a/pngwutil.c
+++ b/pngwutil.c
@@ -1,8 +1,8 @@
 
 /* pngwutil.c - utilities to write a PNG file
  *
- * Last changed in libpng 1.6.19 [November 12, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.21 [(PENDING RELEASE)]
+ * Copyright (c) 1998-2002,2004,2006-2015 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.)
  *
@@ -23,10 +23,10 @@
 void PNGAPI
 png_save_uint_32(png_bytep buf, png_uint_32 i)
 {
-   buf[0] = (png_byte)(i >> 24);
-   buf[1] = (png_byte)(i >> 16);
-   buf[2] = (png_byte)(i >> 8);
-   buf[3] = (png_byte)(i     );
+   buf[0] = (png_byte)((i >> 24) & 0xffU);
+   buf[1] = (png_byte)((i >> 16) & 0xffU);
+   buf[2] = (png_byte)((i >>  8) & 0xffU);
+   buf[3] = (png_byte)( i        & 0xffU);
 }
 
 /* Place a 16-bit number into a buffer in PNG byte order.
@@ -36,8 +36,8 @@
 void PNGAPI
 png_save_uint_16(png_bytep buf, unsigned int i)
 {
-   buf[0] = (png_byte)(i >> 8);
-   buf[1] = (png_byte)(i     );
+   buf[0] = (png_byte)((i >> 8) & 0xffU);
+   buf[1] = (png_byte)( i       & 0xffU);
 }
 #endif
 
@@ -665,90 +665,6 @@
 }
 #endif /* WRITE_COMPRESSED_TEXT */
 
-#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
-    defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
-/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
- * and if invalid, correct the keyword rather than discarding the entire
- * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
- * length, forbids leading or trailing whitespace, multiple internal spaces,
- * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
- *
- * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
- * trailing '\0').  If this routine returns 0 then there was no keyword, or a
- * valid one could not be generated, and the caller must png_error.
- */
-static png_uint_32
-png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
-{
-   png_const_charp orig_key = key;
-   png_uint_32 key_len = 0;
-   int bad_character = 0;
-   int space = 1;
-
-   png_debug(1, "in png_check_keyword");
-
-   if (key == NULL)
-   {
-      *new_key = 0;
-      return 0;
-   }
-
-   while (*key && key_len < 79)
-   {
-      png_byte ch = (png_byte)*key++;
-
-      if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
-         *new_key++ = ch, ++key_len, space = 0;
-
-      else if (space == 0)
-      {
-         /* A space or an invalid character when one wasn't seen immediately
-          * before; output just a space.
-          */
-         *new_key++ = 32, ++key_len, space = 1;
-
-         /* If the character was not a space then it is invalid. */
-         if (ch != 32)
-            bad_character = ch;
-      }
-
-      else if (bad_character == 0)
-         bad_character = ch; /* just skip it, record the first error */
-   }
-
-   if (key_len > 0 && space != 0) /* trailing space */
-   {
-      --key_len, --new_key;
-      if (bad_character == 0)
-         bad_character = 32;
-   }
-
-   /* Terminate the keyword */
-   *new_key = 0;
-
-   if (key_len == 0)
-      return 0;
-
-#ifdef PNG_WARNINGS_SUPPORTED
-   /* Try to only output one warning per keyword: */
-   if (*key != 0) /* keyword too long */
-      png_warning(png_ptr, "keyword truncated");
-
-   else if (bad_character != 0)
-   {
-      PNG_WARNING_PARAMETERS(p)
-
-      png_warning_parameter(p, 1, orig_key);
-      png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
-
-      png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
-   }
-#endif /* WARNINGS */
-
-   return key_len;
-}
-#endif /* WRITE_TEXT || WRITE_pCAL || WRITE_iCCP || WRITE_sPLT */
-
 /* Write the IHDR chunk, and update the png_struct with the necessary
  * information.  Note that the rest of this code depends upon this
  * information being correct.
diff --git a/projects/vstudio/readme.txt b/projects/vstudio/README.txt
similarity index 63%
rename from projects/vstudio/readme.txt
rename to projects/vstudio/README.txt
index 3866463..6919cc0 100644
--- a/projects/vstudio/readme.txt
+++ b/projects/vstudio/README.txt
@@ -1,9 +1,9 @@
 
 VisualStudio instructions
 
-libpng version 1.6.20 - December 3, 2015
+libpng version 1.6.22beta03 - February 8, 2016
 
-Copyright (c) 1998-2010 Glenn Randers-Pehrson
+Copyright (c) 2010,2013,2015 Glenn Randers-Pehrson
 
 This code is released under the libpng license.
 For conditions of distribution and use, see the disclaimer
@@ -38,16 +38,17 @@
 If you use Visual Studio defaults to build your application you will have no
 problems.
 
-If you don't use the Visual Studio defaults your application must still be built
-with the default runtime option (/MD).  If, for some reason, it is not then your
-application will crash inside libpng16.dll as soon as libpng tries to read
-from a file handle you pass in.
+If you don't use the Visual Studio defaults your application must still be
+built with the default runtime option (/MD).  If, for some reason, it is not
+then your application will crash inside libpng16.dll as soon as libpng
+tries to read from a file handle you pass in.
 
 If you do not want to use the DLL, for example for a very small application,
 the 'release library' configuration may be more appropriate.  This is built
 with a non-standard runtime library - the "MultiThreaded" version.  When you
 build your application it must be compiled with this option (/MT), otherwise
-it will not build (if you are lucky) or crash (if you are not.)
+it will not build (if you are lucky) or crash (if you are not.) See the
+WARNING file that is distributed along with this readme.txt.
 
 Stop reading here
 =================
@@ -63,3 +64,32 @@
 
 The debug build of libpng is minimally supported.  Support for debug builds of
 zlib is also minimal.  You really don't want to do this.
+
+WARNING
+=======
+Libpng 1.6.x does not use the default run-time library when building static
+library builds of libpng; instead of the shared DLL runtime it uses a static
+runtime.  If you need to change this make sure to change the setting on all the
+relevant projects:
+
+    libpng
+    zlib
+    all the test programs
+
+The runtime library settings for each build are as follows:
+
+               Release        Debug
+    DLL         /MD            /MDd
+    Library     /MT            /MTd
+
+NOTICE that libpng 1.5.x erroneously used /MD for Debug DLL builds; if you used
+the debug builds in your app and you changed your app to use /MD you will need
+to change it back to /MDd for libpng 1.6.0 and later.
+
+The Visual Studio 2010 defaults for a Win32 DLL or Static Library project are
+as follows:
+
+                     Release     Debug
+    DLL               /MD         /MDd
+    Static Library    /MD         /MDd
+
diff --git a/projects/vstudio/WARNING b/projects/vstudio/WARNING
deleted file mode 100644
index da002c9..0000000
--- a/projects/vstudio/WARNING
+++ /dev/null
@@ -1,27 +0,0 @@
-WARNING
-=======
-Libpng 1.6 does not use the default run-time library when building static
-library builds of libpng; instead of the shared DLL runtime it uses a static
-runtime.  If you need to change this make sure to change the setting on all the
-relevant projects:
-
-libpng
-zlib
-all the test programs
-
-The runtime library settings for each build are as follows:
-
-           Release        Debug
-DLL         /MD            /MDd
-Library     /MT            /MTd
-
-NOTICE that libpng 1.5 erroneously used /MD for Debug DLL builds; if you used
-the debug builds in your app and you changed your app to use /MD you will need
-to change it to /MDd for libpng 1.6.
-
-The Visual Studio 2010 defaults for a Win32 DLL or Static Library project are
-as follows:
-
-                 Release     Debug
-DLL               /MD         /MDd
-Static Library    /MD         /MDd
diff --git a/projects/vstudio/zlib.props b/projects/vstudio/zlib.props
index 7faf359..caf5d9c 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.20 - December 3, 2015
+ * libpng version 1.6.22beta03 - February 8, 2016
  *
  * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  *
diff --git a/scripts/README.txt b/scripts/README.txt
index 68245f0..63e0e0e 100644
--- a/scripts/README.txt
+++ b/scripts/README.txt
@@ -1,9 +1,9 @@
 
-Makefiles for  libpng version 1.6.20 - December 3, 2015
+Makefiles for  libpng version 1.6.22beta03 - February 8, 2016
 
 pnglibconf.h.prebuilt       =>  Stores configuration settings
  makefile.linux    =>  Linux/ELF makefile
-                       (gcc, creates libpng16.so.16.1.6.20)
+                       (gcc, creates libpng16.so.16.1.6.22beta03)
  makefile.gcc      =>  Generic makefile (gcc, creates static libpng.a)
  makefile.knr      =>  Archaic UNIX Makefile that converts files with
                        ansi2knr (Requires ansi2knr.c from
@@ -33,12 +33,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.20)
+                       creates libpng16.so.16.1.6.22beta03)
  makefile.sgi      =>  Silicon Graphics IRIX makefile (cc, creates static lib)
  makefile.solaris  =>  Solaris 2.X makefile (gcc,
-                       creates libpng16.so.16.1.6.20)
+                       creates libpng16.so.16.1.6.22beta03)
  makefile.so9      =>  Solaris 9 makefile (gcc,
-                       creates libpng16.so.16.1.6.20)
+                       creates libpng16.so.16.1.6.22beta03)
  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.c b/scripts/def.c
index c3e424d..383738a 100644
--- a/scripts/def.c
+++ b/scripts/def.c
@@ -21,7 +21,7 @@
 PNG_DFN "OS2 CODE PRELOAD MOVEABLE DISCARDABLE"
 PNG_DFN ""
 PNG_DFN "EXPORTS"
-PNG_DFN ";Version 1.6.20"
+PNG_DFN ";Version 1.6.22beta03"
 
 #define PNG_EXPORTA(ordinal, type, name, args, attributes)\
         PNG_DFN "@" SYMBOL_PREFIX "@@" name "@"
diff --git a/scripts/genchk.cmake.in b/scripts/genchk.cmake.in
new file mode 100644
index 0000000..ab3b9d7
--- /dev/null
+++ b/scripts/genchk.cmake.in
@@ -0,0 +1,37 @@
+# genchk.cmake.in
+# Generate .chk from .out with awk (generic), based upon the automake logic.
+
+# Copyright (C) 2016 Glenn Randers-Pehrson
+# Written by Roger Leigh, 2016
+
+# This code is released under the libpng license.
+# For conditions of distribution and use, see the disclaimer
+# and license in png.h
+
+# Variables substituted from CMakeLists.txt
+set(SRCDIR "@CMAKE_CURRENT_SOURCE_DIR@")
+
+set(AWK "@AWK@")
+
+get_filename_component(INPUTEXT "${INPUT}" EXT)
+get_filename_component(OUTPUTEXT "${OUTPUT}" EXT)
+get_filename_component(INPUTBASE "${INPUT}" NAME_WE)
+get_filename_component(OUTPUTBASE "${OUTPUT}" NAME_WE)
+get_filename_component(INPUTDIR "${INPUT}" PATH)
+get_filename_component(OUTPUTDIR "${OUTPUT}" PATH)
+
+if("${INPUTEXT}" STREQUAL ".out" AND "${OUTPUTEXT}" STREQUAL ".chk")
+  # Generate .chk from .out with awk (generic)
+  file(REMOVE "${OUTPUT}" "${OUTPUTDIR}/${OUTPUTBASE}.new")
+  execute_process(COMMAND "${AWK}" -f "${SRCDIR}/scripts/checksym.awk"
+                          "${SRCDIR}/scripts/${INPUTBASE}.def"
+                          "of=${OUTPUTDIR}/${OUTPUTBASE}.new"
+                          "${INPUT}"
+                  RESULT_VARIABLE AWK_FAIL)
+  if(AWK_FAIL)
+    message(FATAL_ERROR "Failed to generate ${OUTPUTDIR}/${OUTPUTBASE}.new")
+  endif()
+  file(RENAME "${OUTPUTDIR}/${OUTPUTBASE}.new" "${OUTPUT}")
+else()
+  message(FATAL_ERROR "Unsupported conversion: ${INPUTEXT} to ${OUTPUTEXT}")
+endif()
diff --git a/scripts/genout.cmake.in b/scripts/genout.cmake.in
new file mode 100644
index 0000000..d57810b
--- /dev/null
+++ b/scripts/genout.cmake.in
@@ -0,0 +1,78 @@
+# genout.cmake.in
+# Generate .out from .c with awk (generic), based upon the automake logic.
+
+# Copyright (C) 2016 Glenn Randers-Pehrson
+# Written by Roger Leigh, 2016
+
+# This code is released under the libpng license.
+# For conditions of distribution and use, see the disclaimer
+# and license in png.h
+
+# Variables substituted from CMakeLists.txt
+set(SRCDIR "@CMAKE_CURRENT_SOURCE_DIR@")
+set(BINDIR "@CMAKE_CURRENT_BINARY_DIR@")
+
+set(AWK "@AWK@")
+set(CMAKE_C_COMPILER "@CMAKE_C_COMPILER@")
+set(CMAKE_C_FLAGS "@CMAKE_C_FLAGS@")
+set(INCDIR "@CMAKE_CURRENT_BINARY_DIR@")
+set(PNG_PREFIX "@PNG_PREFIX@")
+set(PNGLIB_MAJOR "@PNGLIB_MAJOR@")
+set(PNGLIB_MINOR "@PNGLIB_MINOR@")
+set(PNGLIB_VERSION "@PNGLIB_VERSION@")
+set(ZLIBINCDIR "@ZLIB_INCLUDE_DIR@")
+
+get_filename_component(INPUTEXT "${INPUT}" EXT)
+get_filename_component(OUTPUTEXT "${OUTPUT}" EXT)
+get_filename_component(INPUTBASE "${INPUT}" NAME_WE)
+get_filename_component(OUTPUTBASE "${OUTPUT}" NAME_WE)
+get_filename_component(INPUTDIR "${INPUT}" PATH)
+get_filename_component(OUTPUTDIR "${OUTPUT}" PATH)
+
+if ("${INPUTEXT}" STREQUAL ".c" AND "${OUTPUTEXT}" STREQUAL ".out")
+  get_filename_component(GENDIR "${OUTPUT}" PATH)
+  file(MAKE_DIRECTORY "${GENDIR}")
+
+  file(REMOVE "${OUTPUT}.tf1" "${OUTPUT}.tf2")
+
+  set(INCLUDES "-I${INCDIR}")
+  if(ZLIBINCDIR)
+    list(APPEND INCLUDES "-I${ZLIBINCDIR}")
+  endif()
+
+  if(PNG_PREFIX)
+    set(PNG_PREFIX_DEF "-DPNG_PREFIX=${PNG_PREFIX}")
+  endif()
+
+  execute_process(COMMAND "${CMAKE_C_COMPILER}" "-E"
+                          ${CMAKE_C_FLAGS}
+                          "-I${SRCDIR}"
+                          "-I${BINDIR}"
+                          ${INCLUDES}
+                          "-DPNGLIB_LIBNAME=PNG${PNGLIB_MAJOR}${PNGLIB_MINOR}_0"
+                          "-DPNGLIB_VERSION=${PNGLIB_VERSION}"
+                          "-DSYMBOL_PREFIX=${SYMBOL_PREFIX}"
+                          "-DPNG_NO_USE_READ_MACROS"
+                          "-DPNG_BUILDING_SYMBOL_TABLE"
+                          ${PNG_PREFIX_DEF}
+                          "${INPUT}"
+                  OUTPUT_FILE "${OUTPUT}.tf1"
+                  WORKING_DIRECTORY "${BINDIR}"
+                  RESULT_VARIABLE CPP_FAIL)
+  if(CPP_FAIL)
+    message(FATAL_ERROR "Failed to generate ${OUTPUT}.tf1")
+  endif()
+
+  execute_process(COMMAND "${AWK}" -f "${SRCDIR}/scripts/dfn.awk"
+                          "out=${OUTPUT}.tf2" "${OUTPUT}.tf1"
+                  WORKING_DIRECTORY "${BINDIR}"
+                  RESULT_VARIABLE AWK_FAIL)
+  if(AWK_FAIL)
+    message(FATAL_ERROR "Failed to generate ${OUTPUT}.tf2")
+  endif()
+
+  file(REMOVE "${OUTPUT}.tf1")
+  file(RENAME "${OUTPUT}.tf2" "${OUTPUT}")
+else()
+  message(FATAL_ERROR "Unsupported conversion: ${INPUTEXT} to ${OUTPUTEXT}")
+endif()
diff --git a/scripts/gensrc.cmake.in b/scripts/gensrc.cmake.in
new file mode 100644
index 0000000..f28a622
--- /dev/null
+++ b/scripts/gensrc.cmake.in
@@ -0,0 +1,138 @@
+# gensrc.cmake.in
+# Generate source files with awk, based upon the automake logic.
+
+# Copyright (C) 2016 Glenn Randers-Pehrson
+# Written by Roger Leigh, 2016
+
+# This code is released under the libpng license.
+# For conditions of distribution and use, see the disclaimer
+# and license in png.h
+
+# Variables substituted from CMakeLists.txt
+set(SRCDIR "@CMAKE_CURRENT_SOURCE_DIR@")
+set(BINDIR "@CMAKE_CURRENT_BINARY_DIR@")
+
+set(AWK "@AWK@")
+set(DFA_XTRA "@DFA_XTRA@")
+set(PNG_PREFIX "@PNG_PREFIX@")
+set(PNGLIB_VERSION "@PNGLIB_VERSION@")
+
+if("${OUTPUT}" STREQUAL "scripts/pnglibconf.c")
+  # Generate scripts/pnglibconf.c
+
+  file(REMOVE "${BINDIR}/pnglibconf.tf6" "${BINDIR}/pnglibconf.tf7")
+
+  execute_process(COMMAND "${CMAKE_COMMAND}" -E echo "com ${PNGLIB_VERSION} STANDARD API DEFINITION"
+                  COMMAND "${AWK}" -f "${SRCDIR}/scripts/options.awk"
+                          "out=pnglibconf.tf6" "logunsupported=1" "version=search"
+                          "${SRCDIR}/pngconf.h" "-"
+                          "${SRCDIR}/scripts/pnglibconf.dfa"
+                  WORKING_DIRECTORY "${BINDIR}"
+                  RESULT_VARIABLE AWK_FAIL)
+  if(AWK_FAIL)
+    message(FATAL_ERROR "Failed to generate pnglibconf.tf6")
+  endif()
+
+  execute_process(COMMAND "${AWK}" -f "${SRCDIR}/scripts/options.awk"
+                  "out=pnglibconf.tf7" "pnglibconf.tf6"
+                  WORKING_DIRECTORY "${BINDIR}"
+                  RESULT_VARIABLE AWK_FAIL)
+  if(AWK_FAIL)
+    message(FATAL_ERROR "Failed to generate pnglibconf.tf7")
+  endif()
+
+  file(REMOVE "pnglibconf.tf6")
+  file(MAKE_DIRECTORY "${BINDIR}/scripts")
+  file(RENAME "pnglibconf.tf7" "${BINDIR}/scripts/pnglibconf.c")
+
+elseif ("${OUTPUT}" STREQUAL "pnglibconf.c")
+  # Generate pnglibconf.c
+
+  file(REMOVE "${BINDIR}/pnglibconf.tf4" "${BINDIR}/pnglibconf.tf5")
+
+  execute_process(COMMAND "${AWK}" -f "${SRCDIR}/scripts/options.awk"
+                  out=pnglibconf.tf4 version=search
+                  ${SRCDIR}/pngconf.h ${SRCDIR}/scripts/pnglibconf.dfa
+                  ${SRCDIR}/pngusr.dfa ${DFA_XTRA}
+                  WORKING_DIRECTORY "${BINDIR}"
+                  RESULT_VARIABLE AWK_FAIL)
+  if(AWK_FAIL)
+    message(FATAL_ERROR "Failed to generate pnglibconf.tf4")
+  endif()
+
+  execute_process(COMMAND "${AWK}" -f "${SRCDIR}/scripts/options.awk"
+                  out=pnglibconf.tf5 pnglibconf.tf4
+                  WORKING_DIRECTORY "${BINDIR}"
+                  RESULT_VARIABLE AWK_FAIL)
+  if(AWK_FAIL)
+    message(FATAL_ERROR "Failed to generate pnglibconf.tf5")
+  endif()
+
+  file(REMOVE "pnglibconf.tf4")
+  file(MAKE_DIRECTORY "${BINDIR}/scripts")
+  file(RENAME "pnglibconf.tf5" "${BINDIR}/pnglibconf.c")
+
+elseif ("${OUTPUT}" STREQUAL "pnglibconf.h")
+  # Generate pnglibconf.h
+
+  file(REMOVE "${BINDIR}/${OUTPUT}")
+  if(PNG_PREFIX)
+    file(REMOVE "pnglibconf.tf8")
+
+    execute_process(COMMAND "${AWK}" "s==0 && NR>1{print prev}
+                             s==0{prev=\$0}
+                             s==1{print \"#define\", \$1, \"${PNG_PREFIX}\" \$1}
+                             s==2{print \"#define ${PNG_PREFIX}png_\" \$1, \"PNG_\" \$1}
+                             END{print prev}" s=0 pnglibconf.out s=1 "${BINDIR}/scripts/prefix.out"
+                             s=2 "${SRCDIR}/scripts/macro.lst"
+                    OUTPUT_FILE pnglibconf.tf8
+                    RESULT_VARIABLE AWK_FAIL)
+    if(AWK_FAIL)
+      message(FATAL_ERROR "Failed to generate pnglibconf.tf8")
+    endif()
+
+    file(RENAME "pnglibconf.tf8" "${BINDIR}/${OUTPUT}")
+  else()
+    execute_process(COMMAND "${CMAKE_COMMAND}" -E copy "${BINDIR}/pnglibconf.out"
+                                                       "${BINDIR}/${OUTPUT}"
+                    RESULT_VARIABLE COPY_FAIL)
+    if(COPY_FAIL)
+      message(FATAL_ERROR "Failed to create pnglibconf.h")
+    endif()
+  endif()
+
+elseif ("${OUTPUT}" STREQUAL "pngprefix.h")
+  # Generate pngprefix.h
+
+  file(REMOVE "${BINDIR}/${OUTPUT}")
+
+  if(PNG_PREFIX)
+    file(REMOVE "pngprefix.tf1")
+
+    execute_process(COMMAND "${AWK}"
+                            "{print \"#define\", \$1, \"${PNG_PREFIX}\" \$1}"
+                            "${BINDIR}/scripts/intprefix.out"
+                    OUTPUT_FILE "pngprefix.tf1"
+                    RESULT_VARIABLE AWK_FAIL)
+    if(AWK_FAIL)
+      message(FATAL_ERROR "Failed to generate pngprefix.tf1")
+    endif()
+
+    file(RENAME "pngprefix.tf1" "${BINDIR}/${OUTPUT}")
+  else()
+    file(WRITE "${BINDIR}/${OUTPUT}" "/* No libpng symbol prefix configured. */")
+  endif()
+
+elseif("${OUTPUT}" STREQUAL "scripts/pnglibconf.h.prebuilt")
+  # Generate scripts/pnglibconf.h.prebuilt (fails build)
+
+  message(STATUS "Attempting to build scripts/pnglibconf.h.prebuilt")
+  message(STATUS "This is a machine generated file, but if you want to make")
+  message(STATUS "a new one simply build the 'genfiles' target, and copy")
+  message(STATUS "scripts/pnglibconf.out to scripts/pnglibconf.h.prebuilt")
+  message(STATUS "AND set PNG_ZLIB_VERNUM to 0 (you MUST do this)")
+  message(FATAL_ERROR "Stopping build")
+
+else()
+  message(FATAL_ERROR "Unsupported output: ${OUTPUT}")
+endif()
diff --git a/scripts/libpng-config-head.in b/scripts/libpng-config-head.in
index 8e25732..e558caf 100644
--- a/scripts/libpng-config-head.in
+++ b/scripts/libpng-config-head.in
@@ -11,7 +11,7 @@
 
 # Modeled after libxml-config.
 
-version=1.6.20
+version=1.6.22beta03
 prefix=""
 libdir=""
 libs=""
diff --git a/scripts/libpng.pc.in b/scripts/libpng.pc.in
index 83f7acc..ce3530f 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.20
+Version: 1.6.22beta03
 Libs: -L${libdir} -lpng16
 Cflags: -I${includedir}
diff --git a/scripts/makefile.cegcc b/scripts/makefile.cegcc
index 45eea77..ea4f0ad 100644
--- a/scripts/makefile.cegcc
+++ b/scripts/makefile.cegcc
@@ -23,7 +23,7 @@
 
 VERMAJ = 1
 VERMIN = 6
-VERMIC = 20
+VERMIC = 22
 VER = $(VERMAJ).$(VERMIN).$(VERMIC)
 NAME = libpng
 PACKAGE = $(NAME)-$(VER)
diff --git a/scripts/makefile.linux b/scripts/makefile.linux
index 27dda85..782a255 100644
--- a/scripts/makefile.linux
+++ b/scripts/makefile.linux
@@ -10,7 +10,7 @@
 # Library name:
 LIBNAME = libpng16
 PNGMAJ = 16
-RELEASE = 20
+RELEASE = 22
 
 # Shared library names:
 LIBSO=$(LIBNAME).so
diff --git a/scripts/makefile.msys b/scripts/makefile.msys
index fea7427..5a1a988 100644
--- a/scripts/makefile.msys
+++ b/scripts/makefile.msys
@@ -18,7 +18,7 @@
 # Library name:
 LIBNAME = libpng16
 PNGMAJ = 16
-RELEASE = 20
+RELEASE = 22
 
 # Shared library names:
 LIBSO=$(LIBNAME).dll
diff --git a/scripts/makefile.ne12bsd b/scripts/makefile.ne12bsd
index 58f4bda..a4da989 100644
--- a/scripts/makefile.ne12bsd
+++ b/scripts/makefile.ne12bsd
@@ -17,7 +17,7 @@
 
 LIB=	png16
 SHLIB_MAJOR=	0
-SHLIB_MINOR=	1.6.20
+SHLIB_MINOR=	1.6.22beta03
 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 407290e..0e4d8f2 100644
--- a/scripts/makefile.netbsd
+++ b/scripts/makefile.netbsd
@@ -17,7 +17,7 @@
 
 LIB=	png
 SHLIB_MAJOR=	16
-SHLIB_MINOR=	1.6.20
+SHLIB_MINOR=	1.6.22beta03
 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 ef5be81..fea4a7a 100644
--- a/scripts/makefile.openbsd
+++ b/scripts/makefile.openbsd
@@ -11,7 +11,7 @@
 MANDIR= ${PREFIX}/man/cat
 
 SHLIB_MAJOR=	16
-SHLIB_MINOR=	1.6.20
+SHLIB_MINOR=	1.6.22beta03
 
 LIB=	png
 SRCS=	png.c pngerror.c pngget.c pngmem.c pngpread.c \
diff --git a/scripts/pnglibconf.dfa b/scripts/pnglibconf.dfa
index b2b7b43..2c936c2 100644
--- a/scripts/pnglibconf.dfa
+++ b/scripts/pnglibconf.dfa
@@ -8,7 +8,7 @@
 com
 version
 com
-com Copyright (c) 1998-2014 Glenn Randers-Pehrson
+com Copyright (c) 1998-2016 Glenn Randers-Pehrson
 com
 com This code is released under the libpng license.
 com For conditions of distribution and use, see the disclaimer
@@ -274,12 +274,12 @@
 
 option READ_INT_FUNCTIONS requires READ
 
-# The same for write, but these can only be switched off if
-# no writing is required at all - hence the use of an 'enables'
-# not a 'requires' below:
+# The same for write  but these can only be switched off if no writing
+# is required at all - hence the use of a 'disabled', not a 'requires'.
+# If these are needed, they are enabled in the 'WRITE options' section
+# below.
 
 option WRITE_INT_FUNCTIONS disabled
-option WRITE enables WRITE_INT_FUNCTIONS
 
 # Error controls
 #
@@ -490,7 +490,7 @@
 
 # WRITE options
 
-option WRITE
+option WRITE enables WRITE_INT_FUNCTIONS
 
 # Disabling WRITE_16BIT prevents 16-bit PNG files from being
 # generated.
@@ -873,9 +873,12 @@
 
 # Write:
 option SIMPLIFIED_WRITE,
-   requires WRITE STDIO, SETJMP, WRITE_SWAP, WRITE_PACK,
+   requires WRITE, SETJMP, WRITE_SWAP, WRITE_PACK,
       WRITE_tRNS, WRITE_gAMA, WRITE_sRGB, WRITE_cHRM
 
+# 1.6.22: allow simplified write without stdio support:
+option SIMPLIFIED_WRITE_STDIO requires SIMPLIFIED_WRITE STDIO
+
 option SIMPLIFIED_WRITE_AFIRST enables FORMAT_AFIRST,
    requires SIMPLIFIED_WRITE WRITE_SWAP_ALPHA
 
diff --git a/scripts/pnglibconf.h.prebuilt b/scripts/pnglibconf.h.prebuilt
index adf4238..7204c6d 100644
--- a/scripts/pnglibconf.h.prebuilt
+++ b/scripts/pnglibconf.h.prebuilt
@@ -1,8 +1,8 @@
-/* libpng 1.6.20 STANDARD API DEFINITION */
+/* libpng 1.6.22beta03 STANDARD API DEFINITION */
 
 /* pnglibconf.h - library build configuration */
 
-/* Libpng version 1.6.20 - December 3, 2015 */
+/* Libpng version 1.6.22beta03 - February 8, 2016 */
 
 /* Copyright (c) 1998-2015 Glenn Randers-Pehrson */
 
@@ -109,6 +109,7 @@
 #define PNG_SIMPLIFIED_READ_SUPPORTED
 #define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
 #define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
+#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
 #define PNG_SIMPLIFIED_WRITE_SUPPORTED
 #define PNG_STDIO_SUPPORTED
 #define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
diff --git a/scripts/symbols.def b/scripts/symbols.def
index a4b806b..3d79d0c 100644
--- a/scripts/symbols.def
+++ b/scripts/symbols.def
@@ -1,4 +1,4 @@
-;Version 1.6.20
+;Version 1.6.22beta03
 ;--------------------------------------------------------------
 ; LIBPNG symbol list as a Win32 DEF file
 ; Contains all the symbols that can be exported from libpng
@@ -249,3 +249,4 @@
  png_set_check_for_invalid_index @242
  png_get_palette_max @243
  png_set_option @244
+ png_image_write_to_memory @245
diff --git a/scripts/test.cmake.in b/scripts/test.cmake.in
new file mode 100644
index 0000000..fa6a889
--- /dev/null
+++ b/scripts/test.cmake.in
@@ -0,0 +1,31 @@
+# test.cmake.in
+
+# Copyright (C) 2016 Glenn Randers-Pehrson
+# Written by Roger Leigh, 2016
+
+# This code is released under the libpng license.
+# For conditions of distribution and use, see the disclaimer
+# and license in png.h
+
+set(TEST_OPTIONS "@TEST_OPTIONS@")
+set(TEST_FILES "@TEST_FILES@")
+
+foreach(file ${TEST_FILES})
+  file(TO_NATIVE_PATH "${file}" native_file)
+  list(APPEND NATIVE_TEST_FILES "${native_file}")
+endforeach()
+
+# Add the directory containing libpng to the PATH (Windows only)
+if(WIN32)
+  get_filename_component(LIBPNG_DIR "${LIBPNG}" PATH)
+  file(TO_NATIVE_PATH "${LIBPNG_DIR}" LIBPNG_DIR)
+  set(ENV{PATH} "${LIBPNG_DIR};$ENV{PATH}")
+endif()
+
+execute_process(COMMAND "${CMAKE_COMMAND}" -E echo "Running ${TEST_COMMAND}" ${TEST_OPTIONS} ${NATIVE_TEST_FILES})
+
+execute_process(COMMAND "${TEST_COMMAND}" ${TEST_OPTIONS} ${NATIVE_TEST_FILES}
+                RESULT_VARIABLE TEST_STATUS)
+if(TEST_STATUS)
+  message(FATAL_ERROR "Returned failed status ${TEST_STATUS}!")
+endif()
diff --git a/tests/pngstest b/tests/pngstest
index 255ed09..9d1b776 100755
--- a/tests/pngstest
+++ b/tests/pngstest
@@ -17,36 +17,38 @@
 shift
 alpha="$1"
 shift
-exec ./pngstest --tmpfile "${gamma}-${alpha}-" --log ${1+"$@"} $(
-   for f in "${srcdir}/contrib/testpngs/"*.png
-   do
-      g=
-      case "$f" in
-         *-linear[.-]*)
-            test "$gamma" = "linear" && g="$f";;
+args=
+LC_ALL="C" # fix glob sort order to ASCII:
+for f in "${srcdir}/contrib/testpngs/"*.png
+do
+   g=
+   case "$f" in
+      *-linear[.-]*)
+         test "$gamma" = "linear" && g="$f";;
 
-         *-sRGB[.-]*)
-            test "$gamma" = "sRGB" && g="$f";;
+      *-sRGB[.-]*)
+         test "$gamma" = "sRGB" && g="$f";;
 
-         *-1.8[.-]*)
-            test "$gamma" = "1.8" && g="$f";;
+      *-1.8[.-]*)
+         test "$gamma" = "1.8" && g="$f";;
 
-         *)
-            test "$gamma" = "none" && g="$f";;
-      esac
+      *)
+         test "$gamma" = "none" && g="$f";;
+   esac
 
-      case "$g" in
-         "")
-            :;;
+   case "$g" in
+      "")
+         :;;
 
-         *-alpha[-.]*)
-            test "$alpha" = "alpha" && echo "$g";;
+      *-alpha[-.]*)
+         test "$alpha" = "alpha" && args="$args $g";;
 
-         *-tRNS[-.]*)
-            test "$alpha" = "tRNS" -o "$alpha" = "none" && echo "$g";;
+      *-tRNS[-.]*)
+         test "$alpha" = "tRNS" -o "$alpha" = "none" && args="$args $g";;
 
-         *)
-            test "$alpha" = "opaque" -o "$alpha" = "none" && echo "$g";;
-      esac
-   done
-)
+      *)
+         test "$alpha" = "opaque" -o "$alpha" = "none" && args="$args $g";;
+   esac
+done
+# This only works if the arguments don't contain spaces; they don't.
+exec ./pngstest --tmpfile "${gamma}-${alpha}-" --log ${1+"$@"} $args