[master] Imported from libpng-1.6.29.tar
diff --git a/ANNOUNCE b/ANNOUNCE
index 70a71e3..d3ae02c 100644
--- a/ANNOUNCE
+++ b/ANNOUNCE
@@ -1,4 +1,4 @@
-Libpng 1.6.28 - January 5, 2017
+Libpng 1.6.29 - March 16, 2017
 
 This is a public release of libpng, intended for use in production codes.
 
@@ -7,28 +7,37 @@
 Source files with LF line endings (for Unix/Linux) and with a
 "configure" script
 
-   libpng-1.6.28.tar.xz (LZMA-compressed, recommended)
-   libpng-1.6.28.tar.gz
+   libpng-1.6.29.tar.xz (LZMA-compressed, recommended)
+   libpng-1.6.29.tar.gz
 
 Source files with CRLF line endings (for Windows), without the
 "configure" script
 
-   lpng1628.7z  (LZMA-compressed, recommended)
-   lpng1628.zip
+   lpng1629.7z  (LZMA-compressed, recommended)
+   lpng1629.zip
 
 Other information:
 
-   libpng-1.6.28-README.txt
-   libpng-1.6.28-LICENSE.txt
-   libpng-1.6.28-*.asc (armored detached GPG signatures)
+   libpng-1.6.29-README.txt
+   libpng-1.6.29-LICENSE.txt
+   libpng-1.6.29-*.asc (armored detached GPG signatures)
 
-Changes since the last public release (1.6.27):
-  Fixed arm/aarch64 detection in CMakeLists.txt (Gianfranco Costamagna).
-  Added option to Cmake build allowing a custom location of zlib to be
-    specified in a scenario where libpng is being built as a subproject
-    alongside zlib by another project (Sam Serrels).
-  Changed png_ptr->options from a png_byte to png_uint_32, to accomodate
-    up to 16 options.
+Changes since the last public release (1.6.28):
+
+  Readded "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna).
+  Moved SSE2 optimization code into the main libpng source directory.
+    Configure libpng with "configure --enable-intel-sse" or compile
+    libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it.
+  Simplified conditional compilation in pngvalid.c, for AIX (Michael Felt).
+  Avoid conditional directives that break statements in pngrutil.c (Romero
+    Malaquias)
+  The contrib/examples/pngtopng.c recovery code was in the wrong "if"
+    branches; the comments were correct.
+  Added code for PowerPC VSX optimisation (Vadim Barkov).
+  Avoid potential overflow of shift operations in png_do_expand() (Aaron Boxer).
+  Change test ZLIB_VERNUM >= 0x1281 to ZLIB_VERNUM >= 0x1290 in pngrutil.c
+    because Solaris 11 distributes zlib-1.2.8.f that is older than 1.2.8.1.
+  Suppress clang warnings about implicit sign changes in png.c
 
 Send comments/corrections/commendations to png-mng-implement at lists.sf.net
 (subscription required; visit
diff --git a/CHANGES b/CHANGES
index 0b5e944..5f5147d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -5794,6 +5794,29 @@
 Version 1.6.28 [January 5, 2017]
   No changes.
 
+Version 1.6.29beta01 [January 12, 2017]
+  Readded "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna).
+  Moved SSE2 optimization code into the main libpng source directory.
+    Configure libpng with "configure --enable-intel-sse" or compile
+    libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it.
+  Simplified conditional compilation in pngvalid.c, for AIX (Michael Felt).
+
+Version 1.6.29beta02 [February 22, 2017]
+  Avoid conditional directives that break statements in pngrutil.c (Romero
+    Malaquias)
+  The contrib/examples/pngtopng.c recovery code was in the wrong "if"
+    branches; the comments were correct.
+  Added code for PowerPC VSX optimisation (Vadim Barkov).
+
+Version 1.6.29beta03 [March 1, 2017]
+  Avoid potential overflow of shift operations in png_do_expand() (Aaron Boxer).
+  Change test ZLIB_VERNUM >= 0x1281 to ZLIB_VERNUM >= 0x1290 in pngrutil.c
+    because Solaris 11 distributes zlib-1.2.8.f that is older than 1.2.8.1.
+  Suppress clang warnings about implicit sign changes in png.c
+
+Version 1.6.29 [March 16, 2017]
+  No changes.
+
 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 e076d5e..3b6c1f3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -36,13 +36,15 @@
 
 set(PNGLIB_MAJOR 1)
 set(PNGLIB_MINOR 6)
-set(PNGLIB_RELEASE 28)
+set(PNGLIB_RELEASE 29)
 set(PNGLIB_NAME libpng${PNGLIB_MAJOR}${PNGLIB_MINOR})
 set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_RELEASE})
 
+include(GNUInstallDirs)
+
 # needed packages
 
-#Allow users to specify location of Zlib, 
+#Allow users to specify location of Zlib,
 # Useful if zlib is being built alongside this as a sub-project
 option(PNG_BUILD_ZLIB "Custom zlib Location, else find_package is used" OFF)
 
@@ -96,7 +98,7 @@
       arm/arm_init.c
       arm/filter_neon.S
       arm/filter_neon_intrinsics.c)
-      
+
     if(${PNG_ARM_NEON} STREQUAL "on")
       add_definitions(-DPNG_ARM_NEON_OPT=2)
     elseif(${PNG_ARM_NEON} STREQUAL "check")
@@ -107,6 +109,38 @@
   endif()
 endif()
 
+# set definitions and sources for powerpc
+if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^powerpc*" OR
+	${CMAKE_SYSTEM_PROCESSOR} MATCHES "^ppc64*" )
+  set(PNG_POWERPC_VSX_POSSIBLE_VALUES check on off)
+  set(PNG_POWERPC_VSX "check" CACHE STRING "Enable POWERPC VSX optimizations:
+     check: (default) use internal checking code;
+     off: disable the optimizations;
+     on: turn on unconditionally.")
+  set_property(CACHE PNG_POWERPC_VSX PROPERTY STRINGS
+     ${PNG_POWERPC_VSX_POSSIBLE_VALUES})
+  list(FIND PNG_POWERPC_VSX_POSSIBLE_VALUES ${PNG_POWERPC_VSX} index)
+  if(index EQUAL -1)
+    message(FATAL_ERROR
+      " PNG_POWERPC_VSX must be one of [${PNG_POWERPC_VSX_POSSIBLE_VALUES}]")
+  elseif(NOT ${PNG_POWERPC_VSX} STREQUAL "no")
+    set(libpng_powerpc_sources
+      powerpc/powerpc_init.c
+      powerpc/filter_vsx_intrinsics.c)
+
+    if(${PNG_POWERPC_VSX} STREQUAL "on")
+      add_definitions(-DPNG_POWERPC_VSX_OPT=2)
+    elseif(${PNG_POWERPC_VSX} STREQUAL "check")
+      add_definitions(-DPNG_POWERPC_VSX_CHECK_SUPPORTED)
+      message(WARNING
+      "[PNG_POWERPC_VSX==check] Please check contrib/powerpc/README file for the list of supported OSes.")
+    endif()
+  else()
+    add_definitions(-DPNG_POWERPC_VSX_OPT=0)
+  endif()
+endif()
+
+
 # SET LIBNAME
 set(PNG_LIB_NAME png${PNGLIB_MAJOR}${PNGLIB_MINOR})
 
@@ -398,6 +432,7 @@
   pngwtran.c
   pngwutil.c
   ${libpng_arm_sources}
+  ${libpng_powerpc_sources}
 )
 set(pngtest_sources
   pngtest.c
@@ -735,7 +770,7 @@
 # SET UP LINKS
 if(PNG_SHARED)
   set_target_properties(png PROPERTIES
-#   VERSION 16.${PNGLIB_RELEASE}.1.6.28
+#   VERSION 16.${PNGLIB_RELEASE}.1.6.29
     VERSION 16.${PNGLIB_RELEASE}.0
     SOVERSION 16
     CLEAN_DIRECT_OUTPUT 1)
@@ -840,4 +875,3 @@
 # to create msvc import lib for mingw compiled shared lib
 # pexports libpng.dll > libpng.def
 # lib /def:libpng.def /machine:x86
-
diff --git a/LICENSE b/LICENSE
index 912552e..aac9f74 100644
--- a/LICENSE
+++ b/LICENSE
@@ -10,7 +10,7 @@
 
 This code is released under the libpng license.
 
-libpng versions 1.0.7, July 1, 2000 through 1.6.28, January 5, 2017 are
+libpng versions 1.0.7, July 1, 2000 through 1.6.29, March 16, 2017 are
 Copyright (c) 2000-2002, 2004, 2006-2017 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
@@ -23,6 +23,8 @@
    Gilles Vollant
    James Yu
    Mandar Sahastrabuddhe
+   Google Inc.
+   Vadim Barkov
 
 and with the following additions to the disclaimer:
 
@@ -128,4 +130,4 @@
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-January 5, 2017
+March 16, 2017
diff --git a/Makefile.am b/Makefile.am
index fb209ed..18ac748 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -102,6 +102,16 @@
 	mips/filter_msa_intrinsics.c
 endif
 
+if PNG_INTEL_SSE
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += intel/intel_init.c\
+	intel/filter_sse2_intrinsics.c
+endif
+
+if PNG_POWERPC_VSX
+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += powerpc/powerpc_init.c\
+        powerpc/filter_vsx_intrinsics.c
+endif
+
 nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h
 
 libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \
diff --git a/README b/README
index 67b579d..07562fc 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
-README for libpng version 1.6.28 - January 5, 2017 (shared library 16.0)
+README for libpng version 1.6.29 - March 16, 2017 (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.
@@ -179,14 +179,16 @@
       pngwtran.c    =>  Write data transformations
       pngwutil.c    =>  Write utility functions
       arm           =>  Contains optimized code for the ARM platform
+      powerpc       =>  Contains optimized code for the PowerPC platform
       contrib       =>  Contributions
        arm-neon         =>  Optimized code for ARM-NEON platform
+       powerpc-vsx      =>  Optimized code for POWERPC-VSX platform
        examples         =>  Example programs
        gregbook         =>  source code for PNG reading and writing, from
                             Greg Roelofs' "PNG: The Definitive Guide",
                             O'Reilly, 1999
-       intel            =>  Optimized code for INTEL-SSE2 platform
        libtests         =>  Test programs
+       mips-msa         =>  Optimized code for MIPS-MSA platform
        pngminim         =>  Minimal decoder, encoder, and progressive decoder
                             programs demonstrating use of pngusr.dfa
        pngminus         =>  Simple pnm2png and png2pnm programs
@@ -194,6 +196,8 @@
        testpngs
        tools            =>  Various tools
        visupng          =>  Contains a MSVC workspace for VisualPng
+      intel             =>  Optimized code for INTEL-SSE2 platform
+      mips              =>  Optimized code for MIPS platform
       projects      =>  Contains project files and workspaces for
                         building a DLL
        owatcom          =>  Contains a WATCOM project for building libpng
diff --git a/TODO b/TODO
index fe9de4b..36d6092 100644
--- a/TODO
+++ b/TODO
@@ -25,5 +25,6 @@
 Investigate pre-incremented loop counters and other loop constructions.
 Add interpolated method of handling interlacing.
 Extend pngvalid.c to validate more of the libpng transformations.
+Refactor preprocessor conditionals to compile entire statements
 
 */
diff --git a/configure.ac b/configure.ac
index 8c474a6..765a4ad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -25,7 +25,7 @@
 
 dnl Version number stuff here:
 
-AC_INIT([libpng],[1.6.28],[png-mng-implement@lists.sourceforge.net])
+AC_INIT([libpng],[1.6.29],[png-mng-implement@lists.sourceforge.net])
 AC_CONFIG_MACRO_DIR([scripts])
 
 # libpng does not follow GNU file name conventions (hence 'foreign')
@@ -46,7 +46,7 @@
 dnl AM_PREREQ([1.11.2])
 dnl stop configure from automagically running automake
 
-PNGLIB_VERSION=1.6.28
+PNGLIB_VERSION=1.6.29
 PNGLIB_MAJOR=1
 PNGLIB_MINOR=6
 PNGLIB_RELEASE=28
@@ -391,6 +391,89 @@
       mipsel*|mips64el*) :;;
     esac])
 
