summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthestig <thestig@chromium.org>2016-08-03 16:29:18 -0700
committerCommit bot <commit-bot@chromium.org>2016-08-03 16:29:18 -0700
commit6d5c56b44d1821a715f4496668373ac6d1f1d3c6 (patch)
tree8eea2b264c779be6c35ddaa33f1496dd73300167
parent96a07863120273c8b89cba0e7d53ef29ae56d580 (diff)
downloadpdfium-6d5c56b44d1821a715f4496668373ac6d1f1d3c6.tar.xz
Update libpng to 1.6.22.
Sync up with Chromium's copy of libpng. Review-Url: https://codereview.chromium.org/2132263002
-rw-r--r--build_overrides/build.gni5
-rw-r--r--third_party/BUILD.gn26
-rw-r--r--third_party/libpng16/0001-disable-arm-neon.patch12
-rw-r--r--third_party/libpng16/README.pdfium11
-rw-r--r--third_party/libpng16/arm/arm_init.c135
-rw-r--r--third_party/libpng16/arm/filter_neon.S253
-rw-r--r--third_party/libpng16/arm/filter_neon_intrinsics.c387
-rw-r--r--third_party/libpng16/contrib/intel/INSTALL158
-rw-r--r--third_party/libpng16/contrib/intel/filter_sse2_intrinsics.c379
-rw-r--r--third_party/libpng16/contrib/intel/intel_init.c54
-rw-r--r--third_party/libpng16/contrib/intel/intel_sse.patch164
-rw-r--r--third_party/libpng16/png.c13
-rw-r--r--third_party/libpng16/png.h253
-rw-r--r--third_party/libpng16/pngconf.h4
-rw-r--r--third_party/libpng16/pngdebug.h2
-rw-r--r--third_party/libpng16/pngerror.c4
-rw-r--r--third_party/libpng16/pngget.c16
-rw-r--r--third_party/libpng16/pnginfo.h2
-rw-r--r--third_party/libpng16/pngmem.c2
-rw-r--r--third_party/libpng16/pngpread.c12
-rw-r--r--third_party/libpng16/pngpriv.h60
-rw-r--r--third_party/libpng16/pngread.c150
-rw-r--r--third_party/libpng16/pngrio.c2
-rw-r--r--third_party/libpng16/pngrtran.c15
-rw-r--r--third_party/libpng16/pngrutil.c4
-rw-r--r--third_party/libpng16/pngset.c97
-rw-r--r--third_party/libpng16/pngstruct.h2
-rw-r--r--third_party/libpng16/pngtrans.c2
-rw-r--r--third_party/libpng16/pngwio.c2
-rw-r--r--third_party/libpng16/pngwrite.c173
-rw-r--r--third_party/libpng16/pngwtran.c2
-rw-r--r--third_party/libpng16/pngwutil.c237
-rw-r--r--third_party/third_party.gyp30
33 files changed, 2363 insertions, 305 deletions
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
index 1c0b53fe19..c172f9cc8d 100644
--- a/build_overrides/build.gni
+++ b/build_overrides/build.gni
@@ -20,3 +20,8 @@ default_android_ndk_version = "r11c"
# Some non-Chromium builds don't support building java targets.
enable_java_templates = false
+
+# Whether to use the neon FPU instruction set or not.
+if (current_cpu == "arm" ) {
+ arm_use_neon = true
+}
diff --git a/third_party/BUILD.gn b/third_party/BUILD.gn
index 03f11c1cf9..9a80d5f6b6 100644
--- a/third_party/BUILD.gn
+++ b/third_party/BUILD.gn
@@ -2,6 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build_overrides/build.gni")
import("../pdfium.gni")
group("third_party") {
@@ -338,6 +339,31 @@ static_library("fx_lpng") {
"libpng16/pngwtran.c",
"libpng16/pngwutil.c",
]
+
+ defines = []
+ cflags = []
+
+ if (current_cpu == "x86" || current_cpu == "x64") {
+ sources += [
+ "libpng16/contrib/intel/filter_sse2_intrinsics.c",
+ "libpng16/contrib/intel/intel_init.c",
+ ]
+ defines += [ "PNG_INTEL_SSE_OPT=1" ]
+ } else if ((current_cpu == "arm" || current_cpu == "arm64") && arm_use_neon) {
+ sources += [
+ "libpng16/arm/arm_init.c",
+ "libpng16/arm/filter_neon_intrinsics.c",
+ ]
+ defines += [
+ "PNG_ARM_NEON_OPT=2",
+ "PNG_ARM_NEON_IMPLEMENTATION=1",
+ ]
+ }
+
+ if (is_win) {
+ # Unary minus applied to unsigned type.
+ cflags += [ "/wd4146" ]
+ }
}
if (pdf_enable_xfa) {
diff --git a/third_party/libpng16/0001-disable-arm-neon.patch b/third_party/libpng16/0001-disable-arm-neon.patch
deleted file mode 100644
index 91616bbf84..0000000000
--- a/third_party/libpng16/0001-disable-arm-neon.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff a/third_party/libpng16/pngpriv.h b/third_party/libpng16/pngpriv.h
---- a/third_party/libpng16/pngpriv.h
-+++ b/third_party/libpng16/pngpriv.h
-@@ -127,7 +127,7 @@
- */
- # if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && \
- defined(PNG_ALIGNED_MEMORY_SUPPORTED)
--# define PNG_ARM_NEON_OPT 2
-+# define PNG_ARM_NEON_OPT 0
- # else
- # define PNG_ARM_NEON_OPT 0
- # endif
diff --git a/third_party/libpng16/README.pdfium b/third_party/libpng16/README.pdfium
index b0e6805537..733867b782 100644
--- a/third_party/libpng16/README.pdfium
+++ b/third_party/libpng16/README.pdfium
@@ -1,16 +1,19 @@
Name: libpng
-URL: http://www.libpng.org/pub/png/libpng.html
-Version: 1.6.20
+URL: http://libpng.org/
+Version: 1.6.22
Security Critical: yes
License: libpng license
+License Android Compatible: yes
Description:
PNG library.
Local Modifications:
+Local changes in Chromium's copy of libpng as of https://crrev.com/404379 - see
+README.chromium.
+
pnglibconf.h: a copy of libpng's scripts/pnglibconf.h.prebuilt.
-pngprefix.h: manually-created redefinitions to avoid conflicts with chome.
+pngprefix.h: manually-created redefinitions to avoid conflicts with Chromium.
0000-build-config.patch: Local build configuration changes.
-0001-disable-arm-neon.diff: Disable ARM NEON optimizations.
0002-static-png-gt.patch: Unconditionally use static png_gt() in png.c to avoid compilation warning.
diff --git a/third_party/libpng16/arm/arm_init.c b/third_party/libpng16/arm/arm_init.c
new file mode 100644
index 0000000000..02df812e77
--- /dev/null
+++ b/third_party/libpng16/arm/arm_init.c
@@ -0,0 +1,135 @@
+
+/* arm_init.c - NEON optimised filter functions
+ *
+ * Copyright (c) 2014,2016 Glenn Randers-Pehrson
+ * Written by Mans Rullgard, 2011.
+ * Last changed in libpng 1.6.22 [May 26, 2016]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
+ * called.
+ */
+#define _POSIX_SOURCE 1
+
+#include "../pngpriv.h"
+
+#ifdef PNG_READ_SUPPORTED
+
+#if PNG_ARM_NEON_OPT > 0
+#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */
+/* WARNING: it is strongly recommended that you do not build libpng with
+ * run-time checks for CPU features if at all possible. In the case of the ARM
+ * NEON instructions there is no processor-specific way of detecting the
+ * presence of the required support, therefore run-time detection is extremely
+ * OS specific.
+ *
+ * You may set the macro PNG_ARM_NEON_FILE to the file name of file containing
+ * a fragment of C source code which defines the png_have_neon function. There
+ * are a number of implementations in contrib/arm-neon, but the only one that
+ * has partial support is contrib/arm-neon/linux.c - a generic Linux
+ * implementation which reads /proc/cpufino.
+ */
+#ifndef PNG_ARM_NEON_FILE
+# ifdef __linux__
+# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
+# endif
+#endif
+
+#ifdef PNG_ARM_NEON_FILE
+
+#include <signal.h> /* for sig_atomic_t */
+static int png_have_neon(png_structp png_ptr);
+#include PNG_ARM_NEON_FILE
+
+#else /* PNG_ARM_NEON_FILE */
+# error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks"
+#endif /* PNG_ARM_NEON_FILE */
+#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
+
+#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
+# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
+#endif
+
+void
+png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
+{
+ /* The switch statement is compiled in for ARM_NEON_API, the call to
+ * png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined
+ * the check is only performed if the API has not set the NEON option on
+ * or off explicitly. In this case the check controls what happens.
+ *
+ * If the CHECK is not compiled in and the option is UNSET the behavior prior
+ * to 1.6.7 was to use the NEON code - this was a bug caused by having the
+ * wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF,
+ * as documented in png.h
+ */
+ png_debug(1, "in png_init_filter_functions_neon");
+#ifdef PNG_ARM_NEON_API_SUPPORTED
+ switch ((pp->options >> PNG_ARM_NEON) & 3)
+ {
+ case PNG_OPTION_UNSET:
+ /* Allow the run-time check to execute if it has been enabled -
+ * thus both API and CHECK can be turned on. If it isn't supported
+ * this case will fall through to the 'default' below, which just
+ * returns.
+ */
+#endif /* PNG_ARM_NEON_API_SUPPORTED */
+#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
+ {
+ static volatile sig_atomic_t no_neon = -1; /* not checked */
+
+ if (no_neon < 0)
+ no_neon = !png_have_neon(pp);
+
+ if (no_neon)
+ return;
+ }
+#ifdef PNG_ARM_NEON_API_SUPPORTED
+ break;
+#endif
+#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
+
+#ifdef PNG_ARM_NEON_API_SUPPORTED
+ default: /* OFF or INVALID */
+ return;
+
+ case PNG_OPTION_ON:
+ /* Option turned on */
+ break;
+ }
+#endif
+
+ /* IMPORTANT: any new external functions used here must be declared using
+ * PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
+ * 'prefix' option to configure works:
+ *
+ * ./configure --with-libpng-prefix=foobar_
+ *
+ * Verify you have got this right by running the above command, doing a build
+ * and examining pngprefix.h; it must contain a #define for every external
+ * function you add. (Notice that this happens automatically for the
+ * initialization function.)
+ */
+ pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
+
+ if (bpp == 3)
+ {
+ pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
+ pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
+ pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
+ png_read_filter_row_paeth3_neon;
+ }
+
+ else if (bpp == 4)
+ {
+ pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
+ pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
+ pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
+ png_read_filter_row_paeth4_neon;
+ }
+}
+#endif /* PNG_ARM_NEON_OPT > 0 */
+#endif /* READ */
diff --git a/third_party/libpng16/arm/filter_neon.S b/third_party/libpng16/arm/filter_neon.S
new file mode 100644
index 0000000000..3b061d6bbf
--- /dev/null
+++ b/third_party/libpng16/arm/filter_neon.S
@@ -0,0 +1,253 @@
+
+/* filter_neon.S - NEON optimised filter functions
+ *
+ * Copyright (c) 2014 Glenn Randers-Pehrson
+ * Written by Mans Rullgard, 2011.
+ * Last changed in libpng 1.6.16 [December 22, 2014]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+/* This is required to get the symbol renames, which are #defines, and the
+ * definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
+ */
+#define PNG_VERSION_INFO_ONLY
+#include "../pngpriv.h"
+
+#if defined(__linux__) && defined(__ELF__)
+.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
+#endif
+
+#ifdef PNG_READ_SUPPORTED
+
+/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for
+ * ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it
+ * only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h
+ * for the logic which sets PNG_USE_ARM_NEON_ASM:
+ */
+#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */
+
+#if PNG_ARM_NEON_OPT > 0
+
+#ifdef __ELF__
+# define ELF
+#else
+# define ELF @
+#endif
+
+ .arch armv7-a
+ .fpu neon
+
+.macro func name, export=0
+ .macro endfunc
+ELF .size \name, . - \name
+ .endfunc
+ .purgem endfunc
+ .endm
+ .text
+
+ /* Explicitly specifying alignment here because some versions of
+ * GAS don't align code correctly. This is harmless in correctly
+ * written versions of GAS.
+ */
+ .align 2
+
+ .if \export
+ .global \name
+ .endif
+ELF .type \name, STT_FUNC
+ .func \name
+\name:
+.endm
+
+func png_read_filter_row_sub4_neon, export=1
+ ldr r3, [r0, #4] @ rowbytes
+ vmov.i8 d3, #0
+1:
+ vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
+ vadd.u8 d0, d3, d4
+ vadd.u8 d1, d0, d5
+ vadd.u8 d2, d1, d6
+ vadd.u8 d3, d2, d7
+ vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
+ subs r3, r3, #16
+ bgt 1b
+
+ bx lr
+endfunc
+
+func png_read_filter_row_sub3_neon, export=1
+ ldr r3, [r0, #4] @ rowbytes
+ vmov.i8 d3, #0
+ mov r0, r1
+ mov r2, #3
+ mov r12, #12
+ vld1.8 {q11}, [r0], r12
+1:
+ vext.8 d5, d22, d23, #3
+ vadd.u8 d0, d3, d22
+ vext.8 d6, d22, d23, #6
+ vadd.u8 d1, d0, d5
+ vext.8 d7, d23, d23, #1
+ vld1.8 {q11}, [r0], r12
+ vst1.32 {d0[0]}, [r1,:32], r2
+ vadd.u8 d2, d1, d6
+ vst1.32 {d1[0]}, [r1], r2
+ vadd.u8 d3, d2, d7
+ vst1.32 {d2[0]}, [r1], r2
+ vst1.32 {d3[0]}, [r1], r2
+ subs r3, r3, #12
+ bgt 1b
+
+ bx lr
+endfunc
+
+func png_read_filter_row_up_neon, export=1
+ ldr r3, [r0, #4] @ rowbytes
+1:
+ vld1.8 {q0}, [r1,:128]
+ vld1.8 {q1}, [r2,:128]!
+ vadd.u8 q0, q0, q1
+ vst1.8 {q0}, [r1,:128]!
+ subs r3, r3, #16
+ bgt 1b
+
+ bx lr
+endfunc
+
+func png_read_filter_row_avg4_neon, export=1
+ ldr r12, [r0, #4] @ rowbytes
+ vmov.i8 d3, #0
+1:
+ vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
+ vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
+ vhadd.u8 d0, d3, d16
+ vadd.u8 d0, d0, d4
+ vhadd.u8 d1, d0, d17
+ vadd.u8 d1, d1, d5
+ vhadd.u8 d2, d1, d18
+ vadd.u8 d2, d2, d6
+ vhadd.u8 d3, d2, d19
+ vadd.u8 d3, d3, d7
+ vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
+ subs r12, r12, #16
+ bgt 1b
+
+ bx lr
+endfunc
+
+func png_read_filter_row_avg3_neon, export=1
+ push {r4,lr}
+ ldr r12, [r0, #4] @ rowbytes
+ vmov.i8 d3, #0
+ mov r0, r1
+ mov r4, #3
+ mov lr, #12
+ vld1.8 {q11}, [r0], lr
+1:
+ vld1.8 {q10}, [r2], lr
+ vext.8 d5, d22, d23, #3
+ vhadd.u8 d0, d3, d20
+ vext.8 d17, d20, d21, #3
+ vadd.u8 d0, d0, d22
+ vext.8 d6, d22, d23, #6
+ vhadd.u8 d1, d0, d17
+ vext.8 d18, d20, d21, #6
+ vadd.u8 d1, d1, d5
+ vext.8 d7, d23, d23, #1
+ vld1.8 {q11}, [r0], lr
+ vst1.32 {d0[0]}, [r1,:32], r4
+ vhadd.u8 d2, d1, d18
+ vst1.32 {d1[0]}, [r1], r4
+ vext.8 d19, d21, d21, #1
+ vadd.u8 d2, d2, d6
+ vhadd.u8 d3, d2, d19
+ vst1.32 {d2[0]}, [r1], r4
+ vadd.u8 d3, d3, d7
+ vst1.32 {d3[0]}, [r1], r4
+ subs r12, r12, #12
+ bgt 1b
+
+ pop {r4,pc}
+endfunc
+
+.macro paeth rx, ra, rb, rc
+ vaddl.u8 q12, \ra, \rb @ a + b
+ vaddl.u8 q15, \rc, \rc @ 2*c
+ vabdl.u8 q13, \rb, \rc @ pa
+ vabdl.u8 q14, \ra, \rc @ pb
+ vabd.u16 q15, q12, q15 @ pc
+ vcle.u16 q12, q13, q14 @ pa <= pb
+ vcle.u16 q13, q13, q15 @ pa <= pc
+ vcle.u16 q14, q14, q15 @ pb <= pc
+ vand q12, q12, q13 @ pa <= pb && pa <= pc
+ vmovn.u16 d28, q14
+ vmovn.u16 \rx, q12
+ vbsl d28, \rb, \rc
+ vbsl \rx, \ra, d28
+.endm
+
+func png_read_filter_row_paeth4_neon, export=1
+ ldr r12, [r0, #4] @ rowbytes
+ vmov.i8 d3, #0
+ vmov.i8 d20, #0
+1:
+ vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
+ vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
+ paeth d0, d3, d16, d20
+ vadd.u8 d0, d0, d4
+ paeth d1, d0, d17, d16
+ vadd.u8 d1, d1, d5
+ paeth d2, d1, d18, d17
+ vadd.u8 d2, d2, d6
+ paeth d3, d2, d19, d18
+ vmov d20, d19
+ vadd.u8 d3, d3, d7
+ vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
+ subs r12, r12, #16
+ bgt 1b
+
+ bx lr
+endfunc
+
+func png_read_filter_row_paeth3_neon, export=1
+ push {r4,lr}
+ ldr r12, [r0, #4] @ rowbytes
+ vmov.i8 d3, #0
+ vmov.i8 d4, #0
+ mov r0, r1
+ mov r4, #3
+ mov lr, #12
+ vld1.8 {q11}, [r0], lr
+1:
+ vld1.8 {q10}, [r2], lr
+ paeth d0, d3, d20, d4
+ vext.8 d5, d22, d23, #3
+ vadd.u8 d0, d0, d22
+ vext.8 d17, d20, d21, #3
+ paeth d1, d0, d17, d20
+ vst1.32 {d0[0]}, [r1,:32], r4
+ vext.8 d6, d22, d23, #6
+ vadd.u8 d1, d1, d5
+ vext.8 d18, d20, d21, #6
+ paeth d2, d1, d18, d17
+ vext.8 d7, d23, d23, #1
+ vld1.8 {q11}, [r0], lr
+ vst1.32 {d1[0]}, [r1], r4
+ vadd.u8 d2, d2, d6
+ vext.8 d19, d21, d21, #1
+ paeth d3, d2, d19, d18
+ vst1.32 {d2[0]}, [r1], r4
+ vmov d4, d19
+ vadd.u8 d3, d3, d7
+ vst1.32 {d3[0]}, [r1], r4
+ subs r12, r12, #12
+ bgt 1b
+
+ pop {r4,pc}
+endfunc
+#endif /* PNG_ARM_NEON_OPT > 0 */
+#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */
+#endif /* READ */
diff --git a/third_party/libpng16/arm/filter_neon_intrinsics.c b/third_party/libpng16/arm/filter_neon_intrinsics.c
new file mode 100644
index 0000000000..ea7e356bcc
--- /dev/null
+++ b/third_party/libpng16/arm/filter_neon_intrinsics.c
@@ -0,0 +1,387 @@
+
+/* filter_neon_intrinsics.c - NEON optimised filter functions
+ *
+ * Copyright (c) 2014,2016 Glenn Randers-Pehrson
+ * Written by James Yu <james.yu at linaro.org>, October 2013.
+ * Based on filter_neon.S, written by Mans Rullgard, 2011.
+ *
+ * Last changed in libpng 1.6.22 [May 26, 2016]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#include "../pngpriv.h"
+
+#ifdef PNG_READ_SUPPORTED
+
+/* This code requires -mfpu=neon on the command line: */
+#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
+
+#include <arm_neon.h>
+
+/* libpng row pointers are not necessarily aligned to any particular boundary,
+ * however this code will only work with appropriate alignment. arm/arm_init.c
+ * checks for this (and will not compile unless it is done). This code uses
+ * variants of png_aligncast to avoid compiler warnings.
+ */
+#define png_ptr(type,pointer) png_aligncast(type *,pointer)
+#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
+
+/* The following relies on a variable 'temp_pointer' being declared with type
+ * 'type'. This is written this way just to hide the GCC strict aliasing
+ * warning; note that the code is safe because there never is an alias between
+ * the input and output pointers.
+ */
+#define png_ldr(type,pointer)\
+ (temp_pointer = png_ptr(type,pointer), *temp_pointer)
+
+#if PNG_ARM_NEON_OPT > 0
+
+void
+png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ png_bytep rp = row;
+ png_bytep rp_stop = row + row_info->rowbytes;
+ png_const_bytep pp = prev_row;
+
+ png_debug(1, "in png_read_filter_row_up_neon");
+
+ for (; rp < rp_stop; rp += 16, pp += 16)
+ {
+ uint8x16_t qrp, qpp;
+
+ qrp = vld1q_u8(rp);
+ qpp = vld1q_u8(pp);
+ qrp = vaddq_u8(qrp, qpp);
+ vst1q_u8(rp, qrp);
+ }
+}
+
+void
+png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ png_bytep rp = row;
+ png_bytep rp_stop = row + row_info->rowbytes;
+
+ uint8x16_t vtmp = vld1q_u8(rp);
+ uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp);
+ uint8x8x2_t vrp = *vrpt;
+
+ uint8x8x4_t vdest;
+ vdest.val[3] = vdup_n_u8(0);
+
+ png_debug(1, "in png_read_filter_row_sub3_neon");
+
+ for (; rp < rp_stop;)
+ {
+ uint8x8_t vtmp1, vtmp2;
+ uint32x2_t *temp_pointer;
+
+ vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
+ vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
+ vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6);
+ vdest.val[1] = vadd_u8(vdest.val[0], vtmp1);
+
+ vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
+ vdest.val[2] = vadd_u8(vdest.val[1], vtmp2);
+ vdest.val[3] = vadd_u8(vdest.val[2], vtmp1);
+
+ vtmp = vld1q_u8(rp + 12);
+ vrpt = png_ptr(uint8x8x2_t, &vtmp);
+ vrp = *vrpt;
+
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
+ rp += 3;
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
+ rp += 3;
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
+ rp += 3;
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
+ rp += 3;
+ }
+
+ PNG_UNUSED(prev_row)
+}
+
+void
+png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ png_bytep rp = row;
+ png_bytep rp_stop = row + row_info->rowbytes;
+
+ uint8x8x4_t vdest;
+ vdest.val[3] = vdup_n_u8(0);
+
+ png_debug(1, "in png_read_filter_row_sub4_neon");
+
+ for (; rp < rp_stop; rp += 16)
+ {
+ uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp));
+ uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
+ uint8x8x4_t vrp = *vrpt;
+ uint32x2x4_t *temp_pointer;
+
+ vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
+ vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
+ vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
+ vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
+ vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
+ }
+
+ PNG_UNUSED(prev_row)
+}
+
+void
+png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ png_bytep rp = row;
+ png_const_bytep pp = prev_row;
+ png_bytep rp_stop = row + row_info->rowbytes;
+
+ uint8x16_t vtmp;
+ uint8x8x2_t *vrpt;
+ uint8x8x2_t vrp;
+ uint8x8x4_t vdest;
+ vdest.val[3] = vdup_n_u8(0);
+
+ vtmp = vld1q_u8(rp);
+ vrpt = png_ptr(uint8x8x2_t,&vtmp);
+ vrp = *vrpt;
+
+ png_debug(1, "in png_read_filter_row_avg3_neon");
+
+ for (; rp < rp_stop; pp += 12)
+ {
+ uint8x8_t vtmp1, vtmp2, vtmp3;
+
+ uint8x8x2_t *vppt;
+ uint8x8x2_t vpp;
+
+ uint32x2_t *temp_pointer;
+
+ vtmp = vld1q_u8(pp);
+ vppt = png_ptr(uint8x8x2_t,&vtmp);
+ vpp = *vppt;
+
+ vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
+ vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
+ vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
+
+ vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
+ vtmp3 = vext_u8(vrp.val[0], vrp.val[1], 6);
+ vdest.val[1] = vhadd_u8(vdest.val[0], vtmp2);
+ vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
+
+ vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 6);
+ vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
+
+ vtmp = vld1q_u8(rp + 12);
+ vrpt = png_ptr(uint8x8x2_t,&vtmp);
+ vrp = *vrpt;
+
+ vdest.val[2] = vhadd_u8(vdest.val[1], vtmp2);
+ vdest.val[2] = vadd_u8(vdest.val[2], vtmp3);
+
+ vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
+
+ vdest.val[3] = vhadd_u8(vdest.val[2], vtmp2);
+ vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
+
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
+ rp += 3;
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
+ rp += 3;
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
+ rp += 3;
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
+ rp += 3;
+ }
+}
+
+void
+png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ png_bytep rp = row;
+ png_bytep rp_stop = row + row_info->rowbytes;
+ png_const_bytep pp = prev_row;
+
+ uint8x8x4_t vdest;
+ vdest.val[3] = vdup_n_u8(0);
+
+ png_debug(1, "in png_read_filter_row_avg4_neon");
+
+ for (; rp < rp_stop; rp += 16, pp += 16)
+ {
+ uint32x2x4_t vtmp;
+ uint8x8x4_t *vrpt, *vppt;
+ uint8x8x4_t vrp, vpp;
+ uint32x2x4_t *temp_pointer;
+
+ vtmp = vld4_u32(png_ptr(uint32_t,rp));
+ vrpt = png_ptr(uint8x8x4_t,&vtmp);
+ vrp = *vrpt;
+ vtmp = vld4_u32(png_ptrc(uint32_t,pp));
+ vppt = png_ptr(uint8x8x4_t,&vtmp);
+ vpp = *vppt;
+
+ vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
+ vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
+ vdest.val[1] = vhadd_u8(vdest.val[0], vpp.val[1]);
+ vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
+ vdest.val[2] = vhadd_u8(vdest.val[1], vpp.val[2]);
+ vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
+ vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
+ vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
+
+ vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
+ }
+}
+
+static uint8x8_t
+paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
+{
+ uint8x8_t d, e;
+ uint16x8_t p1, pa, pb, pc;
+
+ p1 = vaddl_u8(a, b); /* a + b */
+ pc = vaddl_u8(c, c); /* c * 2 */
+ pa = vabdl_u8(b, c); /* pa */
+ pb = vabdl_u8(a, c); /* pb */
+ pc = vabdq_u16(p1, pc); /* pc */
+
+ p1 = vcleq_u16(pa, pb); /* pa <= pb */
+ pa = vcleq_u16(pa, pc); /* pa <= pc */
+ pb = vcleq_u16(pb, pc); /* pb <= pc */
+
+ p1 = vandq_u16(p1, pa); /* pa <= pb && pa <= pc */
+
+ d = vmovn_u16(pb);
+ e = vmovn_u16(p1);
+
+ d = vbsl_u8(d, b, c);
+ e = vbsl_u8(e, a, d);
+
+ return e;
+}
+
+void
+png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ png_bytep rp = row;
+ png_const_bytep pp = prev_row;
+ png_bytep rp_stop = row + row_info->rowbytes;
+
+ uint8x16_t vtmp;
+ uint8x8x2_t *vrpt;
+ uint8x8x2_t vrp;
+ uint8x8_t vlast = vdup_n_u8(0);
+ uint8x8x4_t vdest;
+ vdest.val[3] = vdup_n_u8(0);
+
+ vtmp = vld1q_u8(rp);
+ vrpt = png_ptr(uint8x8x2_t,&vtmp);
+ vrp = *vrpt;
+
+ png_debug(1, "in png_read_filter_row_paeth3_neon");
+
+ for (; rp < rp_stop; pp += 12)
+ {
+ uint8x8x2_t *vppt;
+ uint8x8x2_t vpp;
+ uint8x8_t vtmp1, vtmp2, vtmp3;
+ uint32x2_t *temp_pointer;
+
+ vtmp = vld1q_u8(pp);
+ vppt = png_ptr(uint8x8x2_t,&vtmp);
+ vpp = *vppt;
+
+ vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
+ vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
+
+ vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
+ vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
+ vdest.val[1] = paeth(vdest.val[0], vtmp2, vpp.val[0]);
+ vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
+
+ vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 6);
+ vtmp3 = vext_u8(vpp.val[0], vpp.val[1], 6);
+ vdest.val[2] = paeth(vdest.val[1], vtmp3, vtmp2);
+ vdest.val[2] = vadd_u8(vdest.val[2], vtmp1);
+
+ vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
+ vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
+
+ vtmp = vld1q_u8(rp + 12);
+ vrpt = png_ptr(uint8x8x2_t,&vtmp);
+ vrp = *vrpt;
+
+ vdest.val[3] = paeth(vdest.val[2], vtmp2, vtmp3);
+ vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
+
+ vlast = vtmp2;
+
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
+ rp += 3;
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
+ rp += 3;
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
+ rp += 3;
+ vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
+ rp += 3;
+ }
+}
+
+void
+png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev_row)
+{
+ png_bytep rp = row;
+ png_bytep rp_stop = row + row_info->rowbytes;
+ png_const_bytep pp = prev_row;
+
+ uint8x8_t vlast = vdup_n_u8(0);
+ uint8x8x4_t vdest;
+ vdest.val[3] = vdup_n_u8(0);
+
+ png_debug(1, "in png_read_filter_row_paeth4_neon");
+
+ for (; rp < rp_stop; rp += 16, pp += 16)
+ {
+ uint32x2x4_t vtmp;
+ uint8x8x4_t *vrpt, *vppt;
+ uint8x8x4_t vrp, vpp;
+ uint32x2x4_t *temp_pointer;
+
+ vtmp = vld4_u32(png_ptr(uint32_t,rp));
+ vrpt = png_ptr(uint8x8x4_t,&vtmp);
+ vrp = *vrpt;
+ vtmp = vld4_u32(png_ptrc(uint32_t,pp));
+ vppt = png_ptr(uint8x8x4_t,&vtmp);
+ vpp = *vppt;
+
+ vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
+ vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
+ vdest.val[1] = paeth(vdest.val[0], vpp.val[1], vpp.val[0]);
+ vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
+ vdest.val[2] = paeth(vdest.val[1], vpp.val[2], vpp.val[1]);
+ vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
+ vdest.val[3] = paeth(vdest.val[2], vpp.val[3], vpp.val[2]);
+ vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
+
+ vlast = vpp.val[3];
+
+ vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
+ }
+}
+
+#endif /* PNG_ARM_NEON_OPT > 0 */
+#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */
+#endif /* READ */
diff --git a/third_party/libpng16/contrib/intel/INSTALL b/third_party/libpng16/contrib/intel/INSTALL
new file mode 100644
index 0000000000..cd5cdd94eb
--- /dev/null
+++ b/third_party/libpng16/contrib/intel/INSTALL
@@ -0,0 +1,158 @@
+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/third_party/libpng16/contrib/intel/filter_sse2_intrinsics.c b/third_party/libpng16/contrib/intel/filter_sse2_intrinsics.c
new file mode 100644
index 0000000000..aea3f86af5
--- /dev/null
+++ b/third_party/libpng16/contrib/intel/filter_sse2_intrinsics.c
@@ -0,0 +1,379 @@
+
+/* filter_sse2_intrinsics.c - SSE2 optimized filter functions
+ *
+ * Copyright (c) 2016 Google, Inc.
+ * Written by Mike Klein and Matt Sarett
+ * Derived from arm/filter_neon_intrinsics.c, which was
+ * Copyright (c) 2014,2016 Glenn Randers-Pehrson
+ *
+ * Last changed in libpng 1.6.22 [May 26, 2016]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#include "../../pngpriv.h"
+
+#ifdef PNG_READ_SUPPORTED
+
+#if PNG_INTEL_SSE_IMPLEMENTATION > 0
+
+#include <immintrin.h>
+
+/* Functions in this file look at most 3 pixels (a,b,c) to predict the 4th (d).
+ * They're positioned like this:
+ * prev: c b
+ * row: a d
+ * The Sub filter predicts d=a, Avg d=(a+b)/2, and Paeth predicts d to be
+ * whichever of a, b, or c is closest to p=a+b-c.
+ */
+
+static __m128i load4(const void* p) {
+ return _mm_cvtsi32_si128(*(const int*)p);
+}
+
+static void store4(void* p, __m128i v) {
+ *(int*)p = _mm_cvtsi128_si32(v);
+}
+
+static __m128i load3(const void* p) {
+ /* We'll load 2 bytes, then 1 byte,
+ * then mask them together, and finally load into SSE.
+ */
+ const png_uint_16* p01 = p;
+ const png_byte* p2 = (const png_byte*)(p01+1);
+
+ png_uint_32 v012 = (png_uint_32)(*p01)
+ | (png_uint_32)(*p2) << 16;
+ return load4(&v012);
+}
+
+static void store3(void* p, __m128i v) {
+ /* We'll pull from SSE as a 32-bit int, then write
+ * its bottom two bytes, then its third byte.
+ */
+ png_uint_32 v012;
+ store4(&v012, v);
+
+ png_uint_16* p01 = p;
+ png_byte* p2 = (png_byte*)(p01+1);
+ *p01 = v012;
+ *p2 = v012 >> 16;
+}
+
+void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev)
+{
+ /* The Sub filter predicts each pixel as the previous pixel, a.
+ * There is no pixel to the left of the first pixel. It's encoded directly.
+ * That works with our main loop if we just say that left pixel was zero.
+ */
+ png_debug(1, "in png_read_filter_row_sub3_sse2");
+ __m128i a, d = _mm_setzero_si128();
+
+ int rb = row_info->rowbytes;
+ while (rb >= 4) {
+ a = d; d = load4(row);
+ d = _mm_add_epi8(d, a);
+ store3(row, d);
+
+ row += 3;
+ rb -= 3;
+ }
+ if (rb > 0) {
+ a = d; d = load3(row);
+ d = _mm_add_epi8(d, a);
+ store3(row, d);
+
+ row += 3;
+ rb -= 3;
+ }
+}
+
+void png_read_filter_row_sub4_sse2(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev)
+{
+ /* The Sub filter predicts each pixel as the previous pixel, a.
+ * There is no pixel to the left of the first pixel. It's encoded directly.
+ * That works with our main loop if we just say that left pixel was zero.
+ */
+ png_debug(1, "in png_read_filter_row_sub4_sse2");
+ __m128i a, d = _mm_setzero_si128();
+
+ int rb = row_info->rowbytes;
+ while (rb > 0) {
+ a = d; d = load4(row);
+ d = _mm_add_epi8(d, a);
+ store4(row, d);
+
+ row += 4;
+ rb -= 4;
+ }
+}
+
+void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev)
+{
+ /* The Avg filter predicts each pixel as the (truncated) average of a and b.
+ * There's no pixel to the left of the first pixel. Luckily, it's
+ * predicted to be half of the pixel above it. So again, this works
+ * perfectly with our loop if we make sure a starts at zero.
+ */
+ png_debug(1, "in png_read_filter_row_avg3_sse2");
+ const __m128i zero = _mm_setzero_si128();
+ __m128i b;
+ __m128i a, d = zero;
+
+ int rb = row_info->rowbytes;
+ while (rb >= 4) {
+ b = load4(prev);
+ a = d; d = load4(row );
+
+ /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
+ __m128i avg = _mm_avg_epu8(a,b);
+ /* ...but we can fix it up by subtracting off 1 if it rounded up. */
+ avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
+ _mm_set1_epi8(1)));
+ d = _mm_add_epi8(d, avg);
+ store3(row, d);
+
+ prev += 3;
+ row += 3;
+ rb -= 3;
+ }
+ if (rb > 0) {
+ b = load3(prev);
+ a = d; d = load3(row );
+
+ /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
+ __m128i avg = _mm_avg_epu8(a,b);
+ /* ...but we can fix it up by subtracting off 1 if it rounded up. */
+ avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
+ _mm_set1_epi8(1)));
+
+ d = _mm_add_epi8(d, avg);
+ store3(row, d);
+
+ prev += 3;
+ row += 3;
+ rb -= 3;
+ }
+}
+
+void png_read_filter_row_avg4_sse2(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev)
+{
+ /* The Avg filter predicts each pixel as the (truncated) average of a and b.
+ * There's no pixel to the left of the first pixel. Luckily, it's
+ * predicted to be half of the pixel above it. So again, this works
+ * perfectly with our loop if we make sure a starts at zero.
+ */
+ png_debug(1, "in png_read_filter_row_avg4_sse2");
+ const __m128i zero = _mm_setzero_si128();
+ __m128i b;
+ __m128i a, d = zero;
+
+ int rb = row_info->rowbytes;
+ while (rb > 0) {
+ b = load4(prev);
+ a = d; d = load4(row );
+
+ /* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
+ __m128i avg = _mm_avg_epu8(a,b);
+ /* ...but we can fix it up by subtracting off 1 if it rounded up. */
+ avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
+ _mm_set1_epi8(1)));
+
+ d = _mm_add_epi8(d, avg);
+ store4(row, d);
+
+ prev += 4;
+ row += 4;
+ rb -= 4;
+ }
+}
+
+/* Returns |x| for 16-bit lanes. */
+static __m128i abs_i16(__m128i x) {
+#if PNG_INTEL_SSE_IMPLEMENTATION >= 2
+ return _mm_abs_epi16(x);
+#else
+ /* Read this all as, return x<0 ? -x : x.
+ * To negate two's complement, you flip all the bits then add 1.
+ */
+ __m128i is_negative = _mm_cmplt_epi16(x, _mm_setzero_si128());
+
+ /* Flip negative lanes. */
+ x = _mm_xor_si128(x, is_negative);
+
+ /* +1 to negative lanes, else +0. */
+ x = _mm_add_epi16(x, _mm_srli_epi16(is_negative, 15));
+ return x;
+#endif
+}
+
+/* Bytewise c ? t : e. */
+static __m128i if_then_else(__m128i c, __m128i t, __m128i e) {
+#if PNG_INTEL_SSE_IMPLEMENTATION >= 3
+ return _mm_blendv_epi8(e,t,c);
+#else
+ return _mm_or_si128(_mm_and_si128(c, t), _mm_andnot_si128(c, e));
+#endif
+}
+
+void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev)
+{
+ /* Paeth tries to predict pixel d using the pixel to the left of it, a,
+ * and two pixels from the previous row, b and c:
+ * prev: c b
+ * row: a d
+ * The Paeth function predicts d to be whichever of a, b, or c is nearest to
+ * p=a+b-c.
+ *
+ * The first pixel has no left context, and so uses an Up filter, p = b.
+ * This works naturally with our main loop's p = a+b-c if we force a and c
+ * to zero.
+ * Here we zero b and d, which become c and a respectively at the start of
+ * the loop.
+ */
+ png_debug(1, "in png_read_filter_row_paeth3_sse2");
+ const __m128i zero = _mm_setzero_si128();
+ __m128i c, b = zero,
+ a, d = zero;
+
+ int rb = row_info->rowbytes;
+ while (rb >= 4) {
+ /* It's easiest to do this math (particularly, deal with pc) with 16-bit
+ * intermediates.
+ */
+ c = b; b = _mm_unpacklo_epi8(load4(prev), zero);
+ a = d; d = _mm_unpacklo_epi8(load4(row ), zero);
+
+ /* (p-a) == (a+b-c - a) == (b-c) */
+ __m128i pa = _mm_sub_epi16(b,c);
+
+ /* (p-b) == (a+b-c - b) == (a-c) */
+ __m128i pb = _mm_sub_epi16(a,c);
+
+ /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
+ __m128i pc = _mm_add_epi16(pa,pb);
+
+ pa = abs_i16(pa); /* |p-a| */
+ pb = abs_i16(pb); /* |p-b| */
+ pc = abs_i16(pc); /* |p-c| */
+
+ __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
+
+ /* Paeth breaks ties favoring a over b over c. */
+ __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
+ if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
+ c));
+
+ /* Note `_epi8`: we need addition to wrap modulo 255. */
+ d = _mm_add_epi8(d, nearest);
+ store3(row, _mm_packus_epi16(d,d));
+
+ prev += 3;
+ row += 3;
+ rb -= 3;
+ }
+ if (rb > 0) {
+ /* It's easiest to do this math (particularly, deal with pc) with 16-bit
+ * intermediates.
+ */
+ c = b; b = _mm_unpacklo_epi8(load3(prev), zero);
+ a = d; d = _mm_unpacklo_epi8(load3(row ), zero);
+
+ /* (p-a) == (a+b-c - a) == (b-c) */
+ __m128i pa = _mm_sub_epi16(b,c);
+
+ /* (p-b) == (a+b-c - b) == (a-c) */
+ __m128i pb = _mm_sub_epi16(a,c);
+
+ /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
+ __m128i pc = _mm_add_epi16(pa,pb);
+
+ pa = abs_i16(pa); /* |p-a| */
+ pb = abs_i16(pb); /* |p-b| */
+ pc = abs_i16(pc); /* |p-c| */
+
+ __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
+
+ /* Paeth breaks ties favoring a over b over c. */
+ __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
+ if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
+ c));
+
+ /* Note `_epi8`: we need addition to wrap modulo 255. */
+ d = _mm_add_epi8(d, nearest);
+ store3(row, _mm_packus_epi16(d,d));
+
+ prev += 3;
+ row += 3;
+ rb -= 3;
+ }
+}
+
+void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row,
+ png_const_bytep prev)
+{
+ /* Paeth tries to predict pixel d using the pixel to the left of it, a,
+ * and two pixels from the previous row, b and c:
+ * prev: c b
+ * row: a d
+ * The Paeth function predicts d to be whichever of a, b, or c is nearest to
+ * p=a+b-c.
+ *
+ * The first pixel has no left context, and so uses an Up filter, p = b.
+ * This works naturally with our main loop's p = a+b-c if we force a and c
+ * to zero.
+ * Here we zero b and d, which become c and a respectively at the start of
+ * the loop.
+ */
+ png_debug(1, "in png_read_filter_row_paeth4_sse2");
+ const __m128i zero = _mm_setzero_si128();
+ __m128i c, b = zero,
+ a, d = zero;
+
+ int rb = row_info->rowbytes;
+ while (rb > 0) {
+ /* It's easiest to do this math (particularly, deal with pc) with 16-bit
+ * intermediates.
+ */
+ c = b; b = _mm_unpacklo_epi8(load4(prev), zero);
+ a = d; d = _mm_unpacklo_epi8(load4(row ), zero);
+
+ /* (p-a) == (a+b-c - a) == (b-c) */
+ __m128i pa = _mm_sub_epi16(b,c);
+
+ /* (p-b) == (a+b-c - b) == (a-c) */
+ __m128i pb = _mm_sub_epi16(a,c);
+
+ /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
+ __m128i pc = _mm_add_epi16(pa,pb);
+
+ pa = abs_i16(pa); /* |p-a| */
+ pb = abs_i16(pb); /* |p-b| */
+ pc = abs_i16(pc); /* |p-c| */
+
+ __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
+
+ /* Paeth breaks ties favoring a over b over c. */
+ __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
+ if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
+ c));
+
+ /* Note `_epi8`: we need addition to wrap modulo 255. */
+ d = _mm_add_epi8(d, nearest);
+ store4(row, _mm_packus_epi16(d,d));
+
+ prev += 4;
+ row += 4;
+ rb -= 4;
+ }
+}
+
+#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */
+#endif /* READ */
diff --git a/third_party/libpng16/contrib/intel/intel_init.c b/third_party/libpng16/contrib/intel/intel_init.c
new file mode 100644
index 0000000000..328e90e9af
--- /dev/null
+++ b/third_party/libpng16/contrib/intel/intel_init.c
@@ -0,0 +1,54 @@
+
+/* 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
+ *
+ * Last changed in libpng 1.6.22 [May 26, 2016]
+ *
+ * This code is released under the libpng license.
+ * For conditions of distribution and use, see the disclaimer
+ * and license in png.h
+ */
+
+#include "../../pngpriv.h"
+
+#ifdef PNG_READ_SUPPORTED
+#if PNG_INTEL_SSE_IMPLEMENTATION > 0
+
+void
+png_init_filter_functions_sse2(png_structp pp, unsigned int bpp)
+{
+ /* The techniques used to implement each of these filters in SSE operate on
+ * one pixel at a time.
+ * So they generally speed up 3bpp images about 3x, 4bpp images about 4x.
+ * They can scale up to 6 and 8 bpp images and down to 2 bpp images,
+ * but they'd not likely have any benefit for 1bpp images.
+ * Most of these can be implemented using only MMX and 64-bit registers,
+ * but they end up a bit slower than using the equally-ubiquitous SSE2.
+ */
+ png_debug(1, "in png_init_filter_functions_sse2");
+ if (bpp == 3)
+ {
+ pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_sse2;
+ pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_sse2;
+ pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
+ png_read_filter_row_paeth3_sse2;
+ }
+ else if (bpp == 4)
+ {
+ pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_sse2;
+ pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_sse2;
+ pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
+ png_read_filter_row_paeth4_sse2;
+ }
+
+ /* No need optimize PNG_FILTER_VALUE_UP. The compiler should
+ * autovectorize.
+ */
+}
+
+#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */
+#endif /* PNG_READ_SUPPORTED */
diff --git a/third_party/libpng16/contrib/intel/intel_sse.patch b/third_party/libpng16/contrib/intel/intel_sse.patch
new file mode 100644
index 0000000000..d9d02bb8fc
--- /dev/null
+++ b/third_party/libpng16/contrib/intel/intel_sse.patch
@@ -0,0 +1,164 @@
+diff --git libpng-1.6.22-orig/configure.ac libpng-1.6.22/configure.ac
+--- libpng-1.6.22-orig/configure.ac 2016-05-25 18:59:10.000000000 -0400
++++ libpng-1.6.22/configure.ac 2016-05-25 19:48:10.631751170 -0400
+@@ -341,16 +341,50 @@ AC_ARG_ENABLE([arm-neon],
+
+ AM_CONDITIONAL([PNG_ARM_NEON],
+ [test "$enable_arm_neon" != 'no' &&
+ case "$host_cpu" in
+ arm*|aarch64*) :;;
+ *) test "$enable_arm_neon" != '';;
+ 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 libpng-1.6.22-orig/Makefile.am libpng-1.6.22/Makefile.am
+--- libpng-1.6.22-orig/Makefile.am 2016-05-17 18:15:12.000000000 -0400
++++ libpng-1.6.22/Makefile.am 2016-05-25 19:48:10.631751170 -0400
+@@ -89,16 +89,20 @@ libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SO
+ pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\
+ png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h pngusr.dfa
+
+ if PNG_ARM_NEON
+ libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += arm/arm_init.c\
+ arm/filter_neon.S arm/filter_neon_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 libpng-1.6.22-orig/pngpriv.h libpng-1.6.22/pngpriv.h
+--- libpng-1.6.22-orig/pngpriv.h 2016-05-25 18:59:10.000000000 -0400
++++ libpng-1.6.22/pngpriv.h 2016-05-25 19:48:10.635751171 -0400
+@@ -177,16 +177,52 @@
+ # endif /* !PNG_ARM_NEON_IMPLEMENTATION */
+
+ # ifndef PNG_ARM_NEON_IMPLEMENTATION
+ /* Use the intrinsics code by default. */
+ # define PNG_ARM_NEON_IMPLEMENTATION 1
+ # endif
+ #endif /* PNG_ARM_NEON_OPT > 0 */
+
++#ifndef PNG_INTEL_SSE_OPT
++# ifdef PNG_INTEL_SSE
++ /* Only check for SSE if the build configuration has been modified to
++ * enable SSE optimizations. This means that these optimizations will
++ * be off by default. See contrib/intel for more details.
++ */
++# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
++ defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
++ (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
++# define PNG_INTEL_SSE_OPT 1
++# endif
++# endif
++#endif
++
++#if PNG_INTEL_SSE_OPT > 0
++# ifndef PNG_INTEL_SSE_IMPLEMENTATION
++# if defined(__SSE4_1__) || defined(__AVX__)
++ /* We are not actually using AVX, but checking for AVX is the best
++ way we can detect SSE4.1 and SSSE3 on MSVC.
++ */
++# define PNG_INTEL_SSE_IMPLEMENTATION 3
++# elif defined(__SSSE3__)
++# define PNG_INTEL_SSE_IMPLEMENTATION 2
++# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
++ (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
++# define PNG_INTEL_SSE_IMPLEMENTATION 1
++# else
++# define PNG_INTEL_SSE_IMPLEMENTATION 0
++# endif
++# endif
++
++# if PNG_INTEL_SSE_IMPLEMENTATION > 0
++# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2
++# endif
++#endif
++
+ /* Is this a build of a DLL where compilation of the object modules requires
+ * different preprocessor settings to those required for a simple library? If
+ * so PNG_BUILD_DLL must be set.
+ *
+ * If libpng is used inside a DLL but that DLL does not export the libpng APIs
+ * PNG_BUILD_DLL must not be set. To avoid the code below kicking in build a
+ * static library of libpng then link the DLL against that.
+ */
+@@ -1184,16 +1220,29 @@ PNG_INTERNAL_FUNCTION(void,png_read_filt
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+
++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop
++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop
++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop
++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop
++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop
++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
++PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
++ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
++
+ /* Choose the best filter to use and filter the row data */
+ PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
+ png_row_infop row_info),PNG_EMPTY);
+
+ #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
diff --git a/third_party/libpng16/png.c b/third_party/libpng16/png.c
index 1cf5271046..35e14f63d8 100644
--- a/third_party/libpng16/png.c
+++ b/third_party/libpng16/png.c
@@ -2,7 +2,7 @@
/* png.c - location for general purpose libpng functions
*
* Last changed in libpng 1.6.19 [November 12, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -14,7 +14,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_6_20 Your_png_h_is_not_version_1_6_20;
+typedef png_libpng_version_1_6_22 Your_png_h_is_not_version_1_6_22;
/* Tells libpng that we have already handled the first "num_bytes" bytes
* of the PNG file signature. If the PNG data is embedded into another
@@ -775,14 +775,15 @@ png_get_copyright(png_const_structrp png_ptr)
#else
# ifdef __STDC__
return PNG_STRING_NEWLINE \
- "libpng version 1.6.20 - December 3, 2015" PNG_STRING_NEWLINE \
- "Copyright (c) 1998-2015 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+ "libpng version 1.6.22 - May 26, 2016" PNG_STRING_NEWLINE \
+ "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \
+ PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
PNG_STRING_NEWLINE;
# else
- return "libpng version 1.6.20 - December 3, 2015\
- Copyright (c) 1998-2015 Glenn Randers-Pehrson\
+ return "libpng version 1.6.22 - May 26, 2016\
+ Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\
Copyright (c) 1996-1997 Andreas Dilger\
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
# endif
diff --git a/third_party/libpng16/png.h b/third_party/libpng16/png.h
index 4d03dfc136..08c039df0b 100644
--- a/third_party/libpng16/png.h
+++ b/third_party/libpng16/png.h
@@ -1,9 +1,9 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.6.20, December 3, 2015
+ * libpng version 1.6.22, May 26, 2016
*
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -12,7 +12,7 @@
* Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
- * libpng versions 0.97, January 1998, through 1.6.20, December 3, 2015:
+ * libpng versions 0.97, January 1998, through 1.6.22, May 26, 2016:
* Glenn Randers-Pehrson.
* See also "Contributing Authors", below.
*/
@@ -25,8 +25,12 @@
*
* This code is released under the libpng license.
*
- * libpng versions 1.0.7, July 1, 2000, through 1.6.20, December 3, 2015, are
- * Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are
+ * Some files in the "contrib" directory and some configure-generated
+ * files that are distributed with libpng have other copyright owners and
+ * are released under other open source licenses.
+ *
+ * libpng versions 1.0.7, July 1, 2000 through 1.6.22, May 26, 2016 are
+ * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are
* derived from libpng-1.0.6, and are distributed according to the same
* disclaimer and license as libpng-1.0.6 with the following individuals
* added to the list of Contributing Authors:
@@ -47,6 +51,10 @@
* risk of satisfactory quality, performance, accuracy, and effort is with
* the user.
*
+ * Some files in the "contrib" directory have other copyright owners and
+ * are released under other open source licenses.
+ *
+ *
* libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
* Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
* libpng-0.96, and are distributed according to the same disclaimer and
@@ -57,6 +65,9 @@
* Glenn Randers-Pehrson
* Willem van Schaik
*
+ * Some files in the "scripts" directory have different copyright owners
+ * but are also released under this license.
+ *
* libpng versions 0.89, June 1996, through 0.96, May 1997, are
* Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88,
* and are distributed according to the same disclaimer and license as
@@ -70,6 +81,9 @@
* Greg Roelofs
* Tom Tanner
*
+ * Some files in the "scripts" directory have other copyright owners
+ * but are released under this license.
+ *
* libpng versions 0.5, May 1995, through 0.88, January 1996, are
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
*
@@ -109,6 +123,29 @@
* appreciated.
*
* END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
+ *
+ * TRADEMARK:
+ *
+ * The name "libpng" has not been registered by the Copyright owner
+ * as a trademark in any jurisdiction. However, because libpng has
+ * been distributed and maintained world-wide, continually since 1995,
+ * the Copyright owner claims "common-law trademark protection" in any
+ * jurisdiction where common-law trademark is recognized.
+ *
+ * OSI CERTIFICATION:
+ *
+ * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
+ * a certification mark of the Open Source Initiative. OSI has not addressed
+ * the additional disclaimers inserted at version 1.0.7.
+ *
+ * EXPORT CONTROL:
+ *
+ * The Copyright owner believes that the Export Control Classification
+ * Number (ECCN) for libpng is EAR99, which means not subject to export
+ * controls or International Traffic in Arms Regulations (ITAR) because
+ * it is open source, publicly available software, that does not contain
+ * any encryption software. See the EAR, paragraphs 734.3(b)(3) and
+ * 734.7(b).
*/
/*
@@ -122,12 +159,6 @@
*/
/*
- * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
- * a certification mark of the Open Source Initiative. OSI has not addressed
- * the additional disclaimers inserted at version 1.0.7.
- */
-
-/*
* The contributing authors would like to thank all those who helped
* with testing, bug fixes, and patience. This wouldn't have been
* possible without all of you.
@@ -182,11 +213,11 @@
* ...
* 1.0.19 10 10019 10.so.0.19[.0]
* ...
- * 1.2.53 13 10253 12.so.0.53[.0]
+ * 1.2.56 13 10256 12.so.0.56[.0]
* ...
- * 1.5.23 15 10523 15.so.15.23[.0]
+ * 1.5.27 15 10527 15.so.15.27[.0]
* ...
- * 1.6.20 16 10620 16.so.16.20[.0]
+ * 1.6.22 16 10622 16.so.16.22[.0]
*
* Henceforth the source version will match the shared-library major
* and minor numbers; the shared-library major version number will be
@@ -214,13 +245,13 @@
* Y2K compliance in libpng:
* =========================
*
- * December 3, 2015
+ * May 26, 2016
*
* Since the PNG Development group is an ad-hoc body, we can't make
* an official declaration.
*
* This is your unofficial assurance that libpng from version 0.71 and
- * upward through 1.6.20 are Y2K compliant. It is my belief that
+ * upward through 1.6.22 are Y2K compliant. It is my belief that
* earlier versions were also Y2K compliant.
*
* Libpng only has two year fields. One is a 2-byte unsigned integer
@@ -282,9 +313,9 @@
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.6.20"
+#define PNG_LIBPNG_VER_STRING "1.6.22"
#define PNG_HEADER_VERSION_STRING \
- " libpng version 1.6.20 - December 3, 2015\n"
+ " libpng version 1.6.22 - May 26, 2016\n"
#define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16
@@ -292,7 +323,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 20
+#define PNG_LIBPNG_VER_RELEASE 22
/* This should match the numeric part of the final component of
* PNG_LIBPNG_VER_STRING, omitting any leading zero:
@@ -323,7 +354,7 @@
* version 1.0.0 was mis-numbered 100 instead of 10000). From
* version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
*/
-#define PNG_LIBPNG_VER 10620 /* 1.6.20 */
+#define PNG_LIBPNG_VER 10622 /* 1.6.22 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -433,7 +464,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_6_20;
+typedef char* png_libpng_version_1_6_22;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
@@ -734,24 +765,22 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
* data in the info_struct to be written into the output file. The values
* of the PNG_INFO_<chunk> defines should NOT be changed.
*/
-#define PNG_INFO_gAMA 0x0001
-#define PNG_INFO_sBIT 0x0002
-#define PNG_INFO_cHRM 0x0004
-#define PNG_INFO_PLTE 0x0008
-#define PNG_INFO_tRNS 0x0010
-#define PNG_INFO_bKGD 0x0020
-#define PNG_INFO_hIST 0x0040
-#define PNG_INFO_pHYs 0x0080
-#define PNG_INFO_oFFs 0x0100
-#define PNG_INFO_tIME 0x0200
-#define PNG_INFO_pCAL 0x0400
-#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */
-#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */
-#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */
-#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */
-#if INT_MAX >= 0x8000 /* else this might break */
-#define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */
-#endif
+#define PNG_INFO_gAMA 0x0001U
+#define PNG_INFO_sBIT 0x0002U
+#define PNG_INFO_cHRM 0x0004U
+#define PNG_INFO_PLTE 0x0008U
+#define PNG_INFO_tRNS 0x0010U
+#define PNG_INFO_bKGD 0x0020U
+#define PNG_INFO_hIST 0x0040U
+#define PNG_INFO_pHYs 0x0080U
+#define PNG_INFO_oFFs 0x0100U
+#define PNG_INFO_tIME 0x0200U
+#define PNG_INFO_pCAL 0x0400U
+#define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */
+#define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */
+#define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */
+#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */
+#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */
/* This is used for the transformation routines, as some of them
* change these values for the row. It also should enable using
@@ -1322,7 +1351,7 @@ PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */
+#define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */
/* Strip the second byte of information from a 16-bit depth file. */
PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr));
#endif
@@ -1473,8 +1502,8 @@ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
#define PNG_FILTER_UP 0x20
#define PNG_FILTER_AVG 0x40
#define PNG_FILTER_PAETH 0x80
-#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \
- PNG_FILTER_AVG | PNG_FILTER_PAETH)
+#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP)
+#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH)
/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
* These defines should NOT be changed.
@@ -1751,21 +1780,21 @@ PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
#define PNG_SET_WILL_FREE_DATA 1
#define PNG_USER_WILL_FREE_DATA 2
/* Flags for png_ptr->free_me and info_ptr->free_me */
-#define PNG_FREE_HIST 0x0008
-#define PNG_FREE_ICCP 0x0010
-#define PNG_FREE_SPLT 0x0020
-#define PNG_FREE_ROWS 0x0040
-#define PNG_FREE_PCAL 0x0080
-#define PNG_FREE_SCAL 0x0100
+#define PNG_FREE_HIST 0x0008U
+#define PNG_FREE_ICCP 0x0010U
+#define PNG_FREE_SPLT 0x0020U
+#define PNG_FREE_ROWS 0x0040U
+#define PNG_FREE_PCAL 0x0080U
+#define PNG_FREE_SCAL 0x0100U
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
-# define PNG_FREE_UNKN 0x0200
+# define PNG_FREE_UNKN 0x0200U
#endif
-/* PNG_FREE_LIST 0x0400 removed in 1.6.0 because it is ignored */
-#define PNG_FREE_PLTE 0x1000
-#define PNG_FREE_TRNS 0x2000
-#define PNG_FREE_TEXT 0x4000
-#define PNG_FREE_ALL 0x7fff
-#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
+/* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */
+#define PNG_FREE_PLTE 0x1000U
+#define PNG_FREE_TRNS 0x2000U
+#define PNG_FREE_TEXT 0x4000U
+#define PNG_FREE_ALL 0x7fffU
+#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
#ifdef PNG_USER_MEM_SUPPORTED
PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr,
@@ -2889,12 +2918,19 @@ typedef struct
* is the minimum 'row stride', the minimum count of components between each
* row. For a color-mapped image this is the minimum number of bytes in a
* row.
+ *
+ * WARNING: this macro overflows for some images with more than one component
+ * and very large image widths. libpng will refuse to process an image where
+ * this macro would overflow.
*/
#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
(PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
/* Return the size, in bytes, of an image buffer given a png_image and a row
* stride - the number of components to leave space for in each row.
+ *
+ * WARNING: this macro overflows a 32-bit integer for some large PNG images,
+ * libpng will refuse to process an image where such an overflow would occur.
*/
#define PNG_IMAGE_SIZE(image)\
@@ -3015,7 +3051,6 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image));
#endif /* SIMPLIFIED_READ */
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
-#ifdef PNG_STDIO_SUPPORTED
/* WRITE APIS
* ----------
* For write you must initialize a png_image structure to describe the image to
@@ -3032,6 +3067,7 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image));
* values do not correspond to the colors in sRGB.
* colormap_entries: set to the number of entries in the color-map (0 to 256)
*/
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
const char *file, int convert_to_8bit, const void *buffer,
png_int_32 row_stride, const void *colormap));
@@ -3041,8 +3077,9 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
const void *colormap));
/* Write the image to the given (FILE*). */
+#endif /* SIMPLIFIED_WRITE_STDIO */
-/* With both write APIs if image is in one of the linear formats with 16-bit
+/* With all write APIs if image is in one of the linear formats with 16-bit
* data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
* gamma encoded according to the sRGB specification, otherwise a 16-bit linear
* encoded PNG file is written.
@@ -3054,13 +3091,103 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
*
* With all APIs row_stride is handled as in the read APIs - it is the spacing
* from one row to the next in component sized units (1 or 2 bytes) and if
- * negative indicates a bottom-up row layout in the buffer. If row_stride is zero,
- * libpng will calculate it for you from the image width and number of channels.
+ * negative indicates a bottom-up row layout in the buffer. If row_stride is
+ * zero, libpng will calculate it for you from the image width and number of
+ * channels.
*
- * Note that the write API does not support interlacing, sub-8-bit pixels, indexed
- * PNG (color_type 3) or most ancillary chunks.
+ * Note that the write API does not support interlacing, sub-8-bit pixels or
+ * most ancillary chunks. If you need to write text chunks (e.g. for copyright
+ * notices) you need to use one of the other APIs.
*/
-#endif /* STDIO */
+
+PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
+ png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit,
+ const void *buffer, png_int_32 row_stride, const void *colormap));
+ /* Write the image to the given memory buffer. The function both writes the
+ * whole PNG data stream to *memory and updates *memory_bytes with the count
+ * of bytes written.
+ *
+ * 'memory' may be NULL. In this case *memory_bytes is not read however on
+ * success the number of bytes which would have been written will still be
+ * stored in *memory_bytes. On failure *memory_bytes will contain 0.
+ *
+ * If 'memory' is not NULL it must point to memory[*memory_bytes] of
+ * writeable memory.
+ *
+ * If the function returns success memory[*memory_bytes] (if 'memory' is not
+ * NULL) contains the written PNG data. *memory_bytes will always be less
+ * than or equal to the original value.
+ *
+ * If the function returns false and *memory_bytes was not changed an error
+ * occured during write. If *memory_bytes was changed, or is not 0 if
+ * 'memory' was NULL, the write would have succeeded but for the memory
+ * buffer being too small. *memory_bytes contains the required number of
+ * bytes and will be bigger that the original value.
+ */
+
+#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\
+ row_stride, colormap)\
+ png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\
+ row_stride, colormap)
+ /* Return the amount of memory in 'size' required to compress this image.
+ * The png_image structure 'image' must be filled in as in the above
+ * function and must not be changed before the actual write call, the buffer
+ * and all other parameters must also be identical to that in the final
+ * write call. The 'size' variable need not be initialized.
+ *
+ * NOTE: the macro returns true/false, if false is returned 'size' will be
+ * set to zero and the write failed and probably will fail if tried again.
+ */
+
+/* You can pre-allocate the buffer by making sure it is of sufficient size
+ * regardless of the amount of compression achieved. The buffer size will
+ * always be bigger than the original image and it will never be filled. The
+ * following macros are provided to assist in allocating the buffer.
+ */
+#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height)
+ /* The number of uncompressed bytes in the PNG byte encoding of the image;
+ * uncompressing the PNG IDAT data will give this number of bytes.
+ *
+ * NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this
+ * macro can because of the extra bytes used in the PNG byte encoding. You
+ * need to avoid this macro if your image size approaches 2^30 in width or
+ * height. The same goes for the remainder of these macros; they all produce
+ * bigger numbers than the actual in-memory image size.
+ */
+#ifndef PNG_ZLIB_MAX_SIZE
+# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U)
+ /* An upper bound on the number of compressed bytes given 'b' uncompressed
+ * bytes. This is based on deflateBounds() in zlib; different
+ * implementations of zlib compression may conceivably produce more data so
+ * if your zlib implementation is not zlib itself redefine this macro
+ * appropriately.
+ */
+#endif
+
+#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\
+ PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image))
+ /* An upper bound on the size of the data in the PNG IDAT chunks. */
+
+#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\
+ ((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\
+ (((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\
+ 12U+3U*(image).colormap_entries/*PLTE data*/+\
+ (((image).format&PNG_FORMAT_FLAG_ALPHA)?\
+ 12U/*tRNS*/+(image).colormap_entries:0U):0U)+\
+ 12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size))
+ /* A helper for the following macro; if your compiler cannot handle the
+ * following macro use this one with the result of
+ * PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most
+ * compilers should handle this just fine.)
+ */
+
+#define PNG_IMAGE_PNG_SIZE_MAX(image)\
+ PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image))
+ /* An upper bound on the total length of the PNG data stream for 'image'.
+ * The result is of type png_alloc_size_t, on 32-bit systems this may
+ * overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will
+ * run out of buffer space but return a corrected size which should work.
+ */
#endif /* SIMPLIFIED_WRITE */
/*******************************************************************************
* END OF SIMPLIFIED API
@@ -3118,7 +3245,7 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
* one to use is one more than this.)
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
- PNG_EXPORT_LAST_ORDINAL(244);
+ PNG_EXPORT_LAST_ORDINAL(245);
#endif
#ifdef __cplusplus
diff --git a/third_party/libpng16/pngconf.h b/third_party/libpng16/pngconf.h
index 92f250000c..0cabe4b385 100644
--- a/third_party/libpng16/pngconf.h
+++ b/third_party/libpng16/pngconf.h
@@ -1,9 +1,9 @@
/* pngconf.h - machine configurable file for libpng
*
- * libpng version 1.6.20, December 3, 2015
+ * libpng version 1.6.22, May 26, 2016
*
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
diff --git a/third_party/libpng16/pngdebug.h b/third_party/libpng16/pngdebug.h
index 6a01b106ed..15a7ed0c95 100644
--- a/third_party/libpng16/pngdebug.h
+++ b/third_party/libpng16/pngdebug.h
@@ -2,7 +2,7 @@
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
*
* Last changed in libpng 1.6.8 [December 19, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
diff --git a/third_party/libpng16/pngerror.c b/third_party/libpng16/pngerror.c
index bdb959ee51..3fc8092fa6 100644
--- a/third_party/libpng16/pngerror.c
+++ b/third_party/libpng16/pngerror.c
@@ -2,7 +2,7 @@
/* pngerror.c - stub functions for i/o and memory allocation
*
* Last changed in libpng 1.6.15 [November 20, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -44,7 +44,7 @@ png_error,(png_const_structrp png_ptr, png_const_charp error_message),
if (png_ptr != NULL)
{
if ((png_ptr->flags &
- (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0
+ (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
{
if (*error_message == PNG_LITERAL_SHARP)
{
diff --git a/third_party/libpng16/pngget.c b/third_party/libpng16/pngget.c
index 743a6a9bbc..14fc7be520 100644
--- a/third_party/libpng16/pngget.c
+++ b/third_party/libpng16/pngget.c
@@ -2,7 +2,7 @@
/* pngget.c - retrieval of values from info struct
*
* Last changed in libpng 1.6.17 [March 26, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -456,11 +456,11 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
return (retval);
}
#endif /* pHYs */
-#endif /* INCH_CONVERSIONS */
+#endif /* INCH_CONVERSIONS */
/* png_get_channels really belongs in here, too, but it's been around longer */
-#endif /* EASY_ACCESS */
+#endif /* EASY_ACCESS */
png_byte PNGAPI
@@ -1142,19 +1142,19 @@ png_get_compression_buffer_size(png_const_structrp png_ptr)
return 0;
#ifdef PNG_WRITE_SUPPORTED
- if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
#endif
{
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
- return png_ptr->IDAT_read_size;
+ return png_ptr->IDAT_read_size;
#else
- return PNG_IDAT_READ_SIZE;
+ return PNG_IDAT_READ_SIZE;
#endif
}
#ifdef PNG_WRITE_SUPPORTED
- else
- return png_ptr->zbuffer_size;
+ else
+ return png_ptr->zbuffer_size;
#endif
}
diff --git a/third_party/libpng16/pnginfo.h b/third_party/libpng16/pnginfo.h
index 4bd264b869..361ed8be70 100644
--- a/third_party/libpng16/pnginfo.h
+++ b/third_party/libpng16/pnginfo.h
@@ -2,7 +2,7 @@
/* pnginfo.h - header file for PNG reference library
*
* Last changed in libpng 1.6.1 [March 28, 2013]
- * Copyright (c) 1998-2013 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
diff --git a/third_party/libpng16/pngmem.c b/third_party/libpng16/pngmem.c
index db71219520..b5507134fb 100644
--- a/third_party/libpng16/pngmem.c
+++ b/third_party/libpng16/pngmem.c
@@ -2,7 +2,7 @@
/* pngmem.c - stub functions for memory allocation
*
* Last changed in libpng 1.6.15 [November 20, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
diff --git a/third_party/libpng16/pngpread.c b/third_party/libpng16/pngpread.c
index 89ffc4018f..a16fcbef3a 100644
--- a/third_party/libpng16/pngpread.c
+++ b/third_party/libpng16/pngpread.c
@@ -2,7 +2,7 @@
/* pngpread.c - read a png file in push mode
*
* Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -210,12 +210,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
(png_ptr->mode & PNG_HAVE_PLTE) == 0)
png_error(png_ptr, "Missing PLTE before IDAT");
- png_ptr->mode |= PNG_HAVE_IDAT;
png_ptr->process_mode = PNG_READ_IDAT_MODE;
- if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
- if (png_ptr->push_length == 0)
- return;
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+ if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
+ if (png_ptr->push_length == 0)
+ return;
+
+ png_ptr->mode |= PNG_HAVE_IDAT;
if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
png_benign_error(png_ptr, "Too many IDATs found");
diff --git a/third_party/libpng16/pngpriv.h b/third_party/libpng16/pngpriv.h
index 58d3aa8159..9ea023fea7 100644
--- a/third_party/libpng16/pngpriv.h
+++ b/third_party/libpng16/pngpriv.h
@@ -1,8 +1,8 @@
/* pngpriv.h - private declarations for use inside libpng
*
- * Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.22 [May 26, 2016]
+ * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -127,7 +127,7 @@
*/
# if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && \
defined(PNG_ALIGNED_MEMORY_SUPPORTED)
-# define PNG_ARM_NEON_OPT 0
+# define PNG_ARM_NEON_OPT 2
# else
# define PNG_ARM_NEON_OPT 0
# endif
@@ -182,6 +182,42 @@
# endif
#endif /* PNG_ARM_NEON_OPT > 0 */
+#ifndef PNG_INTEL_SSE_OPT
+# ifdef PNG_INTEL_SSE
+ /* Only check for SSE if the build configuration has been modified to
+ * enable SSE optimizations. This means that these optimizations will
+ * be off by default. See contrib/intel for more details.
+ */
+# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
+ defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
+ (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
+# define PNG_INTEL_SSE_OPT 1
+# endif
+# endif
+#endif
+
+#if PNG_INTEL_SSE_OPT > 0
+# ifndef PNG_INTEL_SSE_IMPLEMENTATION
+# if defined(__SSE4_1__) || defined(__AVX__)
+ /* We are not actually using AVX, but checking for AVX is the best
+ way we can detect SSE4.1 and SSSE3 on MSVC.
+ */
+# define PNG_INTEL_SSE_IMPLEMENTATION 3
+# elif defined(__SSSE3__)
+# define PNG_INTEL_SSE_IMPLEMENTATION 2
+# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
+ (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
+# define PNG_INTEL_SSE_IMPLEMENTATION 1
+# else
+# define PNG_INTEL_SSE_IMPLEMENTATION 0
+# endif
+# endif
+
+# if PNG_INTEL_SSE_IMPLEMENTATION > 0
+# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2
+# endif
+#endif
+
/* Is this a build of a DLL where compilation of the object modules requires
* different preprocessor settings to those required for a simple library? If
* so PNG_BUILD_DLL must be set.
@@ -1189,6 +1225,19 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+
/* Choose the best filter to use and filter the row data */
PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
png_row_infop row_info),PNG_EMPTY);
@@ -1915,8 +1964,13 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr,
*/
PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
(png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
+ (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
#endif
+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/third_party/libpng16/pngread.c b/third_party/libpng16/pngread.c
index 9cb4d2e41d..0572c208cc 100644
--- a/third_party/libpng16/pngread.c
+++ b/third_party/libpng16/pngread.c
@@ -2,7 +2,7 @@
/* pngread.c - read a PNG file
*
* Last changed in libpng 1.6.17 [March 26, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -127,7 +127,10 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
}
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+ {
+ png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
png_ptr->mode |= PNG_AFTER_IDAT;
+ }
/* This should be a binary subdivision search or a hash for
* matching the chunk name rather than a linear search.
@@ -785,6 +788,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
png_uint_32 length = png_read_chunk_header(png_ptr);
png_uint_32 chunk_name = png_ptr->chunk_name;
+ if (chunk_name != png_IDAT)
+ png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+
if (chunk_name == png_IEND)
png_handle_IEND(png_ptr, info_ptr, length);
@@ -799,9 +805,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
{
if (chunk_name == png_IDAT)
{
- if ((length > 0) ||
- (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
- png_benign_error(png_ptr, "Too many IDATs found");
+ if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
+ || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
+ png_benign_error(png_ptr, ".Too many IDATs found");
}
png_handle_unknown(png_ptr, info_ptr, length, keep);
if (chunk_name == png_PLTE)
@@ -812,10 +818,14 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
else if (chunk_name == png_IDAT)
{
/* Zero length IDATs are legal after the last IDAT has been
- * read, but not after other chunks have been read.
+ * read, but not after other chunks have been read. 1.6 does not
+ * always read all the deflate data; specifically it cannot be relied
+ * upon to read the Adler32 at the end. If it doesn't ignore IDAT
+ * chunks which are longer than zero as well:
*/
- if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
- png_benign_error(png_ptr, "Too many IDATs found");
+ if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
+ || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
+ png_benign_error(png_ptr, "..Too many IDATs found");
png_crc_finish(png_ptr, length);
}
@@ -3848,16 +3858,16 @@ png_image_read_direct(png_voidp argument)
else
filler = 255;
-# ifdef PNG_FORMAT_AFIRST_SUPPORTED
- if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
- {
- where = PNG_FILLER_BEFORE;
- change &= ~PNG_FORMAT_FLAG_AFIRST;
- }
+#ifdef PNG_FORMAT_AFIRST_SUPPORTED
+ if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ where = PNG_FILLER_BEFORE;
+ change &= ~PNG_FORMAT_FLAG_AFIRST;
+ }
- else
-# endif
- where = PNG_FILLER_AFTER;
+ else
+#endif
+ where = PNG_FILLER_AFTER;
png_set_add_alpha(png_ptr, filler, where);
}
@@ -3965,12 +3975,12 @@ png_image_read_direct(png_voidp argument)
if (info_ptr->bit_depth == 16)
info_format |= PNG_FORMAT_FLAG_LINEAR;
-# ifdef PNG_FORMAT_BGR_SUPPORTED
- if ((png_ptr->transformations & PNG_BGR) != 0)
- info_format |= PNG_FORMAT_FLAG_BGR;
-# endif
+#ifdef PNG_FORMAT_BGR_SUPPORTED
+ if ((png_ptr->transformations & PNG_BGR) != 0)
+ info_format |= PNG_FORMAT_FLAG_BGR;
+#endif
-# ifdef PNG_FORMAT_AFIRST_SUPPORTED
+#ifdef PNG_FORMAT_AFIRST_SUPPORTED
if (do_local_background == 2)
{
if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
@@ -4071,58 +4081,84 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
{
if (image != NULL && image->version == PNG_IMAGE_VERSION)
{
- png_uint_32 check;
+ /* Check for row_stride overflow. This check is not performed on the
+ * original PNG format because it may not occur in the output PNG format
+ * and libpng deals with the issues of reading the original.
+ */
+ const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
- if (row_stride == 0)
- row_stride = PNG_IMAGE_ROW_STRIDE(*image);
+ if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
+ {
+ png_uint_32 check;
+ const png_uint_32 png_row_stride = image->width * channels;
- if (row_stride < 0)
- check = -row_stride;
+ if (row_stride == 0)
+ row_stride = (png_int_32)/*SAFE*/png_row_stride;
- else
- check = row_stride;
+ if (row_stride < 0)
+ check = -row_stride;
- if (image->opaque != NULL && buffer != NULL &&
- check >= PNG_IMAGE_ROW_STRIDE(*image))
- {
- if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
- (image->colormap_entries > 0 && colormap != NULL))
+ else
+ check = row_stride;
+
+ if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
{
- int result;
- png_image_read_control display;
-
- memset(&display, 0, (sizeof display));
- display.image = image;
- display.buffer = buffer;
- display.row_stride = row_stride;
- display.colormap = colormap;
- display.background = background;
- display.local_row = NULL;
-
- /* Choose the correct 'end' routine; for the color-map case all the
- * setup has already been done.
+ /* Now check for overflow of the image buffer calculation; this
+ * limits the whole image size to 32 bits for API compatibility with
+ * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
*/
- if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
- result =
- png_safe_execute(image, png_image_read_colormap, &display) &&
- png_safe_execute(image, png_image_read_colormapped, &display);
+ if (image->height <= 0xFFFFFFFF/png_row_stride)
+ {
+ if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
+ (image->colormap_entries > 0 && colormap != NULL))
+ {
+ int result;
+ png_image_read_control display;
+
+ memset(&display, 0, (sizeof display));
+ display.image = image;
+ display.buffer = buffer;
+ display.row_stride = row_stride;
+ display.colormap = colormap;
+ display.background = background;
+ display.local_row = NULL;
+
+ /* Choose the correct 'end' routine; for the color-map case
+ * all the setup has already been done.
+ */
+ if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
+ result = png_safe_execute(image,
+ png_image_read_colormap, &display) &&
+ png_safe_execute(image,
+ png_image_read_colormapped, &display);
- else
- result =
- png_safe_execute(image, png_image_read_direct, &display);
+ else
+ result =
+ png_safe_execute(image,
+ png_image_read_direct, &display);
+
+ png_image_free(image);
+ return result;
+ }
- png_image_free(image);
- return result;
+ else
+ return png_image_error(image,
+ "png_image_finish_read[color-map]: no color-map");
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_finish_read: image too large");
}
else
return png_image_error(image,
- "png_image_finish_read[color-map]: no color-map");
+ "png_image_finish_read: invalid argument");
}
else
return png_image_error(image,
- "png_image_finish_read: invalid argument");
+ "png_image_finish_read: row_stride too large");
}
else if (image != NULL)
diff --git a/third_party/libpng16/pngrio.c b/third_party/libpng16/pngrio.c
index 38f7fd49d6..5101d54a62 100644
--- a/third_party/libpng16/pngrio.c
+++ b/third_party/libpng16/pngrio.c
@@ -2,7 +2,7 @@
/* pngrio.c - functions for data input
*
* Last changed in libpng 1.6.17 [March 26, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
diff --git a/third_party/libpng16/pngrtran.c b/third_party/libpng16/pngrtran.c
index f129ef129c..3138147aff 100644
--- a/third_party/libpng16/pngrtran.c
+++ b/third_party/libpng16/pngrtran.c
@@ -1,8 +1,8 @@
/* pngrtran.c - transforms the data in a row for PNG readers
*
- * Last changed in libpng 1.6.19 [November 12, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.22 [May 26, 2016]
+ * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -159,7 +159,7 @@ png_set_background(png_structrp png_ptr,
png_set_background_fixed(png_ptr, background_color, background_gamma_code,
need_expand, png_fixed(png_ptr, background_gamma, "png_set_background"));
}
-# endif /* FLOATING_POINT */
+# endif /* FLOATING_POINT */
#endif /* READ_BACKGROUND */
/* Scale 16-bit depth files to 8-bit depth. If both of these are set then the
@@ -289,9 +289,12 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
* is expected to be 1 or greater, but this range test allows for some
* viewing correction values. The intent is to weed out users of this API
* who use the inverse of the gamma value accidentally! Since some of these
- * values are reasonable this may have to be changed.
+ * values are reasonable this may have to be changed:
+ *
+ * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit
+ * gamma of 36, and its reciprocal.)
*/
- if (output_gamma < 70000 || output_gamma > 300000)
+ if (output_gamma < 1000 || output_gamma > 10000000)
png_error(png_ptr, "output gamma out of expected range");
/* The default file gamma is the inverse of the output gamma; the output
@@ -1912,7 +1915,7 @@ png_init_read_transformations(png_structrp png_ptr)
png_ptr->palette[i].blue = (png_byte)component;
}
}
-#endif /* READ_SHIFT */
+#endif /* READ_SHIFT */
}
/* Modify the info structure to reflect the transformations. The
diff --git a/third_party/libpng16/pngrutil.c b/third_party/libpng16/pngrutil.c
index 6189251352..c9747fc27d 100644
--- a/third_party/libpng16/pngrutil.c
+++ b/third_party/libpng16/pngrutil.c
@@ -1,8 +1,8 @@
/* pngrutil.c - utilities to read a PNG file
*
- * Last changed in libpng 1.6.20 [December 3, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.20 [December 3, 2014]
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
diff --git a/third_party/libpng16/pngset.c b/third_party/libpng16/pngset.c
index 8fd7965fca..303328f87e 100644
--- a/third_party/libpng16/pngset.c
+++ b/third_party/libpng16/pngset.c
@@ -1,7 +1,7 @@
/* pngset.c - storage of image information into info struct
*
- * Last changed in libpng 1.6.19 [November 12, 2015]
+ * Last changed in libpng 1.6.21 [January 15, 2016]
* Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
@@ -952,12 +952,15 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
- /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
- png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep,
- png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
-
if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
+ {
+ /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
+ info_ptr->trans_alpha = png_voidcast(png_bytep,
+ png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
+
memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
+ }
+ png_ptr->trans_alpha = info_ptr->trans_alpha;
}
if (trans_color != NULL)
@@ -1644,4 +1647,88 @@ png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
png_ptr->num_palette_max = -1;
}
#endif
+
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \
+ defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
+/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+ * and if invalid, correct the keyword rather than discarding the entire
+ * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
+ * length, forbids leading or trailing whitespace, multiple internal spaces,
+ * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
+ *
+ * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
+ * trailing '\0'). If this routine returns 0 then there was no keyword, or a
+ * valid one could not be generated, and the caller must png_error.
+ */
+png_uint_32 /* PRIVATE */
+png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
+{
+ png_const_charp orig_key = key;
+ png_uint_32 key_len = 0;
+ int bad_character = 0;
+ int space = 1;
+
+ png_debug(1, "in png_check_keyword");
+
+ if (key == NULL)
+ {
+ *new_key = 0;
+ return 0;
+ }
+
+ while (*key && key_len < 79)
+ {
+ png_byte ch = (png_byte)*key++;
+
+ if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
+ *new_key++ = ch, ++key_len, space = 0;
+
+ else if (space == 0)
+ {
+ /* A space or an invalid character when one wasn't seen immediately
+ * before; output just a space.
+ */
+ *new_key++ = 32, ++key_len, space = 1;
+
+ /* If the character was not a space then it is invalid. */
+ if (ch != 32)
+ bad_character = ch;
+ }
+
+ else if (bad_character == 0)
+ bad_character = ch; /* just skip it, record the first error */
+ }
+
+ if (key_len > 0 && space != 0) /* trailing space */
+ {
+ --key_len, --new_key;
+ if (bad_character == 0)
+ bad_character = 32;
+ }
+
+ /* Terminate the keyword */
+ *new_key = 0;
+
+ if (key_len == 0)
+ return 0;
+
+#ifdef PNG_WARNINGS_SUPPORTED
+ /* Try to only output one warning per keyword: */
+ if (*key != 0) /* keyword too long */
+ png_warning(png_ptr, "keyword truncated");
+
+ else if (bad_character != 0)
+ {
+ PNG_WARNING_PARAMETERS(p)
+
+ png_warning_parameter(p, 1, orig_key);
+ png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
+
+ png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
+ }
+#endif /* WARNINGS */
+
+ return key_len;
+}
+#endif /* TEXT || pCAL || iCCP || sPLT */
#endif /* READ || WRITE */
diff --git a/third_party/libpng16/pngstruct.h b/third_party/libpng16/pngstruct.h
index ad1e7a5adc..0b372de4c6 100644
--- a/third_party/libpng16/pngstruct.h
+++ b/third_party/libpng16/pngstruct.h
@@ -2,7 +2,7 @@
/* pngstruct.h - header file for PNG reference library
*
* Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
diff --git a/third_party/libpng16/pngtrans.c b/third_party/libpng16/pngtrans.c
index 0c0d92d8fd..7f8cc455d3 100644
--- a/third_party/libpng16/pngtrans.c
+++ b/third_party/libpng16/pngtrans.c
@@ -2,7 +2,7 @@
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
*
* Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
diff --git a/third_party/libpng16/pngwio.c b/third_party/libpng16/pngwio.c
index db76e6b8d7..586c03b721 100644
--- a/third_party/libpng16/pngwio.c
+++ b/third_party/libpng16/pngwio.c
@@ -2,7 +2,7 @@
/* pngwio.c - functions for data output
*
* Last changed in libpng 1.6.15 [November 20, 2014]
- * Copyright (c) 1998-2014 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
diff --git a/third_party/libpng16/pngwrite.c b/third_party/libpng16/pngwrite.c
index 0d4ee9f7ae..181a899438 100644
--- a/third_party/libpng16/pngwrite.c
+++ b/third_party/libpng16/pngwrite.c
@@ -2,7 +2,7 @@
/* pngwrite.c - general routines to write a PNG file
*
* Last changed in libpng 1.6.19 [November 12, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -12,9 +12,9 @@
*/
#include "pngpriv.h"
-#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
# include <errno.h>
-#endif
+#endif /* SIMPLIFIED_WRITE_STDIO */
#ifdef PNG_WRITE_SUPPORTED
@@ -1452,7 +1452,6 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr,
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
-# ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
/* Initialize the write structure - general purpose utility. */
static int
png_image_write_init(png_imagep image)
@@ -1504,6 +1503,10 @@ typedef struct
png_const_voidp first_row;
ptrdiff_t row_bytes;
png_voidp local_row;
+ /* Byte count for memory writing */
+ png_bytep memory;
+ png_alloc_size_t memory_bytes; /* not used for STDIO */
+ png_alloc_size_t output_bytes; /* running total */
} png_image_write_control;
/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
@@ -1931,9 +1934,43 @@ png_image_write_main(png_voidp argument)
png_set_benign_errors(png_ptr, 0/*error*/);
# endif
- /* Default the 'row_stride' parameter if required. */
- if (display->row_stride == 0)
- display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
+ /* Default the 'row_stride' parameter if required, also check the row stride
+ * and total image size to ensure that they are within the system limits.
+ */
+ {
+ const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
+
+ if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */
+ {
+ png_uint_32 check;
+ const png_uint_32 png_row_stride = image->width * channels;
+
+ if (display->row_stride == 0)
+ display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
+
+ if (display->row_stride < 0)
+ check = -display->row_stride;
+
+ else
+ check = display->row_stride;
+
+ if (check >= png_row_stride)
+ {
+ /* Now check for overflow of the image buffer calculation; this
+ * limits the whole image size to 32 bits for API compatibility with
+ * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
+ */
+ if (image->height > 0xFFFFFFFF/png_row_stride)
+ png_error(image->opaque->png_ptr, "memory image too large");
+ }
+
+ else
+ png_error(image->opaque->png_ptr, "supplied row stride too small");
+ }
+
+ else
+ png_error(image->opaque->png_ptr, "image row stride too large");
+ }
/* Set the required transforms then write the rows in the correct order. */
if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
@@ -2110,6 +2147,122 @@ png_image_write_main(png_voidp argument)
return 1;
}
+
+static void (PNGCBAPI
+image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data,
+ png_size_t size)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
+ const png_alloc_size_t ob = display->output_bytes;
+
+ /* Check for overflow; this should never happen: */
+ if (size <= ((png_alloc_size_t)-1) - ob)
+ {
+ /* I don't think libpng ever does this, but just in case: */
+ if (size > 0)
+ {
+ if (display->memory_bytes >= ob+size) /* writing */
+ memcpy(display->memory+ob, data, size);
+
+ /* Always update the size: */
+ display->output_bytes = ob+size;
+ }
+ }
+
+ else
+ png_error(png_ptr, "png_image_write_to_memory: PNG too big");
+}
+
+static void (PNGCBAPI
+image_memory_flush)(png_structp png_ptr)
+{
+ PNG_UNUSED(png_ptr)
+}
+
+static int
+png_image_write_memory(png_voidp argument)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ argument);
+
+ /* The rest of the memory-specific init and write_main in an error protected
+ * environment. This case needs to use callbacks for the write operations
+ * since libpng has no built in support for writing to memory.
+ */
+ png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/,
+ image_memory_write, image_memory_flush);
+
+ return png_image_write_main(display);
+}
+
+int PNGAPI
+png_image_write_to_memory(png_imagep image, void *memory,
+ png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
+ const void *buffer, png_int_32 row_stride, const void *colormap)
+{
+ /* Write the image to the given buffer, or count the bytes if it is NULL */
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (memory_bytes != NULL && buffer != NULL)
+ {
+ /* This is to give the caller an easier error detection in the NULL
+ * case and guard against uninitialized variable problems:
+ */
+ if (memory == NULL)
+ *memory_bytes = 0;
+
+ if (png_image_write_init(image) != 0)
+ {
+ png_image_write_control display;
+ int result;
+
+ memset(&display, 0, (sizeof display));
+ display.image = image;
+ display.buffer = buffer;
+ display.row_stride = row_stride;
+ display.colormap = colormap;
+ display.convert_to_8bit = convert_to_8bit;
+ display.memory = png_voidcast(png_bytep, memory);
+ display.memory_bytes = *memory_bytes;
+ display.output_bytes = 0;
+
+ result = png_safe_execute(image, png_image_write_memory, &display);
+ png_image_free(image);
+
+ /* write_memory returns true even if we ran out of buffer. */
+ if (result)
+ {
+ /* On out-of-buffer this function returns '0' but still updates
+ * memory_bytes:
+ */
+ if (memory != NULL && display.output_bytes > *memory_bytes)
+ result = 0;
+
+ *memory_bytes = display.output_bytes;
+ }
+
+ return result;
+ }
+
+ else
+ return 0;
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_write_to_memory: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
+
+ else
+ return 0;
+}
+
+#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
int PNGAPI
png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
const void *buffer, png_int_32 row_stride, const void *colormap)
@@ -2117,7 +2270,7 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
/* Write the image to the given (FILE*). */
if (image != NULL && image->version == PNG_IMAGE_VERSION)
{
- if (file != NULL)
+ if (file != NULL && buffer != NULL)
{
if (png_image_write_init(image) != 0)
{
@@ -2167,7 +2320,7 @@ png_image_write_to_file(png_imagep image, const char *file_name,
/* Write the image to the named file. */
if (image != NULL && image->version == PNG_IMAGE_VERSION)
{
- if (file_name != NULL)
+ if (file_name != NULL && buffer != NULL)
{
FILE *fp = fopen(file_name, "wb");
@@ -2225,6 +2378,6 @@ png_image_write_to_file(png_imagep image, const char *file_name,
else
return 0;
}
-# endif /* STDIO */
+#endif /* SIMPLIFIED_WRITE_STDIO */
#endif /* SIMPLIFIED_WRITE */
#endif /* WRITE */
diff --git a/third_party/libpng16/pngwtran.c b/third_party/libpng16/pngwtran.c
index 5dc949157d..038a2ef5dc 100644
--- a/third_party/libpng16/pngwtran.c
+++ b/third_party/libpng16/pngwtran.c
@@ -2,7 +2,7 @@
/* pngwtran.c - transforms the data in a row for PNG writers
*
* Last changed in libpng 1.6.18 [July 23, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
diff --git a/third_party/libpng16/pngwutil.c b/third_party/libpng16/pngwutil.c
index 0ee102b5fb..ca8a03ad5f 100644
--- a/third_party/libpng16/pngwutil.c
+++ b/third_party/libpng16/pngwutil.c
@@ -1,8 +1,8 @@
/* pngwutil.c - utilities to write a PNG file
*
- * Last changed in libpng 1.6.19 [November 12, 2015]
- * Copyright (c) 1998-2015 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.22 [May 26, 2016]
+ * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -23,10 +23,10 @@
void PNGAPI
png_save_uint_32(png_bytep buf, png_uint_32 i)
{
- buf[0] = (png_byte)(i >> 24);
- buf[1] = (png_byte)(i >> 16);
- buf[2] = (png_byte)(i >> 8);
- buf[3] = (png_byte)(i );
+ buf[0] = (png_byte)((i >> 24) & 0xffU);
+ buf[1] = (png_byte)((i >> 16) & 0xffU);
+ buf[2] = (png_byte)((i >> 8) & 0xffU);
+ buf[3] = (png_byte)( i & 0xffU);
}
/* Place a 16-bit number into a buffer in PNG byte order.
@@ -36,8 +36,8 @@ png_save_uint_32(png_bytep buf, png_uint_32 i)
void PNGAPI
png_save_uint_16(png_bytep buf, unsigned int i)
{
- buf[0] = (png_byte)(i >> 8);
- buf[1] = (png_byte)(i );
+ buf[0] = (png_byte)((i >> 8) & 0xffU);
+ buf[1] = (png_byte)( i & 0xffU);
}
#endif
@@ -665,90 +665,6 @@ png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
}
#endif /* WRITE_COMPRESSED_TEXT */
-#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
- defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
-/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
- * and if invalid, correct the keyword rather than discarding the entire
- * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
- * length, forbids leading or trailing whitespace, multiple internal spaces,
- * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
- *
- * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
- * trailing '\0'). If this routine returns 0 then there was no keyword, or a
- * valid one could not be generated, and the caller must png_error.
- */
-static png_uint_32
-png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
-{
- png_const_charp orig_key = key;
- png_uint_32 key_len = 0;
- int bad_character = 0;
- int space = 1;
-
- png_debug(1, "in png_check_keyword");
-
- if (key == NULL)
- {
- *new_key = 0;
- return 0;
- }
-
- while (*key && key_len < 79)
- {
- png_byte ch = (png_byte)*key++;
-
- if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
- *new_key++ = ch, ++key_len, space = 0;
-
- else if (space == 0)
- {
- /* A space or an invalid character when one wasn't seen immediately
- * before; output just a space.
- */
- *new_key++ = 32, ++key_len, space = 1;
-
- /* If the character was not a space then it is invalid. */
- if (ch != 32)
- bad_character = ch;
- }
-
- else if (bad_character == 0)
- bad_character = ch; /* just skip it, record the first error */
- }
-
- if (key_len > 0 && space != 0) /* trailing space */
- {
- --key_len, --new_key;
- if (bad_character == 0)
- bad_character = 32;
- }
-
- /* Terminate the keyword */
- *new_key = 0;
-
- if (key_len == 0)
- return 0;
-
-#ifdef PNG_WARNINGS_SUPPORTED
- /* Try to only output one warning per keyword: */
- if (*key != 0) /* keyword too long */
- png_warning(png_ptr, "keyword truncated");
-
- else if (bad_character != 0)
- {
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter(p, 1, orig_key);
- png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
-
- png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
- }
-#endif /* WARNINGS */
-
- return key_len;
-}
-#endif /* WRITE_TEXT || WRITE_pCAL || WRITE_iCCP || WRITE_sPLT */
-
/* Write the IHDR chunk, and update the png_struct with the necessary
* information. Note that the rest of this code depends upon this
* information being correct.
@@ -2362,6 +2278,28 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp,
return (sum);
}
+static void /* PRIVATE */
+png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp,
+ const png_size_t row_bytes)
+{
+ png_bytep rp, dp, lp;
+ png_size_t i;
+
+ png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
+
+ for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
+ i++, rp++, dp++)
+ {
+ *dp = *rp;
+ }
+
+ for (lp = png_ptr->row_buf + 1; i < row_bytes;
+ i++, rp++, lp++, dp++)
+ {
+ *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+ }
+}
+
static png_size_t /* PRIVATE */
png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes,
const png_size_t lmins)
@@ -2386,6 +2324,21 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes,
return (sum);
}
+static void /* PRIVATE */
+png_setup_up_row_only(png_structrp png_ptr, const png_size_t row_bytes)
+{
+ png_bytep rp, dp, pp;
+ png_size_t i;
+
+ png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
+
+ for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
+ pp = png_ptr->prev_row + 1; i < row_bytes;
+ i++, rp++, pp++, dp++)
+ {
+ *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
+ }
+}
static png_size_t /* PRIVATE */
png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
@@ -2419,6 +2372,27 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
return (sum);
}
+static void /* PRIVATE */
+png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp,
+ const png_size_t row_bytes)
+{
+ png_bytep rp, dp, pp, lp;
+ png_uint_32 i;
+
+ png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
+
+ for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
+ pp = png_ptr->prev_row + 1; i < bpp; i++)
+ {
+ *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+ }
+
+ for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
+ {
+ *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
+ & 0xff);
+ }
+}
static png_size_t /* PRIVATE */
png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
@@ -2473,6 +2447,48 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
return (sum);
}
+static void /* PRIVATE */
+png_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp,
+ const png_size_t row_bytes)
+{
+ png_bytep rp, dp, pp, cp, lp;
+ png_size_t i;
+
+ png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
+
+ for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
+ pp = png_ptr->prev_row + 1; i < bpp; i++)
+ {
+ *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+ }
+
+ for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
+ i++)
+ {
+ int a, b, c, pa, pb, pc, p;
+
+ b = *pp++;
+ c = *cp++;
+ a = *lp++;
+
+ p = b - c;
+ pc = a - c;
+
+#ifdef PNG_USE_ABS
+ pa = abs(p);
+ pb = abs(pc);
+ pc = abs(p + pc);
+#else
+ pa = p < 0 ? -p : p;
+ pb = pc < 0 ? -pc : pc;
+ pc = (p + pc) < 0 ? -(p + pc) : p + pc;
+#endif
+
+ p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
+
+ *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+ }
+}
#endif /* WRITE_FILTER */
void /* PRIVATE */
@@ -2481,7 +2497,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
#ifndef PNG_WRITE_FILTER_SUPPORTED
png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1);
#else
- png_byte filter_to_do = png_ptr->do_filter;
+ unsigned int filter_to_do = png_ptr->do_filter;
png_bytep row_buf;
png_bytep best_row;
png_uint_32 bpp;
@@ -2527,27 +2543,24 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
*/
best_row = png_ptr->row_buf;
-
- if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE)
+ if (PNG_SIZE_MAX/128 <= row_bytes)
+ {
+ /* Overflow can occur in the calculation, just select the lowest set
+ * filter.
+ */
+ filter_to_do &= -filter_to_do;
+ }
+ else if ((filter_to_do & PNG_FILTER_NONE) != 0 &&
+ filter_to_do != PNG_FILTER_NONE)
{
+ /* Overflow not possible and multiple filters in the list, including the
+ * 'none' filter.
+ */
png_bytep rp;
png_size_t sum = 0;
png_size_t i;
int v;
- if (PNG_SIZE_MAX/128 <= row_bytes)
- {
- for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
- {
- /* Check for overflow */
- if (sum > PNG_SIZE_MAX/128 - 256)
- break;
-
- v = *rp;
- sum += (v < 128) ? v : 256 - v;
- }
- }
- else /* Overflow is not possible */
{
for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
{
@@ -2563,7 +2576,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
if (filter_to_do == PNG_FILTER_SUB)
/* It's the only filter so no testing is needed */
{
- (void) png_setup_sub_row(png_ptr, bpp, row_bytes, mins);
+ png_setup_sub_row_only(png_ptr, bpp, row_bytes);
best_row = png_ptr->try_row;
}
@@ -2589,7 +2602,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
/* Up filter */
if (filter_to_do == PNG_FILTER_UP)
{
- (void) png_setup_up_row(png_ptr, row_bytes, mins);
+ png_setup_up_row_only(png_ptr, row_bytes);
best_row = png_ptr->try_row;
}
@@ -2615,7 +2628,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
/* Avg filter */
if (filter_to_do == PNG_FILTER_AVG)
{
- (void) png_setup_avg_row(png_ptr, bpp, row_bytes, mins);
+ png_setup_avg_row_only(png_ptr, bpp, row_bytes);
best_row = png_ptr->try_row;
}
@@ -2641,7 +2654,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
/* Paeth filter */
if ((filter_to_do == PNG_FILTER_PAETH) != 0)
{
- (void) png_setup_paeth_row(png_ptr, bpp, row_bytes, mins);
+ png_setup_paeth_row_only(png_ptr, bpp, row_bytes);
best_row = png_ptr->try_row;
}
diff --git a/third_party/third_party.gyp b/third_party/third_party.gyp
index fae4c8f1f4..caa5bb1af4 100644
--- a/third_party/third_party.gyp
+++ b/third_party/third_party.gyp
@@ -292,6 +292,36 @@
'libpng16/pngwtran.c',
'libpng16/pngwutil.c',
],
+ 'msvs_disabled_warnings': [
+ 4146, # Unary minus applied to unsigned type.
+ # Warnings about conversion from 'size_t' to 'long', possible loss of
+ # data.
+ 4267,
+ ],
+ 'conditions': [
+ # SSE optimizations
+ [ 'target_arch=="ia32" or target_arch=="x64"', {
+ 'defines': [
+ 'PNG_INTEL_SSE_OPT=1',
+ ],
+ 'sources': [
+ 'libpng16/contrib/intel/intel_init.c',
+ 'libpng16/contrib/intel/filter_sse2_intrinsics.c',
+ ],
+ }],
+
+ # ARM optimizations
+ [ '(target_arch=="arm" or target_arch=="arm64") and OS!="ios" and arm_neon==1', {
+ 'defines': [
+ 'PNG_ARM_NEON_OPT=2',
+ 'PNG_ARM_NEON_IMPLEMENTATION=1',
+ ],
+ 'sources': [
+ 'libpng16/arm/arm_init.c',
+ 'libpng16/arm/filter_neon_intrinsics.c',
+ ],
+ }],
+ ],
},
{
'target_name': 'fx_zlib',