diff -ru4NwbB libpng-1.5.6/Makefile.am libpng-1.5.7beta04/Makefile.am --- libpng-1.5.6/Makefile.am 2011-11-02 22:42:58.022435114 -0500 +++ libpng-1.5.7beta04/Makefile.am 2011-11-17 21:03:04.989751989 -0600 @@ -11,15 +11,21 @@ # AUTOMAKE_OPTIONS = foreign color-tests AUTOMAKE_OPTIONS = foreign # test programs - run on make check, make distcheck -check_PROGRAMS= pngtest pngvalid +TESTS_ENVIRONMENT= srcdir=$(srcdir) +check_PROGRAMS= pngtest pngtest_SOURCES = pngtest.c pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +TESTS = test-pngtest.sh + +# Do the following only if the contrib directory is present. +check_PROGRAMS+= pngvalid pngstest pngvalid_SOURCES = pngvalid.c +pngstest_SOURCES = contrib/libtests/pngstest.c pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la -TESTS = test-pngtest.sh test-pngvalid-simple.sh test-pngvalid-full.sh -TESTS_ENVIRONMENT= srcdir=$(srcdir) +pngstest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +TESTS += test-pngvalid-simple.sh test-pngvalid-full.sh test-pngstest.sh # man pages dist_man_MANS= libpng.3 libpngpf.3 png.5 @@ -35,8 +41,12 @@ pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\ pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\ png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h +if PNG_ARM_NEON +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += arm/filter_neon.S +endif + nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_CPPFLAGS = @LIBPNG_DEFINES@ @@ -121,9 +131,9 @@ # The following is necessary to ensure that the local pnglibconf.h is used, not # an installed one (this can happen immediately after on a clean system if # 'make test' is the first thing the user does.) -pngvalid.o pngtest.o: pnglibconf.h +contrib/libtests/pngstest.o pngvalid.o pngtest.o: pnglibconf.h # We must use -DPNG_NO_USE_READ_MACROS here even when the library may actually # be built with PNG_USE_READ_MACROS; this prevents the read macros from # interfering with the symbol file format. @@ -137,19 +147,20 @@ test -d scripts || mkdir scripts echo '#include "$<"' >dfn.c $(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) @LIBPNG_DEFINES@\ $(CPPFLAGS) $(SYMBOL_CFLAGS) dfn.c > dfn1.out - $(SED) -n -e 's|^.*PNG_DEFN_MAGIC-\(.*\)-PNG_DEFN_END.*$$|\1|p'\ + $(SED) -n -e 's|^.*PNG_DEFN_MAGIC *-\(.*\)- *PNG_DEFN_END.*$$|\1|p'\ dfn1.out >dfn2.out - $(SED) -e 's| *@@@ *||g' -e 's| *$$||' dfn2.out >dfn3.out + $(SED) -e 's| *PNG_JOIN *||g' -e 's| *$$||' dfn2.out >dfn3.out rm -f dfn.c dfn[12].out mv dfn3.out $@ # The .dfn file for pnglibconf.h is machine generated -pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk +pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk pngconf.h rm -f $@ dfn?.out - $(AWK) -f ${srcdir}/scripts/options.awk out=dfn1.out\ - ${srcdir}/scripts/pnglibconf.dfa $(DFA_XTRA) 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn1.out version=search\ + ${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\ + $(DFA_XTRA) 1>&2 $(AWK) -f ${srcdir}/scripts/options.awk out=dfn2.out dfn1.out 1>&2 rm dfn1.out mv dfn2.out $@ @@ -162,14 +173,15 @@ mv symbols.new $@ # used on demand to regenerate the standard header, CPPFLAGS should # be empty - no non-standard defines -scripts/pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk +scripts/pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk pngconf.h rm -f $@ dfn?.out test -z "$(CPPFLAGS)" echo "com @PNGLIB_VERSION@ STANDARD API DEFINITION" |\ - $(AWK) -f ${srcdir}/scripts/options.awk out=dfn1.out\ - logunsupported=1 - ${srcdir}/scripts/pnglibconf.dfa 1>&2 + $(AWK) -f ${srcdir}/scripts/options.awk out=dfn1.out logunsupported=1 + version=search ${srcdir}/pngconf.h -\ + ${srcdir}/scripts/pnglibconf.dfa 1>&2 $(AWK) -f ${srcdir}/scripts/options.awk out=dfn2.out dfn1.out 1>&2 rm dfn1.out mv dfn2.out $@ diff -ru4NwbB libpng-1.5.6/arm/filter_neon.S libpng-1.5.7beta04/arm/filter_neon.S --- libpng-1.5.6/arm/filter_neon.S 1969-12-31 18:00:00.000000000 -0600 +++ libpng-1.5.7beta04/arm/filter_neon.S 2011-11-16 23:02:48.612067000 -0600 @@ -0,0 +1,225 @@ + +/* filter_neon.S - NEON optimised filter functions + * + * Copyright (c) 2011 Glenn Randers-Pehrson + * Written by Mans Rullgard, 2011. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */ +#endif + +#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 + .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 diff -ru4NwbB libpng-1.5.6/configure.ac libpng-1.5.7beta04/configure.ac --- libpng-1.5.6/configure.ac 2011-11-02 22:42:58.029005391 -0500 +++ libpng-1.5.7beta04/configure.ac 2011-11-17 21:03:04.997122913 -0600 @@ -35,8 +35,9 @@ # Checks for programs. AC_LANG([C]) AC_PROG_CC +AM_PROG_AS AC_PROG_LD AC_PROG_CPP AC_CHECK_TOOL(SED, sed, :) AC_CHECK_TOOL(AWK, awk, :) @@ -74,8 +75,9 @@ # Checks for typedefs, structures, and compiler characteristics. AC_C_CONST AC_TYPE_SIZE_T AC_STRUCT_TM +AC_C_RESTRICT # Checks for library functions. AC_FUNC_STRTOD AC_CHECK_FUNCS([memset], , AC_ERROR([memset not found in libc])) @@ -88,8 +90,13 @@ AC_CHECK_LIB(z, zlibVersion, , AC_CHECK_LIB(z, ${ZPREFIX}zlibVersion, , AC_ERROR([zlib not installed]))) +# The following is for pngvalid, to ensure it catches FP errors even on +# platforms that don't enable FP exceptions, the function appears in the math +# library (typically), it's not an error if it is not found. +AC_CHECK_LIB([m], [feenableexcept]) +AC_CHECK_FUNCS([feenableexcept]) LIBPNG_DEFINES=-DPNG_CONFIGURE_LIBPNG LIBPNG_DEFINES=$LIBPNG_DEFINES AC_SUBST(LIBPNG_DEFINES) @@ -176,8 +183,21 @@ fi], [binconfigs='${binconfigs}']) AC_SUBST([binconfigs]) +# Because GCC by default assembles code with an executable stack, even though it +# compiles C code with a non-executable stack, it is necessary to do a fixup +# here (this may by GCC specific) +AC_SUBST([AM_CCASFLAGS], [-Wa,--noexecstack]) + +AC_ARG_ENABLE([arm-neon], + AC_HELP_STRING([--enable-arm-neon], [Enable ARM NEON optimizations]), + [if test "${enableval}" = yes; then + AC_DEFINE([PNG_ARM_NEON], [1], [Enable ARM NEON optimizations]) + AC_DEFINE([PNG_ALIGNED_MEMORY_SUPPORTED], [1], [Align row buffers]) + fi]) +AM_CONDITIONAL([PNG_ARM_NEON], [test "${enable_arm_neon:-no}" = yes]) + # 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]) diff -ru4NwbB libpng-1.5.6/contrib/README.txt libpng-1.5.7beta04/contrib/README.txt --- libpng-1.5.6/contrib/README.txt 1969-12-31 18:00:00.000000000 -0600 +++ libpng-1.5.7beta04/contrib/README.txt 2011-11-17 21:02:59.681745845 -0600 @@ -0,0 +1,4 @@ + +This "contrib" directory contains contributions which are not necessarily under +the libpng license, although all are open source. They are not part of +libpng proper and are not used for building the library. diff -ru4NwbB libpng-1.5.6/contrib/libtests/pngstest.c libpng-1.5.7beta04/contrib/libtests/pngstest.c --- libpng-1.5.6/contrib/libtests/pngstest.c 1969-12-31 18:00:00.000000000 -0600 +++ libpng-1.5.7beta04/contrib/libtests/pngstest.c 2011-11-16 22:00:13.004579000 -0600 @@ -0,0 +1,1677 @@ +/*- + * pngstest.c + * + * Test for the PNG 'simplified' APIs. + */ +#define _ISOC90_SOURCE 1 +#define MALLOC_CHECK_ 2/*glibc facility: turn on debugging*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "../../png.h" + +#include "../sRGBtables/sRGB.h" + +/* The following is to support direct compilation of this file as C++ */ +#ifdef __cplusplus +# define voidcast(type, value) static_cast(value) +#else +# define voidcast(type, value) (value) +#endif /* __cplusplus */ + +/* Math support - neither Cygwin nor Visual Studio have C99 support and we need + * a predictable rounding function, so make one here: + */ +static double +closestinteger(double x) +{ + return floor(x + .5); +} + +/* Cast support: remove GCC whines. */ +static png_byte +u8d(double d) +{ + d = closestinteger(d); + return (png_byte)d; +} + +static png_uint_16 +u16d(double d) +{ + d = closestinteger(d); + return (png_uint_16)d; +} + +/* sRGB support: use exact calculations rounded to the nearest int, see the + * fesetround() call in main(). + */ +static png_byte +sRGB(double linear /*range 0.0 .. 1.0*/) +{ + return u8d(255 * sRGB_from_linear(linear)); +} + +static png_byte +isRGB(int fixed_linear) +{ + return sRGB(fixed_linear / 65535.); +} + +static png_uint_16 +ilineara(int fixed_srgb, int alpha) +{ + return u16d((257 * alpha) * linear_from_sRGB(fixed_srgb / 255.)); +} + +static double +YfromRGBint(int ir, int ig, int ib) +{ + double r = ir; + double g = ig; + double b = ib; + return YfromRGB(r, g, b); +} + +#define READ_FILE 1 /* else memory */ +#define USE_STDIO 2 /* else use file name */ +#define USE_BACKGROUND 4 /* else composite in place */ +#define VERBOSE 8 +#define KEEP_TMPFILES 16 /* else delete temporary files */ +#define KEEP_GOING 32 + +static void +print_opts(png_uint_32 opts) +{ + if (opts & READ_FILE) + printf(" --file"); + if (opts & USE_STDIO) + printf(" --stdio"); + if (opts & USE_BACKGROUND) + printf(" --background"); + if (opts & VERBOSE) + printf(" --verbose"); + if (opts & KEEP_TMPFILES) + printf(" --preserve"); + if (opts & KEEP_GOING) + printf(" --keep-going"); +} + +#define FORMAT_NO_CHANGE 0x80000000 /* additional flag */ + +/* A name table for all the formats - defines the format of the '+' arguments to + * pngstest. + */ +static PNG_CONST char * PNG_CONST format_names[32] = +{ + "sRGB-gray", + "sRGB-gray+alpha", + "sRGB-rgb", + "sRGB-rgb+alpha", + "linear-gray", + "linear-gray+alpha", + "linear-rgb", + "linear-rgb+alpha", + "sRGB-gray", + "sRGB-gray+alpha", + "sRGB-bgr", + "sRGB-bgr+alpha", + "linear-gray", + "linear-gray+alpha", + "linear-bgr", + "linear-bgr+alpha", + "sRGB-gray", + "alpha+sRGB-gray", + "sRGB-rgb", + "alpha+sRGB-rgb", + "linear-gray", + "alpha+linear-gray", + "linear-rgb", + "alpha+linear-rgb", + "sRGB-gray", + "alpha+sRGB-gray", + "sRGB-bgr", + "alpha+sRGB-bgr", + "linear-gray", + "alpha+linear-gray", + "linear-bgr", + "alpha+linear-bgr", +}; + +/* Decode an argument to a format number. */ +static png_uint_32 +formatof(const char *arg) +{ + char *ep; + unsigned long format = strtoul(arg, &ep, 0); + + if (ep > arg && *ep == 0 && format < 32) + return (png_uint_32)format; + + else for (format=0; format < 32; ++format) + { + if (strcmp(format_names[format], arg) == 0) + return (png_uint_32)format; + } + + fprintf(stderr, "pngstest: format name '%s' invalid\n", arg); + return 32; +} + +/* THE Image STRUCTURE */ +/* The super-class of a png_image, contains the decoded image plus the input + * data necessary to re-read the file with a different format. + */ +typedef struct +{ + png_image image; + png_uint_32 opts; + const char *file_name; + int stride_extra; + FILE *input_file; + png_voidp input_memory; + png_size_t input_memory_size; + png_bytep buffer; + ptrdiff_t stride; + png_size_t bufsize; + png_size_t allocsize; + png_color background; + char tmpfile_name[32]; +} +Image; + +/* Initializer: also sets the permitted error limit for 16-bit operations. */ +static void +newimage(Image *image) +{ + memset(image, 0, sizeof *image); +} + +/* Reset the image to be read again - only needs to rewind the FILE* at present. + */ +static void +resetimage(Image *image) +{ + if (image->input_file != NULL) + rewind(image->input_file); +} + +/* Free the image buffer; the buffer is re-used on a re-read, this is just for + * cleanup. + */ +static void +freebuffer(Image *image) +{ + if (image->buffer) free(image->buffer); + image->buffer = NULL; + image->bufsize = 0; + image->allocsize = 0; +} + +/* Delete function; cleans out all the allocated data and the temporary file in + * the image. + */ +static void +freeimage(Image *image) +{ + freebuffer(image); + png_image_free(&image->image); + + if (image->input_file != NULL) + { + fclose(image->input_file); + image->input_file = NULL; + } + + if (image->input_memory != NULL) + { + free(image->input_memory); + image->input_memory = NULL; + image->input_memory_size = 0; + } + + if (image->tmpfile_name[0] != 0 && (image->opts & KEEP_TMPFILES) == 0) + { + remove(image->tmpfile_name); + image->tmpfile_name[0] = 0; + } +} + +/* This is actually a re-initializer; allows an image structure to be re-used by + * freeing everything that relates to an old image. + */ +static void initimage(Image *image, png_uint_32 opts, const char *file_name, + int stride_extra) +{ + freeimage(image); + memset(&image->image, 0, sizeof image->image); + image->opts = opts; + image->file_name = file_name; + image->stride_extra = stride_extra; +} + +/* Make sure the image buffer is big enough; allows re-use of the buffer if the + * image is re-read. + */ +#define BUFFER_INIT8 73 +static void +allocbuffer(Image *image) +{ + png_size_t size = PNG_IMAGE_BUFFER_SIZE(image->image, image->stride); + + if (size+32 > image->bufsize) + { + freebuffer(image); + image->buffer = voidcast(png_bytep, malloc(size+32)); + if (image->buffer == NULL) + { + fprintf(stderr, + "simpletest: out of memory allocating %lu(+32) byte buffer\n", + (unsigned long)size); + exit(1); + } + image->bufsize = size+32; + } + + memset(image->buffer, 95, image->bufsize); + memset(image->buffer+16, BUFFER_INIT8, size); + image->allocsize = size; +} + +/* Make sure 16 bytes match the given byte. */ +static int +check16(png_const_bytep bp, int b) +{ + int i = 16; + + do + if (*bp != b) return 1; + while (--i); + + return 0; +} + +/* Check for overwrite in the image buffer. */ +static void +checkbuffer(Image *image, const char *arg) +{ + if (check16(image->buffer, 95)) + { + fprintf(stderr, "%s: overwrite at start of image buffer\n", arg); + exit(1); + } + + if (check16(image->buffer+16+image->allocsize, 95)) + { + fprintf(stderr, "%s: overwrite at end of image buffer\n", arg); + exit(1); + } +} + +/* ERROR HANDLING */ +/* Log a terminal error, also frees the libpng part of the image if necessary. + */ +static int +logerror(Image *image, const char *a1, const char *a2, const char *a3) +{ + if (image->image.warning_or_error) + fprintf(stderr, "%s%s%s: %s\n", a1, a2, a3, image->image.message); + + else + fprintf(stderr, "%s%s%s\n", a1, a2, a3); + + if (image->image.opaque != NULL) + { + fprintf(stderr, "%s: image opaque pointer non-NULL on error\n", + image->file_name); + png_image_free(&image->image); + } + + return 0; +} + +/* Log an error and close a file (just a utility to do both things in one + * function call.) + */ +static int +logclose(Image *image, FILE *f, const char *name, const char *operation) +{ + int e = errno; + + fclose(f); + return logerror(image, name, operation, strerror(e)); +} + +/* Make sure the png_image has been freed - validates that libpng is doing what + * the spec says and freeing the image. + */ +static int +checkopaque(Image *image) +{ + if (image->image.opaque != NULL) + { + png_image_free(&image->image); + return logerror(image, image->file_name, ": opaque not NULL", ""); + } + + else + return 1; +} + +/* IMAGE COMPARISON/CHECKING */ +/* Compare the pixels of two images, which should be the same but aren't. The + * images must have been checked for a size match. + */ +typedef struct +{ + png_uint_32 format; + png_uint_16 r16, g16, b16, y16, a16; + png_byte r8, g8, b8, y8, a8; +} Pixel; + +/* This is not particularly fast, but it works. The input has pixels stored + * either as pre-multiplied linear 16-bit or as sRGB encoded non-pre-multiplied + * 8-bit values. The routine reads either and does exact convertion to the + * other format. + * + * Grayscale values are mapped r==g==b=y. Non-alpha images have alpha + * 65535/255. Color images have a correctly calculated Y value using the sRGB Y + * calculation. + * + * The API returns false if an error is detected; this can only be if the alpha + * value is less than the component in the linear case. + */ +static int +get_pixel(Image *image, Pixel *pixel, png_const_bytep pp) +{ + png_uint_32 format = image->image.format; + int result = 1; + + pixel->format = format; + + /* Initialize the alpha values for opaque: */ + pixel->a8 = 255; + pixel->a16 = 65535; + + switch (PNG_IMAGE_COMPONENT_SIZE(format)) + { + default: + fprintf(stderr, "pngstest: impossible component size: %lu\n", + (unsigned long)PNG_IMAGE_COMPONENT_SIZE(format)); + exit(1); + + case sizeof (png_uint_16): + { + png_const_uint_16p up = (png_const_uint_16p)pp; + + if ((format & PNG_FORMAT_FLAG_AFIRST) != 0 && + (format & PNG_FORMAT_FLAG_ALPHA) != 0) + pixel->a16 = *up++; + + if ((format & PNG_FORMAT_FLAG_COLOR) != 0) + { + if ((format & PNG_FORMAT_FLAG_BGR) != 0) + { + pixel->b16 = *up++; + pixel->g16 = *up++; + pixel->r16 = *up++; + } + + else + { + pixel->r16 = *up++; + pixel->g16 = *up++; + pixel->b16 = *up++; + } + + /* Because the 'Y' calculation is linear the pre-multiplication + * of the r16,g16,b16 values can be ignored. + */ + pixel->y16 = u16d(YfromRGBint(pixel->r16, pixel->g16, + pixel->b16)); + } + + else + pixel->r16 = pixel->g16 = pixel->b16 = pixel->y16 = *up++; + + if ((format & PNG_FORMAT_FLAG_AFIRST) == 0 && + (format & PNG_FORMAT_FLAG_ALPHA) != 0) + pixel->a16 = *up++; + + /* 'a1' is 1/65535 * 1/alpha, for alpha in the range 0..1 */ + if (pixel->a16 == 0) + { + pixel->r8 = pixel->g8 = pixel->b8 = pixel->y8 = 255; + pixel->a8 = 0; + } + + else + { + double a1 = 1. / pixel->a16; + + if (pixel->a16 < pixel->r16) + result = 0, pixel->r8 = 255; + else + pixel->r8 = sRGB(pixel->r16 * a1); + + if (pixel->a16 < pixel->g16) + result = 0, pixel->g8 = 255; + else + pixel->g8 = sRGB(pixel->g16 * a1); + + if (pixel->a16 < pixel->b16) + result = 0, pixel->b8 = 255; + else + pixel->b8 = sRGB(pixel->b16 * a1); + + if (pixel->a16 < pixel->y16) + result = 0, pixel->y8 = 255; + else + pixel->y8 = sRGB(pixel->y16 * a1); + + /* The 8-bit alpha value is just a16/257. */ + pixel->a8 = u8d(pixel->a16 / 257.); + } + } + break; + + case sizeof (png_byte): + { + double y; + + if ((format & PNG_FORMAT_FLAG_AFIRST) != 0 && + (format & PNG_FORMAT_FLAG_ALPHA) != 0) + pixel->a8 = *pp++; + + if ((format & PNG_FORMAT_FLAG_COLOR) != 0) + { + if ((format & PNG_FORMAT_FLAG_BGR) != 0) + { + pixel->b8 = *pp++; + pixel->g8 = *pp++; + pixel->r8 = *pp++; + } + + else + { + pixel->r8 = *pp++; + pixel->g8 = *pp++; + pixel->b8 = *pp++; + } + + /* The y8 value requires convert to linear, convert to &, convert + * to sRGB: + */ + y = YfromRGB(linear_from_sRGB(pixel->r8/255.), + linear_from_sRGB(pixel->g8/255.), + linear_from_sRGB(pixel->b8/255.)); + + pixel->y8 = sRGB(y); + } + + else + { + pixel->r8 = pixel->g8 = pixel->b8 = pixel->y8 = *pp++; + y = linear_from_sRGB(pixel->y8/255.); + } + + if ((format & PNG_FORMAT_FLAG_AFIRST) == 0 && + (format & PNG_FORMAT_FLAG_ALPHA) != 0) + pixel->a8 = *pp++; + + pixel->r16 = ilineara(pixel->r8, pixel->a8); + pixel->g16 = ilineara(pixel->g8, pixel->a8); + pixel->b16 = ilineara(pixel->b8, pixel->a8); + pixel->y16 = u16d((257 * pixel->a8) * y); + pixel->a16 = (png_uint_16)(pixel->a8 * 257); + } + break; + } + + return result; +} + +/* Two pixels are equal if the value of the left equals the value of the right + * as defined by the format of the right, or if it is close enough given the + * permitted error limits. If the formats match the values should (exactly!) + * + * If the right pixel has no alpha channel but the left does it was removed + * somehow. For an 8-bit *output* removal uses the background color if given + * else the default (the value filled in to the row buffer by allocbuffer() + * above.) + * + * The result of this function is NULL if the pixels match else a reason why + * they don't match. + * + * Error values below are inflated because some of the convertions are done + * inside libpng using a simple power law transform of .45455 and others are + * done in the simplified API code using the correct sRGB tables. This needs + * to be made consistent. + */ +static int error_to_linear = 811; /* by experiment */ +static int error_to_linear_grayscale = 424; /* by experiment */ +static int error_to_sRGB = 6; /* by experiment */ +static int error_to_sRGB_grayscale = 11; /* by experiment */ +static int error_in_compose = 0; +static int error_via_linear = 14; /* by experiment */ +static int error_in_premultiply = 1; + +static const char * +cmppixel(Pixel *a, Pixel *b, const png_color *background, int via_linear) +{ + int error_limit = 0; + + if (b->format & PNG_FORMAT_FLAG_LINEAR) + { + /* If the input was non-opaque then use the pre-multiplication error + * limit. + */ + if ((a->format & PNG_FORMAT_FLAG_ALPHA) && a->a16 < 65535) + error_limit = error_in_premultiply; + + if (b->format & PNG_FORMAT_FLAG_ALPHA) + { + /* Expect an exact match. */ + if (b->a16 != a->a16) + return "linear alpha mismatch"; + } + + else if (a->format & PNG_FORMAT_FLAG_ALPHA) + { + /* An alpha channel has been removed, the destination is linear so the + * removal algorithm is just the premultiplication - compose on black - + * and the 16-bit colors are correct already. + */ + } + + if (b->format & PNG_FORMAT_FLAG_COLOR) + { + const char *err = "linear color mismatch"; + + /* Check for an exact match. */ + if (a->r16 == b->r16 && a->g16 == b->g16 && a->b16 == b->b16) + return NULL; + + /* Not an exact match; allow drift only if the input is 8-bit */ + if (!(a->format & PNG_FORMAT_FLAG_LINEAR)) + { + if (error_limit < error_to_linear) + { + error_limit = error_to_linear; + err = "sRGB to linear convertion error"; + } + } + + if (abs(a->r16-b->r16) <= error_limit && + abs(a->g16-b->g16) <= error_limit && + abs(a->b16-b->b16) <= error_limit) + return NULL; + + return err; + } + + else /* b is grayscale */ + { + const char *err = "linear gray mismatch"; + + /* Check for an exact match. */ + if (a->y16 == b->y16) + return NULL; + + /* Not an exact match; allow drift only if the input is 8-bit or if it + * has been converted from color. + */ + if (!(a->format & PNG_FORMAT_FLAG_LINEAR)) + { + /* Converted to linear, check for that drift. */ + if (error_limit < error_to_linear) + { + error_limit = error_to_linear; + err = "8-bit gray to linear convertion error"; + } + + if (abs(a->y16-b->y16) <= error_to_linear) + return NULL; + + } + + if (a->format & PNG_FORMAT_FLAG_COLOR) + { + /* Converted to grayscale, allow drift */ + if (error_limit < error_to_linear_grayscale) + { + error_limit = error_to_linear_grayscale; + err = "color to linear gray convertion error"; + } + } + + if (abs(a->y16-b->y16) <= error_limit) + return NULL; + + return err; + } + } + + else /* RHS is 8-bit */ + { + const char *err; + + /* For 8-bit to 8-bit use 'error_via_linear'; this handles the cases where + * the original image is compared with the output of another convertion: + * see where the parameter is set to non-zero below. + */ + if (!(a->format & PNG_FORMAT_FLAG_LINEAR) && via_linear) + error_limit = error_via_linear; + + if (b->format & PNG_FORMAT_FLAG_COLOR) + err = "8-bit color mismatch"; + + else + err = "8-bit gray mismatch"; + + /* If the original data had an alpha channel and was not pre-multiplied + * pre-multiplication may lose precision in non-opaque pixel values. If + * the output is linear the premultiplied 16-bit values will be used, but + * if 'via_linear' is set an intermediate 16-bit pre-multiplied form has + * been used and this must be taken into account here. + */ + if (via_linear && (a->format & PNG_FORMAT_FLAG_ALPHA) && + !(a->format & PNG_FORMAT_FLAG_LINEAR) && + a->a16 < 65535) + { + if (a->a16 > 0) + { + /* First calculate the rounded 16-bit component values, (r,g,b) or y + * as appropriate, then back-calculate the 8-bit values for + * comparison below. + */ + if (a->format & PNG_FORMAT_FLAG_COLOR) + { + double r = closestinteger((65535. * a->r16) / a->a16)/65535; + double g = closestinteger((65535. * a->g16) / a->a16)/65535; + double blue = closestinteger((65535. * a->b16) / a->a16)/65535; + + a->r16 = u16d(r * a->a16); + a->g16 = u16d(g * a->a16); + a->b16 = u16d(blue * a->a16); + a->y16 = u16d(YfromRGBint(a->r16, a->g16, a->b16)); + + a->r8 = u8d(r * 255); + a->g8 = u8d(g * 255); + a->b8 = u8d(blue * 255); + a->y8 = u8d(255 * YfromRGB(r, g, blue)); + } + + else + { + double y = closestinteger((65535. * a->y16) / a->a16)/65535.; + + a->b16 = a->g16 = a->r16 = a->y16 = u16d(y * a->a16); + a->b8 = a->g8 = a->r8 = a->y8 = u8d(255 * y); + } + } + + else + { + a->r16 = a->g16 = a->b16 = a->y16 = 0; + a->r8 = a->g8 = a->b8 = a->y8 = 255; + } + } + + + if (b->format & PNG_FORMAT_FLAG_ALPHA) + { + /* Expect an exact match on the 8 bit value. */ + if (b->a8 != a->a8) + return "8-bit alpha mismatch"; + + /* If the *input* was linear+alpha as well libpng will have converted + * the non-premultiplied format directly to the sRGB non-premultiplied + * format and the precision loss on an intermediate pre-multiplied + * format will have been avoided. In this case we will get spurious + * values in the non-opaque pixels. + */ + if (!via_linear && (a->format & PNG_FORMAT_FLAG_LINEAR) != 0 && + (a->format & PNG_FORMAT_FLAG_ALPHA) != 0 && + a->a16 < 65535) + { + /* We don't know the original values (libpng has already removed + * them) but we can make sure they are in range here by doing a + * comparison on the pre-multiplied values instead. + */ + if (a->a16 > 0) + { + if (b->format & PNG_FORMAT_FLAG_COLOR) + { + double r, g, blue; + + r = (255. * b->r16)/b->a16; + b->r8 = u8d(r); + + g = (255. * b->g16)/b->a16; + b->g8 = u8d(g); + + blue = (255. * b->b16)/b->a16; + b->b8 = u8d(blue); + + b->y8 = u8d(YfromRGB(r, g, blue)); + } + + else + { + b->r8 = b->g8 = b->b8 = b->y8 = + u8d((255. * b->y16)/b->a16); + } + } + + else + b->r8 = b->g8 = b->b8 = b->y8 = 255; + } + } + + else if (a->format & PNG_FORMAT_FLAG_ALPHA) + { + png_uint_32 alpha; + + /* An alpha channel has been removed; the background will have been + * composed in. Adjust the 'a' pixel to represent this by doing the + * correct compose. Set the error limit, above, to an appropriate + * value for the compose operation. + */ + if (error_limit < error_in_compose) + error_limit = error_in_compose; + + alpha = 65535 - a->a16; /* for the background */ + + if (b->format & PNG_FORMAT_FLAG_COLOR) /* background is rgb */ + { + err = "8-bit color compose error"; + + if (via_linear) + { + /* The 16-bit values are already correct (being pre-multiplied), + * just recalculate the 8-bit values. + */ + a->r8 = isRGB(a->r16); + a->g8 = isRGB(a->g16); + a->b8 = isRGB(a->b16); + a->y8 = isRGB(a->y16); + + /* There should be no libpng error in this (ideally) */ + error_limit = 0; + } + + else if (background == NULL) + { + double add = alpha * linear_from_sRGB(BUFFER_INIT8/255.); + double r, g, blue, y; + + r = a->r16 + add; + a->r16 = u16d(r); + a->r8 = sRGB(r/65535); + + g = a->g16 + add; + a->g16 = u16d(g); + a->g8 = sRGB(g/65535); + + blue = a->b16 + add; + a->b16 = u16d(blue); + a->b8 = sRGB(blue/65535); + + y = YfromRGB(r, g, blue); + a->y16 = u16d(y); + a->y8 = sRGB(y/65535); + } + + else + { + double r, g, blue, y; + + r = a->r16 + alpha * linear_from_sRGB(background->red/255.); + a->r16 = u16d(r); + a->r8 = sRGB(r/65535); + + g = a->g16 + alpha * linear_from_sRGB(background->green/255.); + a->g16 = u16d(g); + a->g8 = sRGB(g/65535); + + blue = a->b16 + alpha * linear_from_sRGB(background->blue/255.); + a->b16 = u16d(blue); + a->b8 = sRGB(blue/65535); + + y = YfromRGB(r, g, blue); + a->y16 = u16d(y * 65535); + a->y8 = sRGB(y); + } + } + + else /* background is gray */ + { + err = "8-bit gray compose error"; + + if (via_linear) + { + a->r8 = a->g8 = a->b8 = a->y8 = isRGB(a->y16); + error_limit = 0; + } + + else + { + /* When the output is gray the background comes from just the + * green channel. + */ + double y = a->y16 + alpha * linear_from_sRGB( + (background == NULL ? BUFFER_INIT8 : background->green)/255.); + + a->r16 = a->g16 = a->b16 = a->y16 = u16d(y); + a->r8 = a->g8 = a->b8 = a->y8 = sRGB(y/65535); + } + } + } + + if (b->format & PNG_FORMAT_FLAG_COLOR) + { + + /* Check for an exact match. */ + if (a->r8 == b->r8 && a->g8 == b->g8 && a->b8 == b->b8) + return NULL; + + /* Check for linear to 8-bit convertion. */ + if (a->format & PNG_FORMAT_FLAG_LINEAR) + { + if (error_limit < error_to_sRGB) + { + err = "linear to sRGB convertion error"; + error_limit = error_to_sRGB; + } + } + + if (abs(a->r8-b->r8) <= error_limit && + abs(a->g8-b->g8) <= error_limit && + abs(a->b8-b->b8) <= error_limit) + return NULL; + + return err; + } + + else /* b is grayscale */ + { + /* Check for an exact match. */ + if (a->y8 == b->y8) + return NULL; + + /* Not an exact match; allow drift only if the input is linear or if it + * has been converted from color. + */ + if (a->format & PNG_FORMAT_FLAG_LINEAR) + { + /* Converted to linear, check for that drift. */ + if (error_limit < error_to_sRGB) + { + error_limit = error_to_sRGB; + err = "linear to 8-bit gray convertion error"; + } + } + + if (a->format & PNG_FORMAT_FLAG_COLOR) + { + /* Converted to grayscale, allow drift */ + if (error_limit < error_to_sRGB_grayscale) + { + error_limit = error_to_sRGB_grayscale; + err = "color to 8-bit gray convertion error"; + } + } + + if (abs(a->y8-b->y8) <= error_limit) + return NULL; + + return err; + } + } +} + +/* Basic image formats; control the data but not the layout thereof. */ +#define BASE_FORMATS\ + (PNG_FORMAT_FLAG_ALPHA|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_LINEAR) + +static void +print_pixel(char string[64], Pixel *pixel) +{ + switch (pixel->format & BASE_FORMATS) + { + case 0: /* 8-bit, one channel */ + sprintf(string, "%s(%d)", format_names[pixel->format], pixel->y8); + break; + + case PNG_FORMAT_FLAG_ALPHA: + sprintf(string, "%s(%d,%d)", format_names[pixel->format], pixel->y8, + pixel->a8); + break; + + case PNG_FORMAT_FLAG_COLOR: + sprintf(string, "%s(%d,%d,%d)", format_names[pixel->format], + pixel->r8, pixel->g8, pixel->b8); + break; + + case PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA: + sprintf(string, "%s(%d,%d,%d,%d)", format_names[pixel->format], + pixel->r8, pixel->g8, pixel->b8, pixel->a8); + break; + + case PNG_FORMAT_FLAG_LINEAR: + sprintf(string, "%s(%d)", format_names[pixel->format], pixel->y16); + break; + + case PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA: + sprintf(string, "%s(%d,%d)", format_names[pixel->format], pixel->y16, + pixel->a16); + break; + + case PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR: + sprintf(string, "%s(%d,%d,%d)", format_names[pixel->format], + pixel->r16, pixel->g16, pixel->b16); + break; + + case PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA: + sprintf(string, "%s(%d,%d,%d,%d)", format_names[pixel->format], + pixel->r16, pixel->g16, pixel->b16, pixel->a16); + break; + + default: + sprintf(string, "invalid-format"); + break; + } +} + +static int +logpixel(Image *image, png_uint_32 x, png_uint_32 y, Pixel *a, Pixel *b, + const char *reason) +{ + char pixel_a[64], pixel_b[64]; + char error_buffer[256]; + + print_pixel(pixel_a, a); + print_pixel(pixel_b, b); + sprintf(error_buffer, "(%lu,%lu) %s: %s -> %s", (unsigned long)x, + (unsigned long)y, reason, pixel_a, pixel_b); + return logerror(image, image->file_name, error_buffer, ""); +} + +/* Compare two images, the original 'a', which was written out then read back in + * to * give image 'b'. The formats may have been changed. + */ +static int +compare_two_images(Image *a, Image *b, int via_linear) +{ + png_uint_32 width = a->image.width; + png_uint_32 height = a->image.height; + png_uint_32 formata = a->image.format; + png_uint_32 formatb = b->image.format; + ptrdiff_t stridea = a->stride; + ptrdiff_t strideb = b->stride; + png_const_bytep rowa = a->buffer+16; + png_const_bytep rowb = b->buffer+16; + png_byte channels; + int linear = 0; + int result = 1; + unsigned int check_alpha = 0; /* must be zero or one */ + png_byte swap_mask[4]; + png_uint_32 x, y; + png_const_bytep ppa, ppb; + const png_color *background = + ((a->opts & USE_BACKGROUND) ? &a->background : NULL); + + /* This should never happen: */ + if (width != b->image.width || height != b->image.height) + return logerror(a, a->file_name, ": width x height changed: ", + b->file_name); + + /* Find the first row and inter-row space. */ + if (formata & PNG_FORMAT_FLAG_LINEAR) + { + stridea *= sizeof (png_uint_16); + ++linear; + } + + if (formatb & PNG_FORMAT_FLAG_LINEAR) + { + strideb *= sizeof (png_uint_16); + ++linear; + } + + if (stridea < 0) rowa += (height-1) * (-stridea); + if (strideb < 0) rowb += (height-1) * (-strideb); + + /* The following are used only if the formats match, except that 'channels' + * is a flag for matching formats. + */ + channels = 0; + swap_mask[3] = swap_mask[2] = swap_mask[1] = swap_mask[0] = 0; + + /* Set up the masks if no base format change, or if the format change was + * just to add an alpha channel. + */ + if (((formata | PNG_FORMAT_FLAG_ALPHA) & BASE_FORMATS) == + (formatb & BASE_FORMATS)) + { + png_byte astart = 0; /* index of first component */ + png_byte bstart = 0; + + /* Set to the actual number of channels in 'a' */ + channels = (formata & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; + + if (formata & PNG_FORMAT_FLAG_ALPHA) + { + /* Both formats have an alpha channel */ + if (formata & PNG_FORMAT_FLAG_AFIRST) + { + astart = 1; + + if (formatb & PNG_FORMAT_FLAG_AFIRST) + { + bstart = 1; + swap_mask[0] = 0; + } + + else + swap_mask[0] = channels; /* 'b' alpha is at end */ + } + + else if (formatb & PNG_FORMAT_FLAG_AFIRST) + { + /* 'a' alpha is at end, 'b' is at start (0) */ + bstart = 1; + swap_mask[channels] = 0; + } + + else + swap_mask[channels] = channels; + + ++channels; + } + + else if (formatb & PNG_FORMAT_FLAG_ALPHA) + { + /* Only 'b' has an alpha channel */ + check_alpha = 1; + if (formatb & PNG_FORMAT_FLAG_AFIRST) + { + bstart = 1; + /* Put the location of the alpha channel in swap_mask[3], since it + * cannot be used if 'a' does not have an alpha channel. + */ + swap_mask[3] = 0; + } + + else + swap_mask[3] = channels; + } + + if (formata & PNG_FORMAT_FLAG_COLOR) + { + unsigned int swap = 0; + + /* Colors match, but are they swapped? */ + if ((formata ^ formatb) & PNG_FORMAT_FLAG_BGR) /* Swapped. */ + swap = 2; + + swap_mask[astart+0] = (png_byte)(bstart+(0^swap)); + swap_mask[astart+1] = (png_byte)(bstart+1); + swap_mask[astart+2] = (png_byte)(bstart+(2^swap)); + } + + else /* grayscale: 1 channel */ + swap_mask[astart] = bstart; + } + + ppa = rowa; + ppb = rowb; + for (x=y=0; yopts & KEEP_GOING) == 0) + return 0; + + result = 0; + } + + ++x; + } + + if (x >= width) + { + x = 0; + ++y; + rowa += stridea; + rowb += strideb; + ppa = rowa; + ppb = rowb; + } + } + + return result; +} + +/* Read the file; how the read gets done depends on which of input_file and + * input_memory have been set. + */ +static int +read_file(Image *image, png_uint_32 format) +{ + if (image->input_memory != NULL) + { + if (!png_image_begin_read_from_memory(&image->image, image->input_memory, + image->input_memory_size)) + return logerror(image, "memory init: ", image->file_name, ""); + } + + else if (image->input_file != NULL) + { + if (!png_image_begin_read_from_stdio(&image->image, image->input_file)) + return logerror(image, "stdio init: ", image->file_name, ""); + } + + else + { + if (!png_image_begin_read_from_file(&image->image, image->file_name)) + return logerror(image, "file init: ", image->file_name, ""); + } + + /* Have an initialized image with all the data we need plus, maybe, an + * allocated file (myfile) or buffer (mybuffer) that need to be freed. + */ + { + int result; + + /* Various random settings for detecting overwrites */ + image->background.red = 89; + image->background.green = 78; + image->background.blue = 178; + + /* Print both original and output formats. */ + if (image->opts & VERBOSE) + printf("%s %lu x %lu %s -> %s\n", image->file_name, + (unsigned long)image->image.width, + (unsigned long)image->image.height, + format_names[image->image.format & 0x1f], + (format & FORMAT_NO_CHANGE) != 0 || image->image.format == format + ? "no change" : format_names[format & 0x1f]); + + if ((format & FORMAT_NO_CHANGE) == 0) + image->image.format = format; + + image->stride = PNG_IMAGE_ROW_STRIDE(image->image) + image->stride_extra; + allocbuffer(image); + + result = png_image_finish_read(&image->image, + (image->opts & USE_BACKGROUND) ? &image->background : NULL, + image->buffer+16, (png_int_32)image->stride); + + checkbuffer(image, image->file_name); + + if (result) + return checkopaque(image); + + else + return logerror(image, image->file_name, ": image read failed", ""); + } +} + +/* Reads from a filename, which must be in image->file_name, but uses + * image->opts to choose the method. + */ +static int +read_one_file(Image *image, png_uint_32 format) +{ + if (!(image->opts & READ_FILE) || (image->opts & USE_STDIO)) + { + /* memory or stdio. */ + FILE *f = fopen(image->file_name, "rb"); + + if (f != NULL) + { + if (image->opts & READ_FILE) + image->input_file = f; + + else /* memory */ + { + if (fseek(f, 0, SEEK_END) == 0) + { + long int cb = ftell(f); + + if (cb >= 0 && (unsigned long int)cb < (size_t)~(size_t)0) + { + png_bytep b = voidcast(png_bytep, malloc((size_t)cb)); + + if (b != NULL) + { + rewind(f); + + if (fread(b, (size_t)cb, 1, f) == 1) + { + fclose(f); + image->input_memory_size = cb; + image->input_memory = b; + } + + else + { + free(b); + return logclose(image, f, image->file_name, + ": read failed"); + } + } + + else + return logclose(image, f, image->file_name, + ": out of memory"); + } + + else + return logclose(image, f, image->file_name, ": tell failed"); + } + + else + return logclose(image, f, image->file_name, ": seek failed: "); + } + } + + else + return logerror(image, image->file_name, ": open failed: ", + strerror(errno)); + } + + return read_file(image, format); +} + +static int +write_one_file(Image *output, Image *image, int convert_to_8bit) +{ + if (image->opts & USE_STDIO) + { + FILE *f = tmpfile(); + + if (f != NULL) + { + if (png_image_write_to_stdio(&image->image, f, convert_to_8bit, + image->buffer+16, (png_int_32)image->stride)) + { + if (fflush(f) == 0) + { + rewind(f); + initimage(output, image->opts, "tmpfile", image->stride_extra); + output->input_file = f; + if (!checkopaque(image)) + return 0; + } + + else + return logclose(image, f, "tmpfile", ": flush"); + } + + else + { + fclose(f); + return logerror(image, "tmpfile", ": write failed", ""); + } + } + + else + return logerror(image, "tmpfile", ": open: ", strerror(errno)); + } + + else + { + static int counter = 0; + char name[32]; + + sprintf(name, "TMP%d.png", ++counter); + + if (png_image_write_to_file(&image->image, name, convert_to_8bit, + image->buffer+16, (png_int_32)image->stride)) + { + initimage(output, image->opts, output->tmpfile_name, + image->stride_extra); + /* Afterwards, or freeimage will delete it! */ + strcpy(output->tmpfile_name, name); + + if (!checkopaque(image)) + return 0; + } + + else + return logerror(image, name, ": write failed", ""); + } + + /* 'output' has an initialized temporary image, read this back in and compare + * this against the original: there should be no change since the original + * format was written unmodified unless 'convert_to_8bit' was specified. + */ + if (read_file(output, FORMAT_NO_CHANGE)) + { + if ((output->image.format & BASE_FORMATS) != + ((image->image.format & BASE_FORMATS) & + ~(convert_to_8bit ? PNG_FORMAT_FLAG_LINEAR : 0))) + return logerror(image, image->file_name, ": format changed on read:", + output->file_name); + + return compare_two_images(image, output, 0); + } + + else + return logerror(output, output->tmpfile_name, + ": read of new file failed", ""); +} + +static int +testimage(Image *image, png_uint_32 opts, png_uint_32 formats) +{ + int result; + Image copy; + + /* Copy the original data, stealing it from 'image' */ + checkopaque(image); + copy = *image; + + copy.opts = opts; + copy.buffer = NULL; + copy.bufsize = 0; + copy.allocsize = 0; + + image->input_file = NULL; + image->input_memory = NULL; + image->input_memory_size = 0; + image->tmpfile_name[0] = 0; + + { + png_uint_32 format; + Image output; + + newimage(&output); + + result = 1; + for (format=0; format<32; ++format) if (formats & (1< 31) + exit(1); + + if (formats == (png_uint_32)~0) + formats = 0; + + formats |= 1< +#include + +#include + +#include "png.h" + +static int read_png(FILE *fp) +{ + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,0,0,0); + png_infop info_ptr = NULL; + png_bytep row = NULL, display = NULL; + + if (png_ptr == NULL) + return 0; + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + if (row != NULL) free(row); + if (display != NULL) free(display); + return 0; + } + + png_init_io(png_ptr, fp); + + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + png_error(png_ptr, "OOM allocating info structure"); + + png_read_info(png_ptr, info_ptr); + + { + png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr); + + row = malloc(rowbytes); + display = malloc(rowbytes); + + if (row == NULL || display == NULL) + png_error(png_ptr, "OOM allocating row buffers"); + + { + png_uint_32 height = png_get_image_height(png_ptr, info_ptr); + int passes = png_set_interlace_handling(png_ptr); + int pass; + + png_start_read_image(png_ptr); + + for (pass = 0; pass < passes; ++pass) + { + png_uint_32 y = height; + + /* NOTE: this trashes the row each time; interlace handling won't + * work, but this avoids memory thrashing for speed testing. + */ + while (y-- > 0) + png_read_row(png_ptr, row, display); + } + } + } + + /* Make sure to read to the end of the file: */ + png_read_end(png_ptr, info_ptr); + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + free(row); + free(display); + return 1; +} + +static int mytime(struct timespec *t) +{ + /* Do the timing using clock_gettime and the per-process timer. */ + if (!clock_gettime(CLOCK_PROCESS_CPUTIME_ID, t)) + return 1; + + perror("CLOCK_PROCESS_CPUTIME_ID"); + fprintf(stderr, "timepng: could not get the time\n"); + return 0; +} + +static int perform_one_test(FILE *fp, int nfiles) +{ + int i; + struct timespec before, after; + + /* Clear out all errors: */ + rewind(fp); + + if (mytime(&before)) + { + for (i=0; i 1) + { + int i; + + for (i=1; i 0) + ok = perform_one_test(fp, nfiles); + + else + fprintf(stderr, "usage: timepng {files} or ls files | timepng\n"); + } + + (void)fclose(fp); + } + + else + fprintf(stderr, "timepng: could not open temporary file\n"); + + /* Exit code 0 on success. */ + return ok == 0; +} diff -ru4NwbB libpng-1.5.6/contrib/sRGBtables/cvtcolor.c libpng-1.5.7beta04/contrib/sRGBtables/cvtcolor.c --- libpng-1.5.6/contrib/sRGBtables/cvtcolor.c 1969-12-31 18:00:00.000000000 -0600 +++ libpng-1.5.7beta04/contrib/sRGBtables/cvtcolor.c 2011-11-17 21:02:59.648707124 -0600 @@ -0,0 +1,181 @@ +/*- + * convert.c + * + * Convert 8-bit sRGB or 16-bit linear values to another format. + */ +#define _ISOC99_SOURCE 1 + +#include +#include +#include +#include + +#include + +#include "sRGB.h" + +static void +usage(const char *prog) +{ + fprintf(stderr, + "%s: usage: %s [-linear|-sRGB] [-gray|-color] component{1,4}\n", + prog, prog); + exit(1); +} + +unsigned long +component(const char *prog, const char *arg, int issRGB) +{ + char *ep; + unsigned long c = strtoul(arg, &ep, 0); + + if (ep <= arg || *ep || c > 65535 || (issRGB && c > 255)) + { + fprintf(stderr, "%s: %s: invalid component value (%lu)\n", prog, arg, c); + usage(prog); + } + + return c; +} + +int +main(int argc, const char **argv) +{ + const char *prog = *argv++; + int to_linear = 0, to_gray = 0, to_color = 0; + int channels = 0; + double c[4]; + + /* FE_TONEAREST is the IEEE754 round to nearest, preferring even, mode; i.e. + * everything rounds to the nearest value except that '.5' rounds to the + * nearest even value. + */ + fesetround(FE_TONEAREST); + + c[3] = c[2] = c[1] = c[0] = 0; + + while (--argc > 0 && **argv == '-') + { + const char *arg = 1+*argv++; + + if (strcmp(arg, "sRGB") == 0) + to_linear = 0; + + else if (strcmp(arg, "linear") == 0) + to_linear = 1; + + else if (strcmp(arg, "gray") == 0) + to_gray = 1, to_color = 0; + + else if (strcmp(arg, "color") == 0) + to_gray = 0, to_color = 1; + + else + usage(prog); + } + + switch (argc) + { + default: + usage(prog); + break; + + case 4: + c[3] = component(prog, argv[3], to_linear); + ++channels; + case 3: + c[2] = component(prog, argv[2], to_linear); + ++channels; + case 2: + c[1] = component(prog, argv[1], to_linear); + ++channels; + case 1: + c[0] = component(prog, argv[0], to_linear); + ++channels; + break; + } + + if (to_linear) + { + int i; + int components = channels; + + if ((components & 1) == 0) + --components; + + for (i=0; i 0) + for (i=0; i 2) + { + fprintf(stderr, "%s: too many channels (%d) for -color\n", + prog, channels); + usage(prog); + } + + c[3] = c[1]; /* alpha, if present */ + c[2] = c[1] = c[0]; + } + + if (to_linear) + { + int i; + if ((channels & 1) == 0) + { + double alpha = c[channels-1]; + for (i=0; i= 0) + c[i] = sRGB_from_linear(c[i]); + + for (i=0; i +#include +#include + +/* pngpriv.h includes the definition of 'PNG_sRGB_FROM_LINEAR' which is required + * to verify the actual code. + */ +#include "../../pngpriv.h" + +#include "sRGB.h" + +/* The tables are declared 'const' in pngpriv.h, so this redefines the tables to + * be used. + */ +#define png_sRGB_table sRGB_table +#define png_sRGB_base sRGB_base +#define png_sRGB_delta sRGB_delta + +static png_uint_16 png_sRGB_table[256]; +static png_uint_16 png_sRGB_base[512]; +static png_byte png_sRGB_delta[512]; + +static const unsigned int max_input = 255*65535; + +double +fsRGB(double l) +{ + return sRGB_from_linear(l/max_input); +} + +double +sRGB(unsigned int i) +{ + return fsRGB(i); +} + +double +finvsRGB(unsigned int i) +{ + return 65535 * linear_from_sRGB(i/255.); +} + +png_uint_16 +invsRGB(unsigned int i) +{ + unsigned int x = nearbyint(finvsRGB(i)); + + if (x > 65535) + { + fprintf(stderr, "invsRGB(%u) overflows to %u\n", i, x); + exit(1); + } + + return (png_uint_16)x; +} + +int +main(int argc, char **argv) +{ + unsigned int i, i16, ibase; + double min_error = 0; + double max_error = 0; + double min_error16 = 0; + double max_error16 = 0; + double adjust; + double adjust_lo = 0.4, adjust_hi = 0.6, adjust_mid = 0.5; + unsigned int ec_lo = 0, ec_hi = 0, ec_mid = 0; + unsigned int error_count = 0; + unsigned int error_count16 = 0; + int test_only = 0; + + if (argc > 1) + test_only = strcmp("--test", argv[1]) == 0; + + /* Initialize the encoding table first. */ + for (i=0; i<256; ++i) + { + png_sRGB_table[i] = invsRGB(i); + } + + /* Now work out the decoding tables (this is where the error comes in because + * there are 512 set points and 512 straight lines between them.) + */ + for (;;) + { + if (ec_lo == 0) + adjust = adjust_lo; + + else if (ec_hi == 0) + adjust = adjust_hi; + + else if (ec_mid == 0) + adjust = adjust_mid; + + else if (ec_mid < ec_hi) + adjust = (adjust_mid + adjust_hi)/2; + + else if (ec_mid < ec_lo) + adjust = (adjust_mid + adjust_lo)/2; + + else + { + fprintf(stderr, "not reached: %u .. %u .. %u\n", ec_lo, ec_mid, ec_hi); + exit(1); + } + + /* Calculate the table using the current 'adjust' */ + for (i=0; i<=511; ++i) + { + double lo = 255 * sRGB(i << 15); + double hi = 255 * sRGB((i+1) << 15); + unsigned int calc; + + calc = nearbyint((lo+adjust) * 256); + if (calc > 65535) + { + fprintf(stderr, "table[%d][0]: overflow %08x (%d)\n", i, calc, + calc); + exit(1); + } + png_sRGB_base[i] = calc; + + calc = nearbyint((hi-lo) * 32); + if (calc > 255) + { + fprintf(stderr, "table[%d][1]: overflow %08x (%d)\n", i, calc, + calc); + exit(1); + } + png_sRGB_delta[i] = calc; + } + + /* Check the 16-bit linear values alone: */ + error_count16 = 0; + for (i16=0; i16 <= 65535; ++i16) + { + unsigned int i = 255*i16; + unsigned int iexact = nearbyint(255*sRGB(i)); + unsigned int icalc = PNG_sRGB_FROM_LINEAR(i); + + if (icalc != iexact) + ++error_count16; + } + + /* Now try changing the adjustment. */ + if (ec_lo == 0) + ec_lo = error_count16; + + else if (ec_hi == 0) + ec_hi = error_count16; + + else if (ec_mid == 0) + { + ec_mid = error_count16; + printf("/* initial error counts: %u .. %u .. %u */\n", ec_lo, ec_mid, + ec_hi); + } + + else if (error_count16 < ec_mid) + { + printf("/* adjust (mid ): %f: %u -> %u */\n", adjust, ec_mid, + error_count16); + ec_mid = error_count16; + adjust_mid = adjust; + } + + else if (adjust < adjust_mid && error_count16 < ec_lo) + { + printf("/* adjust (low ): %f: %u -> %u */\n", adjust, ec_lo, + error_count16); + ec_lo = error_count16; + adjust_lo = adjust; + } + + else if (adjust > adjust_mid && error_count16 < ec_hi) + { + printf("/* adjust (high): %f: %u -> %u */\n", adjust, ec_hi, + error_count16); + ec_hi = error_count16; + adjust_hi = adjust; + } + + else + { + adjust = adjust_mid; + printf("/* adjust: %f: %u */\n", adjust, ec_mid); + break; + } + } + + /* For each entry in the table try to adjust it to minimize the error count + * in that entry. Each entry corresponds to 128 input values. + */ + for (ibase=0; ibase<65536; ibase+=128) + { + png_uint_16 base = png_sRGB_base[ibase >> 7], trybase = base, ob=base; + png_byte delta = png_sRGB_delta[ibase >> 7], trydelta = delta, od=delta; + unsigned int ecbase = 0, eco; + + for (;;) + { + png_sRGB_base[ibase >> 7] = trybase; + png_sRGB_delta[ibase >> 7] = trydelta; + + /* Check the 16-bit linear values alone: */ + error_count16 = 0; + for (i16=ibase; i16 < ibase+128; ++i16) + { + unsigned int i = 255*i16; + unsigned int iexact = nearbyint(255*sRGB(i)); + unsigned int icalc = PNG_sRGB_FROM_LINEAR(i); + + if (icalc != iexact) + ++error_count16; + } + + if (error_count16 == 0) + break; + + if (ecbase == 0) + { + eco = ecbase = error_count16; + ++trybase; /* First test */ + } + + else if (error_count16 < ecbase) + { + if (trybase > base) + { + base = trybase; + ++trybase; + } + else if (trybase < base) + { + base = trybase; + --trybase; + } + else if (trydelta > delta) + { + delta = trydelta; + ++trydelta; + } + else if (trydelta < delta) + { + delta = trydelta; + --trydelta; + } + else + { + fprintf(stderr, "makesRGB: impossible\n"); + exit(1); + } + ecbase = error_count16; + } + + else + { + if (trybase > base) + trybase = base-1; + else if (trybase < base) + { + trybase = base; + ++trydelta; + } + else if (trydelta > delta) + trydelta = delta-1; + else if (trydelta < delta) + break; /* end of tests */ + } + } + + png_sRGB_base[ibase >> 7] = base; + png_sRGB_delta[ibase >> 7] = delta; + if (base != ob || delta != od) + { + printf("/* table[%u]={%u,%u} -> {%u,%u} %u -> %u errors */\n", + ibase>>7, ob, od, base, delta, eco, ecbase); + } + else if (0) + printf("/* table[%u]={%u,%u} %u errors */\n", ibase>>7, ob, od, + ecbase); + } + + /* Only do the full (slow) test at the end: */ + min_error = -.4999; + max_error = .4999; + error_count = 0; + + for (i=0; i <= max_input; ++i) + { + unsigned int iexact = nearbyint(255*sRGB(i)); + unsigned int icalc = PNG_sRGB_FROM_LINEAR(i); + + if (icalc != iexact) + { + double err = 255*sRGB(i) - icalc; + + if (err > (max_error+.001) || err < (min_error-.001)) + { + printf( + "/* 0x%08x: exact: %3d, got: %3d [tables: %08x, %08x] (%f) */\n", + i, iexact, icalc, png_sRGB_base[i>>15], + png_sRGB_delta[i>>15], err); + } + + ++error_count; + if (err > max_error) + max_error = err; + else if (err < min_error) + min_error = err; + } + } + + /* Re-check the 16-bit cases too, including the warning if there is an error + * bigger than 1. + */ + error_count16 = 0; + max_error16 = 0; + min_error16 = 0; + for (i16=0; i16 <= 65535; ++i16) + { + unsigned int i = 255*i16; + unsigned int iexact = nearbyint(255*sRGB(i)); + unsigned int icalc = PNG_sRGB_FROM_LINEAR(i); + + if (icalc != iexact) + { + double err = 255*sRGB(i) - icalc; + + ++error_count16; + if (err > max_error16) + max_error16 = err; + else if (err < min_error16) + min_error16 = err; + + if (abs(icalc - iexact) > 1) + printf( + "/* 0x%04x: exact: %3d, got: %3d [tables: %08x, %08x] (%f) */\n", + i16, iexact, icalc, png_sRGB_base[i>>15], + png_sRGB_delta[i>>15], err); + } + } + + /* Check the round trip for each 8-bit sRGB value. */ + for (i16=0; i16 <= 255; ++i16) + { + unsigned int i = 255 * png_sRGB_table[i16]; + unsigned int iexact = nearbyint(255*sRGB(i)); + unsigned int icalc = PNG_sRGB_FROM_LINEAR(i); + + if (i16 != iexact) + { + fprintf(stderr, "8-bit rounding error: %d -> %d\n", i16, iexact); + exit(1); + } + + if (icalc != i16) + { + double finv = finvsRGB(i16); + + printf("/* 8-bit roundtrip error: %d -> %f -> %d(%f) */\n", + i16, finv, icalc, fsRGB(255*finv)); + } + } + + + printf("/* error: %g - %g, %u (%g%%) of readings inexact */\n", + min_error, max_error, error_count, (100.*error_count)/max_input); + printf("/* 16-bit error: %g - %g, %u (%g%%) of readings inexact */\n", + min_error16, max_error16, error_count16, (100.*error_count16)/65535); + + if (!test_only) + { + printf("PNG_CONST png_uint_16 png_sRGB_table[256] =\n{\n "); + for (i=0; i<255; ) + { + do + { + printf("%d,", png_sRGB_table[i++]); + } + while ((i & 0x7) != 0 && i<255); + if (i<255) printf("\n "); + } + printf("%d\n};\n\n", png_sRGB_table[i]); + + + printf("PNG_CONST png_uint_16 png_sRGB_base[512] =\n{\n "); + for (i=0; i<511; ) + { + do + { + printf("%d,", png_sRGB_base[i++]); + } + while ((i & 0x7) != 0 && i<511); + if (i<511) printf("\n "); + } + printf("%d\n};\n\n", png_sRGB_base[i]); + + printf("PNG_CONST png_byte png_sRGB_delta[512] =\n{\n "); + for (i=0; i<511; ) + { + do + { + printf("%d,", png_sRGB_delta[i++]); + } + while ((i & 0xf) != 0 && i<511); + if (i<511) printf("\n "); + } + printf("%d\n};\n\n", png_sRGB_delta[i]); + } + + return 0; +} diff -ru4NwbB libpng-1.5.6/contrib/sRGBtables/sRGB.h libpng-1.5.7beta04/contrib/sRGBtables/sRGB.h --- libpng-1.5.6/contrib/sRGBtables/sRGB.h 1969-12-31 18:00:00.000000000 -0600 +++ libpng-1.5.7beta04/contrib/sRGBtables/sRGB.h 2011-11-17 21:02:59.672155634 -0600 @@ -0,0 +1,41 @@ +/*- + * sRGB.h + * + * Utility file; not actually a header, this contains definitions of sRGB + * calculation functions for inclusion in those test programs that need them. + * + * All routines take and return a floating point value in the range + * 0 to 1.0, doing a calculation according to the sRGB specification + * (in fact the source of the numbers is the wikipedia article at + * http://en.wikipedia.org/wiki/SRGB). + */ +static double +sRGB_from_linear(double l) +{ + if (l <= 0.0031308) + l *= 12.92; + + else + l = 1.055 * pow(l, 1/2.4) - 0.055; + + return l; +} + +static double +linear_from_sRGB(double s) +{ + if (s <= 0.04045) + return s / 12.92; + + else + return pow((s+0.055)/1.055, 2.4); +} + +static double +YfromRGB(double r, double g, double b) +{ + /* Use the sRGB (rounded) coefficients for Rlinear, Glinear, Blinear to get + * the CIE Y value (also linear). + */ + return 0.2126 * r + 0.7152 * g + 0.0722 * b; +} diff -ru4NwbB libpng-1.5.6/example.c libpng-1.5.7beta04/example.c --- libpng-1.5.6/example.c 2011-11-02 22:42:50.387042477 -0500 +++ libpng-1.5.7beta04/example.c 2011-11-17 21:02:56.958154474 -0600 @@ -1,9 +1,9 @@ #if 0 /* in case someone actually tries to compile this */ /* example.c - an example of using libpng - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.6 [November 3, 2011] * This file has been placed in the public domain by the authors. * Maintained 1998-2011 Glenn Randers-Pehrson * Maintained 1996, 1997 Andreas Dilger) * Written 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) diff -ru4NwbB libpng-1.5.6/png.c libpng-1.5.7beta04/png.c --- libpng-1.5.6/png.c 2011-11-02 22:42:50.399590772 -0500 +++ libpng-1.5.7beta04/png.c 2011-11-17 21:02:56.971141860 -0600 @@ -1,8 +1,8 @@ /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * Copyright (c) 1998-2011 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.) * @@ -2853,5 +2853,263 @@ #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ } } #endif /* READ_GAMMA */ + +/* sRGB support */ +#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\ + defined PNG_SIMPLIFIED_WRITE_SUPPORTED +/* sRGB conversion tables; these are machine generated with the code in + * contrib/sRGBtables/makesRGB.c. The sRGB to linear table is exact (to the + * nearest 16 bit linear fraction). The inverse (linear to sRGB) table has + * accuracies as follows: + * + * For all possible (255*65535+1) input values: + * + * error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact + * + * For the input values corresponding to the 65536 16-bit values: + * + * error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact + * + * In all cases the inexact readings are off by one. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* The convert-to-sRGB table is only currently required for read. */ +PNG_CONST_DATA png_uint_16 png_sRGB_table[256] = +{ + 0,20,40,60,80,99,119,139, + 159,179,199,219,241,264,288,313, + 340,367,396,427,458,491,526,562, + 599,637,677,718,761,805,851,898, + 947,997,1048,1101,1156,1212,1270,1330, + 1391,1453,1517,1583,1651,1720,1790,1863, + 1937,2013,2090,2170,2250,2333,2418,2504, + 2592,2681,2773,2866,2961,3058,3157,3258, + 3360,3464,3570,3678,3788,3900,4014,4129, + 4247,4366,4488,4611,4736,4864,4993,5124, + 5257,5392,5530,5669,5810,5953,6099,6246, + 6395,6547,6700,6856,7014,7174,7335,7500, + 7666,7834,8004,8177,8352,8528,8708,8889, + 9072,9258,9445,9635,9828,10022,10219,10417, + 10619,10822,11028,11235,11446,11658,11873,12090, + 12309,12530,12754,12980,13209,13440,13673,13909, + 14146,14387,14629,14874,15122,15371,15623,15878, + 16135,16394,16656,16920,17187,17456,17727,18001, + 18277,18556,18837,19121,19407,19696,19987,20281, + 20577,20876,21177,21481,21787,22096,22407,22721, + 23038,23357,23678,24002,24329,24658,24990,25325, + 25662,26001,26344,26688,27036,27386,27739,28094, + 28452,28813,29176,29542,29911,30282,30656,31033, + 31412,31794,32179,32567,32957,33350,33745,34143, + 34544,34948,35355,35764,36176,36591,37008,37429, + 37852,38278,38706,39138,39572,40009,40449,40891, + 41337,41785,42236,42690,43147,43606,44069,44534, + 45002,45473,45947,46423,46903,47385,47871,48359, + 48850,49344,49841,50341,50844,51349,51858,52369, + 52884,53401,53921,54445,54971,55500,56032,56567, + 57105,57646,58190,58737,59287,59840,60396,60955, + 61517,62082,62650,63221,63795,64372,64952,65535 +}; + +#endif /* simplified read only */ + +/* The base/delta tables are required for both read and write (but currently + * only the simplified versions.) + */ +PNG_CONST_DATA png_uint_16 png_sRGB_base[512] = +{ + 128,1782,3383,4644,5675,6564,7357,8074, + 8732,9346,9921,10463,10977,11466,11935,12384, + 12816,13233,13634,14024,14402,14769,15125,15473, + 15812,16142,16466,16781,17090,17393,17690,17981, + 18266,18546,18822,19093,19359,19621,19879,20133, + 20383,20630,20873,21113,21349,21583,21813,22041, + 22265,22487,22707,22923,23138,23350,23559,23767, + 23972,24175,24376,24575,24772,24967,25160,25352, + 25542,25730,25916,26101,26284,26465,26645,26823, + 27000,27176,27350,27523,27695,27865,28034,28201, + 28368,28533,28697,28860,29021,29182,29341,29500, + 29657,29813,29969,30123,30276,30429,30580,30730, + 30880,31028,31176,31323,31469,31614,31758,31902, + 32045,32186,32327,32468,32607,32746,32884,33021, + 33158,33294,33429,33564,33697,33831,33963,34095, + 34226,34357,34486,34616,34744,34873,35000,35127, + 35253,35379,35504,35629,35753,35876,35999,36122, + 36244,36365,36486,36606,36726,36845,36964,37083, + 37201,37318,37435,37551,37668,37783,37898,38013, + 38127,38241,38354,38467,38580,38692,38803,38915, + 39026,39136,39246,39356,39465,39574,39682,39790, + 39898,40005,40112,40219,40325,40431,40537,40642, + 40747,40851,40955,41059,41163,41266,41369,41471, + 41573,41675,41777,41878,41979,42079,42179,42279, + 42379,42478,42577,42676,42775,42873,42971,43068, + 43165,43262,43359,43456,43552,43648,43743,43839, + 43934,44028,44123,44217,44311,44405,44499,44592, + 44685,44778,44870,44962,45054,45146,45238,45329, + 45420,45511,45601,45692,45782,45872,45961,46051, + 46140,46229,46318,46406,46494,46583,46670,46758, + 46846,46933,47020,47107,47193,47280,47366,47452, + 47538,47623,47709,47794,47879,47964,48048,48133, + 48217,48301,48385,48468,48552,48635,48718,48801, + 48884,48966,49048,49131,49213,49294,49376,49458, + 49539,49620,49701,49782,49862,49943,50023,50103, + 50183,50263,50342,50422,50501,50580,50659,50738, + 50816,50895,50973,51051,51129,51207,51285,51362, + 51439,51517,51594,51671,51747,51824,51900,51977, + 52053,52129,52205,52280,52356,52432,52507,52582, + 52657,52732,52807,52881,52956,53030,53104,53178, + 53252,53326,53400,53473,53546,53620,53693,53766, + 53839,53911,53984,54056,54129,54201,54273,54345, + 54417,54489,54560,54632,54703,54774,54845,54916, + 54987,55058,55129,55199,55269,55340,55410,55480, + 55550,55620,55689,55759,55828,55898,55967,56036, + 56105,56174,56243,56311,56380,56448,56517,56585, + 56653,56721,56789,56857,56924,56992,57059,57127, + 57194,57261,57328,57395,57462,57529,57595,57662, + 57728,57795,57861,57927,57993,58059,58125,58191, + 58256,58322,58387,58453,58518,58583,58648,58713, + 58778,58843,58908,58972,59037,59101,59165,59230, + 59294,59358,59422,59486,59549,59613,59677,59740, + 59804,59867,59930,59993,60056,60119,60182,60245, + 60308,60370,60433,60495,60558,60620,60682,60744, + 60806,60868,60930,60992,61054,61115,61177,61238, + 61300,61361,61422,61483,61544,61605,61666,61727, + 61788,61848,61909,61969,62030,62090,62150,62211, + 62271,62331,62391,62450,62510,62570,62630,62689, + 62749,62808,62867,62927,62986,63045,63104,63163, + 63222,63281,63340,63398,63457,63515,63574,63632, + 63691,63749,63807,63865,63923,63981,64039,64097, + 64155,64212,64270,64328,64385,64443,64500,64557, + 64614,64672,64729,64786,64843,64900,64956,65013, + 65070,65126,65183,65239,65296,65352,65409,65465 +}; + +PNG_CONST_DATA png_byte png_sRGB_delta[512] = +{ + 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54, + 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36, + 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28, + 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24, + 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21, + 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19, + 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17, + 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16, + 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15, + 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14, + 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13, + 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, + 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, + 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, + 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, + 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; +#endif /* SIMPLIFIED READ/WRITE sRGB support */ + +/* SIMPLIFIED READ/WRITE SUPPORT */ +#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\ + defined PNG_SIMPLIFIED_WRITE_SUPPORTED +static int +png_image_free_function(png_voidp argument) +{ + png_imagep image = png_voidcast(png_imagep, argument); + png_controlp cp = image->opaque; + png_control c; + + /* Double check that we have a png_ptr - it should be impossible to get here + * without one. + */ + if (cp->png_ptr == NULL) + return 0; + + /* First free any data held in the control structure. */ +# ifdef PNG_STDIO_SUPPORTED + if (cp->owned_file) + { + FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr); + cp->owned_file = 0; + + /* Ignore errors here. */ + if (fp != NULL) + { + cp->png_ptr->io_ptr = NULL; + (void)fclose(fp); + } + } +# endif + + /* Copy the control structure so that the original, allocated, version can be + * safely freed. Notice that a png_error here stops the remainder of the + * cleanup, but this is probably fine because that would indicate bad memory + * problems anyway. + */ + c = *cp; + image->opaque = &c; + png_free(c.png_ptr, cp); + + /* Then the structures, calling the correct API. */ + if (c.for_write) + { +# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED + png_destroy_write_struct(&c.png_ptr, &c.info_ptr); +# else + png_error(c.png_ptr, "simplified write not supported"); +# endif + } + else + { +# ifdef PNG_SIMPLIFIED_READ_SUPPORTED + png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL); +# else + png_error(c.png_ptr, "simplified read not supported"); +# endif + } + + /* Success. */ + return 1; +} + +void PNGAPI +png_image_free(png_imagep image) +{ + /* Safely call the real function, but only if doing so is safe at this point + * (if not inside an error handling context). Otherwise assume + * png_safe_execute will call this API after the return. + */ + if (image != NULL && image->opaque != NULL && + image->opaque->error_buf == NULL) + { + /* Ignore errors here: */ + (void)png_safe_execute(image, png_image_free_function, image); + image->opaque = NULL; + } +} + +int /* PRIVATE */ +png_image_error(png_imagep image, png_const_charp error_message) +{ + /* Utility to log an error. */ + png_safecat(image->message, sizeof image->message, 0, error_message); + image->warning_or_error = 1; + png_image_free(image); + return 0; +} + +#endif /* SIMPLIFIED READ/WRITE */ #endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */ diff -ru4NwbB libpng-1.5.6/png.h libpng-1.5.7beta04/png.h --- libpng-1.5.6/png.h 2011-11-02 22:42:50.344556602 -0500 +++ libpng-1.5.7beta04/png.h 2011-11-17 21:02:56.914600464 -0600 @@ -162,8 +162,9 @@ * 1.5.5 15 10505 15.so.15.5[.0] * 1.5.6beta01-07 15 10506 15.so.15.6[.0] * 1.5.6rc01-03 15 10506 15.so.15.6[.0] * 1.5.6 15 10506 15.so.15.6[.0] + * 1.5.7beta01-04 15 10507 15.so.15.7[.0] * * Henceforth the source version will match the shared-library major * and minor numbers; the shared-library major version number will be * used for changes in backward compatibility, as it is intended. The @@ -363,27 +364,30 @@ /* This is not the place to learn how to use libpng. The file libpng-manual.txt * describes how to use libpng, and the file example.c summarizes it * with some code on which to build. This file is useful for looking * at the actual function definitions and structure components. + * + * If you just need to read a PNG file and don't want to read the documentation + * skip to the end of this file and read the section entitled 'simplified API'. */ /* Version information for png.h - this should match the version in png.c */ #define PNG_LIBPNG_VER_STRING "1.5.7beta04" #define PNG_HEADER_VERSION_STRING \ " libpng version 1.5.7beta04 - November 18, 2011\n" -#define PNG_LIBPNG_VER_SONUM %SONUM% -#define PNG_LIBPNG_VER_DLLNUM %DLLNUM% +#define PNG_LIBPNG_VER_SONUM 15 +#define PNG_LIBPNG_VER_DLLNUM 15 /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ -#define PNG_LIBPNG_VER_MAJOR %MAJOR% -#define PNG_LIBPNG_VER_MINOR %MINOR% -#define PNG_LIBPNG_VER_RELEASE %RELEASE% +#define PNG_LIBPNG_VER_MAJOR 1 +#define PNG_LIBPNG_VER_MINOR 5 +#define PNG_LIBPNG_VER_RELEASE 7 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ -#define PNG_LIBPNG_VER_BUILD %BUILDNUM% +#define PNG_LIBPNG_VER_BUILD 02 /* Release Status */ #define PNG_LIBPNG_BUILD_ALPHA 1 #define PNG_LIBPNG_BUILD_BETA 2 @@ -406,9 +410,9 @@ * Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER %VER_NUM% /* %MAJOR%.%MINOR%.%RELEASE% */ +#define PNG_LIBPNG_VER 10507 /* 1.5.7 */ /* Library configuration: these options cannot be changed after * the library has been built. */ @@ -486,8 +490,9 @@ * code when it is built. (Build time configuration is in pnglibconf.h) * 2. Type definitions (base types are defined in pngconf.h), structure * definitions. * 3. Exported library functions. + * 4. Simplified API. * * The library source code has additional files (principally pngpriv.h) that * allow configuration of the library. */ @@ -1122,8 +1127,13 @@ #endif #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED /* Reduce RGB to grayscale. */ +#define PNG_ERROR_ACTION_NONE 1 +#define PNG_ERROR_ACTION_WARN 2 +#define PNG_ERROR_ACTION_ERROR 3 +#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ + PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr, int error_action, double red, double green)); PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr, int error_action, png_fixed_point red, png_fixed_point green)); @@ -2609,8 +2619,292 @@ ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ : (png_int_32)png_get_uint_32(buf))) #endif +/******************************************************************************* + * SIMPLIFIED API + ******************************************************************************* + * + * Please read the documentation in libpng-manual.txt if you don't understand + * what follows. + * + * The simplified API hides the details of both libpng and the PNG file format + * itself. It allows PNG files to be read into a very limited number of + * in-memory bitmap formats or to be written from the same formats. If these + * formats do not accomodate your needs then you can, and should, use the more + * sophisticated APIs above - these support a wide variety of in-memory formats + * and a wide variety of sophisticated transformations to those formats as well + * as a wide variety of APIs to manipulate ancilliary information. + * + * To read a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure (see below) on the stack and memset() it + * to all zero. + * 2) Call the appropriate png_image_begin_read... function. + * 3) Set the png_image 'format' member to the required format and allocate a + * buffer for the image. + * 4) Call png_image_finish_read to read the image into your buffer. + * + * There are no restrictions on the format of the PNG input itself; all valid + * color types, bit depths, and interlace methods are acceptable, and the + * input image is transformed as necessary to the requested in-memory format + * during the png_image_finish_read() step. + * + * To write a PNG file using the simplified API: + * + * 1) Declare a 'png_image' structure on the stack and memset() it to all zero. + * 2) Initialize the members of the structure that describe the image, setting + * the 'format' member to the format of the image in memory. + * 3) Call the appropriate png_image_write... function with a pointer to the + * image to write the PNG data. + * + * png_image is a structure that describes the in-memory format of an image + * when it is being read or define the in-memory format of an image that you + * need to write: + * + */ + +typedef struct png_control *png_controlp; +typedef struct +{ + png_uint_32 width; /* Image width in pixels (columns) */ + png_uint_32 height; /* Image height in pixels (rows) */ + png_uint_32 format; /* Image format as defined below */ + png_uint_32 flags; /* A bit mask containing informational flags */ + png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + + /* In the event of an error or warning the following field will be set to a + * non-zero value and the 'message' field will contain a '\0' terminated + * string with the libpng error or warning message. If both warnings and + * an error were encountered, only the error is recorded. If there + * are multiple warnings, only the first one is recorded. + * + * As of libpng-1.5.7 the values are + * 0 - no warning or error + * 1 - error + * 2 - warning + */ + png_uint_32 warning_or_error; + char message[64]; +} png_image, *png_imagep; + +/* The pixels (samples) of the image have one to four channels whose components + * have original values in the range 0 to 1.0: + * + * 1: A single gray or luminance channel (G). + * 2: A gray/luminance channel and an alpha channel (GA). + * 3: Three red, green, blue color channels (RGB). + * 4: Three color channels and an alpha channel (RGBA). + * + * The channels are encoded in one of two ways: + * + * a) As a small integer, value 0..255, contained in a (png_byte). For the + * alpha channel the original value is simply value/255. For the color or + * luminance channels the value is encoded according to the sRGB specification + * and matches the 8-bit format expected by typical display devices. + * + * The color/gray channels are not scaled (pre-multiplied) by the alpha + * channel and are suitable for passing to color management software. + * + * b) As a value in the range 0..65535, contained in a (png_uint_16). All + * channels can be converted to the original value by dividing by 65535; all + * channels are linear. Color channels use the RGB encoding (RGB end-points) of + * the sRGB specification. This encoding is identified by the + * PNG_FORMAT_FLAG_LINEAR flag below. + * + * When an alpha channel is present it is expected to denote pixel coverage + * of the color or luminance channels and is returned as an associated alpha + * channel: the color/gray channels are scaled (pre-multiplied) by the alpha + * value. + */ + +/* PNG_FORMAT_* + * + * #defines to be used in png_image::format. Each #define identifies a + * particular layout of channel data and, if present, alpha values. There are + * separate defines for each of the two channel encodings. + * + * A format is built up using single bit flag values. Not all combinations are + * valid: use the bit flag values below for testing a format returned by the + * read APIs, but set formats from the derived values. + * + * NOTE: libpng can be built with particular features disabled, if you see + * compiler errors because the definition of one of the following flags has been + * compiled out it is because libpng does not have the required support. It is + * possible, however, for the libpng configuration to enable the format on just + * read or just write; in that case you may see an error at run time. You can + * guard against this by checking for the definition of: + * + * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED + */ +#define PNG_FORMAT_FLAG_ALPHA 0x01 /* format with an alpha channel */ +#define PNG_FORMAT_FLAG_COLOR 0x02 /* color format: otherwise grayscale */ +#define PNG_FORMAT_FLAG_LINEAR 0x04 /* png_uint_16 channels else png_byte */ + +#ifdef PNG_FORMAT_BGR_SUPPORTED +# define PNG_FORMAT_FLAG_BGR 0x08 /* BGR colors, else order is RGB */ +#endif + +#ifdef PNG_FORMAT_AFIRST_SUPPORTED +# define PNG_FORMAT_FLAG_AFIRST 0x10 /* alpha channel comes first */ +#endif + +/* Supported formats are as follows. Future versions of libpng may support more + * formats; for compatibility with older versions simply check if the format + * macro is defined using #ifdef. These defines describe the in-memory layout + * of the components of the pixels of the image. + * + * First the single byte formats: + */ +#define PNG_FORMAT_GRAY 0 +#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA +#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR +#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) +#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) +#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + +/* Then the linear (png_uint_16) formats. When naming these "Y" is used to + * indicate a luminance (gray) channel. The component order within the pixel + * is always the same - there is no provision for swapping the order of the + * components in the linear format. + */ +#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR +#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) +#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) +#define PNG_FORMAT_LINEAR_RGB_ALPHA \ + (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA) + +/* PNG_IMAGE macros + * + * These are convenience macros to derive information from a png_image structure + */ +#define PNG_IMAGE_CHANNELS(fmt)\ + (1+((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))) + /* Return the total number of channels in a given format: 1..4 */ + +#define PNG_IMAGE_COMPONENT_SIZE(fmt)\ + (((fmt) & PNG_FORMAT_FLAG_LINEAR) ? sizeof (png_uint_16) : sizeof (png_byte)) + /* Return the size in bytes of a single component of a pixel in the image. */ + +#define PNG_IMAGE_PIXEL_SIZE(fmt)\ + (PNG_IMAGE_CHANNELS(fmt) * PNG_IMAGE_COMPONENT_SIZE(fmt)) + /* Return the size in bytes of a single pixel in the image. */ + +#define PNG_IMAGE_ROW_STRIDE(image)\ + (PNG_IMAGE_CHANNELS((image).format) * (image).width) + /* Return the total number of components in a single row of the image; this + * is the minimum 'row stride', the minimum count of components between each + * row. + */ + +#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ + (PNG_IMAGE_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. + */ + +/* PNG_IMAGE_FLAG_* + * + * Flags containing additional information about the image are held in the + * 'flags' field of png_image. + */ +#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 1 + /* This indicates the the RGB values of the in-memory bitmap do not + * correspond to the red, green and blue end-points defined by sRGB. + */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* READ APIs + * --------- + * + * The png_image passed to the read APIs must have been initialized by setting + * the png_controlp field 'opaque' to NULL (or, better, memset the whole thing.) + */ +#ifdef PNG_STDIO_SUPPORTED +PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, + const char *file_name)); + /* The named file is opened for read and the image header is filled in + * from the PNG header in the file. + */ + +PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, + FILE* file)); + /* The PNG header is read from the stdio FILE object. */ +#endif /* PNG_STDIO_SUPPORTED */ + +PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, + png_const_voidp memory, png_size_t size)); + /* The PNG header is read from the given memory buffer. */ + +PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, + png_colorp background, void *buffer, png_int_32 row_stride)); + /* Finish reading the image into the supplied buffer and clean up the + * png_image structure. + * + * row_stride is the step, in png_byte or png_uint_16 units as appropriate, + * between adjacent rows. A positive stride indicates that the top-most row + * is first in the buffer - the normal top-down arrangement. A negative + * stride indicates that the bottom-most row is first in the buffer. + * + * background need only be supplied if an alpha channel must be removed from + * a png_byte format and the removal is to be done by compositing on a solid + * color; otherwise it may be NULL and any composition will be done directly + * onto the buffer. The value is an sRGB color to use for the background, + * for grayscale output the green channel is used. + * + * For linear output removing the alpha channel is always done by compositing + * on black. + */ + +PNG_EXPORT(238, void, png_image_free, (png_imagep image)); + /* Free any data allocated by libpng in image->opaque, setting the pointer to + * NULL. May be called at any time after the structure is initialized. + */ +#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ + +#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED +/* WRITE APIS + * ---------- + * For write you must initialize a png_image structure to describe the image to + * be written: + * + * opaque: must be initialized to NULL + * width: image width in pixels + * height: image height in rows + * format: the format of the data you wish to write + * flags: set to 0 unless one of the defined flags applies; set + * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB + * values do not correspond to the colors in sRGB. + */ +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)); + /* Write the image to the named file. */ + +PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, + int convert_to_8_bit, const void *buffer, png_int_32 row_stride)); + /* Write the image to the given (FILE*). */ + +/* With all write APIs if image is in one of the linear formats with + * (png_uint_16) data then setting convert_to_8_bit will cause the output to be + * a (png_byte) PNG gamma encoded according to the sRGB specification, otherwise + * a 16-bit linear encoded PNG file is written. + * + * 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 (float) and if negative + * indicates a bottom-up row layout in the buffer. + * + * Note that the write API does not support interlacing, sub-8-bit pixels, + * and indexed (paletted) images. + */ +#endif /* PNG_SIMPLIFIED_WRITE_SUPPORTED */ +/******************************************************************************* + * END OF SIMPLIFIED API + ******************************************************************************/ + /* Maintainer: Put new public prototypes here ^, in libpng.3, and project * defs */ @@ -2618,9 +2912,9 @@ * one to use is one more than this.) Maintainer, remember to add an entry to * scripts/symbols.def as well. */ #ifdef PNG_EXPORT_LAST_ORDINAL - PNG_EXPORT_LAST_ORDINAL(233); + PNG_EXPORT_LAST_ORDINAL(240); #endif #ifdef __cplusplus } diff -ru4NwbB libpng-1.5.6/pngerror.c libpng-1.5.7beta04/pngerror.c --- libpng-1.5.6/pngerror.c 2011-11-02 22:42:50.406539999 -0500 +++ libpng-1.5.7beta04/pngerror.c 2011-11-17 21:02:56.978349529 -0600 @@ -1,8 +1,8 @@ /* pngerror.c - stub functions for i/o and memory allocation * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * Copyright (c) 1998-2011 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.) * @@ -672,5 +672,88 @@ PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); } } #endif + +#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\ + defined PNG_SIMPLIFIED_WRITE_SUPPORTED + /* Currently the above both depend on SETJMP_SUPPORTED, however it would be + * possible to implement without setjmp support just so long as there is some + * way to handle the error return here: + */ +PNG_FUNCTION(void /* PRIVATE */, +png_safe_error,(png_structp png_ptr, png_const_charp error_message), + PNG_NORETURN) +{ + png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); + + /* An error is always logged here, overwriting anything (typically a warning) + * that is already there: + */ + if (image != NULL) + { + png_safecat(image->message, sizeof image->message, 0, error_message); + image->warning_or_error = 1; + + /* Retrieve the jmp_buf from within the png_control, making this work for + * C++ compilation too is pretty tricky: C++ wants a pointer to the first + * element of a jmp_buf, but C doesn't tell us the type of that. + */ + if (image->opaque != NULL && image->opaque->error_buf != NULL) + longjmp(png_control_jmp_buf(image->opaque), 1); + + /* Missing longjmp buffer, the following is to help debugging: */ + { + size_t pos = png_safecat(image->message, sizeof image->message, 0, + "bad longjmp: "); + png_safecat(image->message, sizeof image->message, pos, error_message); + } + } + + /* Here on an internal programming error. */ + abort(); +} + +#ifdef PNG_WARNINGS_SUPPORTED +void /* PRIVATE */ +png_safe_warning(png_structp png_ptr, png_const_charp warning_message) +{ + png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); + + /* A warning is only logged if there is no prior warning or error. */ + if (image->warning_or_error == 0) + { + png_safecat(image->message, sizeof image->message, 0, warning_message); + image->warning_or_error = 2; + } +} +#endif + +int /* PRIVATE */ +png_safe_execute(png_imagep imageIn, int (*function)(png_voidp), png_voidp arg) +{ + volatile png_imagep image = imageIn; + volatile int result; + volatile png_voidp saved_error_buf; + jmp_buf safe_jmpbuf; + + /* Safely execute function(arg) with png_error returning to this function. */ + saved_error_buf = image->opaque->error_buf; + result = setjmp(safe_jmpbuf) == 0; + + if (result) + { + + image->opaque->error_buf = safe_jmpbuf; + result = function(arg); + } + + image->opaque->error_buf = saved_error_buf; + + /* And do the cleanup prior to any failure return. */ + if (!result) + png_image_free(image); + + return result; +} +#endif /* SIMPLIFIED READ/WRITE */ #endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */ diff -ru4NwbB libpng-1.5.6/pngget.c libpng-1.5.7beta04/pngget.c --- libpng-1.5.6/pngget.c 2011-11-02 22:42:50.414779399 -0500 +++ libpng-1.5.7beta04/pngget.c 2011-11-17 21:02:56.986661549 -0600 @@ -1,8 +1,8 @@ /* pngget.c - retrieval of values from info struct * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * Copyright (c) 1998-2011 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.) * @@ -681,17 +681,18 @@ { png_debug1(1, "in %s retrieval function", "iCCP"); if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) - && name != NULL && profile != NULL && proflen != NULL) + && name != NULL && compression_type != NULL && profile != NULL && + proflen != NULL) { *name = info_ptr->iccp_name; *profile = info_ptr->iccp_profile; /* Compression_type is a dummy so the API won't have to change * if we introduce multiple compression types later. */ - *proflen = (int)info_ptr->iccp_proflen; - *compression_type = (int)info_ptr->iccp_compression; + *proflen = info_ptr->iccp_proflen; + *compression_type = info_ptr->iccp_compression; return (PNG_INFO_iCCP); } return (0); diff -ru4NwbB libpng-1.5.6/pngmem.c libpng-1.5.7beta04/pngmem.c --- libpng-1.5.6/pngmem.c 2011-11-02 22:42:50.421685471 -0500 +++ libpng-1.5.7beta04/pngmem.c 2011-11-17 21:02:56.993587443 -0600 @@ -1,8 +1,8 @@ /* pngmem.c - stub functions for memory allocation * - * Last changed in libpng 1.5.4 [July 7, 2011] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * Copyright (c) 1998-2011 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.) * @@ -55,11 +55,11 @@ # ifdef PNG_USER_MEM_SUPPORTED if (malloc_fn != NULL) { png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - struct_ptr = (*(malloc_fn))(png_ptr, (png_uint_32)size); + memset(&dummy_struct, 0, sizeof dummy_struct); + dummy_struct.mem_ptr=mem_ptr; + struct_ptr = (*(malloc_fn))(&dummy_struct, (png_alloc_size_t)size); } else # endif /* PNG_USER_MEM_SUPPORTED */ @@ -89,11 +89,11 @@ # ifdef PNG_USER_MEM_SUPPORTED if (free_fn != NULL) { png_struct dummy_struct; - png_structp png_ptr = &dummy_struct; - png_ptr->mem_ptr=mem_ptr; - (*(free_fn))(png_ptr, struct_ptr); + memset(&dummy_struct, 0, sizeof dummy_struct); + dummy_struct.mem_ptr=mem_ptr; + (*(free_fn))(&dummy_struct, struct_ptr); return; } # endif /* PNG_USER_MEM_SUPPORTED */ @@ -142,9 +142,9 @@ return (NULL); # ifdef PNG_USER_MEM_SUPPORTED if (png_ptr->malloc_fn != NULL) - ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size)); + ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size)); else ret = (png_malloc_default(png_ptr, size)); diff -ru4NwbB libpng-1.5.6/pngpread.c libpng-1.5.7beta04/pngpread.c --- libpng-1.5.6/pngpread.c 2011-11-02 22:42:50.431199446 -0500 +++ libpng-1.5.7beta04/pngpread.c 2011-11-17 21:02:57.003149445 -0600 @@ -1,8 +1,8 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * Copyright (c) 1998-2011 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.) * @@ -984,9 +984,9 @@ if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) { if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) - png_read_filter_row(&row_info, png_ptr->row_buf + 1, + png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, png_ptr->prev_row + 1, png_ptr->row_buf[0]); else png_error(png_ptr, "bad adaptive filter value"); } diff -ru4NwbB libpng-1.5.6/pngpriv.h libpng-1.5.7beta04/pngpriv.h --- libpng-1.5.6/pngpriv.h 2011-11-02 22:42:50.361693834 -0500 +++ libpng-1.5.7beta04/pngpriv.h 2011-11-17 21:02:56.932404256 -0600 @@ -5,9 +5,9 @@ * Copyright (c) 1998-2011 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.) * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h @@ -195,8 +195,25 @@ #ifndef PNG_STATIC # define PNG_STATIC static #endif +/* C99 restrict is used where possible, to do this 'restrict' is defined as + * empty if we can't be sure it is supported. configure builds have already + * done this work. + */ +#ifdef PNG_CONFIGURE_LIBPNG +# define PNG_RESTRICT restrict +#else + /* Modern compilers support restrict, but assume not for anything not + * recognized here: + */ +# if defined __GNUC__ || defined _MSC_VER || defined __WATCOMC__ +# define PNG_RESTRICT restrict +# else +# define PNG_RESTRICT +# endif +#endif + /* If warnings or errors are turned off the code is disabled or redirected here. * From 1.5.4 functions have been added to allow very limited formatting of * error and warning messages - this code will also be disabled here. */ @@ -216,17 +233,50 @@ # define png_chunk_error(s1,s2) png_err(s1) # define png_fixed_error(s1,s2) png_err(s1) #endif +/* C allows up-casts from (void*) to any pointer and (const void*) to any + * pointer to a const object. C++ regards this as a type error and requires an + * explicit, static, cast and provides the static_cast<> rune to ensure that + * const is not cast away. + */ +#ifdef __cplusplus +# define png_voidcast(type, value) static_cast(value) +#else +# define png_voidcast(type, value) (value) +#endif /* __cplusplus */ + #ifndef PNG_EXTERN /* The functions exported by PNG_EXTERN are internal functions, which * aren't usually used outside the library (as far as I know), so it is * debatable if they should be exported at all. In the future, when it * is possible to have run-time registry of chunk-handling functions, * some of these might be made available again. -# define PNG_EXTERN extern + * + * 1.5.7: turned the use of 'extern' back on, since it is localized to pngpriv.h + * it should be safe now (it is unclear why it was turned off.) */ -# define PNG_EXTERN +# define PNG_EXTERN extern +#endif + +#ifndef PNG_CONST_DATA +/* Some compilers fail if given an "extern const" data declaration followed by a + * "const" definition, therefore declaring const data in pngpriv.h is + * impossible, the following allows a work-round for the problematic compilers + * by defining -DPNG_NO_CONST_DATA on the command line (notice that this does + * not affect static const definitions, where there is no declaration.) + */ +# ifndef PNG_NO_CONST_DATA + /* List of compilers where "extern const" is known to be OK: */ +# if defined __GNUC__ || defined _MSC_VER || defined __WATCOMC__ +# define PNG_CONST_DATA const +# endif +# endif + + /* Default to disabling const data declarations: */ +# ifndef PNG_CONST_DATA +# define PNG_CONST_DATA /*const*/ +# endif #endif /* Some fixed point APIs are still required even if not exported because * they get used by the corresponding floating point APIs. This magic @@ -497,8 +547,28 @@ #define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \ abs((int)((c1).green) - (int)((c2).green)) + \ abs((int)((c1).blue) - (int)((c2).blue))) +/* Added to libpng-1.5.7: sRGB conversion tables */ +#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\ + defined PNG_SIMPLIFIED_WRITE_SUPPORTED +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +extern /*PRIVATE*/ PNG_CONST_DATA png_uint_16 png_sRGB_table[256]; + /* Convert from an sRGB encoded value 0..255 to a 16-bit linear value, + * 0..65535. This table gives the closes 16-bit answers (no errors). + */ +#endif + +extern /*PRIVATE*/ PNG_CONST_DATA png_uint_16 png_sRGB_base[512]; +extern /*PRIVATE*/ PNG_CONST_DATA png_byte png_sRGB_delta[512]; + +#define PNG_sRGB_FROM_LINEAR(linear) ((png_sRGB_base[(linear)>>15] +\ + ((((linear)&0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8) + /* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB + * encoded value with maximum error 0.646365. Note that the input is not a + * 16-bit value; it has been multiplied by 255! */ +#endif /* PNG_SIMPLIFIED_READ/WRITE */ + /* Added to libpng-1.2.6 JB */ #define PNG_ROWBYTES(pixel_bits, width) \ ((pixel_bits) >= 8 ? \ ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ @@ -921,11 +991,26 @@ /* Unfilter a row: check the filter value before calling this, there is no point * calling it for PNG_FILTER_VALUE_NONE. */ -PNG_EXTERN void png_read_filter_row PNGARG((png_row_infop row_info, +PNG_EXTERN void png_read_filter_row PNGARG((png_structp pp, png_row_infop row_info, png_bytep row, png_const_bytep prev_row, int filter)); +PNG_EXTERN void png_read_filter_row_up_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_sub3_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_sub4_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_avg3_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_avg4_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_paeth3_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); +PNG_EXTERN void png_read_filter_row_paeth4_neon PNGARG((png_row_infop row_info, + png_bytep row, png_const_bytep prev_row)); + /* Choose the best filter to use and filter the row data */ PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr, png_row_infop row_info)); @@ -1572,8 +1657,58 @@ PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr, int bit_depth)); #endif +/* SIMPLIFIED READ/WRITE SUPPORT */ +#if defined PNG_SIMPLIFIED_READ_SUPPORTED ||\ + defined PNG_SIMPLIFIED_WRITE_SUPPORTED +/* The internal structure that png_image::opaque points to. */ +typedef struct png_control +{ + png_structp png_ptr; + png_infop info_ptr; + png_voidp error_buf; /* Always a jmp_buf at present. */ + + png_const_bytep memory; /* Memory buffer. */ + png_size_t size; /* Size of the memory buffer. */ + + unsigned int for_write :1; /* Otherwise it is a read structure */ + unsigned int owned_file :1; /* We own the file in io_ptr */ +} png_control; + +/* Return the pointer to the jmp_buf from a png_control: necessary because C + * does not reveal the type of the elements of jmp_buf. + */ +#ifdef __cplusplus +# define png_control_jmp_buf(pc) (((jmp_buf*)((pc)->error_buf))[0]) +#else +# define png_control_jmp_buf(pc) ((pc)->error_buf) +#endif + +/* Utility to safely execute a piece of libpng code catching and logging any + * errors that might occur. Returns true on success, false on failure (either + * of the function or as a result of a png_error.) + */ +PNG_FUNCTION(void, png_safe_error, (png_structp png_ptr, + png_const_charp error_message), PNG_NORETURN); + +#ifdef PNG_WARNINGS_SUPPORTED + PNG_EXTERN void png_safe_warning(png_structp png_ptr, + png_const_charp warning_message); +#else +# define png_safe_warning 0/*dummy argument*/ +#endif + +PNG_EXTERN int png_safe_execute PNGARG((png_imagep image, + int (*function)(png_voidp), png_voidp arg)); + +/* Utility to log an error, this also cleans up the png_image, the function + * always returns 0 (false). + */ +PNG_EXTERN int png_image_error(png_imagep image, png_const_charp error_message); + +#endif /* SIMPLIFIED READ/WRITE */ + /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */ #include "pngdebug.h" diff -ru4NwbB libpng-1.5.6/pngread.c libpng-1.5.7beta04/pngread.c --- libpng-1.5.6/pngread.c 2011-11-02 22:42:50.439731962 -0500 +++ libpng-1.5.7beta04/pngread.c 2011-11-17 21:02:57.014158876 -0600 @@ -1,8 +1,8 @@ /* pngread.c - read a PNG file * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * Copyright (c) 1998-2011 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,8 +14,11 @@ * read a PNG file or stream. */ #include "pngpriv.h" +#if defined PNG_SIMPLIFIED_READ_SUPPORTED && defined PNG_STDIO_SUPPORTED +# include +#endif #ifdef PNG_READ_SUPPORTED /* Create a PNG structure for reading, and allocate any memory needed. */ @@ -79,10 +82,11 @@ #endif #ifdef PNG_SETJMP_SUPPORTED /* Applications that neglect to set up their own setjmp() and then - encounter a png_error() will longjmp here. Since the jmpbuf is - then meaningless we abort instead of returning. */ + * encounter a png_error() will longjmp here. Since the jmpbuf is + * then meaningless we abort instead of returning. + */ #ifdef USE_FAR_KEYWORD if (setjmp(tmp_jmpbuf)) #else if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */ @@ -577,9 +581,9 @@ if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) { if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) - png_read_filter_row(&row_info, png_ptr->row_buf + 1, + png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, png_ptr->prev_row + 1, png_ptr->row_buf[0]); else png_error(png_ptr, "bad adaptive filter value"); } @@ -1303,5 +1307,1151 @@ } #endif /* PNG_INFO_IMAGE_SUPPORTED */ #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED +/* SIMPLIFIED READ + * + * This code currently relies on the sequential reader, though it could easily + * be made to work with the progressive one. + */ +/* Do all the *safe* initialization - 'safe' means that png_error won't be + * called, so setting up the jmp_buf is not required. This means that anything + * called from here must *not* call png_malloc - it has to call png_malloc_warn + * instead so that control is returned safely back to this routine. + */ +static int +png_image_read_init(png_imagep image) +{ + png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image, + png_safe_error, png_safe_warning); + + if (png_ptr != NULL) + { + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (info_ptr != NULL) + { + png_controlp control = png_voidcast(png_controlp, + png_malloc_warn(png_ptr, sizeof *control)); + + if (control != NULL) + { + memset(control, 0, sizeof *control); + + control->png_ptr = png_ptr; + control->info_ptr = info_ptr; + control->for_write = 0; + + image->opaque = control; + return 1; + } + + /* Error clean up */ + png_destroy_info_struct(png_ptr, &info_ptr); + } + + png_destroy_read_struct(&png_ptr, NULL, NULL); + } + + return png_image_error(image, "png_image_read: out of memory"); +} + +/* Utility to find the base format of a PNG file from a png_struct. */ +static png_uint_32 +png_image_format(png_structp png_ptr, png_infop info_ptr) +{ + png_uint_32 format = 0; + + if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) + format |= PNG_FORMAT_FLAG_COLOR; + + if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) + format |= PNG_FORMAT_FLAG_ALPHA; + + else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS)) + format |= PNG_FORMAT_FLAG_ALPHA; + + if (png_ptr->bit_depth == 16) + format |= PNG_FORMAT_FLAG_LINEAR; + + return format; +} + +/* Do the main body of a 'png_image_begin_read' function; read the PNG file + * header and fill in all the information. This is executed in a safe context, + * unlike the init routine above. + */ +static int +png_image_read_header(png_voidp argument) +{ + png_imagep image = png_voidcast(png_imagep, argument); + png_structp png_ptr = image->opaque->png_ptr; + png_infop info_ptr = image->opaque->info_ptr; + + png_read_info(png_ptr, info_ptr); + + /* Do this the fast way; just read directly out of png_struct. */ + image->width = png_ptr->width; + image->height = png_ptr->height; + + { + png_uint_32 format = png_image_format(png_ptr, info_ptr); + + image->format = format; + image->flags = 0; + + /* Now try to work out whether the color data does not match sRGB. */ + if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && + (info_ptr->valid & PNG_INFO_sRGB) == 0) + { + /* gamma is irrelevant because libpng does gamma correction, what + * matters is if the cHRM chunk doesn't match or, in the absence of + * cRHM, if the iCCP profile appears to have different end points. + */ + if (info_ptr->valid & PNG_INFO_cHRM) + { + /* TODO: this is a copy'n'paste from pngrutil.c, make a common + * checking function. This checks for a 1% error. + */ + /* The cHRM chunk is used in preference to iCCP */ + if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_red, 64000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_green, 60000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) || + PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000)) + image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB; + } + + else if (info_ptr->valid & PNG_INFO_iCCP) + { +# if 0 + /* TODO: IMPLEMENT THIS! Remember to remove iCCP from + the chunks_to_ignore list */ + /* Here if we just have an iCCP chunk. */ + if (!png_iCCP_is_sRGB(png_ptr, info_ptr)) +# endif + image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB; + } + } + } + + return 1; +} + +#ifdef PNG_STDIO_SUPPORTED +int PNGAPI +png_image_begin_read_from_stdio(png_imagep image, FILE* file) +{ + if (image != NULL) + { + if (file != NULL) + { + if (png_image_read_init(image)) + { + /* This is slightly evil, but png_init_io doesn't do anything other + * than this and we haven't changed the standard IO functions so + * this saves a 'safe' function. + */ + image->opaque->png_ptr->io_ptr = file; + return png_safe_execute(image, png_image_read_header, image); + } + } + + else + return png_image_error(image, + "png_image_begin_read_from_stdio: invalid argument"); + } + + return 0; +} + +int PNGAPI +png_image_begin_read_from_file(png_imagep image, const char *file_name) +{ + if (image != NULL) + { + if (file_name != NULL) + { + FILE *fp = fopen(file_name, "rb"); + + if (fp != NULL) + { + if (png_image_read_init(image)) + { + image->opaque->png_ptr->io_ptr = fp; + image->opaque->owned_file = 1; + return png_safe_execute(image, png_image_read_header, image); + } + + /* Clean up: just the opened file. */ + (void)fclose(fp); + } + + else + return png_image_error(image, strerror(errno)); + } + + else + return png_image_error(image, + "png_image_begin_read_from_file: invalid argument"); + } + + return 0; +} +#endif /* PNG_STDIO_SUPPORTED */ + +static void PNGCBAPI +png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) +{ + if (png_ptr != NULL) + { + png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr); + if (image != NULL) + { + png_controlp cp = image->opaque; + if (cp != NULL) + { + png_const_bytep memory = cp->memory; + png_size_t size = cp->size; + + if (memory != NULL && size >= need) + { + memcpy(out, memory, need); + cp->memory = memory + need; + cp->size = size - need; + return; + } + + png_error(png_ptr, "read beyond end of data"); + } + } + + png_error(png_ptr, "invalid memory read"); + } +} + +int PNGAPI png_image_begin_read_from_memory(png_imagep image, + png_const_voidp memory, png_size_t size) +{ + if (image != NULL) + { + if (memory != NULL && size > 0) + { + if (png_image_read_init(image)) + { + /* Now set the IO functions to read from the memory buffer and + * store it into io_ptr. Again do this in-place to avoid calling a + * libpng function that requires error handling. + */ + image->opaque->memory = png_voidcast(png_const_bytep, memory); + image->opaque->size = size; + image->opaque->png_ptr->io_ptr = image; + image->opaque->png_ptr->read_data_fn = png_image_memory_read; + + return png_safe_execute(image, png_image_read_header, image); + } + } + + else + return png_image_error(image, + "png_image_begin_read_from_memory: invalid argument"); + } + + return 0; +} + +/* Arguments to png_image_finish_read: */ +typedef struct +{ + /* Arguments: */ + png_imagep image; + png_voidp buffer; + png_int_32 row_stride; + png_colorp background; + /* Local variables: */ + png_bytep local_row; + png_bytep first_row; + ptrdiff_t row_bytes; /* unsigned arithmetic step between rows */ +} png_image_read_control; + +/* Just the row reading part of png_image_read. */ +static int +png_image_read_composite(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_structp png_ptr = image->opaque->png_ptr; + png_byte interlace_type = png_ptr->interlaced; + int passes; + + switch (interlace_type) + { + case PNG_INTERLACE_NONE: + passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + passes = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + png_error(png_ptr, "unknown interlace type"); + } + + { + png_uint_32 height = image->height; + png_uint_32 width = image->width; + unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; + int pass; + + for (pass = 0; pass < passes; ++pass) + { + png_bytep row = display->first_row; + unsigned int startx, stepx, stepy; + png_uint_32 y; + + if (interlace_type == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass); + stepx = PNG_PASS_COL_OFFSET(pass); + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = stepy = 1; + } + + /* The following are invariants across all the rows: */ + startx *= channels; + stepx *= channels; + + for (; ylocal_row; + png_bytep outrow = row + startx; + png_const_bytep end_row = row + width * channels; + + /* Read the row, which is packed: */ + png_read_row(png_ptr, inrow, NULL); + + /* Now do the composition on each pixel in this row. */ + for (; outrow < end_row; outrow += stepx) + { + png_byte alpha = inrow[channels]; + + if (alpha > 0) /* else no change to the output */ + { + unsigned int c; + + for (c=0; crow_bytes; + } + } + } + + return 1; +} + +/* The do_local_background case; called when all the following transforms are to + * be done: + * + * PNG_RGB_TO_GRAY + * PNG_COMPOSITE + * PNG_GAMMA + * + * This is a work-round for the fact that both the PNG_RGB_TO_GRAY and + * PNG_COMPOSITE code performs gamma correction, so we get double gamma + * correction. The fix-up is to prevent the PNG_COMPOSITE operation happening + * inside libpng, so this routine sees an 8 or 16-bit gray+alpha row and handles + * the removal or pre-multiplication of the alpha channel. + */ +static int +png_image_read_background(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_structp png_ptr = image->opaque->png_ptr; + png_infop info_ptr = image->opaque->info_ptr; + png_byte interlace_type = png_ptr->interlaced; + png_uint_32 height = image->height; + png_uint_32 width = image->width; + int pass, passes; + + /* Double check the convoluted logic below. We expect to get here with + * libpng doing rgb to gray and gamma correction but background processing + * left to the png_image_read_background function. The rows libpng produce + * might be 8 or 16-bit but should always have two channels; gray plus alpha. + */ + if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) + png_error(png_ptr, "lost rgb to gray"); + + if ((png_ptr->transformations & PNG_COMPOSE) != 0) + png_error(png_ptr, "unexpected compose"); + + /* The palette code zaps PNG_GAMMA in place... */ + if ((png_ptr->color_type & PNG_COLOR_MASK_PALETTE) == 0 && + (png_ptr->transformations & PNG_GAMMA) == 0) + png_error(png_ptr, "lost gamma correction"); + + if (png_get_channels(png_ptr, info_ptr) != 2) + png_error(png_ptr, "lost/gained channels"); + + switch (interlace_type) + { + case PNG_INTERLACE_NONE: + passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + passes = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + png_error(png_ptr, "unknown interlace type"); + } + + switch (png_get_bit_depth(png_ptr, info_ptr)) + { + default: + png_error(png_ptr, "unexpected bit depth"); + break; + + case 8: + /* 8-bit sRGB gray values with an alpha channel; the alpha channel is + * to be removed by composing on a backgroundi: either the row if + * display->background is NULL or display->background.green if not. + * Unlike the code above ALPHA_OPTIMIZED has *not* been done. + */ + for (pass = 0; pass < passes; ++pass) + { + png_bytep row = display->first_row; + unsigned int startx, stepx, stepy; + png_uint_32 y; + + if (interlace_type == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass); + stepx = PNG_PASS_COL_OFFSET(pass); + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = stepy = 1; + } + + if (display->background == NULL) + { + for (; ylocal_row; + png_bytep outrow = row + startx; + png_const_bytep end_row = row + width; + + /* Read the row, which is packed: */ + png_read_row(png_ptr, inrow, NULL); + + /* Now do the composition on each pixel in this row. */ + for (; outrow < end_row; outrow += stepx) + { + png_byte alpha = inrow[1]; + + if (alpha > 0) /* else no change to the output */ + { + png_uint_32 component = inrow[0]; + + if (alpha < 255) /* else just use component */ + { + /* Since PNG_OPTIMIZED_ALPHA was not set it is + * necessary to invert the sRGB transfer + * function and multiply the alpha out. + */ + component = png_sRGB_table[component] * alpha; + component += png_sRGB_table[outrow[0]] * + (255-alpha); + component = PNG_sRGB_FROM_LINEAR(component); + } + + outrow[0] = (png_byte)component; + } + + inrow += 2; /* gray and alpha channel */ + } + + row += display->row_bytes; + } + } + + else /* constant background value */ + { + png_byte background8 = display->background->green; + png_uint_16 background = png_sRGB_table[background8]; + + for (; ylocal_row; + png_bytep outrow = row + startx; + png_const_bytep end_row = row + width; + + /* Read the row, which is packed: */ + png_read_row(png_ptr, inrow, NULL); + + /* Now do the composition on each pixel in this row. */ + for (; outrow < end_row; outrow += stepx) + { + png_byte alpha = inrow[1]; + + if (alpha > 0) /* else use background */ + { + png_uint_32 component = inrow[0]; + + if (alpha < 255) /* else just use component */ + { + component = png_sRGB_table[component] * alpha; + component += background * (255-alpha); + component = PNG_sRGB_FROM_LINEAR(component); + } + + outrow[0] = (png_byte)component; + } + + else + outrow[0] = background8; + + inrow += 2; /* gray and alpha channel */ + } + + row += display->row_bytes; + } + } + } + break; + + case 16: + /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must + * still be done and, maybe, the alpha channel removed. This code also + * handles the alpha-first option. + */ + { + unsigned int outchannels = png_get_channels(png_ptr, info_ptr); + int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; + int swap_alpha = 0; + + if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST)) + swap_alpha = 1; + + for (pass = 0; pass < passes; ++pass) + { + png_uint_16p row = (png_uint_16p)display->first_row; + unsigned int startx, stepx, stepy; /* all in pixels */ + png_uint_32 y; + + if (interlace_type == PNG_INTERLACE_ADAM7) + { + /* The row may be empty for a short image: */ + if (PNG_PASS_COLS(width, pass) == 0) + continue; + + startx = PNG_PASS_START_COL(pass); + stepx = PNG_PASS_COL_OFFSET(pass); + y = PNG_PASS_START_ROW(pass); + stepy = PNG_PASS_ROW_OFFSET(pass); + } + + else + { + y = 0; + startx = 0; + stepx = stepy = 1; + } + + startx *= outchannels; + stepx *= outchannels; + + for (; ylocal_row, NULL); + inrow = (png_uint_16p)display->local_row; + + /* Now do the pre-multiplication on each pixel in this row. + */ + for (; outrow < end_row; outrow += stepx) + { + png_uint_32 component = inrow[0]; + png_uint_16 alpha = inrow[1]; + + if (alpha > 0) /* else 0 */ + { + if (alpha < 65535) /* else just use component */ + { + component *= alpha; + component += 32767; + component /= 65535; + } + } + + else + component = 0; + + outrow[swap_alpha] = (png_uint_16)component; + if (outchannels > 1) + outrow[1 ^ swap_alpha] = alpha; + + inrow += 2; /* components and alpha channel */ + } + + row += display->row_bytes; + } + } + } + break; + } + + return 1; +} + +/* The guts of png_image_finish_read as a png_safe_execute callback. */ +static int +png_image_read_end(png_voidp argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_imagep image = display->image; + png_structp png_ptr = image->opaque->png_ptr; + png_infop info_ptr = image->opaque->info_ptr; + + png_uint_32 format = image->format; + int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; + int do_local_compose = 0; + int do_local_background = 0; /* to avoid double gamma correction bug */ + int passes = 0; + + /* Add transforms to ensure the correct output format is produced then check + * that the required implementation support is there. Always expand; always + * need 8 bits minimum, no palette and expanded tRNS. + */ + png_set_expand(png_ptr); + + /* Now check the format to see if it was modified. */ + { + png_uint_32 base_format = png_image_format(png_ptr, info_ptr); + png_uint_32 change = format ^ base_format; + png_fixed_point output_gamma; + int mode; /* alpha mode */ + + /* Do this first so that we have a record if rgb to gray is happening. */ + if (change & PNG_FORMAT_FLAG_COLOR) + { + /* gray<->color transformation required. */ + if (format & PNG_FORMAT_FLAG_COLOR) + png_set_gray_to_rgb(png_ptr); + + else + { + /* libpng can't do both rgb to gray and + * background/pre-multiplication if there is also significant gamma + * correction, because both operations require linear colors and + * the code only supports one transform doing the gamma correction. + * Handle this by doing the pre-multiplication or background + * operation in this code, if necessary. + * + * TODO: fix this by rewriting pngrtran.c (!) + * + * For the moment (given that fixing this in pngrtran.c is an + * enormous change) 'do_local_background' is used to indicate that + * the problem exists. + */ + if (base_format & PNG_FORMAT_FLAG_ALPHA) + do_local_background = 1/*maybe*/; + + png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, + PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); + } + + change &= ~PNG_FORMAT_FLAG_COLOR; + } + + /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise. + */ + { + png_fixed_point input_gamma_default; + + if (base_format & PNG_FORMAT_FLAG_LINEAR) + input_gamma_default = PNG_GAMMA_LINEAR; + else + input_gamma_default = PNG_DEFAULT_sRGB; + + /* Call png_set_alpha_mode to set the default for the input gamma; the + * output gamma is set by a second call below. + */ + png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default); + } + + if (linear) + { + /* If there *is* an alpha channel in the input it must be multiplied + * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG. + */ + if (base_format & PNG_FORMAT_FLAG_ALPHA) + mode = PNG_ALPHA_STANDARD; /* associated alpha */ + + else + mode = PNG_ALPHA_PNG; + + output_gamma = PNG_GAMMA_LINEAR; + } + + else + { + mode = PNG_ALPHA_PNG; + output_gamma = PNG_DEFAULT_sRGB; + } + + /* If 'do_local_background' is set check for the presence of gamma + * correction; this is part of the work-round for the libpng bug + * described above. + * + * TODO: fix libpng and remove this. + */ + if (do_local_background) + { + png_fixed_point gtest; + + /* This is 'png_gamma_threshold' from pngrtran.c; the test used for + * gamma correction, the screen gamma hasn't been set on png_struct + * yet; it's set below. png_struct::gamma, however, is set to the + * final value. + */ + if (png_muldiv(>est, output_gamma, png_ptr->gamma, PNG_FP_1) && + !png_gamma_significant(gtest)) + do_local_background = 0; + + else if (mode == PNG_ALPHA_STANDARD) + { + do_local_background = 2/*required*/; + mode = PNG_ALPHA_PNG; /* prevent libpng doing it */ + } + + /* else leave as 1 for the checks below */ + } + + /* If the bit-depth changes then handle that here. */ + if (change & PNG_FORMAT_FLAG_LINEAR) + { + if (linear /*16-bit output*/) + png_set_expand_16(png_ptr); + + else /* 8-bit output */ + png_set_scale_16(png_ptr); + + change &= ~PNG_FORMAT_FLAG_LINEAR; + } + + /* Now the background/alpha channel changes. */ + if (change & PNG_FORMAT_FLAG_ALPHA) + { + /* Removing an alpha channel requires composition for the 8-bit + * formats; for the 16-bit it is already done, above, by the + * pre-multiplication and the channel just needs to be stripped. + */ + if (base_format & PNG_FORMAT_FLAG_ALPHA) + { + /* If RGB->gray is happening the alpha channel must be left and the + * operation completed locally. + * + * TODO: fix libpng and remove this. + */ + if (do_local_background) + do_local_background = 2/*required*/; + + /* 16-bit output: just remove the channel */ + else if (linear) /* compose on black (well, pre-multiply) */ + png_set_strip_alpha(png_ptr); + + /* 8-bit output: do an appropriate compose */ + else if (display->background != NULL) + { + png_color_16 c; + + c.index = 0; /*unused*/ + c.red = display->background->red; + c.green = display->background->green; + c.blue = display->background->blue; + c.gray = display->background->green; + + /* This is always an 8-bit sRGB value, using the 'green' channel + * for gray is much better than calculating the luminance here; + * we can get off-by-one errors in that calculation relative to + * the app expectations and that will show up in transparent + * pixels. + */ + png_set_background_fixed(png_ptr, &c, + PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, + 0/*gamma: not used*/); + } + + else /* compose on row: implemented below. */ + { + do_local_compose = 1; + /* This leaves the alpha channel in the output, so it has to be + * removed by the code below. Set the encoding to the 'OPTIMIZE' + * one so the code only has to hack on the pixels that require + * composition. + */ + mode = PNG_ALPHA_OPTIMIZED; + } + } + + else /* output needs an alpha channel */ + { + /* This is tricky because it happens before the swap operation has + * been accomplished; however, the swap does *not* swap the added + * alpha channel (weird API), so it must be added in the correct + * place. + */ + png_uint_32 filler; /* opaque filler */ + int where; + + if (linear) + filler = 65535; + + else + filler = 255; + +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + { + where = PNG_FILLER_BEFORE; + change &= ~PNG_FORMAT_FLAG_AFIRST; + } + + else +# endif + where = PNG_FILLER_AFTER; + + png_set_add_alpha(png_ptr, filler, where); + } + + /* This stops the (irrelevant) call to swap_alpha below. */ + change &= ~PNG_FORMAT_FLAG_ALPHA; + } + + /* Now set the alpha mode correctly; this is always done, even if there is + * no alpha channel in either the input or the output because it correctly + * sets the output gamma. + */ + png_set_alpha_mode_fixed(png_ptr, mode, output_gamma); + +# ifdef PNG_FORMAT_BGR_SUPPORTED + if (change & PNG_FORMAT_FLAG_BGR) + { + /* Check only the output format; PNG is never BGR; don't do this if + * the output is gray, but fix up the 'format' value in that case. + */ + if (format & PNG_FORMAT_FLAG_COLOR) + png_set_bgr(png_ptr); + + else + format &= ~PNG_FORMAT_FLAG_BGR; + + change &= ~PNG_FORMAT_FLAG_BGR; + } +# endif + +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (change & PNG_FORMAT_FLAG_AFIRST) + { + /* Only relevant if there is an alpha channel - it's particularly + * important to handle this correctly because do_local_compose may + * be set above and then libpng will keep the alpha channel for this + * code to remove. + */ + if (format & PNG_FORMAT_FLAG_ALPHA) + { + /* Disable this if doing a local background, + * TODO: remove this when local background is no longer required. + */ + if (do_local_background != 2) + png_set_swap_alpha(png_ptr); + } + + else + format &= ~PNG_FORMAT_FLAG_AFIRST; + + change &= ~PNG_FORMAT_FLAG_AFIRST; + } +# endif + + /* If the *output* is 16-bit then we need to check for a byte-swap on this + * architecture. + */ + if (linear) + { + PNG_CONST png_uint_16 le = 0x0001; + + if (*(png_const_bytep)&le) + png_set_swap(png_ptr); + } + + /* If change is not now 0 some transformation is missing - error out. */ + if (change) + png_error(png_ptr, "png_read_image: unsupported transformation"); + } + +# ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED + /* Prepare the reader to ignore all recognized chunks whose data will not + * be used, i.e., all chunks recognized by libpng except for those + * involved in basic image reading: + * + * IHDR, PLTE, IDAT, IEND + * + * Or image data handling: + * + * tRNS, bKGD, gAMA, cHRM, sRGB, iCCP and sBIT. + * + * This provides a small performance improvement and eliminates any + * potential vulnerability to security problems in the unused chunks. + * + * TODO: make it so that this is an explicit list to process, not a list + * to ignore? + */ + { + static PNG_CONST png_byte chunks_to_ignore[] = { + 104, 73, 83, 84, '\0', /* hIST */ + 105, 84, 88, 116, '\0', /* iTXt */ + 111, 70, 70, 115, '\0', /* oFFs */ + 112, 67, 65, 76, '\0', /* pCAL */ + 112, 72, 89, 115, '\0', /* pHYs */ + 115, 67, 65, 76, '\0', /* sCAL */ + 115, 80, 76, 84, '\0', /* sPLT */ + 116, 69, 88, 116, '\0', /* tEXt */ + 116, 73, 77, 69, '\0', /* tIME */ + 122, 84, 88, 116, '\0' /* zTXt */ + }; + + /* Ignore unknown chunks */ + png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */, + NULL, 0); + + /* Ignore known but unused chunks */ + png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */, + chunks_to_ignore, (sizeof chunks_to_ignore)/5); + } +# endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ + + /* Update the 'info' structure and make sure the result is as required; first + * make sure to turn on the interlace handling if it will be required + * (because it can't be turned on *after* the call to png_read_update_info!) + * + * TODO: remove the do_local_background fixup below. + */ + if (!do_local_compose && do_local_background != 2) + passes = png_set_interlace_handling(png_ptr); + + png_read_update_info(png_ptr, info_ptr); + + { + png_uint_32 info_format = 0; + + if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + info_format |= PNG_FORMAT_FLAG_COLOR; + + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + { + /* do_local_compose removes this channel below. */ + if (!do_local_compose) + { + /* do_local_background does the same if required. */ + if (do_local_background != 2 || + (format & PNG_FORMAT_FLAG_ALPHA) != 0) + info_format |= PNG_FORMAT_FLAG_ALPHA; + } + } + + else if (do_local_compose) /* internal error */ + png_error(png_ptr, "png_image_read: alpha channel lost"); + + if (info_ptr->bit_depth == 16) + info_format |= PNG_FORMAT_FLAG_LINEAR; + +# ifdef PNG_FORMAT_BGR_SUPPORTED + if (png_ptr->transformations & PNG_BGR) + info_format |= PNG_FORMAT_FLAG_BGR; +# endif + +# ifdef PNG_FORMAT_AFIRST_SUPPORTED + if (png_ptr->transformations & PNG_SWAP_ALPHA || + ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 && + (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0)) + info_format |= PNG_FORMAT_FLAG_AFIRST; +# endif + + /* This is actually an internal error. */ + if (info_format != format) + png_error(png_ptr, "png_read_image: invalid transformations"); + } + + /* Now read the rows. If do_local_compose is set then it is necessary to use + * a local row buffer. The output will be GA, RGBA or BGRA and must be + * converted to G, RGB or BGR as appropriate. The 'local_row' member of the + * display acts as a flag. + */ + { + png_bytep first_row = png_voidcast(png_bytep, display->buffer); + ptrdiff_t row_bytes = display->row_stride; + + if (linear) + row_bytes *= sizeof (png_uint_16); + + /* The following expression is designed to work correctly whether it gives + * a signed or an unsigned result. + */ + if (row_bytes < 0) + first_row += (image->height-1) * (-row_bytes); + + display->first_row = first_row; + display->row_bytes = row_bytes; + } + + if (do_local_compose) + { + int result; + png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr))); + + display->local_row = row; + result = png_safe_execute(image, png_image_read_composite, display); + display->local_row = NULL; + png_free(png_ptr, row); + + return result; + } + + else if (do_local_background == 2) + { + int result; + png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr))); + + display->local_row = row; + result = png_safe_execute(image, png_image_read_background, display); + display->local_row = NULL; + png_free(png_ptr, row); + + return result; + } + + else + { + png_alloc_size_t row_bytes = display->row_bytes; + + while (--passes >= 0) + { + png_uint_32 y = image->height; + png_bytep row = display->first_row; + + while (y-- > 0) + { + png_read_row(png_ptr, row, NULL); + row += row_bytes; + } + } + + return 1; + } +} + +int PNGAPI +png_image_finish_read(png_imagep image, png_colorp background, void *buffer, + png_int_32 row_stride) +{ + if (image != NULL) + { + png_uint_32 check; + + if (row_stride < 0) + check = -row_stride; + + else + check = row_stride; + + if (buffer != NULL && check >= PNG_IMAGE_ROW_STRIDE(*image)) + { + int result; + png_image_read_control display; + + memset(&display, 0, sizeof display); + display.image = image; + display.buffer = buffer; + display.row_stride = row_stride; + display.background = background; + display.local_row = NULL; + result = png_safe_execute(image, png_image_read_end, &display); + png_image_free(image); + return result; + } + + else + return png_image_error(image, + "png_image_finish_read: invalid argument"); + } + + return 0; +} + +#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ #endif /* PNG_READ_SUPPORTED */ diff -ru4NwbB libpng-1.5.6/pngrtran.c libpng-1.5.7beta04/pngrtran.c --- libpng-1.5.6/pngrtran.c 2011-11-02 22:42:50.462840407 -0500 +++ libpng-1.5.7beta04/pngrtran.c 2011-11-17 21:02:57.037600630 -0600 @@ -1,8 +1,8 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * Copyright (c) 1998-2011 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.) * @@ -935,17 +935,17 @@ return; switch(error_action) { - case 1: + case PNG_ERROR_ACTION_NONE: png_ptr->transformations |= PNG_RGB_TO_GRAY; break; - case 2: + case PNG_ERROR_ACTION_WARN: png_ptr->transformations |= PNG_RGB_TO_GRAY_WARN; break; - case 3: + case PNG_ERROR_ACTION_ERROR: png_ptr->transformations |= PNG_RGB_TO_GRAY_ERR; break; default: @@ -1464,8 +1464,30 @@ # undef CHOP } #endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \ + (defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \ + defined(PNG_READ_STRIP_16_TO_8_SUPPORTED)) + if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) && + (png_ptr->transformations & PNG_COMPOSE) && + !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) && + png_ptr->bit_depth == 16) + { + /* On the other hand, if a 16-bit file is to be reduced to 8-bits per + * component this will also happen after PNG_COMPOSE and so the background + * color must be pre-expanded here. + * + * TODO: fix this too. + */ + png_ptr->background.red = (png_uint_16)(png_ptr->background.red * 257); + png_ptr->background.green = + (png_uint_16)(png_ptr->background.green * 257); + png_ptr->background.blue = (png_uint_16)(png_ptr->background.blue * 257); + png_ptr->background.gray = (png_uint_16)(png_ptr->background.gray * 257); + } +#endif + /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the * background support (see the comments in scripts/pnglibconf.dfa), this * allows pre-multiplication of the alpha channel to be implemented as * compositing on black. This is probably sub-optimal and has been done in @@ -1511,8 +1533,18 @@ #ifdef PNG_READ_BACKGROUND_SUPPORTED if (png_ptr->transformations & PNG_COMPOSE) { + /* Issue a warning about this combination: because RGB_TO_GRAY is + * optimized to do the gamma transform if present yet do_background has + * to do the same thing if both options are set a + * double-gamma-correction happens. This is true in all versions of + * libpng to date. + */ + if (png_ptr->transformations & PNG_RGB_TO_GRAY) + png_warning(png_ptr, + "libpng does not support gamma+background+rgb_to_gray"); + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { /* We don't get to here unless there is a tRNS chunk with non-opaque * entries - see the checking code at the start of this function. @@ -1725,9 +1757,15 @@ else /* Transformation does not include PNG_BACKGROUND */ #endif /* PNG_READ_BACKGROUND_SUPPORTED */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* RGB_TO_GRAY needs to have non-gamma-corrected values! */ + && ((png_ptr->transformations & PNG_EXPAND) == 0 || + (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) +#endif + ) { png_colorp palette = png_ptr->palette; int num_palette = png_ptr->num_palette; int i; @@ -2164,14 +2202,24 @@ #endif #ifdef PNG_READ_GAMMA_SUPPORTED if ((png_ptr->transformations & PNG_GAMMA) && +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* Because RGB_TO_GRAY does the gamma transform. */ + !(png_ptr->transformations & PNG_RGB_TO_GRAY) && +#endif #if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\ (defined PNG_READ_ALPHA_MODE_SUPPORTED) + /* Because PNG_COMPOSE does the gamma transform if there is something to + * do (if there is an alpha channel or transparency.) + */ !((png_ptr->transformations & PNG_COMPOSE) && ((png_ptr->num_trans != 0) || (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) && #endif + /* Because png_init_read_transformations transforms the palette, unless + * RGB_TO_GRAY will do the transform. + */ (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)) png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr); #endif @@ -2561,9 +2609,9 @@ if (row_info->bit_depth == 16) { png_bytep sp = row; /* source */ - png_bytep dp = row; /* destinaton */ + png_bytep dp = row; /* destination */ png_bytep ep = sp + row_info->rowbytes; /* end+1 */ while (sp < ep) { @@ -2622,9 +2670,9 @@ if (row_info->bit_depth == 16) { png_bytep sp = row; /* source */ - png_bytep dp = row; /* destinaton */ + png_bytep dp = row; /* destination */ png_bytep ep = sp + row_info->rowbytes; /* end+1 */ while (sp < ep) { @@ -3330,9 +3378,9 @@ if (red != green || red != blue) rgb_error |= 1; - /* From 1.5.5 in the 16 bit case do the accurate convertion even + /* From 1.5.5 in the 16 bit case do the accurate conversion even * in the 'fast' case - this is because this is where the code * ends up when handling linear 16 bit data. */ gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> diff -ru4NwbB libpng-1.5.6/pngrutil.c libpng-1.5.7beta04/pngrutil.c --- libpng-1.5.6/pngrutil.c 2011-11-02 22:42:50.478366695 -0500 +++ libpng-1.5.7beta04/pngrutil.c 2011-11-17 21:02:57.052773946 -0600 @@ -1,8 +1,8 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * Copyright (c) 1998-2011 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.) * @@ -2766,20 +2766,15 @@ chunk_name >>= 8; } } -/* Combines the row recently read in with the existing pixels in the - * row. This routine takes care of alpha and transparency if requested. - * This routine also handles the two methods of progressive display - * of interlaced images, depending on the mask value. - * The mask value describes which pixels are to be combined with - * the row. The pattern always repeats every 8 pixels, so just 8 - * bits are needed. A one indicates the pixel is to be combined, - * a zero indicates the pixel is to be skipped. This is in addition - * to any alpha or transparency value associated with the pixel. If - * you want all pixels to be combined, pass 0xff (255) in mask. +/* Combines the row recently read in with the existing pixels in the row. This + * routine takes care of alpha and transparency if requested. This routine also + * handles the two methods of progressive display of interlaced images, + * depending on the 'display' value; if 'display' is true then the whole row + * (dp) is filled from the start by replicating the available pixels. If + * 'display' is false only those pixels present in the pass are filled in. */ - void /* PRIVATE */ png_combine_row(png_structp png_ptr, png_bytep dp, int display) { unsigned int pixel_depth = png_ptr->transformed_pixel_depth; @@ -2849,26 +2844,26 @@ return; if (pixel_depth < 8) { - /* For pixel depths up to 4-bpp the 8-pixel mask can be expanded to fit + /* For pixel depths up to 4 bpp the 8-pixel mask can be expanded to fit * into 32 bits, then a single loop over the bytes using the four byte * values in the 32-bit mask can be used. For the 'display' option the * expanded mask may also not require any masking within a byte. To * make this work the PACKSWAP option must be taken into account - it * simply requires the pixels to be reversed in each byte. * * The 'regular' case requires a mask for each of the first 6 passes, * the 'display' case does a copy for the even passes in the range - * 0..6. This has already been handled in the tst above. + * 0..6. This has already been handled in the test above. * * The masks are arranged as four bytes with the first byte to use in * the lowest bits (little-endian) regardless of the order (PACKSWAP or * not) of the pixels in each byte. * * NOTE: the whole of this logic depends on the caller of this function * only calling it on rows appropriate to the pass. This function only - * understands the 'x' logic, the 'y' logic is handled by the caller. + * understands the 'x' logic; the 'y' logic is handled by the caller. * * The following defines allow generation of compile time constant bit * masks for each pixel depth and each possibility of swapped or not * swapped bytes. Pass 'p' is in the range 0..6; 'x', a pixel index, @@ -2884,9 +2879,9 @@ * because the right hand side of the ?: expression is evaluated by * the compiler even though it isn't used. Microsoft Visual C (various * versions) and the Intel C compiler are known to do this. To avoid * this the following macros are used in 1.5.6. This is a temporary - * solution to avoid destablizing the code during the release process. + * solution to avoid destabilizing the code during the release process. */ # if PNG_USE_COMPILE_TIME_MASKS # define PNG_LSR(x,s) ((x)>>((s) & 0x1f)) # define PNG_LSL(x,s) ((x)<<((s) & 0x1f)) @@ -2929,9 +2924,9 @@ #if PNG_USE_COMPILE_TIME_MASKS /* Utility macros to construct all the masks for a depth/swap * combination. The 's' parameter says whether the format is PNG - * (big endian bytes) or not. Only the three odd numbered passes are + * (big endian bytes) or not. Only the three odd-numbered passes are * required for the display/block algorithm. */ # define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\ S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) } @@ -2942,9 +2937,10 @@ /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and * then pass: */ - static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = { + static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = + { /* Little-endian byte masks for PACKSWAP */ { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) }, /* Normal (big-endian byte) masks - PNG format */ { S_MASKS(1,1), S_MASKS(2,1), S_MASKS(4,1) } @@ -2952,9 +2948,10 @@ /* display_mask has only three entries for the odd passes, so index by * pass>>1. */ - static PNG_CONST png_uint_32 display_mask[2][3][3] = { + static PNG_CONST png_uint_32 display_mask[2][3][3] = + { /* Little-endian byte masks for PACKSWAP */ { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) }, /* Normal (big-endian byte) masks - PNG format */ { B_MASKS(1,1), B_MASKS(2,1), B_MASKS(4,1) } @@ -3128,9 +3125,9 @@ #if PNG_ALIGN_TYPE != PNG_ALIGN_NONE /* Check for double byte alignment and, if possible, use a * 16-bit copy. Don't attempt this for narrow images - ones that * are less than an interlace panel wide. Don't attempt it for - * wide bytes-to-copy either - use the png_memcpy there. + * wide bytes_to_copy either - use the png_memcpy there. */ if (bytes_to_copy < 16 /*else use png_memcpy*/ && png_isaligned(dp, png_uint_16) && png_isaligned(sp, png_uint_16) && @@ -3497,36 +3494,36 @@ #endif } #endif /* PNG_READ_INTERLACING_SUPPORTED */ -/* 1.5.6: Changed to just take a png_row_info (not png_ptr) and to ignore bad - * adaptive filter bytes. - */ -void /* PRIVATE */ -png_read_filter_row(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row, int filter) -{ - switch (filter) - { - case PNG_FILTER_VALUE_NONE: - break; - - case PNG_FILTER_VALUE_SUB: +static void +png_read_filter_row_sub(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) { png_size_t i; png_size_t istop = row_info->rowbytes; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; png_bytep rp = row + bpp; +#if 0 png_bytep lp = row; +#endif + + PNG_UNUSED(prev_row) for (i = bpp; i < istop; i++) { +#if 0 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff); +#else + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); +#endif rp++; } - break; } - case PNG_FILTER_VALUE_UP: + +static void +png_read_filter_row_up(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) { png_size_t i; png_size_t istop = row_info->rowbytes; png_bytep rp = row; @@ -3536,16 +3533,20 @@ { *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); rp++; } - break; } - case PNG_FILTER_VALUE_AVG: + +static void +png_read_filter_row_avg(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) { png_size_t i; png_bytep rp = row; png_const_bytep pp = prev_row; +#if 0 png_bytep lp = row; +#endif unsigned int bpp = (row_info->pixel_depth + 7) >> 3; png_size_t istop = row_info->rowbytes - bpp; for (i = 0; i < bpp; i++) @@ -3558,37 +3559,92 @@ for (i = 0; i < istop; i++) { *rp = (png_byte)(((int)(*rp) + +#if 0 (int)(*pp++ + *lp++) / 2 ) & 0xff); +#else + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); +#endif rp++; } - break; } - case PNG_FILTER_VALUE_PAETH: + +static void +png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) { - png_size_t i; - png_bytep rp = row; - png_const_bytep pp = prev_row; - png_bytep lp = row; - png_const_bytep cp = prev_row; - unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop=row_info->rowbytes - bpp; + png_bytep rp_end = row + row_info->rowbytes; + int a, c; - for (i = 0; i < bpp; i++) + /* First pixel/byte */ + c = *prev_row++; + a = *row + c; + *row++ = (png_byte)a; + + /* Remainder */ + while (row < rp_end) { - *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); - rp++; + int b, pa, pb, pc, p; + + a &= 0xff; /* From previous iteration or start */ + b = *prev_row++; + + p = b - c; + pc = a - c; + +# ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +# else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +# endif + + /* Find the best predictor, the least of pa, pb, pc favoring the earlier + * ones in the case of a tie. + */ + if (pb < pa) pa = pb, a = b; + if (pc < pa) a = c; + + /* Calculate the current pixel in a, and move the previous row pixel to c + * for the next time round the loop + */ + c = b; + a += *row; + *row++ = (png_byte)a; + } } - for (i = 0; i < istop; i++) /* Use leftover rp,pp */ +static void +png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, + png_const_bytep prev_row) +{ + int bpp = (row_info->pixel_depth + 7) >> 3; + png_bytep rp_end = row + bpp; + + /* Process the first pixel in the row completely (this is the same as 'up' + * because there is only one candidate predictor for the first row). + */ + while (row < rp_end) + { + int a = *row + *prev_row++; + *row++ = (png_byte)a; + } + + /* Remainder */ + rp_end += row_info->rowbytes - bpp; + + while (row < rp_end) { int a, b, c, pa, pb, pc, p; - a = *lp++; - b = *pp++; - c = *cp++; + c = *(prev_row - bpp); + a = *(row - bpp); + b = *prev_row++; p = b - c; pc = a - c; @@ -3601,30 +3657,105 @@ pb = pc < 0 ? -pc : pc; pc = (p + pc) < 0 ? -(p + pc) : p + pc; #endif - /* - if (pa <= pb && pa <= pc) - p = a; + if (pb < pa) pa = pb, a = b; + if (pc < pa) a = c; + + c = b; + a += *row; + *row++ = (png_byte)a; + } +} - else if (pb <= pc) - p = b; +#ifdef PNG_ARM_NEON - else - p = c; - */ +#ifdef __linux__ +#include +#include +#include - p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c; +static int png_have_hwcap(unsigned cap) +{ + FILE *f = fopen("/proc/self/auxv", "r"); + Elf32_auxv_t aux; + int have_cap = 0; - *rp = (png_byte)(((int)(*rp) + p) & 0xff); - rp++; - } + if (!f) + return 0; + + while (fread(&aux, sizeof(aux), 1, f) > 0) + { + if (aux.a_type == AT_HWCAP && + aux.a_un.a_val & cap) + { + have_cap = 1; break; } - default: - /* NOT REACHED */ - break; } + + fclose(f); + + return have_cap; +} +#endif /* __linux__ */ + +static void +png_init_filter_functions_neon(png_structp pp, unsigned int bpp) +{ +#ifdef __linux__ + if (!png_have_hwcap(HWCAP_NEON)) + return; +#endif + + 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 */ + +static void +png_init_filter_functions(png_structp pp) +{ + unsigned int bpp = (pp->pixel_depth + 7) >> 3; + + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub; + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg; + if (bpp == 1) + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth_1byte_pixel; + else + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = + png_read_filter_row_paeth_multibyte_pixel; + +#ifdef PNG_ARM_NEON + png_init_filter_functions_neon(pp, bpp); +#endif +} + +void /* PRIVATE */ +png_read_filter_row(png_structp pp, png_row_infop row_info, png_bytep row, + png_const_bytep prev_row, int filter) +{ + if (pp->read_filter[0] == NULL) + png_init_filter_functions(pp); + if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST) + pp->read_filter[filter-1](row_info, row, prev_row); } #ifdef PNG_SEQUENTIAL_READ_SUPPORTED void /* PRIVATE */ @@ -3810,8 +3941,18 @@ } max_pixel_depth = png_ptr->pixel_depth; + /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of + * calculations to calculate the final pixel depth, then + * png_do_read_transforms actually does the transforms. This means that the + * code which effectively calculates this value is actually repeated in three + * separate places. They must all match. Innocent changes to the order of + * transformations can and will break libpng in a way that causes memory + * overwrites. + * + * TODO: fix this. + */ #ifdef PNG_READ_PACK_SUPPORTED if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8) max_pixel_depth = 8; #endif @@ -3868,21 +4009,19 @@ #ifdef PNG_READ_FILLER_SUPPORTED if (png_ptr->transformations & (PNG_FILLER)) { - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - max_pixel_depth = 32; - - else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) + if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) { if (max_pixel_depth <= 8) max_pixel_depth = 16; else max_pixel_depth = 32; } - else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB) + else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB || + png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { if (max_pixel_depth <= 32) max_pixel_depth = 32; diff -ru4NwbB libpng-1.5.6/pngset.c libpng-1.5.7beta04/pngset.c --- libpng-1.5.6/pngset.c 2011-11-02 22:42:50.486944000 -0500 +++ libpng-1.5.7beta04/pngset.c 2011-11-17 21:02:57.064130790 -0600 @@ -1,8 +1,8 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.6 [November 3, 2011] * Copyright (c) 1998-2011 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 -ru4NwbB libpng-1.5.6/pngstruct.h libpng-1.5.7beta04/pngstruct.h --- libpng-1.5.6/pngstruct.h 2011-11-02 22:42:50.368044918 -0500 +++ libpng-1.5.7beta04/pngstruct.h 2011-11-17 21:02:56.938838669 -0600 @@ -352,6 +352,9 @@ #endif /* New member added in libpng-1.5.6 */ png_bytep big_prev_row; + + void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, + png_bytep row, png_const_bytep prev_row); }; #endif /* PNGSTRUCT_H */ diff -ru4NwbB libpng-1.5.6/pngtest.c libpng-1.5.7beta04/pngtest.c --- libpng-1.5.6/pngtest.c 2011-11-02 22:42:50.496589188 -0500 +++ libpng-1.5.7beta04/pngtest.c 2011-11-17 21:02:57.073726797 -0600 @@ -1,8 +1,8 @@ /* pngtest.c - a simple test program to test libpng * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.6 [November 3, 2011] * Copyright (c) 1998-2011 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 -ru4NwbB libpng-1.5.6/pngvalid.c libpng-1.5.7beta04/pngvalid.c --- libpng-1.5.6/pngvalid.c 2011-11-02 22:42:50.531808873 -0500 +++ libpng-1.5.7beta04/pngvalid.c 2011-11-17 21:02:57.109106565 -0600 @@ -1,8 +1,8 @@ /* pngvalid.c - validate libpng by constructing then reading png files. * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * Copyright (c) 2011 Glenn Randers-Pehrson * Written by John Cunningham Bowler * * This code is released under the libpng license. @@ -19,10 +19,23 @@ * transformations performed by libpng. */ #define _POSIX_SOURCE 1 +#define _ISOC99_SOURCE 1 /* For floating point */ +#define _GNU_SOURCE 1 /* For the floating point exception extension */ + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_FEENABLEEXCEPT +# include +#endif #include "png.h" + #if PNG_LIBPNG_VER < 10500 /* This delibarately lacks the PNG_CONST. */ typedef png_byte *png_const_bytep; @@ -830,8 +843,21 @@ if (ps->verbose) store_verbose(ps, pp, is_error ? "error: " : "warning: ", message); } +/* Internal error function, called with a png_store but no libpng stuff. */ +static void +internal_error(png_store *ps, png_const_charp message) +{ + store_log(ps, NULL, message, 1 /* error */); + + /* And finally throw an exception. */ + { + struct exception_context *the_exception_context = &ps->exception_context; + Throw ps; + } +} + /* Functions to use as PNG callbacks. */ static void store_error(png_structp pp, png_const_charp message) /* PNG_NORETURN */ { @@ -1331,9 +1357,23 @@ ++new; } else - store_pool_error(pool->store, pp, "out of memory"); + { + /* NOTE: the PNG user malloc function cannot use the png_ptr it is passed + * other than to retrieve the allocation pointer! libpng calls the + * store_malloc callback in two basic cases: + * + * 1) From png_malloc; png_malloc will do a png_error itself if NULL is + * returned. + * 2) From png_struct or png_info structure creation; png_malloc is + * to return so cleanup can be performed. + * + * To handle this store_malloc can log a message, but can't do anything + * else. + */ + store_log(pool->store, pp, "out of memory", 1 /* is_error */); + } return new; } @@ -1342,8 +1382,16 @@ { store_pool *pool = voidcast(store_pool*, png_get_mem_ptr(pp)); store_memory *this = voidcast(store_memory*, memory), **test; + /* Because libpng calls store_free with a dummy png_struct when deleting + * png_struct or png_info via png_destroy_struct_2 it is necessary to check + * the passed in png_structp to ensure it is valid, and not pass it to + * png_error if it is not. + */ + if (pp != pool->store->pread && pp != pool->store->pwrite) + pp = NULL; + /* First check that this 'memory' really is valid memory - it must be in the * pool list. If it is, use the shared memory_free function to free it. */ --this; @@ -3656,11 +3704,13 @@ { sBIT_error_fn, "sBIT(too big): failed to detect error", 1 }, }; static void -make_error(png_store* volatile ps, png_byte PNG_CONST colour_type, +make_error(png_store* volatile psIn, png_byte PNG_CONST colour_type, png_byte bit_depth, int interlace_type, int test, png_const_charp name) { + png_store * volatile ps = psIn; + context(ps, fault); Try { @@ -3942,8 +3992,10 @@ dp->ps = ps; dp->colour_type = COL_FROM_ID(id); dp->bit_depth = DEPTH_FROM_ID(id); + if (dp->bit_depth < 1 || dp->bit_depth > 16) + internal_error(ps, "internal: bad bit depth"); if (dp->colour_type == 3) dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = 8; else dp->red_sBIT = dp->blue_sBIT = dp->green_sBIT = dp->alpha_sBIT = @@ -5310,10 +5362,14 @@ if (test_pixel.colour_type == PNG_COLOR_TYPE_PALETTE) test_pixel.sample_depth = 8; else test_pixel.sample_depth = test_pixel.bit_depth; - /* Don't need sBIT here */ + /* Don't need sBIT here, but it must be set to non-zero to avoid + * arithmetic overflows. + */ test_pixel.have_tRNS = dp->this.is_transparent; + test_pixel.red_sBIT = test_pixel.green_sBIT = test_pixel.blue_sBIT = + test_pixel.alpha_sBIT = test_pixel.sample_depth; dp->transform_list->mod(dp->transform_list, &test_pixel, pp, dp); if (test_pixel.colour_type != dp->output_colour_type) @@ -9244,8 +9300,74 @@ /*green:*/ { 0.101020574397477, 0.724682314948566, 0.051211818965388 }, /*blue: */ { 0.146774385252705, 0.016589442011321, 0.773892783545073} }, }; +/* signal handler + * + * This attempts to trap signals and escape without crashing. It needs a + * context pointer so that it can throw an exception (call longjmp) to recover + * from the condition; this is handled by making the png_modifier used by 'main' + * into a global variable. + */ +static png_modifier pm; + +static void signal_handler(int signum) +{ + + size_t pos = 0; + char msg[64]; + + pos = safecat(msg, sizeof msg, pos, "caught signal: "); + + switch (signum) + { + case SIGABRT: + pos = safecat(msg, sizeof msg, pos, "abort"); + break; + + case SIGFPE: + pos = safecat(msg, sizeof msg, pos, "floating point exception"); + break; + + case SIGILL: + pos = safecat(msg, sizeof msg, pos, "illegal instruction"); + break; + + case SIGINT: + pos = safecat(msg, sizeof msg, pos, "interrupt"); + break; + + case SIGSEGV: + pos = safecat(msg, sizeof msg, pos, "invalid memory access"); + break; + + case SIGTERM: + pos = safecat(msg, sizeof msg, pos, "termination request"); + break; + + default: + pos = safecat(msg, sizeof msg, pos, "unknown "); + pos = safecatn(msg, sizeof msg, pos, signum); + break; + } + + store_log(&pm.this, NULL/*png_structp*/, msg, 1/*error*/); + + /* And finally throw an exception so we can keep going, unless this is + * SIGTERM in which case stop now. + */ + if (signum != SIGTERM) + { + struct exception_context *the_exception_context = + &pm.this.exception_context; + + Throw &pm.this; + } + + else + exit(1); +} + /* main program */ int main(int argc, PNG_CONST char **argv) { volatile int summary = 1; /* Print the error summary at the end */ @@ -9265,11 +9387,26 @@ /* This records the command and arguments: */ size_t cp = 0; char command[1024]; - png_modifier pm; context(&pm.this, fault); + /* Add appropriate signal handlers, just the ANSI specified ones: */ + signal(SIGABRT, signal_handler); + signal(SIGFPE, signal_handler); + signal(SIGILL, signal_handler); + signal(SIGINT, signal_handler); + signal(SIGSEGV, signal_handler); + signal(SIGTERM, signal_handler); + +#ifdef HAVE_FEENABLEEXCEPT + /* Only required to enable FP exceptions on platforms where they start off + * disabled; this is not necessary but if it is not done pngvalid will likely + * end up ignoring FP conditions that other platforms fault. + */ + feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); +#endif + modifier_init(&pm); /* Preallocate the image buffer, because we know how big it needs to be, * note that, for testing purposes, it is deliberately mis-aligned by tag diff -ru4NwbB libpng-1.5.6/pngwrite.c libpng-1.5.7beta04/pngwrite.c --- libpng-1.5.6/pngwrite.c 2011-11-02 22:42:50.547268135 -0500 +++ libpng-1.5.7beta04/pngwrite.c 2011-11-17 21:02:57.126280923 -0600 @@ -1,8 +1,8 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.7 [(PENDING RELEASE)] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -11,8 +11,11 @@ * and license in png.h */ #include "pngpriv.h" +#if defined PNG_SIMPLIFIED_WRITE_SUPPORTED && defined PNG_STDIO_SUPPORTED +# include +#endif #ifdef PNG_WRITE_SUPPORTED /* Writes all the PNG information. This is the suggested way to use the @@ -489,10 +492,11 @@ #endif #ifdef PNG_SETJMP_SUPPORTED /* Applications that neglect to set up their own setjmp() and then - encounter a png_error() will longjmp here. Since the jmpbuf is - then meaningless we abort instead of returning. */ + * encounter a png_error() will longjmp here. Since the jmpbuf is + * then meaningless we abort instead of returning. + */ #ifdef USE_FAR_KEYWORD if (setjmp(tmp_jmpbuf)) #else if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */ @@ -1650,5 +1654,560 @@ PNG_UNUSED(transforms) /* Quiet compiler warnings */ PNG_UNUSED(params) } #endif + + +#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) +{ + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image, + png_safe_error, png_safe_warning); + + if (png_ptr != NULL) + { + png_infop info_ptr = png_create_info_struct(png_ptr); + + if (info_ptr != NULL) + { + png_controlp control = png_voidcast(png_controlp, + png_malloc_warn(png_ptr, sizeof *control)); + + if (control != NULL) + { + memset(control, 0, sizeof *control); + + control->png_ptr = png_ptr; + control->info_ptr = info_ptr; + control->for_write = 1; + + image->opaque = control; + return 1; + } + + /* Error clean up */ + png_destroy_info_struct(png_ptr, &info_ptr); + } + + png_destroy_write_struct(&png_ptr, NULL); + } + + return png_image_error(image, "png_image_read: out of memory"); +} + +/* Arguments to png_image_write_main: */ +typedef struct +{ + /* Arguments: */ + png_imagep image; + png_const_voidp buffer; + png_int_32 row_stride; + int convert_to_8bit; + /* Local variables: */ + png_const_voidp first_row; + ptrdiff_t row_bytes; + png_voidp local_row; +} png_image_write_control; + +/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to + * do any necessary byte swapping. The component order is defined by the + * png_image format value. + */ +static int +png_write_image_16bit(png_voidp argument) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); + png_imagep image = display->image; + png_structp png_ptr = image->opaque->png_ptr; + + png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, + display->first_row); + png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); + png_uint_16p row_end; + int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; + int aindex = 0; + png_uint_32 y = image->height; + + if (image->format & PNG_FORMAT_FLAG_ALPHA) + { + if (image->format & PNG_FORMAT_FLAG_AFIRST) + { + aindex = -1; + ++input_row; /* To point to the first component */ + ++output_row; + } + + else + aindex = channels; + } + + else + png_error(png_ptr, "png_write_image: internal call error"); + + /* Work out the output row end and count over this, note that the increment + * above to 'row' means that row_end can actually be beyond the end of the + * row; this is correct. + */ + row_end = output_row + image->width * (channels+1); + + while (y-- > 0) + { + png_const_uint_16p in_ptr = input_row; + png_uint_16p out_ptr = output_row; + + while (out_ptr < row_end) + { + png_uint_16 alpha = in_ptr[aindex]; + png_uint_32 reciprocal = 0; + int c; + + out_ptr[aindex] = alpha; + + /* Calculate a reciprocal. The correct calculation is simply + * component/alpha*65535 << 15. (I.e. 15 bits of precision); this + * allows correct rounding by adding .5 before the shift. 'reciprocal' + * is only initialized when required. + */ + if (alpha > 0 && alpha < 65535) + reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; + + c = channels; + do /* always at least one channel */ + { + png_uint_16 component = *in_ptr++; + + /* The following gives 65535 for an alpha of 0, which is fine, + * otherwise if 0/0 is represented as some other value there is more + * likely to be a discontinuity which will probably damage + * compression when moving from a fully transparent area to a + * nearly transparent one. (The assumption here is that opaque + * areas tend not to be 0 intensity.) + */ + if (component >= alpha) + component = 65535; + + /* component 0 && alpha < 65535) + { + png_uint_32 calc = component * reciprocal; + calc += 16384; /* round to nearest */ + component = (png_uint_16)(calc >> 15); + } + + *out_ptr++ = component; + } + while (--c > 0); + + /* Skip to next component (skip the intervening alpha channel) */ + ++in_ptr; + ++out_ptr; + } + + png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); + input_row += display->row_bytes/(sizeof (png_uint_16)); + } + + return 1; +} + +/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel + * is present it must be removed from the components, the components are then + * written in sRGB encoding. No components are added or removed. + */ +static int +png_write_image_8bit(png_voidp argument) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); + png_imagep image = display->image; + png_structp png_ptr = image->opaque->png_ptr; + + png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, + display->first_row); + png_bytep output_row = png_voidcast(png_bytep, display->local_row); + png_uint_32 y = image->height; + int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; + + if (image->format & PNG_FORMAT_FLAG_ALPHA) + { + png_bytep row_end; + int aindex; + + if (image->format & PNG_FORMAT_FLAG_AFIRST) + { + aindex = -1; + ++input_row; /* To point to the first component */ + ++output_row; + } + + else + aindex = channels; + + /* Use row_end in place of a loop counter: */ + row_end = output_row + image->width * (channels+1); + + while (y-- > 0) + { + png_const_uint_16p in_ptr = input_row; + png_bytep out_ptr = output_row; + + if (aindex != 0) while (out_ptr < row_end) /* Alpha channel case */ + { + png_uint_16 alpha = in_ptr[aindex]; + png_uint_32 reciprocal = 0; + int c; + + /* Scale and write the alpha channel. See pngrtran.c + * png_do_scale_16_to_8 for a discussion of this calculation. The + * code here has machine native values, so use: + * + * (V * 255 + 32895) >> 16 + */ + out_ptr[aindex] = (png_byte)((alpha * 255 + 32895) >> 16); + + /* Calculate a reciprocal. As above the calculation can be done to + * 15 bits of accuracy, however the output needs to be scaled in the + * range 0..255*65535, so include that scaling here. + */ + if (alpha > 0 && alpha < 65535) + reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha; + + c = channels; + do /* always at least one channel */ + { + /* Need 32 bit accuracy in the sRGB tables */ + png_uint_32 component = *in_ptr++; + + /* The following gives 1.0 for an alpha of 0, which is fine, + * otherwise if 0/0 is represented as some other value there is + * more likely to be a discontinuity which will probably damage + * compression when moving from a fully transparent area to a + * nearly transparent one. (The assumption here is that opaque + * areas tend not to be 0 intensity.) + */ + if (component >= alpha) + *out_ptr++ = 255; + + /* component 0) + { + if (alpha < 65535) + { + component *= reciprocal; + component += 64; /* round to nearest */ + component >>= 7; + } + + else + component *= 255; + + /* Convert the component to sRGB. */ + *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component); + } + + else + *out_ptr++ = 0; + } + while (--c > 0); + + /* Skip to next component (skip the intervening alpha channel) */ + ++in_ptr; + ++out_ptr; + } /* while out_ptr < row_end */ + + png_write_row(png_ptr, png_voidcast(png_const_bytep, + display->local_row)); + input_row += display->row_bytes/(sizeof (png_uint_16)); + } /* while y */ + } + + else + { + /* No alpha channel, so the row_end really is the end of the row and it + * is sufficient to loop over the components one by one. + */ + png_bytep row_end = output_row + image->width * channels; + + while (y-- > 0) + { + png_const_uint_16p in_ptr = input_row; + png_bytep out_ptr = output_row; + + while (out_ptr < row_end) + { + png_uint_32 component = *in_ptr++; + + component *= 255; + *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component); + } + + png_write_row(png_ptr, output_row); + input_row += display->row_bytes/(sizeof (png_uint_16)); + } + } + + return 1; +} + +static int +png_image_write_main(png_voidp argument) +{ + png_image_write_control *display = png_voidcast(png_image_write_control*, + argument); + png_imagep image = display->image; + png_structp png_ptr = image->opaque->png_ptr; + png_infop info_ptr = image->opaque->info_ptr; + png_uint_32 format = image->format; + + int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; /* input */ + int alpha = (format & PNG_FORMAT_FLAG_ALPHA) != 0; + int write_16bit = linear && !display->convert_to_8bit; + + /* Set the required transforms then write the rows in the correct order. */ + png_set_IHDR(png_ptr, info_ptr, image->width, image->height, + write_16bit ? 16 : 8, + ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + + ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* Counter-intuitively the data transformations must be called *after* + * png_write_info, not before as in the read code, but the 'set' functions + * must still be called before. Just set the color space information, never + * write an interlaced image. + */ + if (write_16bit) + { + /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */ + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR); + + if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB)) + png_set_cHRM_fixed(png_ptr, info_ptr, + /* color x y */ + /* white */ 31270, 32900, + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000 + ); + } + + else if (!(image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB)) + png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL); + + /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit + * space must still be gamma encoded. + */ + else + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); + + /* Write the file header. */ + png_write_info(png_ptr, info_ptr); + + /* Now set up the data transformations (*after* the header is written), + * remove the handled transformations from the 'format' flags for checking. + * + * First check for a little endian system if writing 16 bit files. + */ + if (write_16bit) + { + PNG_CONST png_uint_16 le = 0x0001; + + if (*(png_const_bytep)&le) + png_set_swap(png_ptr); + } + +# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED + if (format & PNG_FORMAT_FLAG_BGR) + { + if (format & PNG_FORMAT_FLAG_COLOR) + png_set_bgr(png_ptr); + format &= ~PNG_FORMAT_FLAG_BGR; + } +# endif + +# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED + if (format & PNG_FORMAT_FLAG_AFIRST) + { + if (format & PNG_FORMAT_FLAG_ALPHA) + png_set_swap_alpha(png_ptr); + format &= ~PNG_FORMAT_FLAG_AFIRST; + } +# endif + + /* That should have handled all (both) the transforms. */ + if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR | + PNG_FORMAT_FLAG_ALPHA)) != 0) + png_error(png_ptr, "png_write_image: unsupported transformation"); + + { + png_const_bytep row = png_voidcast(png_const_bytep, display->buffer); + ptrdiff_t row_bytes = display->row_stride; + + if (linear) + row_bytes *= sizeof (png_uint_16); + + if (row_bytes < 0) + row += (image->height-1) * (-row_bytes); + + display->first_row = row; + display->row_bytes = row_bytes; + } + + /* Check for the cases that currently require a pre-transform on the row + * before it is written. This only applies when the input is 16-bit and + * either there is an alpha channel or it is converted to 8-bit. + */ + if ((linear && alpha) || display->convert_to_8bit) + { + png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_get_rowbytes(png_ptr, info_ptr))); + int result; + + display->local_row = row; + if (write_16bit) + result = png_safe_execute(image, png_write_image_16bit, display); + else + result = png_safe_execute(image, png_write_image_8bit, display); + display->local_row = NULL; + + png_free(png_ptr, row); + + /* Skip the 'write_end' on error: */ + if (!result) + return 0; + } + + /* Otherwise this is the case where the input is in a format currently + * supported by the rest of the libpng write code; call it directly. + */ + else + { + png_const_bytep row = png_voidcast(png_const_bytep, display->first_row); + ptrdiff_t row_bytes = display->row_bytes; + png_uint_32 y = image->height; + + while (y-- > 0) + { + png_write_row(png_ptr, row); + row += row_bytes; + } + } + + png_write_end(png_ptr, info_ptr); + return 1; +} + +int PNGAPI +png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, + const void *buffer, png_int_32 row_stride) +{ + /* Write the image to the given (FILE*). */ + if (image != NULL) + { + if (file != NULL) + { + if (png_image_write_init(image)) + { + png_image_write_control display; + int result; + + /* This is slightly evil, but png_init_io doesn't do anything other + * than this and we haven't changed the standard IO functions so + * this saves a 'safe' function. + */ + image->opaque->png_ptr->io_ptr = file; + + memset(&display, 0, sizeof display); + display.image = image; + display.buffer = buffer; + display.row_stride = row_stride; + display.convert_to_8bit = convert_to_8bit; + + result = png_safe_execute(image, png_image_write_main, &display); + png_image_free(image); + return result; + } + + else + return 0; + } + + else + return png_image_error(image, + "png_image_write_to_stdio: invalid argument"); + } + + else + return 0; +} + +int PNGAPI +png_image_write_to_file(png_imagep image, const char *file_name, + int convert_to_8bit, const void *buffer, png_int_32 row_stride) +{ + /* Write the image to the named file. */ + if (image != NULL) + { + if (file_name != NULL) + { + FILE *fp = fopen(file_name, "wb"); + + if (fp != NULL) + { + if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, + row_stride)) + { + int error; /* from fflush/fclose */ + + /* Make sure the file is flushed correctly. */ + if (fflush(fp) == 0 && ferror(fp) == 0) + { + if (fclose(fp) == 0) + return 1; + + error = errno; /* from fclose */ + } + + else + { + error = errno; /* from fflush or ferror */ + (void)fclose(fp); + } + + (void)remove(file_name); + /* The image has already been cleaned up; this is just used to + * set the error (because the original write succeeded). + */ + return png_image_error(image, strerror(error)); + } + + else + { + /* Clean up: just the opened file. */ + (void)fclose(fp); + (void)remove(file_name); + return 0; + } + } + + else + return png_image_error(image, strerror(errno)); + } + + else + return png_image_error(image, + "png_image_write_to_file: invalid argument"); + } + + else + return 0; +} +#endif /* PNG_STDIO_SUPPORTED */ +#endif /* SIMPLIFIED_WRITE */ #endif /* PNG_WRITE_SUPPORTED */ diff -ru4NwbB libpng-1.5.6/pngwtran.c libpng-1.5.7beta04/pngwtran.c --- libpng-1.5.6/pngwtran.c 2011-11-02 22:42:50.554047247 -0500 +++ libpng-1.5.7beta04/pngwtran.c 2011-11-17 21:02:57.133180903 -0600 @@ -1,8 +1,8 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.6 [November 3, 2011] * Copyright (c) 1998-2011 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 -ru4NwbB libpng-1.5.6/pngwutil.c libpng-1.5.7beta04/pngwutil.c --- libpng-1.5.6/pngwutil.c 2011-11-02 22:42:50.567056497 -0500 +++ libpng-1.5.7beta04/pngwutil.c 2011-11-17 21:02:57.145984367 -0600 @@ -1,8 +1,8 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.5.6 [(PENDING RELEASE)] + * Last changed in libpng 1.5.6 [November 3, 2011] * Copyright (c) 1998-2011 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 -ru4NwbB libpng-1.5.6/projects/owatcom/libpng.wpj libpng-1.5.7beta04/projects/owatcom/libpng.wpj --- libpng-1.5.6/projects/owatcom/libpng.wpj 2011-06-11 06:32:45.000000000 -0500 +++ libpng-1.5.7beta04/projects/owatcom/libpng.wpj 2011-11-16 11:53:54.637303000 -0600 @@ -4,11 +4,11 @@ VpeMain 1 WRect 256 -146 -8966 -9303 +0 +8960 +9294 2 MProject 3 MCommand @@ -24,9 +24,9 @@ 4 MCommand 19 @type pngconfig.inf -3 +4 5 WFileName 10 libpng.tgt @@ -38,55 +38,75 @@ WFileName 12 pngvalid.tgt 8 -WVList -3 +WFileName +12 +pngstest.tgt 9 -VComponent +WVList +4 10 +VComponent +11 WRect 0 0 -5644 -4183 +5638 +4174 0 0 -11 +12 WFileName 10 libpng.tgt 0 0 -12 -VComponent 13 +VComponent +14 WRect 1280 -1560 -5644 -4183 +1550 +5638 +4174 0 0 -14 +15 WFileName 11 pngtest.tgt 0 1 -15 -VComponent 16 +VComponent +17 WRect -530 -507 -5644 -4183 +524 +497 +5638 +4174 0 0 -17 +18 WFileName 12 pngvalid.tgt 0 1 -9 +19 +VComponent +20 +WRect +2054 +2701 +5674 +4232 +0 +0 +21 +WFileName +12 +pngstest.tgt +0 +1 +19 diff -ru4NwbB libpng-1.5.6/projects/owatcom/pngconfig.mak libpng-1.5.7beta04/projects/owatcom/pngconfig.mak --- libpng-1.5.6/projects/owatcom/pngconfig.mak 2011-06-11 06:11:41.000000000 -0500 +++ libpng-1.5.7beta04/projects/owatcom/pngconfig.mak 2011-11-08 19:12:49.511653000 -0600 @@ -56,11 +56,11 @@ instructions consult and edit projects/openwatcom/pngconfig.dfa << $(DELETE) dfn.c dfn1.out dfn2.out -pnglibconf.dfn: ..\..\scripts\pnglibconf.dfa ..\..\scripts\options.awk pngconfig.dfa +pnglibconf.dfn: ..\..\scripts\pnglibconf.dfa ..\..\scripts\options.awk pngconfig.dfa ..\..\pngconf.h $(DELETE) $@ dfn1.out dfn2.out - $(AWK) -f ..\..\scripts\options.awk out=dfn1.out ..\..\scripts\pnglibconf.dfa pngconfig.dfa $(DFA_XTRA) 1>&2 + $(AWK) -f ..\..\scripts\options.awk out=dfn1.out version=search ..\..\pngconf.h ..\..\scripts\pnglibconf.dfa pngconfig.dfa $(DFA_XTRA) 1>&2 $(AWK) -f ..\..\scripts\options.awk out=dfn2.out dfn1.out 1>&2 $(COPY) dfn2.out $@ $(DELETE) dfn1.out dfn2.out diff -ru4NwbB libpng-1.5.6/projects/owatcom/pngstest.tgt libpng-1.5.7beta04/projects/owatcom/pngstest.tgt --- libpng-1.5.6/projects/owatcom/pngstest.tgt 1969-12-31 18:00:00.000000000 -0600 +++ libpng-1.5.7beta04/projects/owatcom/pngstest.tgt 2011-11-16 11:53:54.647113000 -0600 @@ -0,0 +1,219 @@ +40 +targetIdent +0 +MProject +1 +MComponent +0 +2 +WString +4 +NEXE +3 +WString +5 +nc2en +1 +0 +0 +4 +MCommand +0 +5 +MCommand +1035 +pngstest --log ../../contrib/pngsuite/basn0g01.png ../../contrib/pngsuite/basn0g02.png ../../contrib/pngsuite/basn0g04.png ../../contrib/pngsuite/basn0g08.png ../../contrib/pngsuite/basn0g16.png ../../contrib/pngsuite/basn2c08.png ../../contrib/pngsuite/basn2c16.png ../../contrib/pngsuite/basn3p01.png ../../contrib/pngsuite/basn3p02.png ../../contrib/pngsuite/basn3p04.png ../../contrib/pngsuite/basn3p08.png ../../contrib/pngsuite/basn4a08.png ../../contrib/pngsuite/basn4a16.png ../../contrib/pngsuite/basn6a08.png ../../contrib/pngsuite/basn6a16.png ../../contrib/pngsuite/ftbbn1g04.png ../../contrib/pngsuite/ftbbn2c16.png ../../contrib/pngsuite/ftbbn3p08.png ../../contrib/pngsuite/ftbgn2c16.png ../../contrib/pngsuite/ftbgn3p08.png ../../contrib/pngsuite/ftbrn2c08.png ../../contrib/pngsuite/ftbwn1g16.png ../../contrib/pngsuite/ftbwn3p08.png ../../contrib/pngsuite/ftbyn3p08.png ../../contrib/pngsuite/ftp0n1g08.png ../../contrib/pngsuite/ftp0n2c08.png ../../contrib/pngsuite/ftp0n3p08.png ../../contrib/pngsuite/ftp1n3p08.png +6 +MItem +12 +pngstest.exe +7 +WString +4 +NEXE +8 +WVList +6 +9 +MVState +10 +WString +7 +WINLINK +11 +WString +11 +?????Stack: +1 +12 +WString +4 +768k +0 +13 +MVState +14 +WString +7 +WINLINK +15 +WString +28 +?????Library directories(;): +1 +16 +WString +8 +$(%zlib) +0 +17 +MVState +18 +WString +7 +WINLINK +19 +WString +18 +?????Libraries(,): +1 +20 +WString +19 +libpng.lib zlib.lib +0 +21 +MVState +22 +WString +7 +WINLINK +23 +WString +11 +?????Stack: +0 +24 +WString +4 +768k +0 +25 +MVState +26 +WString +7 +WINLINK +27 +WString +28 +?????Library directories(;): +0 +28 +WString +8 +$(%zlib) +0 +29 +MVState +30 +WString +7 +WINLINK +31 +WString +18 +?????Libraries(,): +0 +32 +WString +19 +libpng.lib zlib.lib +0 +33 +WVList +1 +34 +ActionStates +35 +WString +4 +&Run +36 +WVList +0 +-1 +1 +1 +0 +37 +WPickList +2 +38 +MItem +3 +*.c +39 +WString +4 +COBJ +40 +WVList +2 +41 +MVState +42 +WString +3 +WCC +43 +WString +25 +n????Include directories: +1 +44 +WString +39 +"$(%zlib);$(%watcom)/h;$(%watcom)/h/nt" +0 +45 +MVState +46 +WString +3 +WCC +47 +WString +25 +n????Include directories: +0 +48 +WString +39 +"$(%zlib);$(%watcom)/h;$(%watcom)/h/nt" +0 +49 +WVList +0 +-1 +1 +1 +0 +50 +MItem +33 +..\..\contrib\libtests\pngstest.c +51 +WString +4 +COBJ +52 +WVList +0 +53 +WVList +0 +38 +1 +1 +0 diff -ru4NwbB libpng-1.5.6/projects/vstudio/pngstest/pngstest.vcxproj libpng-1.5.7beta04/projects/vstudio/pngstest/pngstest.vcxproj --- libpng-1.5.6/projects/vstudio/pngstest/pngstest.vcxproj 1969-12-31 18:00:00.000000000 -0600 +++ libpng-1.5.7beta04/projects/vstudio/pngstest/pngstest.vcxproj 2011-11-16 11:53:54.666881000 -0600 @@ -0,0 +1,218 @@ + + + + + Debug Library + Win32 + + + Debug + Win32 + + + Release Library + Win32 + + + Release + Win32 + + + + {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8} + Win32Proj + pngstest + + + + + Application + Unicode + + + Application + Unicode + + + Application + Unicode + + + Application + Unicode + + + + + + + + + + + + + + + + + + + false + + + + false + + + + false + + + + false + + + + + NotUsing + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + WIN32;_DEBUG;_CONSOLE;PNG_USE_DLL;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + true + false + true + false + + + Console + true + libpng15.lib;zlib.lib + $(OutDir) + + + Executing libpng simplified API test program + "$(OutDir)pngstest.exe" --log --touch "$(IntDir)pngstest.out" ../../../contrib/pngsuite/basn0g01.png ../../../contrib/pngsuite/basn0g02.png ../../../contrib/pngsuite/basn0g04.png ../../../contrib/pngsuite/basn0g08.png ../../../contrib/pngsuite/basn0g16.png ../../../contrib/pngsuite/basn2c08.png ../../../contrib/pngsuite/basn2c16.png ../../../contrib/pngsuite/basn3p01.png ../../../contrib/pngsuite/basn3p02.png ../../../contrib/pngsuite/basn3p04.png ../../../contrib/pngsuite/basn3p08.png ../../../contrib/pngsuite/basn4a08.png ../../../contrib/pngsuite/basn4a16.png ../../../contrib/pngsuite/basn6a08.png ../../../contrib/pngsuite/basn6a16.png ../../../contrib/pngsuite/ftbbn1g04.png ../../../contrib/pngsuite/ftbbn2c16.png ../../../contrib/pngsuite/ftbbn3p08.png ../../../contrib/pngsuite/ftbgn2c16.png ../../../contrib/pngsuite/ftbgn3p08.png ../../../contrib/pngsuite/ftbrn2c08.png ../../../contrib/pngsuite/ftbwn1g16.png ../../../contrib/pngsuite/ftbwn3p08.png ../../../contrib/pngsuite/ftbyn3p08.png ../../../contrib/pngsuite/ftp0n1g08.png ../../../contrib/pngsuite/ftp0n2c08.png ../../../contrib/pngsuite/ftp0n3p08.png ../../../contrib/pngsuite/ftp1n3p08.png + $(IntDir)pngstest.out + $(OutDir)pngstest.exe + + + + + NotUsing + Level4 + false + ProgramDatabase + Disabled + EnableFastChecks + MultiThreadedDebug + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + true + false + true + false + + + Console + true + libpng15.lib;zlib.lib + $(OutDir) + + + Executing libpng simplified API test program + "$(OutDir)pngstest.exe" --log --touch "$(IntDir)pngstest.out" ../../../contrib/pngsuite/basn0g01.png ../../../contrib/pngsuite/basn0g02.png ../../../contrib/pngsuite/basn0g04.png ../../../contrib/pngsuite/basn0g08.png ../../../contrib/pngsuite/basn0g16.png ../../../contrib/pngsuite/basn2c08.png ../../../contrib/pngsuite/basn2c16.png ../../../contrib/pngsuite/basn3p01.png ../../../contrib/pngsuite/basn3p02.png ../../../contrib/pngsuite/basn3p04.png ../../../contrib/pngsuite/basn3p08.png ../../../contrib/pngsuite/basn4a08.png ../../../contrib/pngsuite/basn4a16.png ../../../contrib/pngsuite/basn6a08.png ../../../contrib/pngsuite/basn6a16.png ../../../contrib/pngsuite/ftbbn1g04.png ../../../contrib/pngsuite/ftbbn2c16.png ../../../contrib/pngsuite/ftbbn3p08.png ../../../contrib/pngsuite/ftbgn2c16.png ../../../contrib/pngsuite/ftbgn3p08.png ../../../contrib/pngsuite/ftbrn2c08.png ../../../contrib/pngsuite/ftbwn1g16.png ../../../contrib/pngsuite/ftbwn3p08.png ../../../contrib/pngsuite/ftbyn3p08.png ../../../contrib/pngsuite/ftp0n1g08.png ../../../contrib/pngsuite/ftp0n2c08.png ../../../contrib/pngsuite/ftp0n3p08.png ../../../contrib/pngsuite/ftp1n3p08.png + $(IntDir)pngstest.out + $(OutDir)pngstest.exe + + + + + Level4 + NotUsing + ProgramDatabase + Full + false + true + WIN32;NDEBUG;_CONSOLE;PNG_USE_DLL;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + false + true + true + false + + + Console + true + true + true + libpng15.lib;zlib.lib + $(OutDir) + UseLinkTimeCodeGeneration + + + Executing libpng simplified API test program + "$(OutDir)pngstest.exe" --log --touch "$(IntDir)pngstest.out" ../../../contrib/pngsuite/basn0g01.png ../../../contrib/pngsuite/basn0g02.png ../../../contrib/pngsuite/basn0g04.png ../../../contrib/pngsuite/basn0g08.png ../../../contrib/pngsuite/basn0g16.png ../../../contrib/pngsuite/basn2c08.png ../../../contrib/pngsuite/basn2c16.png ../../../contrib/pngsuite/basn3p01.png ../../../contrib/pngsuite/basn3p02.png ../../../contrib/pngsuite/basn3p04.png ../../../contrib/pngsuite/basn3p08.png ../../../contrib/pngsuite/basn4a08.png ../../../contrib/pngsuite/basn4a16.png ../../../contrib/pngsuite/basn6a08.png ../../../contrib/pngsuite/basn6a16.png ../../../contrib/pngsuite/ftbbn1g04.png ../../../contrib/pngsuite/ftbbn2c16.png ../../../contrib/pngsuite/ftbbn3p08.png ../../../contrib/pngsuite/ftbgn2c16.png ../../../contrib/pngsuite/ftbgn3p08.png ../../../contrib/pngsuite/ftbrn2c08.png ../../../contrib/pngsuite/ftbwn1g16.png ../../../contrib/pngsuite/ftbwn3p08.png ../../../contrib/pngsuite/ftbyn3p08.png ../../../contrib/pngsuite/ftp0n1g08.png ../../../contrib/pngsuite/ftp0n2c08.png ../../../contrib/pngsuite/ftp0n3p08.png ../../../contrib/pngsuite/ftp1n3p08.png + $(IntDir)pngstest.out + $(OutDir)pngstest.exe + + + + + Level4 + NotUsing + ProgramDatabase + Full + MultiThreaded + false + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + $(ZLibSrcDir);..\..\..\scripts;%(AdditionalIncludeDirectories) + 4996;4127 + false + true + true + false + true + true + false + + + Console + true + true + true + libpng15.lib;zlib.lib + $(OutDir) + UseLinkTimeCodeGeneration + + + Executing libpng simplified API test program + "$(OutDir)pngstest.exe" --log --touch "$(IntDir)pngstest.out" ../../../contrib/pngsuite/basn0g01.png ../../../contrib/pngsuite/basn0g02.png ../../../contrib/pngsuite/basn0g04.png ../../../contrib/pngsuite/basn0g08.png ../../../contrib/pngsuite/basn0g16.png ../../../contrib/pngsuite/basn2c08.png ../../../contrib/pngsuite/basn2c16.png ../../../contrib/pngsuite/basn3p01.png ../../../contrib/pngsuite/basn3p02.png ../../../contrib/pngsuite/basn3p04.png ../../../contrib/pngsuite/basn3p08.png ../../../contrib/pngsuite/basn4a08.png ../../../contrib/pngsuite/basn4a16.png ../../../contrib/pngsuite/basn6a08.png ../../../contrib/pngsuite/basn6a16.png ../../../contrib/pngsuite/ftbbn1g04.png ../../../contrib/pngsuite/ftbbn2c16.png ../../../contrib/pngsuite/ftbbn3p08.png ../../../contrib/pngsuite/ftbgn2c16.png ../../../contrib/pngsuite/ftbgn3p08.png ../../../contrib/pngsuite/ftbrn2c08.png ../../../contrib/pngsuite/ftbwn1g16.png ../../../contrib/pngsuite/ftbwn3p08.png ../../../contrib/pngsuite/ftbyn3p08.png ../../../contrib/pngsuite/ftp0n1g08.png ../../../contrib/pngsuite/ftp0n2c08.png ../../../contrib/pngsuite/ftp0n3p08.png ../../../contrib/pngsuite/ftp1n3p08.png + $(IntDir)pngstest.out + $(OutDir)pngstest.exe + + + + + + + + + diff -ru4NwbB libpng-1.5.6/projects/vstudio/pngvalid/pngvalid.vcxproj libpng-1.5.7beta04/projects/vstudio/pngvalid/pngvalid.vcxproj --- libpng-1.5.6/projects/vstudio/pngvalid/pngvalid.vcxproj 2011-11-02 22:42:52.845365823 -0500 +++ libpng-1.5.7beta04/projects/vstudio/pngvalid/pngvalid.vcxproj 2011-11-17 21:02:59.549080250 -0600 @@ -203,9 +203,8 @@ UseLinkTimeCodeGeneration Executing PNG validation program - $(OutDir)pngvalid.exe ..\..\..\pngvalid.png $(IntDir)pngout.png "$(OutDir)pngvalid.exe" --touch "$(IntDir)pngvalid.out" $(IntDir)pngvalid.out $(OutDir)pngvalid.exe diff -ru4NwbB libpng-1.5.6/projects/vstudio/vstudio.sln libpng-1.5.7beta04/projects/vstudio/vstudio.sln --- libpng-1.5.6/projects/vstudio/vstudio.sln 2010-08-24 15:04:11.000000000 -0500 +++ libpng-1.5.7beta04/projects/vstudio/vstudio.sln 2011-11-16 11:53:54.683367000 -0600 @@ -1,30 +1,37 @@ Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "libpng\libpng.vcxproj", "{D6973076-9317-4EF2-A0B8-B7A18AC0713E}" ProjectSection(ProjectDependencies) = postProject - {64CE4900-97EA-2DD5-4226-F2E36FFF2867} = {64CE4900-97EA-2DD5-4226-F2E36FFF2867} + {60F89955-91C6-3A36-8000-13C592FEC2DF} = {60F89955-91C6-3A36-8000-13C592FEC2DF} {EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {EB33566E-DA7F-4D28-9077-88C0B7C77E35} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pngtest", "pngtest\pngtest.vcxproj", "{228BA965-50D5-42B2-8BCF-AFCC227E3C1D}" ProjectSection(ProjectDependencies) = postProject - {64CE4900-97EA-2DD5-4226-F2E36FFF2867} = {64CE4900-97EA-2DD5-4226-F2E36FFF2867} + {60F89955-91C6-3A36-8000-13C592FEC2DF} = {60F89955-91C6-3A36-8000-13C592FEC2DF} {EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {EB33566E-DA7F-4D28-9077-88C0B7C77E35} {D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E} EndProjectSection EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib.vcxproj", "{64CE4900-97EA-2DD5-4226-F2E36FFF2867}" +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "zlib\zlib.vcxproj", "{60F89955-91C6-3A36-8000-13C592FEC2DF}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pngvalid", "pngvalid\pngvalid.vcxproj", "{9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}" ProjectSection(ProjectDependencies) = postProject - {64CE4900-97EA-2DD5-4226-F2E36FFF2867} = {64CE4900-97EA-2DD5-4226-F2E36FFF2867} + {60F89955-91C6-3A36-8000-13C592FEC2DF} = {60F89955-91C6-3A36-8000-13C592FEC2DF} {EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {EB33566E-DA7F-4D28-9077-88C0B7C77E35} {D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pnglibconf", "pnglibconf\pnglibconf.vcxproj", "{EB33566E-DA7F-4D28-9077-88C0B7C77E35}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pngstest", "pngstest\pngstest.vcxproj", "{277AC57F-313B-4D06-B119-A3CDB672D2FF}" + ProjectSection(ProjectDependencies) = postProject + {60F89955-91C6-3A36-8000-13C592FEC2DF} = {60F89955-91C6-3A36-8000-13C592FEC2DF} + {EB33566E-DA7F-4D28-9077-88C0B7C77E35} = {EB33566E-DA7F-4D28-9077-88C0B7C77E35} + {D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug Library|Win32 = Debug Library|Win32 Debug|Win32 = Debug|Win32 @@ -47,16 +54,16 @@ {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release Library|Win32.ActiveCfg = Release Library|Win32 {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release Library|Win32.Build.0 = Release Library|Win32 {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release|Win32.ActiveCfg = Release|Win32 {228BA965-50D5-42B2-8BCF-AFCC227E3C1D}.Release|Win32.Build.0 = Release|Win32 - {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 - {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug Library|Win32.Build.0 = Debug Library|Win32 - {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug|Win32.ActiveCfg = Debug|Win32 - {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Debug|Win32.Build.0 = Debug|Win32 - {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release Library|Win32.ActiveCfg = Release Library|Win32 - {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release Library|Win32.Build.0 = Release Library|Win32 - {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release|Win32.ActiveCfg = Release|Win32 - {64CE4900-97EA-2DD5-4226-F2E36FFF2867}.Release|Win32.Build.0 = Release|Win32 + {60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 + {60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug Library|Win32.Build.0 = Debug Library|Win32 + {60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug|Win32.ActiveCfg = Debug|Win32 + {60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug|Win32.Build.0 = Debug|Win32 + {60F89955-91C6-3A36-8000-13C592FEC2DF}.Release Library|Win32.ActiveCfg = Release Library|Win32 + {60F89955-91C6-3A36-8000-13C592FEC2DF}.Release Library|Win32.Build.0 = Release Library|Win32 + {60F89955-91C6-3A36-8000-13C592FEC2DF}.Release|Win32.ActiveCfg = Release|Win32 + {60F89955-91C6-3A36-8000-13C592FEC2DF}.Release|Win32.Build.0 = Release|Win32 {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug Library|Win32.Build.0 = Debug Library|Win32 {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug|Win32.ActiveCfg = Debug|Win32 {9B36B6FE-7FC0-434F-A71F-BBEF8099F1D8}.Debug|Win32.Build.0 = Debug|Win32 @@ -71,8 +78,16 @@ {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release Library|Win32.ActiveCfg = Release|Win32 {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release Library|Win32.Build.0 = Release|Win32 {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release|Win32.ActiveCfg = Release|Win32 {EB33566E-DA7F-4D28-9077-88C0B7C77E35}.Release|Win32.Build.0 = Release|Win32 + {277AC57F-313B-4D06-B119-A3CDB672D2FF}.Debug Library|Win32.ActiveCfg = Debug Library|Win32 + {277AC57F-313B-4D06-B119-A3CDB672D2FF}.Debug Library|Win32.Build.0 = Debug Library|Win32 + {277AC57F-313B-4D06-B119-A3CDB672D2FF}.Debug|Win32.ActiveCfg = Debug|Win32 + {277AC57F-313B-4D06-B119-A3CDB672D2FF}.Debug|Win32.Build.0 = Debug|Win32 + {277AC57F-313B-4D06-B119-A3CDB672D2FF}.Release Library|Win32.ActiveCfg = Release Library|Win32 + {277AC57F-313B-4D06-B119-A3CDB672D2FF}.Release Library|Win32.Build.0 = Release Library|Win32 + {277AC57F-313B-4D06-B119-A3CDB672D2FF}.Release|Win32.ActiveCfg = Release|Win32 + {277AC57F-313B-4D06-B119-A3CDB672D2FF}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection diff -ru4NwbB libpng-1.5.6/scripts/def.dfn libpng-1.5.7beta04/scripts/def.dfn --- libpng-1.5.6/scripts/def.dfn 2011-01-04 09:45:35.000000000 -0600 +++ libpng-1.5.7beta04/scripts/def.dfn 2011-11-03 16:13:57.945898000 -0500 @@ -26,13 +26,13 @@ S--E S-EXPORTS-E S-;Version 1.5.0beta58-E -/* NOTE: @@@ is interpreted by the calling script as a signal to +/* NOTE: PNG_JOIN is interpreted by the calling script as a signal to * join the two things on either side, so we can do symbol * substitution within the name, regular C ## joins the pp-tokens, * not their final values. */ #define PNG_EXPORTA(ordinal, type, name, args, attributes)\ - PNG_DEFN_MAGIC- SYMBOL_PREFIX @@@ name-PNG_DEFN_END + PNG_DEFN_MAGIC- SYMBOL_PREFIX PNG_JOIN name-PNG_DEFN_END #include "../png.h" diff -ru4NwbB libpng-1.5.6/scripts/makefile.std libpng-1.5.7beta04/scripts/makefile.std --- libpng-1.5.6/scripts/makefile.std 2011-11-02 22:42:52.714325462 -0500 +++ libpng-1.5.7beta04/scripts/makefile.std 2011-11-17 21:02:59.390192582 -0600 @@ -49,11 +49,11 @@ all: libpng.a pngtest # The standard pnglibconf.h exists as scripts/pnglibconf.h.prebuilt, # copy this if the following doesn't work. -pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk +pnglibconf.dfn: scripts/pnglibconf.dfa scripts/options.awk pngconf.h $(RM_F) $@ dfn?.out - $(AWK) -f scripts/options.awk out=dfn1.out\ + $(AWK) -f scripts/options.awk out=dfn1.out version=search pngconf.h\ scripts/pnglibconf.dfa $(DFA_XTRA) 1>&2 $(AWK) -f scripts/options.awk out=dfn2.out dfn1.out 1>&2 cp dfn2.out $@ $(RM_F) dfn?.out @@ -61,11 +61,11 @@ pnglibconf.h: pnglibconf.dfn $(RM_F) $@ dfn.c dfn?.out $(ECHO) '#include "pnglibconf.dfn"' >dfn.c $(CPP) $(DFNFLAGS) dfn.c >dfn1.out - $(SED) -n -e 's|^.*PNG_DEFN_MAGIC-\(.*\)-PNG_DEFN_END.*$$|\1|p'\ + $(SED) -n -e 's|^.*PNG_DEFN_MAGIC *-\(.*\)- *PNG_DEFN_END.*$$|\1|p'\ dfn1.out >dfn2.out - $(SED) -e 's| *@@@ *||g' -e 's| *$$||' dfn2.out >dfn3.out + $(SED) -e 's| *PNG_JOIN *||g' -e 's| *$$||' dfn2.out >dfn3.out cp dfn3.out $@ $(RM_F) dfn.c dfn?.out libpng.a: $(OBJS) diff -ru4NwbB libpng-1.5.6/scripts/options.awk libpng-1.5.7beta04/scripts/options.awk --- libpng-1.5.6/scripts/options.awk 2011-05-07 10:30:44.000000000 -0500 +++ libpng-1.5.7beta04/scripts/options.awk 2011-11-17 21:02:59.449314399 -0600 @@ -1,8 +1,8 @@ #!/bin/awk -f # scripts/options.awk - library build configuration control # -# last changed in libpng version 1.5.0 - January 6, 2011 +# last changed in libpng version 1.5.7 - (PENDING RELEASE) # # Copyright (c) 1998-2011 Glenn Randers-Pehrson # # This code is released under the libpng license. @@ -31,18 +31,21 @@ BEGIN{ out="/dev/null" # intermediate, preprocessed, file pre=-1 # preprocess (first line) + version="libpng version unknown" # version information + version_file="" # where to find the version err=0 # in-line exit sets this start="PNG_DEFN_MAGIC-" # Arbitrary start end="-PNG_DEFN_END" # Arbitrary end - cx= "/@@@*" # Open C comment for output file + ct="PNG_JOIN" # Join two tokens + cx= "/" ct "*" # Open C comment for output file comment=start cx # Comment start cend="*/" end # Comment end - def=start "#define PNG_@@@" # Arbitrary define - sup="@@@_SUPPORTED" end # end supported option - und=comment "#undef PNG_@@@" # Unsupported option - une="@@@_SUPPORTED" cend # end unsupported option + def=start "#define PNG_" ct # Arbitrary define + sup=ct "_SUPPORTED" end # end supported option + und=comment "#undef PNG_" ct # Unsupported option + une=ct "_SUPPORTED" cend # end unsupported option error=start "ERROR:" # error message # Variables deb=0 # debug - set on command line @@ -84,8 +87,30 @@ # And fall through to continue processing } } +# While pre-processing if version is set to "search" look for a version string +# in the following file. +pre && version == "search" && version_file == ""{ + version_file = FILENAME +} + +pre && version == "search" && version_file != FILENAME{ + print "version string not found in", version_file + err = 1 + exit 1 +} + +pre && version == "search" && $0 ~ /^ \* libpng version/{ + version = substr($0, 4) + print "version =", version >out + next +} + +pre && FILENAME == version_file{ + next +} + # variable=value # Sets the given variable to the given value (the syntax is fairly # free form, except for deb (you are expected to understand how to # set the debug variable...) @@ -93,8 +118,13 @@ # This happens before the check on 'pre' below skips most of the # rest of the actions, so the variable settings happen during # preprocessing but are recorded in the END action too. This # allows them to be set on the command line too. +$0 ~ /^[ ]*version[ ]*=/{ + sub(/^[ ]*version[ ]*=[ ]*/, "") + version = $0 + next +} $0 ~ /^[ ]*everything[ =]*off[ ]*$/{ everything = "off" next } @@ -164,8 +194,21 @@ print start end >out next } +# version +# Inserts a version comment +$1 == "version" && NF == 1{ + if (version == "") { + print "ERROR: no version string set" + err = 1 # prevent END{} running + exit 1 + } + + print comment, version, cend >out + next +} + # file output input protect # Informational: the official name of the input file (without # make generated local directories), the official name of the # output file and, if required, a name to use in a protection diff -ru4NwbB libpng-1.5.6/scripts/pnglibconf.dfa libpng-1.5.7beta04/scripts/pnglibconf.dfa --- libpng-1.5.6/scripts/pnglibconf.dfa 2011-10-13 19:32:21.681776000 -0500 +++ libpng-1.5.7beta04/scripts/pnglibconf.dfa 2011-11-07 22:23:46.790837000 -0600 @@ -5,9 +5,9 @@ @ */ # com pnglibconf.h - library build configuration com -com libpng version 1.5.3 - July 7, 2011 +version com com Copyright (c) 1998-2011 Glenn Randers-Pehrson com com This code is released under the libpng license. @@ -575,4 +575,32 @@ # Turn this off to disable png_read_png() and png_write_png() and # leave the row_pointers member out of the info structure. option INFO_IMAGE + +# Simplified API options +# Read: +option SIMPLIFIED_READ requires SEQUENTIAL_READ READ_TRANSFORMS SETJMP +option SIMPLIFIED_READ enables READ_EXPAND READ_16BIT READ_EXPAND_16 +option SIMPLIFIED_READ enables READ_SCALE_16_TO_8 READ_RGB_TO_GRAY +option SIMPLIFIED_READ enables READ_ALPHA_MODE READ_BACKGROUND READ_STRIP_ALPHA +option SIMPLIFIED_READ enables READ_FILLER READ_SWAP + +option SIMPLIFIED_READ_AFIRST requires SIMPLIFIED_READ disabled +option READ_SWAP_ALPHA enables SIMPLIFIED_READ_AFIRST + +option SIMPLIFIED_READ_BGR requires SIMPLIFIED_READ disabled +option READ_BGR enables SIMPLIFIED_READ_BGR + +# Write: +option SIMPLIFIED_WRITE requires WRITE STDIO SETJMP +option SIMPLIFIED_WRITE enables WRITE_SWAP WRITE_gAMA WRITE_sRGB WRITE_cHRM + +option SIMPLIFIED_WRITE_AFIRST requires SIMPLIFIED_WRITE disabled +option WRITE_SWAP_ALPHA enables SIMPLIFIED_WRITE_AFIRST + +option SIMPLIFIED_WRITE_BGR requires SIMPLIFIED_WRITE disabled +option WRITE_BGR enables SIMPLIFIED_WRITE_BGR + +# Formats: +option FORMAT_AFIRST if SIMPLIFIED_READ_AFIRST SIMPLIFIED_WRITE_AFIRST +option FORMAT_BGR if SIMPLIFIED_READ_BGR SIMPLIFIED_WRITE_BGR diff -ru4NwbB libpng-1.5.6/scripts/pnglibconf.h.prebuilt libpng-1.5.7beta04/scripts/pnglibconf.h.prebuilt --- libpng-1.5.6/scripts/pnglibconf.h.prebuilt 2011-10-13 19:32:27.985999000 -0500 +++ libpng-1.5.7beta04/scripts/pnglibconf.h.prebuilt 2011-11-17 21:02:59.460914648 -0600 @@ -2,9 +2,9 @@ /* libpng STANDARD API DEFINITION */ /* pnglibconf.h - library build configuration */ -/* libpng version 1.5.4 - last changed on June 22, 2011 */ +/* Libpng 1.5.7beta04 - November 18, 2011 */ /* Copyright (c) 1998-2011 Glenn Randers-Pehrson */ /* This code is released under the libpng license. */ @@ -53,8 +53,10 @@ #define PNG_ERROR_TEXT_SUPPORTED #define PNG_FIXED_POINT_SUPPORTED #define PNG_FLOATING_ARITHMETIC_SUPPORTED #define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED #define PNG_gAMA_SUPPORTED #define PNG_HANDLE_AS_UNKNOWN_SUPPORTED #define PNG_hIST_SUPPORTED #define PNG_iCCP_SUPPORTED @@ -125,8 +127,14 @@ #define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED #define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED #define PNG_SETJMP_SUPPORTED #define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED #define PNG_sPLT_SUPPORTED #define PNG_sRGB_SUPPORTED #define PNG_STDIO_SUPPORTED #define PNG_tEXt_SUPPORTED diff -ru4NwbB libpng-1.5.6/scripts/pnglibconf.mak libpng-1.5.7beta04/scripts/pnglibconf.mak --- libpng-1.5.6/scripts/pnglibconf.mak 2011-05-07 10:31:01.000000000 -0500 +++ libpng-1.5.7beta04/scripts/pnglibconf.mak 2011-11-08 19:12:49.536424000 -0600 @@ -34,20 +34,21 @@ $(DELETE) $@ dfn.c dfn1.out dfn2.out dfn3.out $(ECHO) '#include "pnglibconf.dfn"' >dfn.c $(CPP) $(DFNFLAGS) dfn.c >dfn1.out $(ECHO) "If 'cpp -e' crashes try /lib/cpp (e.g. CPP='/lib/cpp')" >&2 - $(SED) -n -e 's|^.*PNG_DEFN_MAGIC-\(.*\)-PNG_DEFN_END.*$$|\1|p'\ + $(SED) -n -e 's|^.*PNG_DEFN_MAGIC *-\(.*\)- *PNG_DEFN_END.*$$|\1|p'\ dfn1.out >dfn2.out - $(SED) -e 's| *@@@ *||g' -e 's| *$$||' dfn2.out >dfn3.out + $(SED) -e 's| *PNG_JOIN *||g' -e 's| *$$||' dfn2.out >dfn3.out $(COPY) dfn3.out $@ $(DELETE) dfn.c dfn1.out dfn2.out dfn3.out -pnglibconf.dfn: $(srcdir)/scripts/pnglibconf.dfa $(srcdir)/scripts/options.awk +pnglibconf.dfn: $(srcdir)/scripts/pnglibconf.dfa $(srcdir)/scripts/options.awk $(srcdir)/pngconf.h $(DELETE) $@ dfn1.out dfn2.out $(ECHO) "Calling $(AWK) from scripts/pnglibconf.mak" >&2 $(ECHO) "If 'awk' crashes try a better awk (e.g. AWK='nawk')" >&2 - $(AWK) -f $(srcdir)/scripts/options.awk out=dfn1.out\ - $(srcdir)/scripts/pnglibconf.dfa $(DFA_XTRA) 1>&2 + $(AWK) -f $(srcdir)/scripts/options.awk out=dfn1.out version=search\ + $(srcdir)/pngconf.h $(srcdir)/scripts/pnglibconf.dfa\ + $(DFA_XTRA) 1>&2 $(AWK) -f $(srcdir)/scripts/options.awk out=dfn2.out dfn1.out 1>&2 $(COPY) dfn2.out $@ $(DELETE) dfn1.out dfn2.out diff -ru4NwbB libpng-1.5.6/scripts/sym.dfn libpng-1.5.7beta04/scripts/sym.dfn --- libpng-1.5.6/scripts/sym.dfn 2011-01-21 19:20:38.000000000 -0600 +++ libpng-1.5.7beta04/scripts/sym.dfn 2011-11-03 16:13:57.962584000 -0500 @@ -9,7 +9,7 @@ * and license in png.h */ #define PNG_EXPORTA(ordinal, type, name, args, attributes)\ - PNG_DEFN_MAGIC-SYMBOL_PREFIX @@@ name-PNG_DEFN_END + PNG_DEFN_MAGIC-SYMBOL_PREFIX PNG_JOIN name-PNG_DEFN_END #include "../png.h" diff -ru4NwbB libpng-1.5.6/scripts/symbols.def libpng-1.5.7beta04/scripts/symbols.def --- libpng-1.5.6/scripts/symbols.def 2011-11-02 22:42:52.770319277 -0500 +++ libpng-1.5.7beta04/scripts/symbols.def 2011-11-17 21:02:59.472572610 -0600 @@ -238,4 +238,11 @@ png_get_cHRM_XYZ @230 png_get_cHRM_XYZ_fixed @231 png_set_cHRM_XYZ @232 png_set_cHRM_XYZ_fixed @233 + png_image_begin_read_from_file @234 + png_image_begin_read_from_stdio @235 + png_image_begin_read_from_memory @236 + png_image_finish_read @237 + png_image_free @238 + png_image_write_to_file @239 + png_image_write_to_stdio @240 diff -ru4NwbB libpng-1.5.6/scripts/vers.dfn libpng-1.5.7beta04/scripts/vers.dfn --- libpng-1.5.6/scripts/vers.dfn 2011-01-21 19:20:50.000000000 -0600 +++ libpng-1.5.7beta04/scripts/vers.dfn 2011-11-03 16:13:57.969672000 -0500 @@ -10,15 +10,15 @@ */ #define HEADER PNG_DEFN_MAGIC-PNGLIB_LIBNAME {global:-PNG_DEFN_END -/* NOTE: @@@ is interpreted by the calling script as a signal to +/* NOTE: PNG_JOIN is interpreted by the calling script as a signal to * join the two things on either side, so we can do symbol * substitution within the name, regular C ## joins the pp-tokens, * not their final values. */ #define PNG_EXPORTA(ordinal, type, name, args, attributes)\ - PNG_DEFN_MAGIC- SYMBOL_PREFIX @@@ name;-PNG_DEFN_END + PNG_DEFN_MAGIC- SYMBOL_PREFIX PNG_JOIN name;-PNG_DEFN_END #define TRAILER PNG_DEFN_MAGIC-local: *; };-PNG_DEFN_END HEADER