+# 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])
+
+# PowerPC
+# ===
+#
+# PowerPC VSX (SIMD) support.
+
+AC_ARG_ENABLE([powerpc-vsx],
+AS_HELP_STRING([[[--enable-powerpc-vsx]]],
+      [Enable POWERPC VSX optimizations: =no/off, check, api, yes/on:]
+      [no/off: disable the optimizations; check: use internal checking code]
+      [api: disable by default, enable by a call to png_set_option]
+      [yes/on: turn on unconditionally.]
+      [If not specified: determined by the compiler.]),
+   [case "$enableval" in
+      no|off)
+         # disable the default enabling on __ppc64__ systems:
+         AC_DEFINE([PNG_POWERPC_VSX_OPT], [0],
+                   [Disable POWERPC VSX optimizations])
+         # Prevent inclusion of the platform specific files below:
+         enable_powerpc_vsx=no;;
+      check)
+         AC_DEFINE([PNG_POWERPC_VSX_CHECK_SUPPORTED], [],
+                   [Check for POWERPC VSX support at run-time])
+         AC_MSG_WARN([--enable-powerpc-vsx Please check contrib/powerpc/README file]
+            [for the list of supported OSes.]);;
+      api)
+         AC_DEFINE([PNG_POWERPC_VSX_API_SUPPORTED], [],
+                   [Turn on POWERPC VSX optimizations at run-time]);;
+      yes|on)
+         AC_DEFINE([PNG_POWERPC_VSX_OPT], [2],
+                   [Enable POWERPC VSX optimizations])
+         AC_MSG_WARN([--enable-powerpc-vsx: please specify 'check' or 'api', if]
+            [you want the optimizations unconditionally pass '-maltivec -mvsx']
+            [or '-mcpu=power8'to the compiler.]);;
+      *)
+         AC_MSG_ERROR([--enable-powerpc-vsx=${enable_powerpc_vsx}: invalid value])
+   esac])
+
+# Add PowerPC specific files to all builds where the host_cpu is powerpc('powerpc*') or
+# where POWERPC optimizations were explicitly requested (this allows a fallback if a
+# future host CPU does not match 'powerpc*')
+
+AM_CONDITIONAL([PNG_POWERPC_VSX],
+   [test "$enable_powerpc_vsx" != 'no' &&
+    case "$host_cpu" in
+      powerpc*|ppc64*) :;;
+    esac])
+
+
 AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]])
 
 # Config files, substituting as above
diff --git a/contrib/examples/pngtopng.c b/contrib/examples/pngtopng.c
index 4acf6b3..d4a51a8 100644
--- a/contrib/examples/pngtopng.c
+++ b/contrib/examples/pngtopng.c
@@ -1,10 +1,12 @@
 /*- pngtopng
  *
- * COPYRIGHT: Written by John Cunningham Bowler, 2011.
+ * COPYRIGHT: Written by John Cunningham Bowler, 2011, 2017.
  * To the extent possible under law, the author has waived all copyright and
  * related or neighboring rights to this work.  This work is published from:
  * United States.
  *
+ * Last changed in libpng 1.6.29 [%RDATE%]
+ *
  * Read a PNG and write it out in a fixed format, using the 'simplified API'
  * that was introduced in libpng-1.6.0.
  *
@@ -59,26 +61,27 @@
                else
                   fprintf(stderr, "pngtopng: write %s: %s\n", argv[2],
                       image.message);
-
-               free(buffer);
             }
 
             else
-            {
                fprintf(stderr, "pngtopng: read %s: %s\n", argv[1],
                    image.message);
 
-               /* This is the only place where a 'free' is required; libpng does
-                * the cleanup on error and success, but in this case we couldn't
-                * complete the read because of running out of memory.
-                */
-               png_image_free(&image);
-            }
+            free(buffer);
          }
 
          else
+         {
             fprintf(stderr, "pngtopng: out of memory: %lu bytes\n",
                (unsigned long)PNG_IMAGE_SIZE(image));
+
+            /* This is the only place where a 'free' is required; libpng does
+             * the cleanup on error and success, but in this case we couldn't
+             * complete the read because of running out of memory and so libpng
+             * has not got to the point where it can do cleanup.
+             */
+            png_image_free(&image);
+         }
       }
 
       else
diff --git a/contrib/intel/INSTALL b/contrib/intel/INSTALL
deleted file mode 100644
index cd5cdd9..0000000
--- a/contrib/intel/INSTALL
+++ /dev/null
@@ -1,158 +0,0 @@
-Enabling SSE support
-
-Copyright (c) 2016 Google, Inc.
-Written by Mike Klein, Matt Sarett
-
-This INSTALL file written by Glenn Randers-Pehrson, 2016.
-
-If you have moved intel_init.c and filter_sse2_intrinsics.c to a different
-directory, be sure to update the '#include "../../pngpriv.h"' line in both
-files if necessary to point to the correct relative location of pngpriv.h
-with respect to the new location of those files.
-
-To enable SSE support in libpng, follow the instructions in I, II, or III,
-below:
-
-I. Using patched "configure" scripts:
-
-First, apply intel_sse.patch in your build directory.
-
-   patch -i contrib/intel/intel_sse.patch -p1
-
-Then, if you are not building in a new GIT clone, e.g., in a tar
-distribution, remove any existing pre-built configure scripts:
-
-   ./configure --enable-maintainer-mode
-   make maintainer-clean
-   ./autogen.sh --maintainer --clean
-
-Finally, configure libpng with -DPNG_INTEL_SSE in CPPFLAGS:
-
-   ./autogen.sh --maintainer
-   CPPFLAGS="-DPNG_INTEL_SSE" ./configure [options]
-   make CPPFLAGS="-DPNG_INTEL_SSE" [options]
-   make
-
-II. Using a custom makefile:
-
-If you are using a custom makefile makefile, you will have to update it
-manually to include contrib/intel/*.o in the dependencies, and to define
-PNG_INTEL_SSE.
-
-III. Using manually updated "configure" scripts:
-
-If you prefer, manually edit pngpriv.h, configure.ac, and Makefile.am,
-following the instructions below, then follow the instructions in
-section II of INSTALL in the main libpng directory, then configure libpng
-with -DPNG_INTEL_SSE in CPPFLAGS.
-
-1. Add the following code to configure.ac under HOST SPECIFIC OPTIONS
-directly beneath the section for ARM:
-
------------------cut----------------
-# 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])
------------------cut----------------
-
-2. Add the following code to Makefile.am under HOST SPECIFIC OPTIONS
-directly beneath the "if PNG_ARM_NEON ... endif" statement:
-
------------------cut----------------
-if PNG_INTEL_SSE
-libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += contrib/intel/intel_init.c\
-    contrib/intel/filter_sse2_intrinsics.c
-endif
------------------cut----------------
-
-3. Add the following lines to pngpriv.h, following the PNG_ARM_NEON_OPT
-code:
-
------------------cut----------------
-#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
-
------------------cut----------------
-
-4. Add the following lines to pngpriv.h, following the prototype for
-png_read_filter_row_paeth4_neon:
-
------------------cut----------------
-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);
-
------------------cut----------------
diff --git a/contrib/intel/intel_sse.patch b/contrib/intel/intel_sse.patch
deleted file mode 100644
index 24d4883..0000000
--- a/contrib/intel/intel_sse.patch
+++ /dev/null
@@ -1,190 +0,0 @@
-diff --git a/configure.ac b/configure.ac
---- a/configure.ac	2016-08-29 11:46:27.000000000 -0400
-+++ b/configure.ac	2016-08-29 16:57:03.866355018 -0400
-@@ -386,16 +386,51 @@ AC_ARG_ENABLE([mips-msa],
- # future host CPU does not match 'mips*')
- 
- AM_CONDITIONAL([PNG_MIPS_MSA],
-    [test "$enable_mips_msa" != 'no' &&
-     case "$host_cpu" in
-       mipsel*|mips64el*) :;;
-     esac])
- 
-+# 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])
-+
- AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]])
- 
- # Config files, substituting as above
- AC_CONFIG_FILES([Makefile libpng.pc:libpng.pc.in])
- AC_CONFIG_FILES([libpng-config:libpng-config.in],
-    [chmod +x libpng-config])
- 
- AC_OUTPUT
-diff --git a/Makefile.am b/Makefile.am
---- a/Makefile.am	2016-08-29 11:46:27.000000000 -0400
-+++ b/Makefile.am	2016-08-29 16:57:45.955528215 -0400
-@@ -97,16 +97,21 @@ libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SO
- 	arm/filter_neon.S arm/filter_neon_intrinsics.c
- endif
- 
- if PNG_MIPS_MSA
- libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += mips/mips_init.c\
- 	mips/filter_msa_intrinsics.c
- endif
- 
-+if PNG_INTEL_SSE
-+libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += contrib/intel/intel_init.c\
-+    contrib/intel/filter_sse2_intrinsics.c
-+endif
-+
- nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h
- 
- libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \
- 	-version-number @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0
- 
- if HAVE_LD_VERSION_SCRIPT
- #   Versioned symbols and restricted exports
- if HAVE_SOLARIS_LD
-diff --git a/pngpriv.h b/pngpriv.h
---- debug16/pngpriv.h	2016-08-30 10:46:36.000000000 -0400
-+++ libpng16/pngpriv.h	2016-08-30 11:57:25.672280202 -0400
-@@ -185,16 +185,52 @@
- #ifndef PNG_MIPS_MSA_OPT
- #  if defined(__mips_msa) && (__mips_isa_rev >= 5) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
- #     define PNG_MIPS_MSA_OPT 2
- #  else
- #     define PNG_MIPS_MSA_OPT 0
- #  endif
- #endif
- 
-+#ifndef PNG_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
-+
- #if PNG_MIPS_MSA_OPT > 0
- #  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa
- #  ifndef PNG_MIPS_MSA_IMPLEMENTATION
- #     if defined(__mips_msa)
- #        if defined(__clang__)
- #        elif defined(__GNUC__)
- #           if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
- #              define PNG_MIPS_MSA_IMPLEMENTATION 2
-@@ -1251,16 +1287,31 @@ PNG_INTERNAL_FUNCTION(void,png_read_filt
- PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_msa,(png_row_infop
-     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
- PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_msa,(png_row_infop
-     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
- PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_msa,(png_row_infop
-     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
- #endif
- 
-+#if PNG_INTEL_SSE_IMPLEMENTATION > 0
-+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop
-+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop
-+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop
-+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop
-+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop
-+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
-+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
-+#endif
-+
- /* Choose the best filter to use and filter the row data */
- PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
-     png_row_infop row_info),PNG_EMPTY);
- 
- #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
- PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr,
-    png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY);
-    /* Read 'avail_out' bytes of data from the IDAT stream.  If the output buffer
-@@ -1986,16 +2037,21 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_O
- PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
-    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
- #endif
- 
- #if PNG_MIPS_MSA_OPT > 0
- PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa,
-    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
- #endif
-+
-+#  if PNG_INTEL_SSE_IMPLEMENTATION > 0
-+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
-+   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
-+#  endif
- #endif
- 
- PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
-    png_const_charp key, png_bytep new_key), PNG_EMPTY);
- 
- /* Maintainer: Put new private prototypes here ^ */
- 
- #include "pngdebug.h"
diff --git a/contrib/libtests/pngvalid.c b/contrib/libtests/pngvalid.c
index 499801b..b0daa18 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.6.27 [December 29, 2016]
- * Copyright (c) 2014-2016 John Cunningham Bowler
+ * Last changed in libpng 1.6.29 [March 16, 2017]
+ * Copyright (c) 2014-2017 John Cunningham Bowler
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
@@ -7742,13 +7742,11 @@
           * 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
-            2.0
-#        else
-            1.0
-#        endif
-            /255, data.gamma);
+#if DIGITIZE
+          that->pm->limit += pow( 2.0/255, data.gamma);
+#else
+          that->pm->limit += pow( 1.0/255, data.gamma);
+#endif
       }
    }
 
diff --git a/contrib/powerpc-vsx/README b/contrib/powerpc-vsx/README
new file mode 100644
index 0000000..e566147
--- /dev/null
+++ b/contrib/powerpc-vsx/README
@@ -0,0 +1,81 @@
+OPERATING SYSTEM SPECIFIC POWERPC DETECTION
+--------------------------------------------
+
+Detection of the ability to execute POWERPC on processor requires
+operating system support.  (The information is not available in user mode.)
+
+Currently only this feature is supported only for linux platform.
+
+HOW TO USE THIS
+---------------
+
+This directory contains C code fragments that can be included in powerpc/powerpc_init.c
+by setting the macro PNG_POWERPC_VSX_FILE to the file name in "" or <> at build
+time.  This setting is not recorded in pnglibconf.h and can be changed simply by
+rebuilding arm/arm_init.o with the required macro definition.
+
+For any of this code to be used the POWERPC code must be enabled and run time
+checks must be supported.  I.e.:
+
+#if PNG_POWERPC_VSX_OPT > 0
+#ifdef PNG_POWERPC_VSX_CHECK_SUPPORTED
+
+This is done in a 'configure' build by passing configure the argument:
+
+   --enable-powerpc-vsx=check
+
+FILE FORMAT
+-----------
+
+Each file documents its testing status as of the last time it was tested (which
+may have been a long time ago):
+
+STATUS: one of:
+   SUPPORTED: This indicates that the file is included in the regularly
+         performed test builds and bugs are fixed when discovered.
+   COMPILED: This indicates that the code did compile at least once.  See the
+         more detailed description for the extent to which the result was
+         successful.
+   TESTED: This means the code was fully compiled into the libpng test programs
+         and these were run at least once.
+
+BUG REPORTS: an email address to which to send reports of problems
+
+The file is a fragment of C code. It should not define any 'extern' symbols;
+everything should be static.  It must define the function:
+
+static int png_have_vsx(png_structp png_ptr);
+
+That function must return 1 if ARM NEON instructions are supported, 0 if not.
+It must not execute png_error unless it detects a bug.  A png_error will prevent
+the reading of the PNG and in the future, writing too.
+
+BUG REPORTS
+-----------
+
+If you mail a bug report for any file that is not SUPPORTED there may only be
+limited response.  Consider fixing it and sending a patch to fix the problem -
+this is more likely to result in action.
+
+CONTRIBUTIONS
+-------------
+
+You may send contributions of new implementations to
+png-mng-implement@sourceforge.net.  Please write code in strict C90 C where
+possible.  Obviously OS dependencies are to be expected.  If you submit code you
+must have the authors permission and it must have a license that is acceptable
+to the current maintainer; in particular that license must permit modification
+and redistribution.
+
+Please try to make the contribution a single file and give the file a clear and
+unambiguous name that identifies the target OS.  If multiple files really are
+required put them all in a sub-directory.
+
+You must also be prepared to handle bug reports from users of the code, either
+by joining the png-mng-implement mailing list or by providing an email for the
+"BUG REPORTS" entry or both.  Please make sure that the header of the file
+contains the STATUS and BUG REPORTS fields as above.
+
+Please list the OS requirements as precisely as possible.  Ideally you should
+also list the environment in which the code has been tested and certainly list
+any environments where you suspect it might not work.
diff --git a/contrib/powerpc-vsx/linux.c b/contrib/powerpc-vsx/linux.c
new file mode 100644
index 0000000..32ed9d7
--- /dev/null
+++ b/contrib/powerpc-vsx/linux.c
@@ -0,0 +1,57 @@
+/* contrib/powerpc-vsx/linux.c
+ *
+ * Copyright (c) 2017 Glenn Randers-Pehrson
+ * Written by Vadim Barkov, 2017.
+ * Last changed in libpng 1.6.29 [March 16, 2017]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * STATUS: TESTED
+ * BUG REPORTS: png-mng-implement@sourceforge.net
+ *
+ * png_have_vsx implemented for Linux by reading the widely available
+ * pseudo-file /proc/cpuinfo. 
+ *
+ * This code is strict ANSI-C and is probably moderately portable; it does
+ * however use <stdio.h> and it assumes that /proc/cpuinfo is never localized.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include "png.h"
+
+#ifndef MAXLINE
+#  define MAXLINE 1024
+#endif
+
+static int
+png_have_vsx(png_structp png_ptr)
+{
+   FILE *f;
+
+   const char *string = "altivec supported";
+   char input[MAXLINE];
+   char *token = NULL;
+
+   PNG_UNUSED(png_ptr)
+
+   f = fopen("/proc/cpuinfo", "r");
+   if (f != NULL)
+   {
+      memset(input,0,MAXLINE);
+      while(fgets(input,MAXLINE,f) != NULL)
+      {
+         token = strstr(input,string);
+         if(token != NULL)
+            return 1;
+      }
+   }
+#ifdef PNG_WARNINGS_SUPPORTED
+   else
+      png_warning(png_ptr, "/proc/cpuinfo open failed");
+#endif
+   return 0;
+}
diff --git a/contrib/powerpc-vsx/linux_aux.c b/contrib/powerpc-vsx/linux_aux.c
new file mode 100644
index 0000000..796922d
--- /dev/null
+++ b/contrib/powerpc-vsx/linux_aux.c
@@ -0,0 +1,36 @@
+/* contrib/powerpc-vsx/linux_aux.c
+ *
+ * Copyright (c) 2017 Glenn Randers-Pehrson
+ * Written by Vadim Barkov, 2017.
+ * Last changed in libpng 1.6.29 [March 16, 2017]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ *
+ * STATUS: TESTED
+ * BUG REPORTS: png-mng-implement@sourceforge.net
+ *
+ * png_have_vsx implemented for Linux by using the auxiliary vector mechanism.
+ *
+ * This code is strict ANSI-C and is probably moderately portable; it does
+ * however use <stdio.h> and it assumes that /proc/cpuinfo is never localized.
+ */
+
+#include "sys/auxv.h"
+#include "png.h"
+
+static int
+png_have_vsx(png_structp png_ptr)
+{
+
+   const unsigned long auxv = getauxval( AT_HWCAP );
+
+   PNG_UNUSED(png_ptr)
+
+   if(auxv & (PPC_FEATURE_HAS_ALTIVEC|PPC_FEATURE_HAS_VSX ))
+      return 1;
+   else
+      return 0;
+}
+
diff --git a/contrib/intel/filter_sse2_intrinsics.c b/intel/filter_sse2_intrinsics.c
similarity index 97%
rename from contrib/intel/filter_sse2_intrinsics.c
rename to intel/filter_sse2_intrinsics.c
index b02840c..b91d8da 100644
--- a/contrib/intel/filter_sse2_intrinsics.c
+++ b/intel/filter_sse2_intrinsics.c
@@ -1,19 +1,18 @@
 
 /* filter_sse2_intrinsics.c - SSE2 optimized filter functions
  *
- * Copyright (c) 2016 Google, Inc.
+ * Copyright (c) 2016-2017 Glenn Randers-Pehrson
  * Written by Mike Klein and Matt Sarett
- * Derived from arm/filter_neon_intrinsics.c, which was
- * Copyright (c) 2014,2016 Glenn Randers-Pehrson
+ * Derived from arm/filter_neon_intrinsics.c
  *
- * Last changed in libpng 1.6.24 [August 4, 2016]
+ * Last changed in libpng 1.6.29 [March 16, 2017]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
-#include "../../pngpriv.h"
+#include "../pngpriv.h"
 
 #ifdef PNG_READ_SUPPORTED
 
diff --git a/contrib/intel/intel_init.c b/intel/intel_init.c
similarity index 86%
rename from contrib/intel/intel_init.c
rename to intel/intel_init.c
index 328e90e..8f08baf 100644
--- a/contrib/intel/intel_init.c
+++ b/intel/intel_init.c
@@ -1,19 +1,18 @@
 
 /* intel_init.c - SSE2 optimized filter functions
  *
- * Copyright (c) 2016 Google, Inc.
- * Written by Mike Klein and Matt Sarett
- * Derived from arm/arm_init.c, which was
- * Copyright (c) 2014,2016 Glenn Randers-Pehrson
+ * Copyright (c) 2016-2017 Glenn Randers-Pehrson
+ * Written by Mike Klein and Matt Sarett, Google, Inc.
+ * Derived from arm/arm_init.c
  *
- * Last changed in libpng 1.6.22 [May 26, 2016]
+ * Last changed in libpng 1.6.29 [March 16, 2017]
  *
  * This code is released under the libpng license.
  * For conditions of distribution and use, see the disclaimer
  * and license in png.h
  */
 
-#include "../../pngpriv.h"
+#include "../pngpriv.h"
 
 #ifdef PNG_READ_SUPPORTED
 #if PNG_INTEL_SSE_IMPLEMENTATION > 0
diff --git a/libpng-manual.txt b/libpng-manual.txt
index 048ba31..57ebbda 100644
--- a/libpng-manual.txt
+++ b/libpng-manual.txt
@@ -1,6 +1,6 @@
 libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.6.28 - January 5, 2017
+ libpng version 1.6.29 - March 16, 2017
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
  Copyright (c) 1998-2016 Glenn Randers-Pehrson
@@ -11,7 +11,7 @@
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.6.28 - January 5, 2017
+ libpng versions 0.97, January 1998, through 1.6.29 - March 16, 2017
  Updated and distributed by Glenn Randers-Pehrson
  Copyright (c) 1998-2016 Glenn Randers-Pehrson
 
@@ -5355,7 +5355,7 @@
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.6.28 are Y2K compliant.  It is my belief that earlier
+upward through 1.6.29 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 27b673c..080dfe5 100644
--- a/libpng.3
+++ b/libpng.3
@@ -1,6 +1,6 @@
-.TH LIBPNG 3 "January 5, 2017"
+.TH LIBPNG 3 "March 16, 2017"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.6.28
+libpng \- Portable Network Graphics (PNG) Reference Library 1.6.29
 .SH SYNOPSIS
 \fB
 #include <png.h>\fP
@@ -510,7 +510,7 @@
 .SH LIBPNG.TXT
 libpng-manual.txt - A description on how to use and modify libpng
 
- libpng version 1.6.28 - January 5, 2017
+ libpng version 1.6.29 - March 16, 2017
  Updated and distributed by Glenn Randers-Pehrson
  <glennrp at users.sourceforge.net>
  Copyright (c) 1998-2016 Glenn Randers-Pehrson
@@ -521,7 +521,7 @@
 
  Based on:
 
- libpng versions 0.97, January 1998, through 1.6.28 - January 5, 2017
+ libpng versions 0.97, January 1998, through 1.6.29 - March 16, 2017
  Updated and distributed by Glenn Randers-Pehrson
  Copyright (c) 1998-2016 Glenn Randers-Pehrson
 
@@ -5865,7 +5865,7 @@
 an official declaration.
 
 This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.6.28 are Y2K compliant.  It is my belief that earlier
+upward through 1.6.29 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
@@ -5967,7 +5967,7 @@
  ...
  1.5.28                  15    10528  15.so.15.28[.0]
  ...
- 1.6.28                  16    10628  16.so.16.28[.0]
+ 1.6.29                  16    10629  16.so.16.29[.0]
 
 Henceforth the source version will match the shared-library minor
 and patch numbers; the shared-library major version number will be
@@ -6023,7 +6023,7 @@
 
 Thanks to Frank J. T. Wojcik for helping with the documentation.
 
-Libpng version 1.6.28 - January 5, 2017:
+Libpng version 1.6.29 - March 16, 2017:
 Initially created in 1995 by Guy Eric Schalnat, then of Group 42, Inc.
 Currently maintained by Glenn Randers-Pehrson (glennrp at users.sourceforge.net).
 
@@ -6048,7 +6048,7 @@
 
 This code is released under the libpng license.
 
-libpng versions 1.0.7, July 1, 2000 through 1.6.28, January 5, 2017 are
+libpng versions 1.0.7, July 1, 2000 through 1.6.29, March 16, 2017 are
 Copyright (c) 2000-2002, 2004, 2006-2017 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
@@ -6061,6 +6061,8 @@
    Gilles Vollant
    James Yu
    Mandar Sahastrabuddhe
+   Google Inc.
+   Vadim Barkov
 
 and with the following additions to the disclaimer:
 
@@ -6174,7 +6176,7 @@
 
 Glenn Randers-Pehrson
 glennrp at users.sourceforge.net
-January 5, 2017
+March 16, 2017
 
 .\" end of man page
 
diff --git a/libpngpf.3 b/libpngpf.3
index 585fd24..04e4b3b 100644
--- a/libpngpf.3
+++ b/libpngpf.3
@@ -1,6 +1,6 @@
-.TH LIBPNGPF 3 "January 5, 2017"
+.TH LIBPNGPF 3 "March 16, 2017"
 .SH NAME
-libpng \- Portable Network Graphics (PNG) Reference Library 1.6.28
+libpng \- Portable Network Graphics (PNG) Reference Library 1.6.29
 (private functions)
 .SH SYNOPSIS
 \fB#include \fI"pngpriv.h"
diff --git a/png.5 b/png.5
index 5be0059..08da75b 100644
--- a/png.5
+++ b/png.5
@@ -1,4 +1,4 @@
-.TH PNG 5 "January 5, 2017"
+.TH PNG 5 "March 16, 2017"
 .SH NAME
 png \- Portable Network Graphics (PNG) format
 .SH DESCRIPTION
diff --git a/png.c b/png.c
index 78ce39f..2c9fea2 100644
--- a/png.c
+++ b/png.c
@@ -1,7 +1,7 @@
 
 /* png.c - location for general purpose libpng functions
  *
- * Last changed in libpng 1.6.28 [January 5, 2017]
+ * Last changed in libpng 1.6.29 [March 16, 2017]
  * Copyright (c) 1998-2002,2004,2006-2017 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_28 Your_png_h_is_not_version_1_6_28;
+typedef png_libpng_version_1_6_29 Your_png_h_is_not_version_1_6_29;
 
 /* 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
@@ -776,14 +776,14 @@
 #else
 #  ifdef __STDC__
    return PNG_STRING_NEWLINE \
-      "libpng version 1.6.28 - January 5, 2017" PNG_STRING_NEWLINE \
+      "libpng version 1.6.29 - March 16, 2017" PNG_STRING_NEWLINE \
       "Copyright (c) 1998-2002,2004,2006-2017 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.28 - January 5, 2017\
+   return "libpng version 1.6.29 - March 16, 2017\
       Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson\
       Copyright (c) 1996-1997 Andreas Dilger\
       Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
@@ -4260,13 +4260,13 @@
    if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT &&
       (option & 1) == 0)
    {
-      png_uint_32 mask = 3 << option;
-      png_uint_32 setting = (2 + (onoff != 0)) << option;
+      png_uint_32 mask = 3U << option;
+      png_uint_32 setting = (2U + (onoff != 0)) << option;
       png_uint_32 current = png_ptr->options;
 
       png_ptr->options = (png_uint_32)(((current & ~mask) | setting) & 0xff);
 
-      return (current & mask) >> option;
+      return (int)(current & mask) >> option;
    }
 
    return PNG_OPTION_INVALID;
diff --git a/png.h b/png.h
index e4cf032..2431e0d 100644
--- a/png.h
+++ b/png.h
@@ -1,7 +1,7 @@
 
 /* png.h - header file for PNG reference library
  *
- * libpng version 1.6.28, January 5, 2017
+ * libpng version 1.6.29, March 16, 2017
  *
  * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
@@ -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.28, January 5, 2017:
+ *   libpng versions 0.97, January 1998, through 1.6.29, March 16, 2017:
  *     Glenn Randers-Pehrson.
  *   See also "Contributing Authors", below.
  */
@@ -25,7 +25,7 @@
  *
  * This code is released under the libpng license.
  *
- * libpng versions 1.0.7, July 1, 2000 through 1.6.28, January 5, 2017 are
+ * libpng versions 1.0.7, July 1, 2000 through 1.6.29, March 16, 2017 are
  * Copyright (c) 2000-2002, 2004, 2006-2017 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
@@ -38,6 +38,8 @@
  *    Gilles Vollant
  *    James Yu
  *    Mandar Sahastrabuddhe
+ *    Google Inc.
+ *    Vadim Barkov
  *
  * and with the following additions to the disclaimer:
  *
@@ -211,7 +213,7 @@
  *    ...
  *    1.5.28                  15    10527  15.so.15.28[.0]
  *    ...
- *    1.6.28                  16    10628  16.so.16.28[.0]
+ *    1.6.29                  16    10629  16.so.16.29[.0]
  *
  *    Henceforth the source version will match the shared-library major
  *    and minor numbers; the shared-library major version number will be
@@ -239,13 +241,13 @@
  * Y2K compliance in libpng:
  * =========================
  *
- *    January 5, 2017
+ *    March 16, 2017
  *
  *    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.28 are Y2K compliant.  It is my belief that
+ *    upward through 1.6.29 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
@@ -307,8 +309,8 @@
  */
 
 /* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.28"
-#define PNG_HEADER_VERSION_STRING " libpng version 1.6.28 - January 5, 2017\n"
+#define PNG_LIBPNG_VER_STRING "1.6.29"
+#define PNG_HEADER_VERSION_STRING " libpng version 1.6.29 - March 16, 2017\n"
 
 #define PNG_LIBPNG_VER_SONUM   16
 #define PNG_LIBPNG_VER_DLLNUM  16
@@ -316,7 +318,7 @@
 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
 #define PNG_LIBPNG_VER_MAJOR   1
 #define PNG_LIBPNG_VER_MINOR   6
-#define PNG_LIBPNG_VER_RELEASE 28
+#define PNG_LIBPNG_VER_RELEASE 29
 
 /* This should match the numeric part of the final component of
  * PNG_LIBPNG_VER_STRING, omitting any leading zero:
@@ -347,7 +349,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 10628 /* 1.6.28 */
+#define PNG_LIBPNG_VER 10629 /* 1.6.29 */
 
 /* Library configuration: these options cannot be changed after
  * the library has been built.
@@ -457,7 +459,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_28;
+typedef char* png_libpng_version_1_6_29;
 
 /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
  *
@@ -3224,7 +3226,10 @@
 #  define PNG_MIPS_MSA   6 /* HARDWARE: MIPS Msa SIMD instructions supported */
 #endif
 #define PNG_IGNORE_ADLER32 8
-#define PNG_OPTION_NEXT  10 /* Next option - numbers must be even */
+#ifdef PNG_POWERPC_VSX_API_SUPPORTED
+#  define PNG_POWERPC_VSX   10 /* HARDWARE: PowerPC VSX SIMD instructions supported */
+#endif
+#define PNG_OPTION_NEXT  12 /* Next option - numbers must be even */
 
 /* Return values: NOTE: there are four values and 'off' is *not* zero */
 #define PNG_OPTION_UNSET   0 /* Unset - defaults to off */
diff --git a/pngconf.h b/pngconf.h
index 5e8b40b..78d8b92 100644
--- a/pngconf.h
+++ b/pngconf.h
@@ -1,7 +1,7 @@
 
 /* pngconf.h - machine configurable file for libpng
  *
- * libpng version 1.6.28, January 5, 2017
+ * libpng version 1.6.29, March 16, 2017
  *
  * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
diff --git a/pngpriv.h b/pngpriv.h
index ed61165..6d2e424 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.26 [October 20, 2016]
- * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.29 [March 16, 2017]
+ * Copyright (c) 1998-2002,2004,2006-2017 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.)
  *
@@ -190,6 +190,50 @@
 #  endif
 #endif
 
+#ifndef PNG_POWERPC_VSX_OPT
+#  if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__)
+#     define PNG_POWERPC_VSX_OPT 2
+#  else
+#     define PNG_POWERPC_VSX_OPT 0
+#  endif
+#endif
+
+#ifndef PNG_INTEL_SSE_OPT
+#   ifdef PNG_INTEL_SSE
+      /* Only check for SSE if the build configuration has been modified to
+       * enable SSE optimizations.  This means that these optimizations will
+       * be off by default.  See contrib/intel for more details.
+       */
+#     if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
+       defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
+       (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
+#         define PNG_INTEL_SSE_OPT 1
+#      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
+
 #if PNG_MIPS_MSA_OPT > 0
 #  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa
 #  ifndef PNG_MIPS_MSA_IMPLEMENTATION
@@ -210,6 +254,11 @@
 #  endif
 #endif /* PNG_MIPS_MSA_OPT > 0 */
 
+#if PNG_POWERPC_VSX_OPT > 0
+#  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx
+#  define PNG_POWERPC_VSX_IMPLEMENTATION 1
+#endif
+
 
 /* Is this a build of a DLL where compilation of the object modules requires
  * different preprocessor settings to those required for a simple library?  If
@@ -1256,6 +1305,38 @@
     row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
 #endif
 
+#if PNG_POWERPC_VSX_OPT > 0
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info,
+    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_vsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_vsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_vsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_vsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_vsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_vsx,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+#endif
+
+#if PNG_INTEL_SSE_IMPLEMENTATION > 0
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
+    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+#endif
+
 /* Choose the best filter to use and filter the row data */
 PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
     png_row_infop row_info),PNG_EMPTY);
@@ -1991,6 +2072,11 @@
 PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa,
    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
 #endif
+
+#  if PNG_INTEL_SSE_IMPLEMENTATION > 0
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
+   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+#  endif
 #endif
 
 PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
diff --git a/pngrtran.c b/pngrtran.c
index 0b4f4f9..16c1ed6 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.24 [August 4, 2016]
- * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.29 [March 16, 2017]
+ * Copyright (c) 1998-2002,2004,2006-2017 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.)
  *
@@ -4302,7 +4302,7 @@
             if (num_trans > 0)
             {
                sp = row + (png_size_t)row_width - 1;
-               dp = row + (png_size_t)(row_width << 2) - 1;
+               dp = row + ((png_size_t)row_width << 2) - 1;
 
                for (i = 0; i < row_width; i++)
                {
@@ -4463,7 +4463,7 @@
             {
                gray = gray & 0xff;
                sp = row + (png_size_t)row_width - 1;
-               dp = row + (png_size_t)(row_width << 1) - 1;
+               dp = row + ((png_size_t)row_width << 1) - 1;
 
                for (i = 0; i < row_width; i++)
                {
@@ -4519,7 +4519,7 @@
             png_byte green = (png_byte)(trans_color->green & 0xff);
             png_byte blue = (png_byte)(trans_color->blue & 0xff);
             sp = row + (png_size_t)row_info->rowbytes - 1;
-            dp = row + (png_size_t)(row_width << 2) - 1;
+            dp = row + ((png_size_t)row_width << 2) - 1;
             for (i = 0; i < row_width; i++)
             {
                if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
@@ -4542,7 +4542,7 @@
             png_byte green_low = (png_byte)(trans_color->green & 0xff);
             png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
             sp = row + row_info->rowbytes - 1;
-            dp = row + (png_size_t)(row_width << 3) - 1;
+            dp = row + ((png_size_t)row_width << 3) - 1;
             for (i = 0; i < row_width; i++)
             {
                if (*(sp - 5) == red_high &&
diff --git a/pngrutil.c b/pngrutil.c
index bee0ea1..76f079a 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.27 [January 5, 2017]
- * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.29 [March 16, 2017]
+ * Copyright (c) 1998-2002,2004,2006-2017 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.)
  *
@@ -418,7 +418,7 @@
             png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
       }
 
-#if ZLIB_VERNUM >= 0x1281 && \
+#if ZLIB_VERNUM >= 0x1290 && \
    defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_IGNORE_ADLER32)
       if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON)
          /* Turn off validation of the ADLER32 checksum in IDAT chunks */
diff --git a/pngtest.c b/pngtest.c
index f8f76bf..255fd14 100644
--- a/pngtest.c
+++ b/pngtest.c
@@ -2088,4 +2088,4 @@
 #endif
 
 /* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_28 Your_png_h_is_not_version_1_6_28;
+typedef png_libpng_version_1_6_29 Your_png_h_is_not_version_1_6_29;
diff --git a/pngwutil.c b/pngwutil.c
index d1a82d4..0f98d58 100644
--- a/pngwutil.c
+++ b/pngwutil.c
@@ -675,6 +675,7 @@
     int interlace_type)
 {
    png_byte buf[13]; /* Buffer to store the IHDR info */
+   int is_invalid_depth;
 
    png_debug(1, "in png_write_IHDR");
 
@@ -700,11 +701,11 @@
          break;
 
       case PNG_COLOR_TYPE_RGB:
+         is_invalid_depth = (bit_depth != 8);
 #ifdef PNG_WRITE_16BIT_SUPPORTED
-         if (bit_depth != 8 && bit_depth != 16)
-#else
-         if (bit_depth != 8)
+         is_invalid_depth = (is_invalid_depth && bit_depth != 16);
 #endif
+         if (is_invalid_depth)
             png_error(png_ptr, "Invalid bit depth for RGB image");
 
          png_ptr->channels = 3;
@@ -726,18 +727,22 @@
          break;
 
       case PNG_COLOR_TYPE_GRAY_ALPHA:
-         if (bit_depth != 8 && bit_depth != 16)
+         is_invalid_depth = (bit_depth != 8);
+#ifdef PNG_WRITE_16BIT_SUPPORTED
+         is_invalid_depth = (is_invalid_depth && bit_depth != 16);
+#endif
+         if (is_invalid_depth)
             png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
 
          png_ptr->channels = 2;
          break;
 
       case PNG_COLOR_TYPE_RGB_ALPHA:
+         is_invalid_depth = (bit_depth != 8);
 #ifdef PNG_WRITE_16BIT_SUPPORTED
-         if (bit_depth != 8 && bit_depth != 16)
-#else
-         if (bit_depth != 8)
+         is_invalid_depth = (is_invalid_depth && bit_depth != 16);
 #endif
+         if (is_invalid_depth)
             png_error(png_ptr, "Invalid bit depth for RGBA image");
 
          png_ptr->channels = 4;
diff --git a/powerpc/filter_vsx_intrinsics.c b/powerpc/filter_vsx_intrinsics.c
new file mode 100644
index 0000000..e3de496
--- /dev/null
+++ b/powerpc/filter_vsx_intrinsics.c
@@ -0,0 +1,767 @@
+/* filter_vsx_intrinsics.c - PowerPC optimised filter functions
+ *
+ * Copyright (c) 2017 Glenn Randers-Pehrson
+ * Written by Vadim Barkov, 2017.
+ * Last changed in libpng 1.6.29 [March 16, 2017]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include "../pngpriv.h"
+
+#ifdef PNG_READ_SUPPORTED
+
+/* This code requires -maltivec and -mvsx on the command line: */
+#if PNG_POWERPC_VSX_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
+
+#include <altivec.h>
+
+#if PNG_POWERPC_VSX_OPT > 0
+
+#ifndef __VSX__
+#  error "This code requires VSX support (POWER7 and later). Please provide -mvsx compiler flag."
+#endif
+
+#define vec_ld_unaligned(vec,data) vec = vec_vsx_ld(0,data)
+#define vec_st_unaligned(vec,data) vec_vsx_st(vec,0,data)
+
+
+/* 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.
+ * ( this is taken from ../intel/filter_sse2_intrinsics.c )
+ */
+
+#define vsx_declare_common_vars(row_info,row,prev_row,offset) \
+   png_byte i;\
+   png_bytep rp = row + offset;\
+   png_const_bytep pp = prev_row;\
+   png_size_t unaligned_top = 16 - (((png_size_t)rp % 16));\
+   png_size_t istop;\
+   if(unaligned_top == 16)\
+      unaligned_top = 0;\
+   istop = row_info->rowbytes;\
+   if((unaligned_top < istop))\
+      istop -= unaligned_top;\
+   else{\
+      unaligned_top = istop;\
+      istop = 0;\
+   }
+
+void png_read_filter_row_up_vsx(png_row_infop row_info, png_bytep row,
+                                png_const_bytep prev_row)
+{
+   vector unsigned char rp_vec;
+   vector unsigned char pp_vec;
+   vsx_declare_common_vars(row_info,row,prev_row,0)
+
+   /* Altivec operations require 16-byte aligned data
+    * but input can be unaligned. So we calculate
+    * unaligned part as usual.
+    */
+   for (i = 0; i < unaligned_top; i++)
+   {
+      *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+      rp++;
+   }
+
+   /* Using SIMD while we can */
+   while( istop >= 16 )
+   {
+      rp_vec = vec_ld(0,rp);
+      vec_ld_unaligned(pp_vec,pp);
+
+      rp_vec = vec_add(rp_vec,pp_vec);
+
+      vec_st(rp_vec,0,rp);
+
+      pp += 16;
+      rp += 16;
+      istop -= 16;
+   }
+
+   if(istop > 0)
+   {
+      /* If byte count of row is not divisible by 16
+       * we will process remaining part as usual
+       */
+      for (i = 0; i < istop; i++)
+      {
+         *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
+         rp++;
+      }
+}
+
+}
+
+static const vector unsigned char VSX_LEFTSHIFTED1_4 = {16,16,16,16, 0, 1, 2, 3,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_LEFTSHIFTED2_4 = {16,16,16,16,16,16,16,16, 4, 5, 6, 7,16,16,16,16};
+static const vector unsigned char VSX_LEFTSHIFTED3_4 = {16,16,16,16,16,16,16,16,16,16,16,16, 8, 9,10,11};
+
+static const vector unsigned char VSX_LEFTSHIFTED1_3 = {16,16,16, 0, 1, 2,16,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_LEFTSHIFTED2_3 = {16,16,16,16,16,16, 3, 4, 5,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_LEFTSHIFTED3_3 = {16,16,16,16,16,16,16,16,16, 6, 7, 8,16,16,16,16};
+static const vector unsigned char VSX_LEFTSHIFTED4_3 = {16,16,16,16,16,16,16,16,16,16,16,16, 9,10,11,16};
+
+static const vector unsigned char VSX_NOT_SHIFTED1_4 = {16,16,16,16, 4, 5, 6, 7,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_NOT_SHIFTED2_4 = {16,16,16,16,16,16,16,16, 8, 9,10,11,16,16,16,16};
+static const vector unsigned char VSX_NOT_SHIFTED3_4 = {16,16,16,16,16,16,16,16,16,16,16,16,12,13,14,15};
+
+static const vector unsigned char VSX_NOT_SHIFTED1_3 = {16,16,16, 3, 4, 5,16,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_NOT_SHIFTED2_3 = {16,16,16,16,16,16, 6, 7, 8,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_NOT_SHIFTED3_3 = {16,16,16,16,16,16,16,16,16, 9,10,11,16,16,16,16};
+static const vector unsigned char VSX_NOT_SHIFTED4_3 = {16,16,16,16,16,16,16,16,16,16,16,16,12,13,14,16};
+
+static const vector unsigned char VSX_CHAR_ZERO = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+#ifdef __LITTLE_ENDIAN__
+
+static const vector unsigned char VSX_CHAR_TO_SHORT1_4 = { 4,16, 5,16, 6,16, 7,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_CHAR_TO_SHORT2_4 = { 8,16, 9,16,10,16,11,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_CHAR_TO_SHORT3_4 = {12,16,13,16,14,16,15,16,16,16,16,16,16,16,16,16};
+
+static const vector unsigned char VSX_SHORT_TO_CHAR1_4 = {16,16,16,16, 0, 2, 4, 6,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_SHORT_TO_CHAR2_4 = {16,16,16,16,16,16,16,16, 0, 2, 4, 6,16,16,16,16};
+static const vector unsigned char VSX_SHORT_TO_CHAR3_4 = {16,16,16,16,16,16,16,16,16,16,16,16, 0, 2, 4, 6};
+
+static const vector unsigned char VSX_CHAR_TO_SHORT1_3 = { 3,16, 4,16, 5,16,16,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_CHAR_TO_SHORT2_3 = { 6,16, 7,16, 8,16,16,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_CHAR_TO_SHORT3_3 = { 9,16,10,16,11,16,16,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_CHAR_TO_SHORT4_3 = {12,16,13,16,14,16,16,16,16,16,16,16,16,16,16,16};
+
+static const vector unsigned char VSX_SHORT_TO_CHAR1_3 = {16,16,16, 0, 2, 4,16,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_SHORT_TO_CHAR2_3 = {16,16,16,16,16,16, 0, 2, 4,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_SHORT_TO_CHAR3_3 = {16,16,16,16,16,16,16,16,16, 0, 2, 4,16,16,16,16};
+static const vector unsigned char VSX_SHORT_TO_CHAR4_3 = {16,16,16,16,16,16,16,16,16,16,16,16, 0, 2, 4,16};
+
+#elif defined(__BIG_ENDIAN__)
+
+static const vector unsigned char VSX_CHAR_TO_SHORT1_4 = {16, 4,16, 5,16, 6,16, 7,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_CHAR_TO_SHORT2_4 = {16, 8,16, 9,16,10,16,11,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_CHAR_TO_SHORT3_4 = {16,12,16,13,16,14,16,15,16,16,16,16,16,16,16,16};
+
+static const vector unsigned char VSX_SHORT_TO_CHAR1_4 = {16,16,16,16, 1, 3, 5, 7,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_SHORT_TO_CHAR2_4 = {16,16,16,16,16,16,16,16, 1, 3, 5, 7,16,16,16,16};
+static const vector unsigned char VSX_SHORT_TO_CHAR3_4 = {16,16,16,16,16,16,16,16,16,16,16,16, 1, 3, 5, 7};
+
+static const vector unsigned char VSX_CHAR_TO_SHORT1_3 = {16, 3,16, 4,16, 5,16,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_CHAR_TO_SHORT2_3 = {16, 6,16, 7,16, 8,16,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_CHAR_TO_SHORT3_3 = {16, 9,16,10,16,11,16,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_CHAR_TO_SHORT4_3 = {16,12,16,13,16,14,16,16,16,16,16,16,16,16,16,16};
+
+static const vector unsigned char VSX_SHORT_TO_CHAR1_3 = {16,16,16, 1, 3, 5,16,16,16,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_SHORT_TO_CHAR2_3 = {16,16,16,16,16,16, 1, 3, 5,16,16,16,16,16,16,16};
+static const vector unsigned char VSX_SHORT_TO_CHAR3_3 = {16,16,16,16,16,16,16,16,16, 1, 3, 5,16,16,16,16};
+static const vector unsigned char VSX_SHORT_TO_CHAR4_3 = {16,16,16,16,16,16,16,16,16,16,16,16, 1, 3, 5,16};
+
+#endif
+
+#define vsx_char_to_short(vec,offset,bpp) (vector unsigned short)vec_perm((vec),VSX_CHAR_ZERO,VSX_CHAR_TO_SHORT##offset##_##bpp)
+#define vsx_short_to_char(vec,offset,bpp) vec_perm(((vector unsigned char)(vec)),VSX_CHAR_ZERO,VSX_SHORT_TO_CHAR##offset##_##bpp)
+
+#ifdef PNG_USE_ABS
+#  define vsx_abs(number) abs(number)
+#else
+#  define vsx_abs(number) (number > 0) ? (number) : -(number)
+#endif
+
+void png_read_filter_row_sub4_vsx(png_row_infop row_info, png_bytep row,
+                                  png_const_bytep prev_row)
+{
+   const png_byte bpp = 4;
+
+   vector unsigned char rp_vec;
+   vector unsigned char part_vec;
+
+   vsx_declare_common_vars(row_info,row,prev_row,bpp)
+
+   PNG_UNUSED(pp)
+
+   /* Altivec operations require 16-byte aligned data
+    * but input can be unaligned. So we calculate
+    * unaligned part as usual.
+    */
+   for (i = 0; i < unaligned_top; i++)
+   {
+      *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
+      rp++;
+   }
+
+   /* Using SIMD while we can */
+   while( istop >= 16 )
+   {
+      for(i=0;i < bpp ; i++)
+      {
+         *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
+         rp++;
+      }
+      rp -= bpp;
+
+      rp_vec = vec_ld(0,rp);
+      part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_4);
+      rp_vec = vec_add(rp_vec,part_vec);
+
+      part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_4);
+      rp_vec = vec_add(rp_vec,part_vec);
+
+      part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_4);
+      rp_vec = vec_add(rp_vec,part_vec);
+
+      vec_st(rp_vec,0,rp);
+
+      rp += 16;
+      istop -= 16;
+   }
+
+   if(istop > 0)
+      for (i = 0; i < istop % 16; i++)
+      {
+         *rp = (png_byte)(((int)(*rp) + (int)(*(rp - bpp))) & 0xff);
+         rp++;
+      }
+
+}
+
+void png_read_filter_row_sub3_vsx(png_row_infop row_info, png_bytep row,
+                                  png_const_bytep prev_row)
+{
+   const png_byte bpp = 3;
+
+   vector unsigned char rp_vec;
+   vector unsigned char part_vec;
+
+   vsx_declare_common_vars(row_info,row,prev_row,bpp)
+
+   PNG_UNUSED(pp)
+
+   /* Altivec operations require 16-byte aligned data
+    * but input can be unaligned. So we calculate
+    * unaligned part as usual.
+    */
+   for (i = 0; i < unaligned_top; i++)
+   {
+      *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
+      rp++;
+   }
+
+   /* Using SIMD while we can */
+   while( istop >= 16 )
+   {
+      for(i=0;i < bpp ; i++)
+      {
+         *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
+         rp++;
+      }
+      rp -= bpp;
+
+      rp_vec = vec_ld(0,rp);
+      part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_3);
+      rp_vec = vec_add(rp_vec,part_vec);
+
+      part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_3);
+      rp_vec = vec_add(rp_vec,part_vec);
+
+      part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_3);
+      rp_vec = vec_add(rp_vec,part_vec);
+
+      part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED4_3);
+      rp_vec = vec_add(rp_vec,part_vec);
+
+      vec_st(rp_vec,0,rp);
+      rp += 15;
+      istop -= 16;
+
+      /* Since 16 % bpp = 16 % 3 = 1, last element of array must
+       * be proceeded manually
+       */
+      *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
+      rp++;
+   }
+
+   if(istop > 0)
+      for (i = 0; i < istop % 16; i++)
+      {
+         *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff);
+         rp++;
+      }
+}
+
+void png_read_filter_row_avg4_vsx(png_row_infop row_info, png_bytep row,
+                                  png_const_bytep prev_row)
+{
+   const png_byte bpp = 4;
+
+   vector unsigned char rp_vec;
+   vector unsigned char pp_vec;
+   vector unsigned char pp_part_vec;
+   vector unsigned char rp_part_vec;
+   vector unsigned char avg_vec;
+
+   vsx_declare_common_vars(row_info,row,prev_row,bpp)
+   rp -= bpp;
+   if(istop >= bpp)
+      istop -= bpp;
+
+   for (i = 0; i < bpp; i++)
+   {
+      *rp = (png_byte)(((int)(*rp) +
+         ((int)(*pp++) / 2 )) & 0xff);
+
+      rp++;
+   }
+
+   /* Altivec operations require 16-byte aligned data
+    * but input can be unaligned. So we calculate
+    * unaligned part as usual.
+    */
+   for (i = 0; i < unaligned_top; i++)
+   {
+      *rp = (png_byte)(((int)(*rp) +
+         (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
+
+      rp++;
+   }
+
+   /* Using SIMD while we can */
+   while( istop >= 16 )
+   {
+      for(i=0;i < bpp ; i++)
+      {
+         *rp = (png_byte)(((int)(*rp) +
+            (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
+
+         rp++;
+      }
+      rp -= bpp;
+      pp -= bpp;
+
+      vec_ld_unaligned(pp_vec,pp);
+      rp_vec = vec_ld(0,rp);
+
+      rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_4);
+      pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED1_4);
+      avg_vec = vec_avg(rp_part_vec,pp_part_vec);
+      avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
+      rp_vec = vec_add(rp_vec,avg_vec);
+
+      rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_4);
+      pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED2_4);
+      avg_vec = vec_avg(rp_part_vec,pp_part_vec);
+      avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
+      rp_vec = vec_add(rp_vec,avg_vec);
+
+      rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_4);
+      pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED3_4);
+      avg_vec = vec_avg(rp_part_vec,pp_part_vec);
+      avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
+      rp_vec = vec_add(rp_vec,avg_vec);
+
+      vec_st(rp_vec,0,rp);
+
+      rp += 16;
+      pp += 16;
+      istop -= 16;
+   }
+
+   if(istop  > 0)
+      for (i = 0; i < istop % 16; i++)
+      {
+         *rp = (png_byte)(((int)(*rp) +
+            (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
+
+         rp++;
+      }
+}
+
+void png_read_filter_row_avg3_vsx(png_row_infop row_info, png_bytep row,
+                                  png_const_bytep prev_row)
+{
+  const png_byte bpp = 3;
+
+  vector unsigned char rp_vec;
+  vector unsigned char pp_vec;
+  vector unsigned char pp_part_vec;
+  vector unsigned char rp_part_vec;
+  vector unsigned char avg_vec;
+
+  vsx_declare_common_vars(row_info,row,prev_row,bpp)
+  rp -= bpp;
+  if(istop >= bpp)
+     istop -= bpp;
+
+  for (i = 0; i < bpp; i++)
+  {
+     *rp = (png_byte)(((int)(*rp) +
+        ((int)(*pp++) / 2 )) & 0xff);
+
+     rp++;
+  }
+
+  /* Altivec operations require 16-byte aligned data
+   * but input can be unaligned. So we calculate
+   * unaligned part as usual.
+   */
+  for (i = 0; i < unaligned_top; i++)
+  {
+     *rp = (png_byte)(((int)(*rp) +
+        (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
+
+     rp++;
+  }
+
+  /* Using SIMD while we can */
+  while( istop >= 16 )
+  {
+     for(i=0;i < bpp ; i++)
+     {
+        *rp = (png_byte)(((int)(*rp) +
+           (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
+
+        rp++;
+     }
+     rp -= bpp;
+     pp -= bpp;
+
+     vec_ld_unaligned(pp_vec,pp);
+     rp_vec = vec_ld(0,rp);
+
+     rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_3);
+     pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED1_3);
+     avg_vec = vec_avg(rp_part_vec,pp_part_vec);
+     avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
+     rp_vec = vec_add(rp_vec,avg_vec);
+
+     rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_3);
+     pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED2_3);
+     avg_vec = vec_avg(rp_part_vec,pp_part_vec);
+     avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
+     rp_vec = vec_add(rp_vec,avg_vec);
+
+     rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_3);
+     pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED3_3);
+     avg_vec = vec_avg(rp_part_vec,pp_part_vec);
+     avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
+     rp_vec = vec_add(rp_vec,avg_vec);
+
+     rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED4_3);
+     pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED4_3);
+     avg_vec = vec_avg(rp_part_vec,pp_part_vec);
+     avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1)));
+     rp_vec = vec_add(rp_vec,avg_vec);
+
+     vec_st(rp_vec,0,rp);
+
+     rp += 15;
+     pp += 15;
+     istop -= 16;
+
+     /* Since 16 % bpp = 16 % 3 = 1, last element of array must
+      * be proceeded manually
+      */
+     *rp = (png_byte)(((int)(*rp) +
+        (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
+     rp++;
+  }
+
+  if(istop  > 0)
+     for (i = 0; i < istop % 16; i++)
+     {
+        *rp = (png_byte)(((int)(*rp) +
+           (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff);
+
+        rp++;
+     }
+}
+
+/* Bytewise c ? t : e. */
+#define if_then_else(c,t,e) vec_sel(e,t,c)
+
+#define vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp) {\
+      c = *(pp - bpp);\
+      a = *(rp - bpp);\
+      b = *pp++;\
+      p = b - c;\
+      pc = a - c;\
+      pa = vsx_abs(p);\
+      pb = vsx_abs(pc);\
+      pc = vsx_abs(p + pc);\
+      if (pb < pa) pa = pb, a = b;\
+      if (pc < pa) a = c;\
+      a += *rp;\
+      *rp++ = (png_byte)a;\
+      }
+
+void png_read_filter_row_paeth4_vsx(png_row_infop row_info, png_bytep row,
+   png_const_bytep prev_row)
+{
+   const png_byte bpp = 4;
+
+   int a, b, c, pa, pb, pc, p;
+   vector unsigned char rp_vec;
+   vector unsigned char pp_vec;
+   vector unsigned short a_vec,b_vec,c_vec,nearest_vec;
+   vector signed short pa_vec,pb_vec,pc_vec,smallest_vec;
+
+   vsx_declare_common_vars(row_info,row,prev_row,bpp)
+   rp -= bpp;
+   if(istop >= bpp)
+      istop -= bpp;
+
+   /* Process the first pixel in the row completely (this is the same as 'up'
+    * because there is only one candidate predictor for the first row).
+    */
+   for(i = 0; i < bpp ; i++)
+   {
+      *rp = (png_byte)( *rp + *pp);
+      rp++;
+      pp++;
+   }
+
+   for(i = 0; i < unaligned_top ; i++)
+   {
+      vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
+   }
+
+   while( istop >= 16)
+   {
+      for(i = 0; i < bpp ; i++)
+      {
+         vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
+      }
+
+      rp -= bpp;
+      pp -= bpp;
+      rp_vec = vec_ld(0,rp);
+      vec_ld_unaligned(pp_vec,pp);
+
+      a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_4),1,4);
+      b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED1_4),1,4);
+      c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_4),1,4);
+      pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
+      pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
+      pc_vec = vec_add(pa_vec,pb_vec);
+      pa_vec = vec_abs(pa_vec);
+      pb_vec = vec_abs(pb_vec);
+      pc_vec = vec_abs(pc_vec);
+      smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
+      nearest_vec =  if_then_else(
+            vec_cmpeq(pa_vec,smallest_vec),
+            a_vec,
+            if_then_else(
+              vec_cmpeq(pb_vec,smallest_vec),
+              b_vec,
+              c_vec
+              )
+            );
+      rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,1,4)));
+
+      a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_4),2,4);
+      b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED2_4),2,4);
+      c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_4),2,4);
+      pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
+      pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
+      pc_vec = vec_add(pa_vec,pb_vec);
+      pa_vec = vec_abs(pa_vec);
+      pb_vec = vec_abs(pb_vec);
+      pc_vec = vec_abs(pc_vec);
+      smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
+      nearest_vec =  if_then_else(
+            vec_cmpeq(pa_vec,smallest_vec),
+            a_vec,
+            if_then_else(
+              vec_cmpeq(pb_vec,smallest_vec),
+              b_vec,
+              c_vec
+              )
+            );
+      rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,2,4)));
+
+      a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_4),3,4);
+      b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED3_4),3,4);
+      c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_4),3,4);
+      pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
+      pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
+      pc_vec = vec_add(pa_vec,pb_vec);
+      pa_vec = vec_abs(pa_vec);
+      pb_vec = vec_abs(pb_vec);
+      pc_vec = vec_abs(pc_vec);
+      smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
+      nearest_vec =  if_then_else(
+            vec_cmpeq(pa_vec,smallest_vec),
+            a_vec,
+            if_then_else(
+              vec_cmpeq(pb_vec,smallest_vec),
+              b_vec,
+              c_vec
+              )
+            );
+      rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,3,4)));
+
+      vec_st(rp_vec,0,rp);
+
+      rp += 16;
+      pp += 16;
+      istop -= 16;
+   }
+
+   if(istop > 0)
+      for (i = 0; i < istop % 16; i++)
+      {
+         vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
+      }
+}
+
+void png_read_filter_row_paeth3_vsx(png_row_infop row_info, png_bytep row,
+   png_const_bytep prev_row)
+{
+  const png_byte bpp = 3;
+
+  int a, b, c, pa, pb, pc, p;
+  vector unsigned char rp_vec;
+  vector unsigned char pp_vec;
+  vector unsigned short a_vec,b_vec,c_vec,nearest_vec;
+  vector signed short pa_vec,pb_vec,pc_vec,smallest_vec;
+
+  vsx_declare_common_vars(row_info,row,prev_row,bpp)
+  rp -= bpp;
+  if(istop >= bpp)
+     istop -= bpp;
+
+  /* Process the first pixel in the row completely (this is the same as 'up'
+   * because there is only one candidate predictor for the first row).
+   */
+  for(i = 0; i < bpp ; i++)
+  {
+     *rp = (png_byte)( *rp + *pp);
+     rp++;
+     pp++;
+  }
+
+  for(i = 0; i < unaligned_top ; i++)
+  {
+     vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
+  }
+
+  while( istop >= 16)
+  {
+     for(i = 0; i < bpp ; i++)
+     {
+        vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
+     }
+
+     rp -= bpp;
+     pp -= bpp;
+     rp_vec = vec_ld(0,rp);
+     vec_ld_unaligned(pp_vec,pp);
+
+     a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_3),1,3);
+     b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED1_3),1,3);
+     c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_3),1,3);
+     pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
+     pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
+     pc_vec = vec_add(pa_vec,pb_vec);
+     pa_vec = vec_abs(pa_vec);
+     pb_vec = vec_abs(pb_vec);
+     pc_vec = vec_abs(pc_vec);
+     smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
+     nearest_vec =  if_then_else(
+           vec_cmpeq(pa_vec,smallest_vec),
+           a_vec,
+           if_then_else(
+             vec_cmpeq(pb_vec,smallest_vec),
+             b_vec,
+             c_vec
+             )
+           );
+     rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,1,3)));
+
+     a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_3),2,3);
+     b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED2_3),2,3);
+     c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_3),2,3);
+     pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
+     pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
+     pc_vec = vec_add(pa_vec,pb_vec);
+     pa_vec = vec_abs(pa_vec);
+     pb_vec = vec_abs(pb_vec);
+     pc_vec = vec_abs(pc_vec);
+     smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
+     nearest_vec =  if_then_else(
+           vec_cmpeq(pa_vec,smallest_vec),
+           a_vec,
+           if_then_else(
+             vec_cmpeq(pb_vec,smallest_vec),
+             b_vec,
+             c_vec
+             )
+           );
+     rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,2,3)));
+
+     a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_3),3,3);
+     b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED3_3),3,3);
+     c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_3),3,3);
+     pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
+     pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
+     pc_vec = vec_add(pa_vec,pb_vec);
+     pa_vec = vec_abs(pa_vec);
+     pb_vec = vec_abs(pb_vec);
+     pc_vec = vec_abs(pc_vec);
+     smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
+     nearest_vec =  if_then_else(
+           vec_cmpeq(pa_vec,smallest_vec),
+           a_vec,
+           if_then_else(
+             vec_cmpeq(pb_vec,smallest_vec),
+             b_vec,
+             c_vec
+             )
+           );
+     rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,3,3)));
+
+     a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED4_3),4,3);
+     b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED4_3),4,3);
+     c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED4_3),4,3);
+     pa_vec = (vector signed short) vec_sub(b_vec,c_vec);
+     pb_vec = (vector signed short) vec_sub(a_vec , c_vec);
+     pc_vec = vec_add(pa_vec,pb_vec);
+     pa_vec = vec_abs(pa_vec);
+     pb_vec = vec_abs(pb_vec);
+     pc_vec = vec_abs(pc_vec);
+     smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec));
+     nearest_vec =  if_then_else(
+           vec_cmpeq(pa_vec,smallest_vec),
+           a_vec,
+           if_then_else(
+             vec_cmpeq(pb_vec,smallest_vec),
+             b_vec,
+             c_vec
+             )
+           );
+     rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,4,3)));
+
+     vec_st(rp_vec,0,rp);
+
+     rp += 15;
+     pp += 15;
+     istop -= 16;
+
+     /* Since 16 % bpp = 16 % 3 = 1, last element of array must
+      * be proceeded manually
+      */
+     vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
+  }
+
+  if(istop > 0)
+     for (i = 0; i < istop % 16; i++)
+     {
+        vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp)
+     }
+}
+
+#endif /* PNG_POWERPC_VSX_OPT > 0 */
+#endif /* PNG_POWERPC_VSX_IMPLEMENTATION == 1 (intrinsics) */
+#endif /* READ */
diff --git a/powerpc/powerpc_init.c b/powerpc/powerpc_init.c
new file mode 100644
index 0000000..0701617
--- /dev/null
+++ b/powerpc/powerpc_init.c
@@ -0,0 +1,125 @@
+
+/* powerpc_init.c - POWERPC optimised filter functions
+ *
+ * Copyright (c) 2017 Glenn Randers-Pehrson
+ * Written by Vadim Barkov, 2017.
+ * Last changed in libpng 1.6.29 [March 16, 2017]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
+ * called.
+ */
+#define _POSIX_SOURCE 1
+
+#include <stdio.h>
+#include "../pngpriv.h"
+
+#ifdef PNG_READ_SUPPORTED
+
+#if PNG_POWERPC_VSX_OPT > 0
+#ifdef PNG_POWERPC_VSX_CHECK_SUPPORTED /* Do run-time checks */
+/* WARNING: it is strongly recommended that you do not build libpng with
+ * run-time checks for CPU features if at all possible.  In the case of the PowerPC
+ * VSX instructions there is no processor-specific way of detecting the
+ * presence of the required support, therefore run-time detection is extremely
+ * OS specific.
+ *
+ * You may set the macro PNG_POWERPC_VSX_FILE to the file name of file containing
+ * a fragment of C source code which defines the png_have_vsx function.  There
+ * are a number of implementations in contrib/powerpc-vsx, but the only one that
+ * has partial support is contrib/powerpc-vsx/linux.c - a generic Linux
+ * implementation which reads /proc/cpufino.
+ */
+#ifndef PNG_POWERPC_VSX_FILE
+#  ifdef __linux__
+#     define  PNG_POWERPC_VSX_FILE "contrib/powerpc-vsx/linux_aux.c"
+#  endif
+#endif
+
+#ifdef PNG_POWERPC_VSX_FILE
+
+#include <signal.h> /* for sig_atomic_t */
+static int png_have_vsx(png_structp png_ptr);
+#include PNG_POWERPC_VSX_FILE
+
+#else  /* PNG_POWERPC_VSX_FILE */
+#  error "PNG_POWERPC_VSX_FILE undefined: no support for run-time POWERPC VSX checks"
+#endif /* PNG_POWERPC_VSX_FILE */
+#endif /* PNG_POWERPC_VSX_CHECK_SUPPORTED */
+
+void
+png_init_filter_functions_vsx(png_structp pp, unsigned int bpp)
+{
+   /* The switch statement is compiled in for POWERPC_VSX_API, the call to
+    * png_have_vsx is compiled in for POWERPC_VSX_CHECK. If both are defined
+    * the check is only performed if the API has not set the PowerPC option on
+    * or off explicitly. In this case the check controls what happens.
+    */
+
+#ifdef PNG_POWERPC_VSX_API_SUPPORTED
+   switch ((pp->options >> PNG_POWERPC_VSX) & 3)
+   {
+      case PNG_OPTION_UNSET:
+         /* Allow the run-time check to execute if it has been enabled -
+          * thus both API and CHECK can be turned on.  If it isn't supported
+          * this case will fall through to the 'default' below, which just
+          * returns.
+          */
+#endif /* PNG_POWERPC_VSX_API_SUPPORTED */
+#ifdef PNG_POWERPC_VSX_CHECK_SUPPORTED
+         {
+            static volatile sig_atomic_t no_vsx = -1; /* not checked */
+
+            if (no_vsx < 0)
+               no_vsx = !png_have_vsx(pp);
+
+            if (no_vsx)
+               return;
+         }
+#ifdef PNG_POWERPC_VSX_API_SUPPORTED
+         break;
+#endif
+#endif /* PNG_POWERPC_VSX_CHECK_SUPPORTED */
+
+#ifdef PNG_POWERPC_VSX_API_SUPPORTED
+      default: /* OFF or INVALID */
+         return;
+
+      case PNG_OPTION_ON:
+         /* Option turned on */
+         break;
+   }
+#endif
+
+   /* IMPORTANT: any new internal functions used here must be declared using
+    * PNG_INTERNAL_FUNCTION in ../pngpriv.h.  This is required so that the
+    * 'prefix' option to configure works:
+    *
+    *    ./configure --with-libpng-prefix=foobar_
+    *
+    * Verify you have got this right by running the above command, doing a build
+    * and examining pngprefix.h; it must contain a #define for every external
+    * function you add.  (Notice that this happens automatically for the
+    * initialization function.)
+    */
+   pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_vsx;
+
+   if (bpp == 3)
+   {
+      pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_vsx;
+      pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_vsx;
+      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_vsx;
+   }
+
+   else if (bpp == 4)
+   {
+      pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_vsx;
+      pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_vsx;
+      pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_vsx;
+   }
+}
+#endif /* PNG_POWERPC_VSX_OPT > 0 */
+#endif /* READ */
diff --git a/projects/vstudio/README.txt b/projects/vstudio/README.txt
index 9fd0f1d..1000d11 100644
--- a/projects/vstudio/README.txt
+++ b/projects/vstudio/README.txt
@@ -1,7 +1,7 @@
 
 VisualStudio instructions
 
-libpng version 1.6.28 - January 5, 2017
+libpng version 1.6.29 - March 16, 2017
 
 Copyright (c) 2010,2013,2015 Glenn Randers-Pehrson
 
diff --git a/projects/vstudio/zlib.props b/projects/vstudio/zlib.props
index e0e0d8f..18da337 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.28 - January 5, 2017
+ * libpng version 1.6.29 - March 16, 2017
  *
  * Copyright (c) 1998-2011 Glenn Randers-Pehrson
  *
diff --git a/scripts/README.txt b/scripts/README.txt
index 1fbdb2e..9b3c090 100644
--- a/scripts/README.txt
+++ b/scripts/README.txt
@@ -1,9 +1,9 @@
 
-Makefiles for  libpng version 1.6.28 - January 5, 2017
+Makefiles for  libpng version 1.6.29 - March 16, 2017
 
 pnglibconf.h.prebuilt       =>  Stores configuration settings
  makefile.linux    =>  Linux/ELF makefile
-                       (gcc, creates libpng16.so.16.1.6.28)
+                       (gcc, creates libpng16.so.16.1.6.29)
  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.28)
+                       creates libpng16.so.16.1.6.29)
  makefile.sgi      =>  Silicon Graphics IRIX makefile (cc, creates static lib)
  makefile.solaris  =>  Solaris 2.X makefile (gcc,
-                       creates libpng16.so.16.1.6.28)
+                       creates libpng16.so.16.1.6.29)
  makefile.so9      =>  Solaris 9 makefile (gcc,
-                       creates libpng16.so.16.1.6.28)
+                       creates libpng16.so.16.1.6.29)
  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 9939612..6a1831b 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.28"
+PNG_DFN ";Version 1.6.29"
 
 #define PNG_EXPORTA(ordinal, type, name, args, attributes)\
         PNG_DFN "@" SYMBOL_PREFIX "@@" name "@"
diff --git a/scripts/libpng-config-head.in b/scripts/libpng-config-head.in
index 9b6b32b..e06ed8e 100644
--- a/scripts/libpng-config-head.in
+++ b/scripts/libpng-config-head.in
@@ -11,7 +11,7 @@
 
 # Modeled after libxml-config.
 
-version=1.6.28
+version=1.6.29
 prefix=""
 libdir=""
 libs=""
diff --git a/scripts/libpng.pc.in b/scripts/libpng.pc.in
index f363b38..e8bf22d 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.28
+Version: 1.6.29
 Libs: -L${libdir} -lpng16
 Cflags: -I${includedir}
diff --git a/scripts/makefile.cegcc b/scripts/makefile.cegcc
index 0fe9eac..ca8ef6a 100644
--- a/scripts/makefile.cegcc
+++ b/scripts/makefile.cegcc
@@ -23,7 +23,7 @@
 
 VERMAJ = 1
 VERMIN = 6
-VERMIC = 28
+VERMIC = 29
 VER = $(VERMAJ).$(VERMIN).$(VERMIC)
 NAME = libpng
 PACKAGE = $(NAME)-$(VER)
diff --git a/scripts/makefile.linux b/scripts/makefile.linux
index ccb866a..c6450bb 100644
--- a/scripts/makefile.linux
+++ b/scripts/makefile.linux
@@ -10,7 +10,7 @@
 # Library name:
 LIBNAME = libpng16
 PNGMAJ = 16
-RELEASE = 28
+RELEASE = 29
 
 # Shared library names:
 LIBSO=$(LIBNAME).so
diff --git a/scripts/makefile.msys b/scripts/makefile.msys
index 72c31c1..4df88f9 100644
--- a/scripts/makefile.msys
+++ b/scripts/makefile.msys
@@ -18,7 +18,7 @@
 # Library name:
 LIBNAME = libpng16
 PNGMAJ = 16
-RELEASE = 28
+RELEASE = 29
 
 # Shared library names:
 LIBSO=$(LIBNAME).dll
diff --git a/scripts/makefile.ne12bsd b/scripts/makefile.ne12bsd
index 4fddc77..fd4e485 100644
--- a/scripts/makefile.ne12bsd
+++ b/scripts/makefile.ne12bsd
@@ -17,7 +17,7 @@
 
 LIB=	png16
 SHLIB_MAJOR=	0
-SHLIB_MINOR=	1.6.28
+SHLIB_MINOR=	1.6.29
 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 4688b62..210c8b6 100644
--- a/scripts/makefile.netbsd
+++ b/scripts/makefile.netbsd
@@ -17,7 +17,7 @@
 
 LIB=	png
 SHLIB_MAJOR=	16
-SHLIB_MINOR=	1.6.28
+SHLIB_MINOR=	1.6.29
 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 ba9def3..4f3d582 100644
--- a/scripts/makefile.openbsd
+++ b/scripts/makefile.openbsd
@@ -11,7 +11,7 @@
 MANDIR= ${PREFIX}/man/cat
 
 SHLIB_MAJOR=	16
-SHLIB_MINOR=	1.6.28
+SHLIB_MINOR=	1.6.29
 
 LIB=	png
 SRCS=	png.c pngerror.c pngget.c pngmem.c pngpread.c \
diff --git a/scripts/pnglibconf.dfa b/scripts/pnglibconf.dfa
index 019c06d..9df2a43 100644
--- a/scripts/pnglibconf.dfa
+++ b/scripts/pnglibconf.dfa
@@ -229,6 +229,33 @@
 option ARM_NEON_CHECK disabled requires ALIGNED_MEMORY,
    sets ARM_NEON_OPT 1
 
+# These options are specific to the PowerPC VSX hardware optimizations.
+#
+# POWERPC_VSX_OPT: unset: check at compile time (__PPC64__,__ALTIVEC__,__VSX__
+#                      must be defined by the compiler, typically as a result
+#                      of specifying
+#                      "-mvsx -maltivec" compiler flags)
+#                   0: disable (even if the CPU supports VSX.)
+#                   1: check at run time (via POWERPC_VSX_{API,CHECK})
+#                   2: switch on unconditionally (inadvisable - instead pass
+#                      -mvsx -maltivec to compiler options)
+#           When building libpng avoid using any setting other than '0'; '1' is
+#           set automatically when either 'API' or 'CHECK' are configured in,
+#           '2' should not be necessary as "-mvsx -maltivec" will achieve the same
+#           effect as well as applying VSX optimizations to the rest of the
+#           libpng code.
+# POWERPC_VSX_API:   (PNG_POWERPC_VSX == 1) allow the optimization to be switched on
+#                 with png_set_option
+# POWERPC_VSX_CHECK: (PNG_POWERPC_VSX == 1) compile a run-time check to see if VSX
+#                 extensions are supported. This is supported not for all OSes
+#                 (see contrib/powerpc/README)
+setting POWERPC_VSX_OPT
+option POWERPC_VSX_API disabled enables SET_OPTION,
+  sets POWERPC_VSX_OPT 1
+option POWERPC_VSX_CHECK disabled,
+  sets POWERPC_VSX_OPT 1
+
+
 # These settings configure the default compression level (0-9) and 'strategy';
 # strategy is as defined by the implementors of zlib. It describes the input
 # data and modifies the zlib parameters in an attempt to optimize the balance
diff --git a/scripts/pnglibconf.h.prebuilt b/scripts/pnglibconf.h.prebuilt
index ee70573..82f6ba4 100644
--- a/scripts/pnglibconf.h.prebuilt
+++ b/scripts/pnglibconf.h.prebuilt
@@ -1,8 +1,8 @@
-/* libpng 1.6.28 STANDARD API DEFINITION */
+/* libpng 1.6.29 STANDARD API DEFINITION */
 
 /* pnglibconf.h - library build configuration */
 
-/* Libpng version 1.6.28 - January 5, 2017 */
+/* Libpng version 1.6.29 - March 16, 2017 */
 
 /* Copyright (c) 1998-2015 Glenn Randers-Pehrson */
 
@@ -20,6 +20,8 @@
 #define PNG_ALIGNED_MEMORY_SUPPORTED
 /*#undef PNG_ARM_NEON_API_SUPPORTED*/
 /*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
+/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
+/*#undef PNG_POWERPC_VSX_CHECK_SUPPORTED*/
 #define PNG_BENIGN_ERRORS_SUPPORTED
 #define PNG_BENIGN_READ_ERRORS_SUPPORTED
 /*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
diff --git a/scripts/symbols.def b/scripts/symbols.def
index 4ebe7d0..6c8eebf 100644
--- a/scripts/symbols.def
+++ b/scripts/symbols.def
@@ -1,4 +1,4 @@
-;Version 1.6.28
+;Version 1.6.29
 ;--------------------------------------------------------------
 ; LIBPNG symbol list as a Win32 DEF file
 ; Contains all the symbols that can be exported from libpng