Merge 3184947a25b78dee14b0dda09f368ab3f6107c8f into 1fc5345bff82118fd6f3138138805083e66656ca

This commit is contained in:
John Bowler 2015-09-15 03:52:31 +00:00
commit ec99b373dd
58 changed files with 18081 additions and 13820 deletions

View File

@ -84,9 +84,12 @@ libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\
pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.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 pngusr.dfa png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h pngusr.dfa
if PNG_ARM_NEON # Include libpng extensions, if appropriate. This uses a Makefile.am fragment,
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += arm/arm_init.c\ # pre-set things that might be changed by addition:
arm/filter_neon.S arm/filter_neon_intrinsics.c AM_CPPFLAGS =
DFA_EXTENSION =
if LIBPNG_EXTENSIONS
include $(top_srcdir)/contrib/extensions.am
endif endif
nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h
@ -244,17 +247,17 @@ endif
rm -f $@ $*.tf[12] rm -f $@ $*.tf[12]
test -d scripts || mkdir scripts || test -d scripts test -d scripts || mkdir scripts || test -d scripts
$(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)\ $(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)\
$(CPPFLAGS) $(SYMBOL_CFLAGS) $< > $*.tf1 $(AM_CPPFLAGS) $(CPPFLAGS) $(SYMBOL_CFLAGS) $< > $*.tf1
$(AWK) -f "${srcdir}/scripts/dfn.awk" out="$*.tf2" $*.tf1 1>&2 $(AWK) -f "${srcdir}/scripts/dfn.awk" out="$*.tf2" $*.tf1 1>&2
rm -f $*.tf1 rm -f $*.tf1
mv $*.tf2 $@ mv $*.tf2 $@
# The .c file for pnglibconf.h is machine generated # The .c file for pnglibconf.h is machine generated
pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h pngusr.dfa $(DFA_XTRA) pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h pngusr.dfa $(DFA_EXTENSION) $(DFA_XTRA)
rm -f $@ $*.tf[45] rm -f $@ $*.tf[45]
$(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf4 version=search\ $(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf4 version=search\
${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\ ${srcdir}/pngconf.h ${srcdir}/scripts/pnglibconf.dfa\
${srcdir}/pngusr.dfa $(DFA_XTRA) 1>&2 $(DFA_EXTENSION) ${srcdir}/pngusr.dfa $(DFA_XTRA) 1>&2
$(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf5 $*.tf4 1>&2 $(AWK) -f ${srcdir}/scripts/options.awk out=$*.tf5 $*.tf4 1>&2
rm $*.tf4 rm $*.tf4
mv $*.tf5 $@ mv $*.tf5 $@
@ -272,8 +275,8 @@ scripts/symbols.chk: scripts/checksym.awk scripts/symbols.def scripts/symbols.ou
# be empty - no non-standard defines # be empty - no non-standard defines
scripts/pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h scripts/pnglibconf.c: scripts/pnglibconf.dfa scripts/options.awk pngconf.h
rm -f $@ pnglibconf.tf[67] rm -f $@ pnglibconf.tf[67]
test -z "$(CPPFLAGS)" test -z "$(CPPFLAGS)" -a -z "$(AM_CPPFLAGS)"
echo "com @PNGLIB_VERSION@ STANDARD API DEFINITION" |\ echo "com libpng @PNGLIB_VERSION@ STANDARD API DEFINITION" |\
$(AWK) -f ${srcdir}/scripts/options.awk out=pnglibconf.tf6\ $(AWK) -f ${srcdir}/scripts/options.awk out=pnglibconf.tf6\
logunsupported=1 version=search ${srcdir}/pngconf.h -\ logunsupported=1 version=search ${srcdir}/pngconf.h -\
${srcdir}/scripts/pnglibconf.dfa 1>&2 ${srcdir}/scripts/pnglibconf.dfa 1>&2

View File

@ -27,7 +27,8 @@ AC_CONFIG_MACRO_DIR([scripts])
# dist-xz requires automake 1.11 or later # dist-xz requires automake 1.11 or later
# 1.12.2 fixes a security issue in 1.11.2 and 1.12.1 # 1.12.2 fixes a security issue in 1.11.2 and 1.12.1
# 1.13 is required for parallel tests # 1.13 is required for parallel tests
AM_INIT_AUTOMAKE([1.13 foreign dist-xz color-tests silent-rules subdir-objects]) # 1.14.1 is required for %reldir% support
AM_INIT_AUTOMAKE([1.14.1 foreign dist-xz color-tests silent-rules subdir-objects])
# The following line causes --disable-maintainer-mode to be the default to # The following line causes --disable-maintainer-mode to be the default to
# configure, this is necessary because libpng distributions cannot rely on the # configure, this is necessary because libpng distributions cannot rely on the
# time stamps of the autotools generated files being correct # time stamps of the autotools generated files being correct
@ -381,54 +382,11 @@ AC_ARG_ENABLE([unversioned-libpng-config],
AM_CONDITIONAL([DO_INSTALL_LIBPNG_CONFIG], AM_CONDITIONAL([DO_INSTALL_LIBPNG_CONFIG],
[test "$enable_unversioned_libpng_config" != "no"]) [test "$enable_unversioned_libpng_config" != "no"])
# HOST SPECIFIC OPTIONS # EXTENSIONS
# ===================== # Configure (and all other) support for extensions is included when autoconf is
# # run by virtue of the existence (or not) of the following file:
# ARM sinclude([contrib/extensions.ac])
# === AM_CONDITIONAL([LIBPNG_EXTENSIONS],[test -n "$libpng_automake_extensions"])
#
# ARM NEON (SIMD) support.
AC_ARG_ENABLE([arm-neon],
AS_HELP_STRING([[[--enable-arm-neon]]],
[Enable ARM NEON optimizations: =no/off, check, api, yes/on:]
[no/off: disable the optimizations; check: use internal checking code]
[(deprecated and poorly supported); api: disable by default, enable by]
[a call to png_set_option; yes/on: turn on unconditionally.]
[If not specified: determined by the compiler.]),
[case "$enableval" in
no|off)
# disable the default enabling on __ARM_NEON__ systems:
AC_DEFINE([PNG_ARM_NEON_OPT], [0],
[Disable ARM Neon optimizations])
# Prevent inclusion of the assembler files below:
enable_arm_neon=no;;
check)
AC_DEFINE([PNG_ARM_NEON_CHECK_SUPPORTED], [],
[Check for ARM Neon support at run-time]);;
api)
AC_DEFINE([PNG_ARM_NEON_API_SUPPORTED], [],
[Turn on ARM Neon optimizations at run-time]);;
yes|on)
AC_DEFINE([PNG_ARM_NEON_OPT], [2],
[Enable ARM Neon optimizations])
AC_MSG_WARN([--enable-arm-neon: please specify 'check' or 'api', if]
[you want the optimizations unconditionally pass -mfpu=neon]
[to the compiler.]);;
*)
AC_MSG_ERROR([--enable-arm-neon=${enable_arm_neon}: invalid value])
esac])
# Add ARM specific files to all builds where the host_cpu is arm ('arm*') or
# where ARM optimizations were explicitly requested (this allows a fallback if a
# future host CPU does not match 'arm*')
AM_CONDITIONAL([PNG_ARM_NEON],
[test "$enable_arm_neon" != 'no' &&
case "$host_cpu" in
arm*|aarch64*) :;;
*) test "$enable_arm_neon" != '';;
esac])
AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]]) AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]])

View File

@ -87,7 +87,7 @@ print_pixel(png_structp png_ptr, png_infop info_ptr, png_const_bytep row,
*/ */
case PNG_COLOR_TYPE_PALETTE: case PNG_COLOR_TYPE_PALETTE:
{ {
PNG_CONST unsigned int index = component(row, x, 0, bit_depth, 1); PNG_CONST int index = component(row, x, 0, bit_depth, 1);
png_colorp palette = NULL; png_colorp palette = NULL;
int num_palette = 0; int num_palette = 0;

16
contrib/extensions.ac Normal file
View File

@ -0,0 +1,16 @@
# CONTRIBUTED EXTENSIONS
#
# The following extensions are part of a standard libpng distribution. They are
# not supported parts of libpng and they are not necessarily released under the
# same license as libpng. Please consult the relevant directory for copyright
# and support information before uncommenting any of the lines below.
#
# After you change this file you MUST re-run "autoreconf" to regenerate the
# configure script, otherwise the change may have no effect.
#
# Include the ARM NEON extension:
#sinclude([contrib/neon/neon.ac])
#
# If any of the extensions require automake support (this is likely) automake
# must include the file contrib/extensions.am
#libpng_automake_extensions="yes"

7
contrib/extensions.am Normal file
View File

@ -0,0 +1,7 @@
# CONTRIBUTED EXTENSIONS
#
# Please read the file "contrib/extensions.ac" before making changes to this
# file.
#
# Include the ARM NEON extension:
#include %reldir%/neon/neon.am

View File

@ -107,7 +107,7 @@ typedef struct chunk_insert
png_charp parameters[1]; png_charp parameters[1];
} chunk_insert; } chunk_insert;
static int static unsigned int
channels_of_type(int color_type) channels_of_type(int color_type)
{ {
if (color_type & PNG_COLOR_MASK_PALETTE) if (color_type & PNG_COLOR_MASK_PALETTE)
@ -128,7 +128,7 @@ channels_of_type(int color_type)
} }
} }
static int static unsigned int
pixel_depth_of_type(int color_type, int bit_depth) pixel_depth_of_type(int color_type, int bit_depth)
{ {
return channels_of_type(color_type) * bit_depth; return channels_of_type(color_type) * bit_depth;
@ -682,7 +682,11 @@ write_png(const char **name, FILE *fp, int color_type, int bit_depth,
png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, filters); png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, filters);
{ {
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
int passes = png_set_interlace_handling(png_ptr); int passes = png_set_interlace_handling(png_ptr);
# else /* !WRITE_INTERLACING */
int passes = 1;
# endif /* !WRITE_INTERLACING */
int pass; int pass;
png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr); png_size_t rowbytes = png_get_rowbytes(png_ptr, info_ptr);

View File

@ -236,10 +236,12 @@ static struct transform_info
*/ */
#endif #endif
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
T(SCALE_16, NONE, X, X, 16, R) T(SCALE_16, NONE, X, X, 16, R),
/* scales 16-bit components to 8-bits. */ /* scales 16-bit components to 8-bits. */
#endif #endif
{ NULL /*name*/, 0, 0, 0, 0, 0, 0, 0/*!tested*/ }
#undef T #undef T
}; };
@ -294,7 +296,7 @@ transform_name(int t)
t &= -t; /* first set bit */ t &= -t; /* first set bit */
for (i=0; i<TTABLE_SIZE; ++i) for (i=0; i<TTABLE_SIZE; ++i) if (transform_info[i].name != NULL)
{ {
if ((transform_info[i].transform & t) != 0) if ((transform_info[i].transform & t) != 0)
return transform_info[i].name; return transform_info[i].name;
@ -315,7 +317,7 @@ validate_T(void)
{ {
unsigned int i; unsigned int i;
for (i=0; i<TTABLE_SIZE; ++i) for (i=0; i<TTABLE_SIZE; ++i) if (transform_info[i].name != NULL)
{ {
if (transform_info[i].when & TRANSFORM_R) if (transform_info[i].when & TRANSFORM_R)
read_transforms |= transform_info[i].transform; read_transforms |= transform_info[i].transform;
@ -505,6 +507,7 @@ typedef enum
#define SKIP_BUGS 0x100 /* Skip over known bugs */ #define SKIP_BUGS 0x100 /* Skip over known bugs */
#define LOG_SKIPPED 0x200 /* Log skipped bugs */ #define LOG_SKIPPED 0x200 /* Log skipped bugs */
#define FIND_BAD_COMBOS 0x400 /* Attempt to deduce bad combos */ #define FIND_BAD_COMBOS 0x400 /* Attempt to deduce bad combos */
#define LIST_COMBOS 0x800 /* List combos by name */
/* Result masks apply to the result bits in the 'results' field below; these /* Result masks apply to the result bits in the 'results' field below; these
* bits are simple 1U<<error_level. A pass requires either nothing worse than * bits are simple 1U<<error_level. A pass requires either nothing worse than
@ -690,7 +693,35 @@ display_log(struct display *dp, error_level level, const char *fmt, ...)
int tr = dp->transforms; int tr = dp->transforms;
if (is_combo(tr)) if (is_combo(tr))
{
if (dp->options & LIST_COMBOS)
{
int trx = tr;
fprintf(stderr, "(");
if (trx)
{
int start = 0;
while (trx)
{
int trz = trx & -trx;
if (start) fprintf(stderr, "+");
fprintf(stderr, "%s", transform_name(trz));
start = 1;
trx &= ~trz;
}
}
else
fprintf(stderr, "-");
fprintf(stderr, ")");
}
else
fprintf(stderr, "(0x%x)", tr); fprintf(stderr, "(0x%x)", tr);
}
else else
fprintf(stderr, "(%s)", transform_name(tr)); fprintf(stderr, "(%s)", transform_name(tr));
@ -910,7 +941,7 @@ update_display(struct display *dp)
int bd = dp->bit_depth; int bd = dp->bit_depth;
unsigned int i; unsigned int i;
for (i=0; i<TTABLE_SIZE; ++i) for (i=0; i<TTABLE_SIZE; ++i) if (transform_info[i].name != NULL)
{ {
int transform = transform_info[i].transform; int transform = transform_info[i].transform;
@ -935,9 +966,6 @@ update_display(struct display *dp)
dp->active_transforms = active; dp->active_transforms = active;
dp->ignored_transforms = inactive; /* excluding write-only transforms */ dp->ignored_transforms = inactive; /* excluding write-only transforms */
if (active == 0)
display_log(dp, INTERNAL_ERROR, "bad transform table");
} }
} }
@ -1588,6 +1616,12 @@ main(const int argc, const char * const * const argv)
else if (strcmp(name, "--nofind-bad-combos") == 0) else if (strcmp(name, "--nofind-bad-combos") == 0)
d.options &= ~FIND_BAD_COMBOS; d.options &= ~FIND_BAD_COMBOS;
else if (strcmp(name, "--list-combos") == 0)
d.options |= LIST_COMBOS;
else if (strcmp(name, "--nolist-combos") == 0)
d.options &= ~LIST_COMBOS;
else if (name[0] == '-' && name[1] == '-') else if (name[0] == '-' && name[1] == '-')
{ {
fprintf(stderr, "pngimage: %s: unknown option\n", name); fprintf(stderr, "pngimage: %s: unknown option\n", name);

View File

@ -363,7 +363,7 @@ ancillary(const char *name)
return PNG_CHUNK_ANCILLARY(PNG_U32(name[0], name[1], name[2], name[3])); return PNG_CHUNK_ANCILLARY(PNG_U32(name[0], name[1], name[2], name[3]));
} }
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED #ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
static int static int
ancillaryb(const png_byte *name) ancillaryb(const png_byte *name)
{ {
@ -554,7 +554,7 @@ read_callback(png_structp pp, png_unknown_chunkp pc)
/* However if there is no support to store unknown chunks don't ask libpng to /* However if there is no support to store unknown chunks don't ask libpng to
* do it; there will be an png_error. * do it; there will be an png_error.
*/ */
# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED # ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
return discard; return discard;
# else # else
return 1; /*handled; discard*/ return 1; /*handled; discard*/
@ -562,7 +562,7 @@ read_callback(png_structp pp, png_unknown_chunkp pc)
} }
#endif /* READ_USER_CHUNKS_SUPPORTED */ #endif /* READ_USER_CHUNKS_SUPPORTED */
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED #ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
static png_uint_32 static png_uint_32
get_unknown(display *d, png_infop info_ptr, int after_IDAT) get_unknown(display *d, png_infop info_ptr, int after_IDAT)
{ {
@ -722,11 +722,17 @@ check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/,
* in this case, so we just check the arguments! This could * in this case, so we just check the arguments! This could
* be improved in the future by using the read callback. * be improved in the future by using the read callback.
*/ */
# if PNG_LIBPNG_VER >= 10700 &&\
!defined(PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED)
if (option < PNG_HANDLE_CHUNK_IF_SAFE)
# endif /* 1.7+ SAVE_UNKNOWN_CHUNKS */
{
png_byte name[5]; png_byte name[5];
memcpy(name, chunk_info[chunk].name, 5); memcpy(name, chunk_info[chunk].name, 5);
png_set_keep_unknown_chunks(d->png_ptr, option, name, 1); png_set_keep_unknown_chunks(d->png_ptr, option, name, 1);
chunk_info[chunk].keep = option; chunk_info[chunk].keep = option;
}
continue; continue;
} }
@ -735,7 +741,12 @@ check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/,
case 7: /* default */ case 7: /* default */
if (memcmp(argv[i], "default", 7) == 0) if (memcmp(argv[i], "default", 7) == 0)
{ {
# if PNG_LIBPNG_VER >= 10700 &&\
!defined(PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED)
if (option < PNG_HANDLE_CHUNK_IF_SAFE)
# endif /* 1.7+ SAVE_UNKNOWN_CHUNKS */
png_set_keep_unknown_chunks(d->png_ptr, option, NULL, 0); png_set_keep_unknown_chunks(d->png_ptr, option, NULL, 0);
d->keep = option; d->keep = option;
continue; continue;
} }
@ -745,7 +756,12 @@ check(FILE *fp, int argc, const char **argv, png_uint_32p flags/*out*/,
case 3: /* all */ case 3: /* all */
if (memcmp(argv[i], "all", 3) == 0) if (memcmp(argv[i], "all", 3) == 0)
{ {
# if PNG_LIBPNG_VER >= 10700 &&\
!defined(PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED)
if (option < PNG_HANDLE_CHUNK_IF_SAFE)
# endif /* 1.7+ SAVE_UNKNOWN_CHUNKS */
png_set_keep_unknown_chunks(d->png_ptr, option, NULL, -1); png_set_keep_unknown_chunks(d->png_ptr, option, NULL, -1);
d->keep = option; d->keep = option;
for (chunk = 0; chunk < NINFO; ++chunk) for (chunk = 0; chunk < NINFO; ++chunk)

File diff suppressed because it is too large Load Diff

View File

@ -70,7 +70,12 @@ read_png(FILE *fp)
{ {
png_uint_32 height = png_get_image_height(png_ptr, info_ptr); png_uint_32 height = png_get_image_height(png_ptr, info_ptr);
# ifdef PNG_READ_DEINTERLACE_SUPPORTED
int passes = png_set_interlace_handling(png_ptr); int passes = png_set_interlace_handling(png_ptr);
# else
int passes = png_get_interlace_type(png_ptr, info_ptr) ==
PNG_INTERLACE_ADAM7 ? PNG_INTERLACE_ADAM7_PASSES : 1;
# endif
int pass; int pass;
png_start_read_image(png_ptr); png_start_read_image(png_ptr);
@ -79,6 +84,11 @@ read_png(FILE *fp)
{ {
png_uint_32 y = height; png_uint_32 y = height;
# ifndef PNG_READ_DEINTERLACE_SUPPORTED
if (passes == PNG_INTERLACE_ADAM7_PASSES)
y = PNG_PASS_ROWS(y, pass);
# endif
/* NOTE: this trashes the row each time; interlace handling won't /* NOTE: this trashes the row each time; interlace handling won't
* work, but this avoids memory thrashing for speed testing. * work, but this avoids memory thrashing for speed testing.
*/ */

View File

@ -14,7 +14,7 @@
*/ */
#define _POSIX_SOURCE 1 #define _POSIX_SOURCE 1
#include "../pngpriv.h" #include "../../pngpriv.h"
#define PNG_SRC_FILE PNG_SRC_FILE_arm_arm_init #define PNG_SRC_FILE PNG_SRC_FILE_arm_arm_init
#ifdef PNG_READ_SUPPORTED #ifdef PNG_READ_SUPPORTED

View File

@ -0,0 +1,10 @@
# To just this extension either copy the 'sinclude' line and the setting of
# libpng_automake_extensions into contrib/extensions.am or link/copy the whole
# file there. Do the same with the associated file extensions.am
#
# Include the ARM NEON extension:
sinclude([contrib/neon/neon.ac])
#
# If any of the extensions require automake support (this is likely) automake
# must include the file contrib/extensions.am
libpng_automake_extensions="yes"

View File

@ -0,0 +1,5 @@
# To just this extension either copy the 'include' line into
# contrib/extensions.am or link/copy the whole file there. Do the same with the
# associated file extensions.ac
# Include the ARM NEON extension:
include %reldir%/neon/neon.am

View File

@ -14,7 +14,7 @@
* definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION. * definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
*/ */
#define PNG_VERSION_INFO_ONLY #define PNG_VERSION_INFO_ONLY
#include "../pngpriv.h" #include "../../pngpriv.h"
#if defined(__linux__) && defined(__ELF__) #if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */ .section .note.GNU-stack,"",%progbits /* mark stack as non-executable */

View File

@ -12,7 +12,7 @@
* and license in png.h * and license in png.h
*/ */
#include "../pngpriv.h" #include "../../pngpriv.h"
#define PNG_SRC_FILE PNG_SRC_FILE_arm_filter_neon_intrinsics #define PNG_SRC_FILE PNG_SRC_FILE_arm_filter_neon_intrinsics
#ifdef PNG_READ_SUPPORTED #ifdef PNG_READ_SUPPORTED
@ -41,11 +41,11 @@
#if PNG_ARM_NEON_OPT > 0 #if PNG_ARM_NEON_OPT > 0
void void
png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_up_neon(png_alloc_size_t rowbytes, unsigned int bpp,
png_const_bytep prev_row) png_bytep row, png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + rowbytes;
png_const_bytep pp = prev_row; png_const_bytep pp = prev_row;
for (; rp < rp_stop; rp += 16, pp += 16) for (; rp < rp_stop; rp += 16, pp += 16)
@ -57,14 +57,15 @@ png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
qrp = vaddq_u8(qrp, qpp); qrp = vaddq_u8(qrp, qpp);
vst1q_u8(rp, qrp); vst1q_u8(rp, qrp);
} }
PNG_UNUSED(bpp)
} }
void void
png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_sub3_neon(png_alloc_size_t rowbytes, unsigned int bpp, png_bytep row, png_const_bytep prev_row)
png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + rowbytes;
uint8x16_t vtmp = vld1q_u8(rp); uint8x16_t vtmp = vld1q_u8(rp);
uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp); uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp);
@ -101,15 +102,16 @@ png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
rp += 3; rp += 3;
} }
PNG_UNUSED(bpp)
PNG_UNUSED(prev_row) PNG_UNUSED(prev_row)
} }
void void
png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_sub4_neon(png_alloc_size_t rowbytes, unsigned int bpp,
png_const_bytep prev_row) png_bytep row, png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + rowbytes;
uint8x8x4_t vdest; uint8x8x4_t vdest;
vdest.val[3] = vdup_n_u8(0); vdest.val[3] = vdup_n_u8(0);
@ -128,16 +130,17 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
} }
PNG_UNUSED(bpp)
PNG_UNUSED(prev_row) PNG_UNUSED(prev_row)
} }
void void
png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_avg3_neon(png_alloc_size_t rowbytes, unsigned int bpp,
png_const_bytep prev_row) png_bytep row, png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_const_bytep pp = prev_row; png_const_bytep pp = prev_row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + rowbytes;
uint8x16_t vtmp; uint8x16_t vtmp;
uint8x8x2_t *vrpt; uint8x8x2_t *vrpt;
@ -195,14 +198,16 @@ png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0); vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
rp += 3; rp += 3;
} }
PNG_UNUSED(bpp)
} }
void void
png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_avg4_neon(png_alloc_size_t rowbytes, unsigned int bpp,
png_const_bytep prev_row) png_bytep row, png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + rowbytes;
png_const_bytep pp = prev_row; png_const_bytep pp = prev_row;
uint8x8x4_t vdest; uint8x8x4_t vdest;
@ -233,6 +238,8 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
} }
PNG_UNUSED(bpp)
} }
static uint8x8_t static uint8x8_t
@ -263,12 +270,12 @@ paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
} }
void void
png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_paeth3_neon(png_alloc_size_t rowbytes, unsigned int bpp,
png_const_bytep prev_row) png_bytep row, png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_const_bytep pp = prev_row; png_const_bytep pp = prev_row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + rowbytes;
uint8x16_t vtmp; uint8x16_t vtmp;
uint8x8x2_t *vrpt; uint8x8x2_t *vrpt;
@ -326,14 +333,16 @@ png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0); vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
rp += 3; rp += 3;
} }
PNG_UNUSED(bpp)
} }
void void
png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, png_read_filter_row_paeth4_neon(png_alloc_size_t rowbytes, unsigned int bpp,
png_const_bytep prev_row) png_bytep row, png_const_bytep prev_row)
{ {
png_bytep rp = row; png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes; png_bytep rp_stop = row + rowbytes;
png_const_bytep pp = prev_row; png_const_bytep pp = prev_row;
uint8x8_t vlast = vdup_n_u8(0); uint8x8_t vlast = vdup_n_u8(0);
@ -367,8 +376,9 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0);
} }
}
PNG_UNUSED(bpp)
}
#endif /* PNG_ARM_NEON_OPT > 0 */ #endif /* PNG_ARM_NEON_OPT > 0 */
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */ #endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */
#endif /* READ */ #endif /* READ */

47
contrib/neon/neon.ac Normal file
View File

@ -0,0 +1,47 @@
# LIBPNG EXTENSION: NEON
#
# ARM NEON (SIMD) support.
#
# This file contains configure.ac additions to libpng configure to enable
# building of the ARM NEON filter optimizations.
#
AC_ARG_ENABLE([arm-neon],
AS_HELP_STRING([[[--enable-arm-neon]]],
[Enable ARM NEON optimizations: =no/off, check, api, yes/on:]
[no/off: disable the optimizations; check: use internal checking code]
[(deprecated and poorly supported); api: disable by default, enable by]
[a call to png_set_option; yes/on: turn on unconditionally.]
[If not specified: determined by the compiler.]),
[case "$enableval" in
no|off)
# disable the default enabling on __ARM_NEON__ systems:
AC_DEFINE([PNG_ARM_NEON_OPT], [0],
[Disable ARM Neon optimizations])
# Prevent inclusion of the assembler files below:
enable_arm_neon=no;;
check)
AC_DEFINE([PNG_ARM_NEON_CHECK_SUPPORTED], [],
[Check for ARM Neon support at run-time]);;
api)
AC_DEFINE([PNG_ARM_NEON_API_SUPPORTED], [],
[Turn on ARM Neon optimizations at run-time]);;
yes|on)
AC_DEFINE([PNG_ARM_NEON_OPT], [2],
[Enable ARM Neon optimizations])
AC_MSG_WARN([--enable-arm-neon: please specify 'check' or 'api', if]
[you want the optimizations unconditionally pass -mfpu=neon]
[to the compiler.]);;
*)
AC_MSG_ERROR([--enable-arm-neon=${enable_arm_neon}: invalid value])
esac])
# Add ARM specific files to all builds where the host_cpu is arm ('arm*') or
# where ARM optimizations were explicitly requested (this allows a fallback if a
# future host CPU does not match 'arm*')
AM_CONDITIONAL([PNG_ARM_NEON],
[test "$enable_arm_neon" != 'no' &&
case "$host_cpu" in
arm*|aarch64*) :;;
*) test "$enable_arm_neon" != '';;
esac])

27
contrib/neon/neon.am Normal file
View File

@ -0,0 +1,27 @@
# contrib/neon/neon.am
#
# This is an automake fragment included by the top-level Makefile.am if
# contrib/neon/neon.ac is included in configure
#
# It builds the source files in this directory into ARM hardware support for
# libpng.
#
if PNG_ARM_NEON
libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += %D%/arm_init.c\
%D%/filter_neon.S %D%/filter_neon_intrinsics.c
DFA_EXTENSION += ${srcdir}/%D%/neon.dfa
# This causes pngpriv.h to include the named header. It is VERY important to
# understand that this MUST be defined and the header MUST define internal
# 'extern' functions with PNG_INTERNAL_FUNCTION. This allows vendors to use
# static library builds of libpng without clashing with the installed system
# libpng; see the libpng-prefix option in configure.ac The value of this
# #define is included in pnglibconf.h
#
# NOTE: you must include the double quotes in the value and you must therefore
# support the whole thing with single quotes. If you need to use <> for a
# header be aware that if you miss out the single quotes you will create a
# random file.
AM_CPPFLAGS += -DPNG_EXTENSION_HEADER='"%D%/neon.h"'
endif

41
contrib/neon/neon.dfa Normal file
View File

@ -0,0 +1,41 @@
# contrib/arm/neon.dfa
#
# This is a dfa fragment that is added to DFA_HARDWARE in Makefile.am and
# consequently is inserted after scripts/pnglibconf.dfa to define extra,
# hardware, options.
#
# The following are required in any fragment to record the copyright holder of
# the *changes* and the appropriate email for bug reports. Note that the
# copyright here is just for the specific configuration; additional files may
# have additional and/or different copyrights.
#
# Later settings (e.g. in user.dfa) will override these settings.
#
setting USER_PRIVATEBUILD default "John Bowler"
setting USER_BUG_REPORTS default "jbowler@acm.org"
#
# These options are specific to the ARM NEON hardware optimizations. At present
# these optimizations depend on GCC specific pre-processing of an assembler (.S)
# file so they probably won't work with other compilers.
#
# ARM_NEON_OPT: unset: check at compile time (__ARM_NEON__ must be defined by
# the compiler, typically as a result of specifying
# CC="gcc -mfpu=neon".)
# 0: disable (even if the CPU has a NEON FPU.)
# 1: check at run time (via ARM_NEON_{API,CHECK})
# 2: switch on unconditionally (inadvisable - instead pass
# -mfpu=neon to GCC in CC)
# When building libpng avoid using any setting other than '0'; '1' is
# set automatically when either 'API' or 'CHECK' are configured in,
# '2' should not be necessary as -mfpu=neon will achieve the same
# effect as well as applying NEON optimizations to the rest of the
# libpng code.
# NOTE: any setting other than '0' requires ALIGNED_MEMORY
# ARM_NEON_API: (PNG_ARM_NEON == 1) allow the optimization to be switched on
# with png_set_option
# ARM_NEON_CHECK: (PNG_ARM_NEON == 1) compile a run-time check to see if Neon
# extensions are supported. This is poorly supported and
# deprecated - use the png_set_option API.
setting ARM_NEON_OPT
option ARM_NEON_API disabled enables SET_OPTION sets ARM_NEON_OPT 1
option ARM_NEON_CHECK disabled sets ARM_NEON_OPT 1

124
contrib/neon/neon.h Normal file
View File

@ -0,0 +1,124 @@
/* Compile time options.
* =====================
* In a multi-arch build the compiler may compile the code several times for the
* same object module, producing different binaries for different architectures.
* When this happens configure-time setting of the target host options cannot be
* done. An example is iOS vs Android compilation of ARM NEON support.
*
* NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because
* this is not possible with certain compilers (Oracle SUN OS CC), as a result
* it is necessary to ensure that all extern functions that *might* be used
* regardless of $(CFLAGS) get declared in this file. The test on __ARM_NEON
* below is one example of this behavior because it is controlled by the
* presence or not of -mfpu=neon on the GCC command line, it is possible to do
* this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely
* do this.
*/
#ifndef PNG_ARM_NEON_OPT
/* ARM NEON optimizations are being controlled by the compiler settings,
* typically the target FPU. If the FPU supports NEON instructions then the
* compiler will define __ARM_NEON and we can rely unconditionally on NEON
* instructions not crashing, otherwise we must disable use of NEON
* instructions.
*
* NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they
* can only be turned on automatically if that is supported too. If
* PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail
* to compile with an appropriate #error if ALIGNED_MEMORY has been turned
* off.
*
* Note that older versions of GCC defined __ARM_NEON__; this is no longer
* supported. Also 32-bit ARM versions of GCC required the NEON FPU mode to
* be turned on explicitly on the command line. If this is not done (on
* 32-bit ARM) NEON code will not be included.
*
* To disable ARM_NEON optimizations entirely, and skip compiling the
* associated assembler code, pass --enable-arm-neon=no to configure
* or put -DPNG_ARM_NEON_OPT=0 in CPPFLAGS.
*/
# if defined(__ARM_NEON) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
# define PNG_ARM_NEON_OPT 2
# else
# define PNG_ARM_NEON_OPT 0
# endif
#endif
#if PNG_ARM_NEON_OPT > 0
/* NEON optimizations are to be at least considered by libpng, so enable the
* callbacks to do this.
*/
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon
/* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used
* if possible - if __ARM_NEON is set and the compiler version is not known
* to be broken. This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can
* be:
*
* 1 The intrinsics code (the default with __ARM_NEON)
* 2 The hand coded assembler (the default without __ARM_NEON)
*
* It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however
* this is *NOT* supported and may cease to work even after a minor revision
* to libpng. It *is* valid to do this for testing purposes, e.g. speed
* testing or a new compiler, but the results should be communicated to the
* libpng implementation list for incorporation in the next minor release.
*/
# ifndef PNG_ARM_NEON_IMPLEMENTATION
# ifdef __ARM_NEON
# if defined(__clang__)
/* At present it is unknown by the libpng developers which versions
* of clang support the intrinsics, however some or perhaps all
* versions do not work with the assembler so this may be
* irrelevant, so just use the default (do nothing here.)
*/
# elif defined(__GNUC__)
/* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to
* work, so if this *is* GCC, or G++, look for a version >4.5
*/
# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
# define PNG_ARM_NEON_IMPLEMENTATION 2
# endif /* no GNUC support */
# endif /* __GNUC__ */
# else /* !defined __ARM_NEON */
/* The 'intrinsics' code simply won't compile without compiler support
* and that support switches on __ARM_NEON, so use the assembler:
*/
# define PNG_ARM_NEON_IMPLEMENTATION 2
# endif /* __ARM_NEON */
# endif /* !defined PNG_ARM_NEON_IMPLEMENTATION */
# ifndef PNG_ARM_NEON_IMPLEMENTATION
/* Use the intrinsics code by default. */
# define PNG_ARM_NEON_IMPLEMENTATION 1
# endif
#endif /* PNG_ARM_NEON_OPT > 0 */
#ifdef PNG_SET_OPTION_SUPPORTED
#ifdef PNG_ARM_NEON_API_SUPPORTED
# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */
#endif
#endif /* SET_OPTION */
#if PNG_ARM_NEON_OPT > 0
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,
(png_alloc_size_t row_bytes, unsigned int bpp, png_bytep row,
png_const_bytep prev_row),PNG_EMPTY);
#endif

View File

@ -0,0 +1,208 @@
/* dynamic-range.c
*
* Last changed in libpng 1.7.0
*
* COPYRIGHT: Written by John Cunningham Bowler, 2015
* To the extent possible under law, the author has waived all copyright and
* related or neighboring rights to this work. This work is published from:
* United States.
*
* Find the dynamic range of a given gamma encoding given a (linear) precision
* and a maximum number of encoded values.
*/
#include <stdlib.h>
#include <stdio.h>
#include <float.h>
#include <math.h>
#include <assert.h>
double range(unsigned int steps, double factor, double gamma)
{
return pow((steps * (pow(factor, 1/gamma) - 1)), gamma);
}
double max_range_gamma(unsigned int steps, double factor, double *max_range,
double glo, double rlo, double gmid, double rmid, double ghi, double rhi)
{
/* Given three values which contain a peak value (so rmid > rlo and rmid >
* rhi) find the peak by repeated division of the range. The algorithm is to
* find the range for two gamma values mid-way between the two pairs
* (glo,gmid), (ghi,gmid) then find the max; this gives us a new glo/ghi
* which must be half the distance apart of the previous pair.
*/
double gammas[5];
double ranges[5];
gammas[0] = glo; ranges[0] = rlo;
gammas[2] = gmid; ranges[2] = rmid;
gammas[4] = ghi; ranges[4] = rhi;
for (;;)
{
int i, m;
ranges[1] = range(steps, factor, gammas[1] = (gammas[0]+gammas[2])/2);
ranges[3] = range(steps, factor, gammas[3] = (gammas[2]+gammas[4])/2);
for (m=1, i=2; i<4; ++i)
if (ranges[i] >= ranges[m])
m = i;
assert(gammas[0] < gammas[m] && gammas[m] < gammas[4]);
assert(ranges[0] < ranges[m] && ranges[m] > ranges[4]);
gammas[0] = gammas[m-1]; ranges[0] = ranges[m-1];
gammas[4] = gammas[m+1]; ranges[4] = ranges[m+1];
gammas[2] = gammas[m]; ranges[2] = ranges[m];
if (((gammas[4] - gammas[0])/gammas[2]-1) < 3*DBL_EPSILON ||
((ranges[2] - ranges[0])/ranges[2]-1) < 6*DBL_EPSILON)
{
*max_range = ranges[2];
return gammas[2];
}
}
}
double best_gamma(unsigned int values, double precision, double *best_range)
{
/* The 'guess' gamma value is determined by the following formula, which is
* itself derived from linear regression using values returned by this
* program:
*/
double gtry = values * precision / 2.736;
double rtry;
/* 'values' needs to be the number of steps after the first, we have to
* reserve the first value, 0, for 0, so subtract 2 from values. precision
* must be adjusted to the step factor.
*/
values -= 2U;
precision += 1;
rtry = range(values, precision, gtry);
/* Now find two values either side of gtry with a lower range. */
{
double glo, ghi, rlo, rhi, gbest, rbest;
glo = gtry;
do
{
glo *= 0.9;
rlo = range(values, precision, glo);
}
while (rlo >= rtry);
ghi = gtry;
do
{
ghi *= 1.1;
rhi = range(values, precision, ghi);
}
while (rhi >= rtry);
gbest = max_range_gamma(values, precision, &rbest,
glo, rlo, gtry, rtry, ghi, rhi);
*best_range = rbest / precision;
return gbest;
}
}
double linear_regression(double precision, double *bp)
{
unsigned int values, count = 0;
double g_sum = 0, g2_sum = 0, v_sum = 0, v2_sum = 0, gv_sum = 0;
/* Perform simple linear regression to get:
*
* gamma = a + b.values
*/
for (values = 128; values < 65536; ++values, ++count)
{
double range;
double gamma = best_gamma(values, precision, &range);
g_sum += gamma;
g2_sum += gamma * gamma;
v_sum += values;
v2_sum += values * (double)values;
gv_sum += gamma * values;
/* printf("%u %g %g\n", values, gamma, range); */
}
g_sum /= count;
g2_sum /= count;
v_sum /= count;
v2_sum /= count;
gv_sum /= count;
{
double b = (gv_sum - g_sum * v_sum) / (v2_sum - v_sum * v_sum);
*bp = b;
return g_sum - b * v_sum;
}
}
int
main(int argc, const char **argv)
{
double precision = argc == 2 ? atof(argv[1]) : 0;
/* Perform a second linear regression here on b:
*
* b = bA + bB * precision
*/
if (precision == 0)
{
double b_sum = 0, b2_sum = 0, p_sum = 0, p2_sum = 0, bp_sum = 0,
a_sum = 0, count = 0;
for (precision = .001; precision <= 0.01; precision += .001, count += 1)
{
double b;
double a = linear_regression(precision, &b);
b_sum += b;
b2_sum += b * b;
p_sum += precision;
p2_sum += precision * precision;
bp_sum += b * precision;
a_sum += a;
}
b_sum /= count;
b2_sum /= count;
p_sum /= count;
p2_sum /= count;
bp_sum /= count;
a_sum /= count;
{
double bB = (bp_sum - b_sum * p_sum) / (p2_sum - p_sum * p_sum);
double bA = b_sum - bB * p_sum;
printf("a = %g, b = %g + precision/%g\n", a_sum, bA, 1/bB);
}
}
else
{
unsigned int bits;
double b;
double a = linear_regression(precision, &b);
printf("precision %g: gamma = %g + values*%g\n", precision, a, b);
/* For information, given a precision: */
for (bits=7U; bits <= 16U; ++bits)
{
unsigned int values = 1U<<bits;
double gamma = values*precision/2.736;
double r = range(values-2U, 1+precision, gamma);
printf("bits: %u, gamma: %g, range: 1:%g\n", bits, gamma, r);
}
}
return 0;
}

View File

@ -52,7 +52,8 @@
#ifdef PNG_SETJMP_SUPPORTED #ifdef PNG_SETJMP_SUPPORTED
#include <setjmp.h> #include <setjmp.h>
#if defined(PNG_READ_SUPPORTED) && defined(PNG_EASY_ACCESS_SUPPORTED) #if defined(PNG_READ_SUPPORTED) && defined(PNG_EASY_ACCESS_SUPPORTED) &&\
defined(PNG_READ_DEINTERLACE_SUPPORTED)
/* zlib.h defines the structure z_stream, an instance of which is included /* zlib.h defines the structure z_stream, an instance of which is included
* in this structure and is required for decompressing the LZ compressed * in this structure and is required for decompressing the LZ compressed
* data in PNG files. * data in PNG files.
@ -4030,7 +4031,7 @@ main(void)
int int
main(void) main(void)
{ {
fprintf(stderr, "pngfix does not work without read support\n"); fprintf(stderr, "pngfix does not work without read deinterlace support\n");
return 77; return 77;
} }
#endif /* PNG_READ_SUPPORTED && PNG_EASY_ACCESS_SUPPORTED */ #endif /* PNG_READ_SUPPORTED && PNG_EASY_ACCESS_SUPPORTED */
@ -4042,4 +4043,3 @@ main(void)
return 77; return 77;
} }
#endif /* PNG_SETJMP_SUPPORTED */ #endif /* PNG_SETJMP_SUPPORTED */

View File

@ -1,12 +1,11 @@
/*=== /*===
cexcept.h 2.0.1 (2008-Jul-19-Sat, modified 2015-Jun-03-Mon) cexcept.h 2.0.1 (2008-Jul-19-Sat)
http://www.nicemice.net/cexcept/ http://www.nicemice.net/cexcept/
Adam M. Costello Adam M. Costello
http://www.nicemice.net/amc/ http://www.nicemice.net/amc/
An interface for exception-handling in ANSI C (C89 and subsequent ISO An interface for exception-handling in ANSI C (C89 and subsequent ISO
standards), developed jointly with Cosmin Truta. Revised by John Bowler, standards), developed jointly with Cosmin Truta.
June 2015, to declare exception_env and exception_prev "volatile".
Copyright (c) 2000-2008 Adam M. Costello and Cosmin Truta. Copyright (c) 2000-2008 Adam M. Costello and Cosmin Truta.
This software may be modified only if its author and version This software may be modified only if its author and version
@ -211,7 +210,7 @@ struct exception_context { \
#define Try \ #define Try \
{ \ { \
jmp_buf * volatile exception__prev, exception__env; \ jmp_buf *exception__prev, exception__env; \
exception__prev = the_exception_context->penv; \ exception__prev = the_exception_context->penv; \
the_exception_context->penv = &exception__env; \ the_exception_context->penv = &exception__env; \
if (setjmp(exception__env) == 0) { \ if (setjmp(exception__env) == 0) { \

View File

@ -524,7 +524,7 @@ void read_png(FILE *fp, int sig_read) /* File is already open */
/* Add filler (or alpha) byte (before/after each RGB triplet) */ /* Add filler (or alpha) byte (before/after each RGB triplet) */
png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
#ifdef PNG_READ_INTERLACING_SUPPORTED #ifdef PNG_READ_DEINTERLACE_SUPPORTED
/* Turn on interlace handling. REQUIRED if you are not using /* Turn on interlace handling. REQUIRED if you are not using
* png_read_image(). To see how to handle interlacing passes, * png_read_image(). To see how to handle interlacing passes,
* see the png_read_row() method below: * see the png_read_row() method below:
@ -532,7 +532,7 @@ void read_png(FILE *fp, int sig_read) /* File is already open */
number_passes = png_set_interlace_handling(png_ptr); number_passes = png_set_interlace_handling(png_ptr);
#else #else
number_passes = 1; number_passes = 1;
#endif /* READ_INTERLACING */ #endif /* READ_DEINTERLACE */
/* Optional call to gamma correct and add the background to the palette /* Optional call to gamma correct and add the background to the palette
@ -715,7 +715,7 @@ row_callback(png_structp png_ptr, png_bytep new_row,
*/ */
png_bytep old_row = ((png_bytep *)our_data)[row_num]; png_bytep old_row = ((png_bytep *)our_data)[row_num];
#ifdef PNG_READ_INTERLACING_SUPPORTED #ifdef PNG_READ_DEINTERLACE_SUPPORTED
/* If both rows are allocated then copy the new row /* If both rows are allocated then copy the new row
* data to the corresponding row data. * data to the corresponding row data.
*/ */
@ -744,7 +744,7 @@ row_callback(png_structp png_ptr, png_bytep new_row,
* to pass the current row as new_row, and the function will combine * to pass the current row as new_row, and the function will combine
* the old row and the new row. * the old row and the new row.
*/ */
#endif /* READ_INTERLACING */ #endif /* READ_DEINTERLACE */
} }
end_callback(png_structp png_ptr, png_infop info) end_callback(png_structp png_ptr, png_infop info)

381
png.c
View File

@ -424,7 +424,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
/* Free any tRNS entry */ /* Free any tRNS entry */
if (((mask & PNG_FREE_TRNS) & info_ptr->free_me) != 0) if (((mask & PNG_FREE_TRNS) & info_ptr->free_me) != 0)
{ {
info_ptr->valid &= ~PNG_INFO_tRNS; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_tRNS);
png_free(png_ptr, info_ptr->trans_alpha); png_free(png_ptr, info_ptr->trans_alpha);
info_ptr->trans_alpha = NULL; info_ptr->trans_alpha = NULL;
info_ptr->num_trans = 0; info_ptr->num_trans = 0;
@ -439,7 +439,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
png_free(png_ptr, info_ptr->scal_s_height); png_free(png_ptr, info_ptr->scal_s_height);
info_ptr->scal_s_width = NULL; info_ptr->scal_s_width = NULL;
info_ptr->scal_s_height = NULL; info_ptr->scal_s_height = NULL;
info_ptr->valid &= ~PNG_INFO_sCAL; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_sCAL);
} }
#endif #endif
@ -462,7 +462,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
png_free(png_ptr, info_ptr->pcal_params); png_free(png_ptr, info_ptr->pcal_params);
info_ptr->pcal_params = NULL; info_ptr->pcal_params = NULL;
} }
info_ptr->valid &= ~PNG_INFO_pCAL; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_pCAL);
} }
#endif #endif
@ -474,7 +474,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
png_free(png_ptr, info_ptr->iccp_profile); png_free(png_ptr, info_ptr->iccp_profile);
info_ptr->iccp_name = NULL; info_ptr->iccp_name = NULL;
info_ptr->iccp_profile = NULL; info_ptr->iccp_profile = NULL;
info_ptr->valid &= ~PNG_INFO_iCCP; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_iCCP);
} }
#endif #endif
@ -504,7 +504,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
png_free(png_ptr, info_ptr->splt_palettes); png_free(png_ptr, info_ptr->splt_palettes);
info_ptr->splt_palettes = NULL; info_ptr->splt_palettes = NULL;
info_ptr->splt_palettes_num = 0; info_ptr->splt_palettes_num = 0;
info_ptr->valid &= ~PNG_INFO_sPLT; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_sPLT);
} }
} }
#endif #endif
@ -539,7 +539,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
{ {
png_free(png_ptr, info_ptr->hist); png_free(png_ptr, info_ptr->hist);
info_ptr->hist = NULL; info_ptr->hist = NULL;
info_ptr->valid &= ~PNG_INFO_hIST; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_hIST);
} }
#endif #endif
@ -548,7 +548,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
{ {
png_free(png_ptr, info_ptr->palette); png_free(png_ptr, info_ptr->palette);
info_ptr->palette = NULL; info_ptr->palette = NULL;
info_ptr->valid &= ~PNG_INFO_PLTE; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_PLTE);
info_ptr->num_palette = 0; info_ptr->num_palette = 0;
} }
@ -565,12 +565,12 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
png_free(png_ptr, info_ptr->row_pointers); png_free(png_ptr, info_ptr->row_pointers);
info_ptr->row_pointers = NULL; info_ptr->row_pointers = NULL;
} }
info_ptr->valid &= ~PNG_INFO_IDAT; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_IDAT);
} }
#endif #endif
if (num != -1) if (num != -1)
mask &= ~PNG_FREE_MUL; mask &= PNG_BIC_MASK(PNG_FREE_MUL);
info_ptr->free_me &= ~mask; info_ptr->free_me &= ~mask;
} }
@ -605,26 +605,31 @@ png_init_io(png_structrp png_ptr, png_FILE_p fp)
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
png_ptr->io_ptr = (png_voidp)fp; if (png_ptr->rw_data_fn == NULL)
} {
# ifdef PNG_READ_SUPPORTED
if (png_ptr->read_struct)
png_set_read_fn(png_ptr, fp, png_default_read_data);
# ifdef PNG_WRITE_SUPPORTED
else
# endif /* WRITE */
# endif /* READ */
# ifdef PNG_WRITE_SUPPORTED
if (!png_ptr->read_struct)
png_set_write_fn(png_ptr, fp, png_default_write_data,
# ifdef PNG_WRITE_FLUSH_SUPPORTED
png_default_flush
# else
NULL
# endif # endif
);
# endif /* WRITE */
}
# ifdef PNG_SAVE_INT_32_SUPPORTED else
/* The png_save_int_32 function assumes integers are stored in two's png_ptr->io_ptr = fp;
* complement format. If this isn't the case, then this routine needs to
* be modified to write data in two's complement format. Note that,
* the following works correctly even if png_int_32 has more than 32 bits
* (compare the more complex code required on read for sign extension.)
*/
void PNGAPI
png_save_int_32(png_bytep buf, png_int_32 i)
{
buf[0] = (png_byte)((i >> 24) & 0xff);
buf[1] = (png_byte)((i >> 16) & 0xff);
buf[2] = (png_byte)((i >> 8) & 0xff);
buf[3] = (png_byte)(i & 0xff);
} }
# endif # endif /* STDIO */
# ifdef PNG_TIME_RFC1123_SUPPORTED # ifdef PNG_TIME_RFC1123_SUPPORTED
/* Convert the supplied time into an RFC 1123 string suitable for use in /* Convert the supplied time into an RFC 1123 string suitable for use in
@ -828,18 +833,6 @@ png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name)
*/ */
return PNG_HANDLE_CHUNK_AS_DEFAULT; return PNG_HANDLE_CHUNK_AS_DEFAULT;
} }
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
int /* PRIVATE */
png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name)
{
png_byte chunk_string[5];
PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
return png_handle_as_unknown(png_ptr, chunk_string);
}
#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
#endif /* SET_UNKNOWN_CHUNKS */ #endif /* SET_UNKNOWN_CHUNKS */
/* This function was added to libpng-1.0.7 */ /* This function was added to libpng-1.0.7 */
@ -938,13 +931,19 @@ png_colorspace_check_gamma(png_const_structrp png_ptr,
* 0: the new gamma value is the libpng estimate for an ICC profile * 0: the new gamma value is the libpng estimate for an ICC profile
* 1: the new gamma value comes from a gAMA chunk * 1: the new gamma value comes from a gAMA chunk
* 2: the new gamma value comes from an sRGB chunk * 2: the new gamma value comes from an sRGB chunk
*
* API CHANGE: libpng 1.7.0: prior to 1.7 the check below used the build-time
* constant PNG_GAMMA_THRESHOLD_FIXED and the results would therefore depend
* on a parameter that was intended for tuning the READ_GAMMA support. In
* 1.7 a fixed value of +/-1% is used instead; this reflects the fact that
* gamma values are rarely quoted to more than 2 decimal digits of precision.
*/ */
{ {
png_fixed_point gtest; png_fixed_point gtest;
if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
(png_muldiv(&gtest, colorspace->gamma, PNG_FP_1, gAMA) == 0 || (png_muldiv(&gtest, colorspace->gamma, PNG_FP_1, gAMA) == 0 ||
png_gamma_significant(gtest) != 0)) gtest < PNG_FP_1 - 1000 || gtest > PNG_FP_1 + 1000))
{ {
/* Either this is an sRGB image, in which case the calculated gamma /* Either this is an sRGB image, in which case the calculated gamma
* approximation should match, or this is an image with a profile and the * approximation should match, or this is an image with a profile and the
@ -986,17 +985,29 @@ png_colorspace_set_gamma(png_const_structrp png_ptr,
* In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
* handling code, which only required the value to be >0. * handling code, which only required the value to be >0.
*/ */
# define ERRMSG (defined PNG_TRANSFORM_MECH_SUPPORTED) &&\
(defined PNG_ERROR_TEXT_SUPPORTED)
# if ERRMSG
png_const_charp errmsg; png_const_charp errmsg;
# endif
if (gAMA < 16 || gAMA > 625000000) if (gAMA < 16 || gAMA > 625000000)
{
# if ERRMSG
errmsg = "gamma value out of range"; errmsg = "gamma value out of range";
# endif
}
# ifdef PNG_READ_gAMA_SUPPORTED # ifdef PNG_READ_gAMA_SUPPORTED
/* Allow the application to set the gamma value more than once */ /* Allow the application to set the gamma value more than once */
else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && else if (png_ptr->read_struct &&
(colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0) (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
{
# if ERRMSG
errmsg = "duplicate"; errmsg = "duplicate";
# endif # endif
}
# endif
/* Do nothing if the colorspace is already invalid */ /* Do nothing if the colorspace is already invalid */
else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
@ -1022,6 +1033,7 @@ png_colorspace_set_gamma(png_const_structrp png_ptr,
} }
/* Error exit - errmsg has been set. */ /* Error exit - errmsg has been set. */
# undef ERRMSG
colorspace->flags |= PNG_COLORSPACE_INVALID; colorspace->flags |= PNG_COLORSPACE_INVALID;
png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR); png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);
} }
@ -1032,7 +1044,7 @@ png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0) if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
{ {
/* Everything is invalid */ /* Everything is invalid */
info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB| info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB|
PNG_INFO_iCCP); PNG_INFO_iCCP);
# ifdef PNG_COLORSPACE_SUPPORTED # ifdef PNG_COLORSPACE_SUPPORTED
@ -1054,20 +1066,20 @@ png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)
info_ptr->valid |= PNG_INFO_sRGB; info_ptr->valid |= PNG_INFO_sRGB;
else else
info_ptr->valid &= ~PNG_INFO_sRGB; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_sRGB);
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
info_ptr->valid |= PNG_INFO_cHRM; info_ptr->valid |= PNG_INFO_cHRM;
else else
info_ptr->valid &= ~PNG_INFO_cHRM; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_cHRM);
# endif # endif
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0) if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0)
info_ptr->valid |= PNG_INFO_gAMA; info_ptr->valid |= PNG_INFO_gAMA;
else else
info_ptr->valid &= ~PNG_INFO_gAMA; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_gAMA);
} }
} }
@ -1085,6 +1097,25 @@ png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
#endif #endif
#ifdef PNG_COLORSPACE_SUPPORTED #ifdef PNG_COLORSPACE_SUPPORTED
/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
static png_fixed_point
png_reciprocal(png_fixed_point a)
{
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
double r = floor(1E10/a+.5);
if (r <= 2147483647. && r >= -2147483648.)
return (png_fixed_point)r;
#else
png_fixed_point res;
if (png_muldiv(&res, PNG_FP_1, PNG_FP_1, a) != 0)
return res;
#endif
return 0; /* error/overflow */
}
/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for /* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
* cHRM, as opposed to using chromaticities. These internal APIs return * cHRM, as opposed to using chromaticities. These internal APIs return
* non-zero on a parameter error. The X, Y and Z values are required to be * non-zero on a parameter error. The X, Y and Z values are required to be
@ -1847,7 +1878,7 @@ png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
int /* PRIVATE */ int /* PRIVATE */
png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
png_const_charp name, png_uint_32 profile_length, png_const_charp name, png_uint_32 profile_length,
png_const_bytep profile/* first 132 bytes only */, int color_type) png_const_bytep profile/* first 132 bytes only */, int is_color)
{ {
png_uint_32 temp; png_uint_32 temp;
@ -1934,13 +1965,13 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
switch (temp) switch (temp)
{ {
case 0x52474220: /* 'RGB ' */ case 0x52474220: /* 'RGB ' */
if ((color_type & PNG_COLOR_MASK_COLOR) == 0) if (!is_color)
return png_icc_profile_error(png_ptr, colorspace, name, temp, return png_icc_profile_error(png_ptr, colorspace, name, temp,
"RGB color space not permitted on grayscale PNG"); "RGB color space not permitted on grayscale PNG");
break; break;
case 0x47524159: /* 'GRAY' */ case 0x47524159: /* 'GRAY' */
if ((color_type & PNG_COLOR_MASK_COLOR) != 0) if (is_color)
return png_icc_profile_error(png_ptr, colorspace, name, temp, return png_icc_profile_error(png_ptr, colorspace, name, temp,
"Gray color space not permitted on RGB PNG"); "Gray color space not permitted on RGB PNG");
break; break;
@ -2270,14 +2301,14 @@ png_icc_set_sRGB(png_const_structrp png_ptr,
int /* PRIVATE */ int /* PRIVATE */
png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
png_const_charp name, png_uint_32 profile_length, png_const_bytep profile, png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,
int color_type) int is_color)
{ {
if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
return 0; return 0;
if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 &&
png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
color_type) != 0 && is_color) != 0 &&
png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
profile) != 0) profile) != 0)
{ {
@ -2292,84 +2323,40 @@ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
return 0; return 0;
} }
#endif /* iCCP */ #endif /* iCCP */
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
void /* PRIVATE */
png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
{
/* Set the rgb_to_gray coefficients from the colorspace. */
if ((png_ptr->colorspace.flags & PNG_COLORSPACE_RGB_TO_GRAY_SET) == 0 &&
(png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
{
/* png_set_background has not been called, get the coefficients from the Y
* values of the colorspace colorants.
*/
png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
png_fixed_point total = r+g+b;
if (total > 0 &&
r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
r+g+b <= 32769)
{
/* We allow 0 coefficients here. r+g+b may be 32769 if two or
* all of the coefficients were rounded up. Handle this by
* reducing the *largest* coefficient by 1; this matches the
* approach used for the default coefficients in pngrtran.c
*/
int add = 0;
if (r+g+b > 32768)
add = -1;
else if (r+g+b < 32768)
add = 1;
if (add != 0)
{
if (g >= r && g >= b)
g += add;
else if (r >= g && r >= b)
r += add;
else
b += add;
}
/* Check for an internal error. */
if (r+g+b != 32768)
impossible("error handling cHRM coefficients");
else
{
png_ptr->rgb_to_gray_red_coeff = png_check_u16(png_ptr, r);
png_ptr->rgb_to_gray_green_coeff = png_check_u16(png_ptr, g);
}
}
/* This is a png_error at present even though it could be ignored -
* it should never happen, but it is important that if it does, the
* bug is fixed.
*/
else
impossible("error handling cHRM->XYZ");
}
}
#endif /* READ_RGB_TO_GRAY */
#endif /* COLORSPACE */ #endif /* COLORSPACE */
#ifdef __GNUC__ png_alloc_size_t /* PRIVATE */
/* This exists solely to work round a warning from GNU C. */ png_calc_rowbytes(png_const_structrp png_ptr, unsigned int pixel_depth,
static int /* PRIVATE */ png_uint_32 row_width)
png_gt(size_t a, size_t b)
{ {
return a > b; png_alloc_size_t rowbytes = row_width;
/* Carefully calculate the row buffer size. */
if (pixel_depth > 8)
{
if ((pixel_depth & 7) != 0)
png_error(png_ptr, "unsupported pixel byte size");
pixel_depth >>= 3; /* Now in bytes */
if (rowbytes > PNG_SIZE_MAX/pixel_depth)
png_error(png_ptr, "image row exceeds system limits");
rowbytes *= pixel_depth;
}
else /* Less than 1 byte per pixel */ switch (pixel_depth)
{
case 1: rowbytes += 7; rowbytes >>= 3; break;
case 2: rowbytes += 3; rowbytes >>= 2; break;
case 4: rowbytes += 1; rowbytes >>= 1; break;
case 8: break;
default:
png_error(png_ptr, "unsupported pixel bit size");
}
return rowbytes;
} }
#else
# define png_gt(a,b) ((a) > (b))
#endif
void /* PRIVATE */ void /* PRIVATE */
png_check_IHDR(png_const_structrp png_ptr, png_check_IHDR(png_const_structrp png_ptr,
@ -2392,28 +2379,6 @@ png_check_IHDR(png_const_structrp png_ptr,
error = 1; error = 1;
} }
if (png_gt(((width + 7) & (~7)),
((PNG_SIZE_MAX
- 48 /* big_row_buf hack */
- 1) /* filter byte */
/ 8) /* 8-byte RGBA pixels */
- 1)) /* extra max_pixel_depth pad */
{
/* The size of the row must be within the limits of this architecture.
* Because the read code can perform arbitrary transformations the
* maximum size is checked here. Because the code in png_read_start_row
* adds extra space "for safety's sake" in several places a conservative
* limit is used here.
*
* NOTE: it would be far better to check the size that is actually used,
* but the effect in the real world is minor and the changes are more
* extensive, therefore much more dangerous and much more difficult to
* write in a way that avoids compiler warnings.
*/
png_warning(png_ptr, "Image width is too large for this architecture");
error = 1;
}
#ifdef PNG_SET_USER_LIMITS_SUPPORTED #ifdef PNG_SET_USER_LIMITS_SUPPORTED
if (width > png_ptr->user_width_max) if (width > png_ptr->user_width_max)
#else #else
@ -2504,7 +2469,7 @@ png_check_IHDR(png_const_structrp png_ptr,
(color_type == PNG_COLOR_TYPE_RGB || (color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA))) color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
{ {
png_warning(png_ptr, "Unknown filter method in IHDR"); png_warning(png_ptr, "Invalid filter method in IHDR");
error = 1; error = 1;
} }
@ -2515,16 +2480,23 @@ png_check_IHDR(png_const_structrp png_ptr,
} }
} }
#else #else /* !MNG_FEATURES */
if (filter_type != PNG_FILTER_TYPE_BASE) if (filter_type != PNG_FILTER_TYPE_BASE)
{ {
png_warning(png_ptr, "Unknown filter method in IHDR"); png_warning(png_ptr, "Unknown filter method in IHDR");
error = 1; error = 1;
} }
#endif #endif /* !MNG_FEATURES */
if (error == 1) if (error == 1)
png_error(png_ptr, "Invalid IHDR data"); png_error(png_ptr, "Invalid IHDR data");
/* Finally, if the IHDR data is correct, check it against the system
* limits (NOTE: this need not be done; the IDAT handling code repeats the
* check in both read and write.)
*/
(void)png_calc_rowbytes(png_ptr,
PNG_COLOR_TYPE_CHANNELS(color_type) * bit_depth, width);
} }
#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) #if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
@ -3260,37 +3232,6 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
} }
#endif /* GAMMA || INCH_CONVERSIONS */ #endif /* GAMMA || INCH_CONVERSIONS */
#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */
/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
png_fixed_point
png_reciprocal(png_fixed_point a)
{
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
double r = floor(1E10/a+.5);
if (r <= 2147483647. && r >= -2147483648.)
return (png_fixed_point)r;
#else
png_fixed_point res;
if (png_muldiv(&res, 100000, 100000, a) != 0)
return res;
#endif
return 0; /* error/overflow */
}
/* This is the shared test on whether a gamma value is 'significant' - whether
* it is worth doing gamma correction.
*/
int /* PRIVATE */
png_gamma_significant(png_fixed_point gamma_val)
{
return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
}
#endif
/* HARDWARE OPTION SUPPORT */ /* HARDWARE OPTION SUPPORT */
#ifdef PNG_SET_OPTION_SUPPORTED #ifdef PNG_SET_OPTION_SUPPORTED
int PNGAPI int PNGAPI
@ -3299,9 +3240,9 @@ png_set_option(png_structrp png_ptr, int option, int onoff)
if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT && if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT &&
(option & 1) == 0) (option & 1) == 0)
{ {
int mask = 3 << option; unsigned int mask = 3U << option;
int setting = (2 + (onoff != 0)) << option; unsigned int setting = (2U + (onoff != 0)) << option;
int current = png_ptr->options; unsigned int current = png_ptr->options;
png_ptr->options = png_check_byte(png_ptr, (current & ~mask) | setting); png_ptr->options = png_check_byte(png_ptr, (current & ~mask) | setting);
@ -3310,7 +3251,48 @@ png_set_option(png_structrp png_ptr, int option, int onoff)
return PNG_OPTION_INVALID; return PNG_OPTION_INVALID;
} }
#endif #endif /* SET_OPTION */
/* SOFTWARE SETTING SUPPORT */
#ifdef PNG_SETTING_SUPPORTED
png_int_32 PNGAPI
png_setting(png_structrp png_ptr, int setting, png_int_32 value)
{
switch (setting)
{
# ifdef PNG_READ_GAMMA_SUPPORTED
case PNG_GAMMA_MINIMUM:
if (value < 0 || value > 0xFFFF)
value = PNG_GAMMA_THRESHOLD_FIXED;
{
png_int_32 old = png_ptr->gamma_threshold;
png_ptr->gamma_threshold = PNG_UINT_16(value);
return old;
}
break;
#if 0 /*NYI*/
case PNG_GAMMA_ACCURACY:
if (value < 0 || value > 1600)
value = PNG_DEFAULT_GAMMA_ACCURACY;
{
png_int_32 old = png_ptr->gamma_accuracy;
png_ptr->gamma_accuracy = value;
return old;
}
break;
#endif /*NYI*/
# endif /* READ_GAMMA */
default:
break;
}
PNG_UNUSED(png_ptr)
PNG_UNUSED(value)
return PNG_UNSUPPORTED_SETTING;
}
#endif /* SETTING */
/* sRGB support */ /* sRGB support */
#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
@ -3501,13 +3483,13 @@ png_image_free_function(png_voidp argument)
# ifdef PNG_STDIO_SUPPORTED # ifdef PNG_STDIO_SUPPORTED
if (cp->owned_file != 0) if (cp->owned_file != 0)
{ {
FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr); FILE *fp = png_voidcast(FILE*, png_get_io_ptr(cp->png_ptr));
cp->owned_file = 0; cp->owned_file = 0;
/* Ignore errors here. */ /* Ignore errors here. */
if (fp != NULL) if (fp != NULL)
{ {
cp->png_ptr->io_ptr = NULL; png_init_io(cp->png_ptr, NULL);
(void)fclose(fp); (void)fclose(fp);
} }
} }
@ -3570,5 +3552,34 @@ png_image_error(png_imagep image, png_const_charp error_message)
return 0; return 0;
} }
#ifdef PNG_STDIO_SUPPORTED
typedef struct
{
png_structrp png_ptr;
png_FILE_p fp;
}
png_image_init_io_struct;
static int
image_init_io(png_voidp display)
{
png_image_init_io_struct *p =
png_voidcast(png_image_init_io_struct*, display);
png_init_io(p->png_ptr, p->fp);
return 1;
}
int /* PRIVATE */
png_image_init_io(png_imagep image, png_FILE_p fp)
{
png_image_init_io_struct s;
s.png_ptr = image->opaque->png_ptr;
s.fp = fp;
return png_safe_execute(image, image_init_io, &s);
}
#endif /* STDIO */
#endif /* SIMPLIFIED READ/WRITE */ #endif /* SIMPLIFIED READ/WRITE */
#endif /* READ || WRITE */ #endif /* READ || WRITE */

501
png.h
View File

@ -568,9 +568,15 @@
* following macro tests for a negative number and generates the machine format * following macro tests for a negative number and generates the machine format
* directly by portable arithmetic operations. The cost is that the argument * directly by portable arithmetic operations. The cost is that the argument
* 'b1' is evaluated twice. * 'b1' is evaluated twice.
*
* NOTE: the 0x7fffffffU BIC is there to ensure that potential overflow in the
* cast does not occur. This fixes the case where 1's complement machines could
* be forced into an overflow by an invalid value in the stream and, therefore,
* potentially raise an arithmetic exception; the invalid value is converted to
* 0 and any resultant problems will be caught later in the libpng checking.
*/ */
#define PNG_S32(b1, b2, b3, b4) ((b1) & 0x80\ #define PNG_S32(b1, b2, b3, b4) ((b1) & 0x80\
? -(png_int_32)((PNG_U32(b1, b2, b3, b4) ^ 0xffffffff) + 1)\ ? -(png_int_32)(((PNG_U32(b1, b2, b3, b4)^0xffffffffU)+1U)&0x7fffffffU)\
: (png_int_32)PNG_U32(b1, b2, b3, b4)) : (png_int_32)PNG_U32(b1, b2, b3, b4))
/* Constants for known chunk types. /* Constants for known chunk types.
@ -892,9 +898,11 @@ typedef png_time * * png_timepp;
*/ */
typedef struct png_unknown_chunk_t typedef struct png_unknown_chunk_t
{ {
png_byte name[5]; /* Textual chunk name with '\0' terminator */
png_byte *data; /* Data, should not be modified on read! */ png_byte *data; /* Data, should not be modified on read! */
size_t size; png_uint_32 size; /* Size of data, must not exceed 0x7fffffff.
* API CHANGE 1.7.0: changed from 'size_t'
*/
png_byte name[5]; /* Textual chunk name with '\0' terminator */
/* On write 'location' must be set using the flag values listed below. /* On write 'location' must be set using the flag values listed below.
* Notice that on read it is set by libpng however the values stored have * Notice that on read it is set by libpng however the values stored have
@ -912,9 +920,9 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
#endif #endif
/* Flag values for the unknown chunk location byte. */ /* Flag values for the unknown chunk location byte. */
#define PNG_HAVE_IHDR 0x01 #define PNG_HAVE_IHDR 0x01U
#define PNG_HAVE_PLTE 0x02 #define PNG_HAVE_PLTE 0x02U
#define PNG_AFTER_IDAT 0x08 #define PNG_AFTER_IDAT 0x08U
/* Maximum positive integer used in PNG is (2^31)-1 */ /* Maximum positive integer used in PNG is (2^31)-1 */
#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) #define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL)
@ -931,12 +939,12 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
/* These describe the color_type field in png_info. */ /* These describe the color_type field in png_info. */
/* color type masks */ /* color type masks */
#define PNG_COLOR_MASK_PALETTE 1 #define PNG_COLOR_MASK_PALETTE 1U
#define PNG_COLOR_MASK_COLOR 2 #define PNG_COLOR_MASK_COLOR 2U
#define PNG_COLOR_MASK_ALPHA 4 #define PNG_COLOR_MASK_ALPHA 4U
/* color types. Note that not all combinations are legal */ /* color types. Note that not all combinations are legal */
#define PNG_COLOR_TYPE_GRAY 0 #define PNG_COLOR_TYPE_GRAY 0U
#define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE) #define PNG_COLOR_TYPE_PALETTE (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_PALETTE)
#define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR) #define PNG_COLOR_TYPE_RGB (PNG_COLOR_MASK_COLOR)
#define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA) #define PNG_COLOR_TYPE_RGB_ALPHA (PNG_COLOR_MASK_COLOR | PNG_COLOR_MASK_ALPHA)
@ -1054,22 +1062,53 @@ typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32,
typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop));
typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop));
/* The following callback receives png_uint_32 row_number, int pass for the /* WARNING: the API for this callback is poorly documented and produces
* png_bytep data of the row. When transforming an interlaced image the * unexpected results when dealing with interlaced images. For non-interlaced
* row number is the row number within the sub-image of the interlace pass, so * images the parameters are straightforward:
* the value will increase to the height of the sub-image (not the full image)
* then reset to 0 for the next pass.
* *
* Use PNG_ROW_FROM_PASS_ROW(row, pass) and PNG_COL_FROM_PASS_COL(col, pass) to * next_row: a pointer to the transformed row read from the PNG input
* find the output pixel (x,y) given an interlaced sub-image pixel * stream, it has png_get_image_width() pixels.
* (row,col,pass). (See below for these macros.) * row_y: the y ordinate of the image; 0..png_get_image_height()-1
* pass: 0
*
* For interlaced images if png_set_interlace_handling has been called (libpng
* does *not* call this itself) the parameters are the same except that the
* pass will be the pass in the range 0..6 (NOTE: one less than the PNG spec)
* and 'next_row' will be NULL if (and only if) the row does not contribute
* to the output in 'blocky' display mode.
*
* pass: 0..6
*
* If 'next_row' is not NULL it is necessary for the application to combine the
* pixels with the output. This can most easily be done by calling
* png_progressive_combine_row(). Note that the 'next_row' data cannot be
* changed; even though the value is passed to png_progressive_combine_row the
* pointer is not used, it is just a flag , if it is NULL nothing will happen.
*
* If png_set_interlace_handling has not been called the callback only gets
* called for original PNG interlaced row:
*
* row_y: the y ordinate in the pass; 0..PNG_PASS_ROWS()-1
*
* What is more if PNG_PASS_COLS() is 0 the entire pass will be skipped. The
* row data is not full width and there is no guarantee that the buffer passed
* in 'next_row' is able to accomodate the full width of output pixels, however
* 'next_row' will never be NULL.
*
* Use PNG_ROW_FROM_PASS_ROW(row_y, pass) and PNG_COL_FROM_PASS_COL(col, pass)
* to find the output pixel (x,y) given an interlaced sub-image pixel
* (row_y,col,pass). (See below for these macros.)
*
* Note that in this latter case if you want to do the 'blocky' display update
* method you have to work out all the details yourself with regard to which
* pixels to set for each row and whether to replicate it to the following
* rows of the image.
*/ */
typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp,
png_uint_32, int)); png_bytep next_row, png_uint_32 row_y, int pass));
#endif #endif
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop,
png_bytep)); png_bytep));
#endif #endif
@ -1335,6 +1374,7 @@ PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr));
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
/* Reduce RGB to grayscale. */ /* Reduce RGB to grayscale. */
#define PNG_ERROR_ACTION_NO_CHECK 0
#define PNG_ERROR_ACTION_NONE 1 #define PNG_ERROR_ACTION_NONE 1
#define PNG_ERROR_ACTION_WARN 2 #define PNG_ERROR_ACTION_WARN 2
#define PNG_ERROR_ACTION_ERROR 3 #define PNG_ERROR_ACTION_ERROR 3
@ -1344,6 +1384,35 @@ PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr,
int error_action, double red, double green)) int error_action, double red, double green))
PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr,
int error_action, png_fixed_point red, png_fixed_point green)) int error_action, png_fixed_point red, png_fixed_point green))
/* Convert RGB pixels to gray (CIE Y) values, the red and green value must be
* less than or equal to 1, if either is negative a set of defaults
* corresponding to the sRGB standard are used.
*
* The error action specifies whether to check for r==g==b in each pixel, if
* it is 0 (PNG_ERROR_ACTION_NO_CHECK; added in libpng 1.7.0) no check will
* be performed, otherwise a check is performed and the result can be
* retrieved using png_get_rgb_to_gray_status (which just returns a
* true if a non-gray pixel was encountered).
*
* Pass PNG_ERROR_ACTION_ERROR if you are confident that the image only
* contains gray pixels (you have already checked); the check is still
* performed but a very optimized code path is used for RGB to gray
* convertion.
*
* If you want to extract a single channel pass PNG_FP_1 for the coefficient
* for that channel and 0 for the rest (0 for both red and green to extract
* blue).
*
* NOTE: the default coefficients used if negative values are passed for red
* or green are based on the cHRM chunk if available, otherwise sRGB. The
* calculation returns the Y (luminance value) corresponding to the white
* point of the PNG. UNLESS THE WHITE POINT IS D50 THIS IS NOT A CIEXYZ Y
* VALUE. It is the luminance of the pixel perceived by a viewer completely
* adapted to the white point of the PNG, this may not be what you want
* because to interpret it you have to also record the white point of the
* PNG. To obtain CIEXYZ Y values read the cHRM chunk XYZ values and
* chromatically adapt them to D50
*/
PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp
png_ptr)); png_ptr));
@ -1536,7 +1605,7 @@ PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p
true_bits)); true_bits));
#endif #endif
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \ #if defined(PNG_READ_DEINTERLACE_SUPPORTED) || \
defined(PNG_WRITE_INTERLACING_SUPPORTED) defined(PNG_WRITE_INTERLACING_SUPPORTED)
/* Have the code handle the interlacing. Returns the number of passes. /* Have the code handle the interlacing. Returns the number of passes.
* MUST be called before png_read_update_info or png_start_read_image, * MUST be called before png_read_update_info or png_start_read_image,
@ -1641,7 +1710,7 @@ PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row,
png_bytep display_row)); png_bytep display_row));
#endif #endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED #ifdef PNG_READ_IMAGE_SUPPORTED
/* Read the whole image into memory at once. */ /* Read the whole image into memory at once. */
PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image));
#endif #endif
@ -1710,13 +1779,28 @@ PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action,
* header file (zlib.h) for an explination of the compression functions. * header file (zlib.h) for an explination of the compression functions.
*/ */
#ifdef PNG_WRITE_SUPPORTED #ifdef PNG_WRITE_FILTER_SUPPORTED
/* Set the filtering method(s) used by libpng. Currently, the only valid /* Control the filtering method(s) used by libpng for the write of subsequent
* value for "method" is 0. * rows of the image. The argument is either a single filter value (one of the
* PNG_FILTER_VALUE_ defines below), in which case that filter will be used on
* following rows, or a mask of filter values (logical or of the PNG_FILTER_
* bit masks and follow PNG_FILTER_VALUE_*).
*
* The set of filters may be changed at any time, the new values will affect the
* next row written.
*
* Prior to 1.7.0 it was only possible to add the filters that use the previous
* row if at least one of them was selected at the start of the write.
*
* In 1.7.0 if a filter is added which causes the previous row to be required
* (anywhere in the interlace pass after row 0) the use of the filter will be
* delayed until the row after the next one.
*
* The 'method' must match that passed to png_set_IHDR; it cannot be changed.
*/ */
PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
int filters)); int filters));
#endif /* WRITE */ #endif /* WRITE_FILTER */
/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. /* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
* These defines match the values in the PNG specification. * These defines match the values in the PNG specification.
@ -1750,13 +1834,13 @@ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
#ifdef PNG_WRITE_SUPPORTED #ifdef PNG_WRITE_SUPPORTED
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, PNG_FP_EXPORT(68, PNG_DEPRECATED void, png_set_filter_heuristics,
int heuristic_method, int num_weights, png_const_doublep filter_weights, (png_structrp png_ptr, int heuristic_method, int num_weights,
png_const_doublep filter_costs) PNG_DEPRECATED) png_const_doublep filter_weights, png_const_doublep filter_costs))
PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, PNG_FIXED_EXPORT(209, PNG_DEPRECATED void, png_set_filter_heuristics_fixed,
(png_structrp png_ptr, int heuristic_method, int num_weights, (png_structrp png_ptr, int heuristic_method, int num_weights,
png_const_fixed_point_p filter_weights, png_const_fixed_point_p filter_weights,
png_const_fixed_point_p filter_costs) PNG_DEPRECATED) png_const_fixed_point_p filter_costs))
#endif /* WRITE_WEIGHTED_FILTER */ #endif /* WRITE_WEIGHTED_FILTER */
/* Set the library compression level. Currently, valid values range from /* Set the library compression level. Currently, valid values range from
@ -1909,8 +1993,8 @@ PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp));
/* This callback is called only for *unknown* chunks. If /* This callback is called only for *unknown* chunks. If
* PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known
* chunks to be treated as unknown, however in this case the callback must do * chunks to be treated as unknown, however in this case the callback must do
* any processing required by the chunk (e.g. by calling the appropriate * any processing required by the chunk and this is not possible for any chunk
* png_set_ APIs.) * that affects the image reading (e.g. PLTE, tRNS).
* *
* There is no write support - on write, by default, all the chunks in the * There is no write support - on write, by default, all the chunks in the
* 'unknown' list are written in the specified position. * 'unknown' list are written in the specified position.
@ -1926,6 +2010,11 @@ PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp));
* happens) so it was not possible to discard unknown chunk data if a * happens) so it was not possible to discard unknown chunk data if a
* user callback was installed. * user callback was installed.
* positive: The chunk was handled, libpng will ignore/discard it. * positive: The chunk was handled, libpng will ignore/discard it.
*
* WARNING: if this callback is set every chunk in the stream is temporarily
* read into a memory buffer. This has potential performance implications,
* particularly for small PNG images with large amounts of ancilliary
* information.
*/ */
PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr,
png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn));
@ -1968,7 +2057,7 @@ PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save));
*/ */
PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp));
#ifdef PNG_READ_INTERLACING_SUPPORTED #ifdef PNG_READ_DEINTERLACE_SUPPORTED
/* Function that combines rows. 'new_row' is a flag that should come from /* Function that combines rows. 'new_row' is a flag that should come from
* the callback and be non-NULL if anything needs to be done; the library * the callback and be non-NULL if anything needs to be done; the library
* stores its own version of the new data internally and ignores the passed * stores its own version of the new data internally and ignores the passed
@ -1976,7 +2065,7 @@ PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp));
*/ */
PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr,
png_bytep old_row, png_const_bytep new_row)); png_bytep old_row, png_const_bytep new_row));
#endif /* READ_INTERLACING */ #endif /* READ_DEINTERLACE */
#endif /* PROGRESSIVE_READ */ #endif /* PROGRESSIVE_READ */
PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr,
@ -2039,16 +2128,18 @@ PNG_REMOVED(101, void, png_free_default, (png_const_structrp png_ptr,
/* Fatal error in PNG image of libpng - can't continue */ /* Fatal error in PNG image of libpng - can't continue */
PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr,
png_const_charp error_message), PNG_NORETURN); png_const_charp error_message), PNG_NORETURN);
/* The same, but the chunk name is prepended to the error string. */
PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr,
png_const_charp error_message), PNG_NORETURN);
#else #else
/* Fatal error in PNG image of libpng - can't continue */ /* Fatal error in PNG image of libpng - can't continue */
PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN);
# define png_error(s1,s2) png_err(s1) # define png_error(s1,s2) png_err(s1)
# define png_chunk_error(s1,s2) png_err(s1) #endif
#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
/* The same, but the chunk name is prepended to the error string. */
PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr,
png_const_charp error_message), PNG_NORETURN);
#else
# define png_chunk_error(s1,s2) png_error(s1,s2)
#endif #endif
#ifdef PNG_WARNINGS_SUPPORTED #ifdef PNG_WARNINGS_SUPPORTED
@ -2080,11 +2171,11 @@ PNG_EXPORT(109, void, png_set_benign_errors,
(png_structrp png_ptr, int allowed)); (png_structrp png_ptr, int allowed));
#else #else
# ifdef PNG_ALLOW_BENIGN_ERRORS # ifdef PNG_ALLOW_BENIGN_ERRORS
# define png_benign_error png_warning # define png_benign_error(pp,e) png_warning(pp,e)
# define png_chunk_benign_error png_chunk_warning # define png_chunk_benign_error(pp,e) png_chunk_warning(pp,e)
# else # else
# define png_benign_error png_error # define png_benign_error(pp,e) png_error(pp,e)
# define png_chunk_benign_error png_chunk_error # define png_chunk_benign_error(pp,e) png_chunk_error(pp,e)
# endif # endif
#endif #endif
@ -2105,16 +2196,18 @@ PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr,
png_const_inforp info_ptr, png_uint_32 flag)); png_const_inforp info_ptr, png_uint_32 flag));
/* Returns number of bytes needed to hold a transformed row. */ /* Returns number of bytes needed to hold a transformed row. */
PNG_EXPORT(111, size_t, png_get_rowbytes, (png_const_structrp png_ptr, PNG_EXPORT(111, png_alloc_size_t, png_get_rowbytes, (png_const_structrp png_ptr,
png_const_inforp info_ptr)); png_const_inforp info_ptr));
#ifdef PNG_INFO_IMAGE_SUPPORTED #ifdef PNG_READ_PNG_SUPPORTED
/* Returns row_pointers, which is an array of pointers to scanlines that was /* Returns row_pointers, which is an array of pointers to scanlines that was
* returned from png_read_png(). * returned from png_read_png().
*/ */
PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr,
png_const_inforp info_ptr)); png_const_inforp info_ptr));
#endif
#ifdef PNG_WRITE_PNG_SUPPORTED
/* Set row_pointers, which is an array of pointers to scanlines for use /* Set row_pointers, which is an array of pointers to scanlines for use
* by png_write_png(). * by png_write_png().
*/ */
@ -2541,7 +2634,7 @@ PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr,
*/ */
PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr,
png_const_bytep chunk_name)); png_const_bytep chunk_name));
#endif #endif /* SET_UNKNOWN_CHUNKS */
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structrp png_ptr, PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structrp png_ptr,
@ -2554,6 +2647,12 @@ PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structrp png_ptr,
* code won't be compiled on earlier versions you can rely on * code won't be compiled on earlier versions you can rely on
* png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing
* the correct thing. * the correct thing.
*
* API CHANGE: in 1.7.0 this API will not work on read unless
* PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED is set; it may be necessary to change
* code to check the latter SUPPORTED flag. png_set_keep_unknown_chunks
* will issue a warning if it is asked to save a chunk and there is no read
* support.
*/ */
PNG_EXPORT(175, void, png_set_unknown_chunk_location, PNG_EXPORT(175, void, png_set_unknown_chunk_location,
@ -2570,17 +2669,15 @@ PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr,
PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr,
png_inforp info_ptr, int mask)); png_inforp info_ptr, int mask));
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* The "params" pointer is currently not used and is for future expansion. */ /* The "params" pointer is currently not used and is for future expansion. */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED #ifdef PNG_READ_PNG_SUPPORTED
PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr,
int transforms, png_voidp params)); int transforms, png_voidp params));
#endif #endif
#ifdef PNG_WRITE_SUPPORTED #ifdef PNG_WRITE_PNG_SUPPORTED
PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr,
int transforms, png_voidp params)); int transforms, png_voidp params));
#endif #endif
#endif
PNG_EXPORT(180, png_const_charp, png_get_copyright, PNG_EXPORT(180, png_const_charp, png_get_copyright,
(png_const_structrp png_ptr)); (png_const_structrp png_ptr));
@ -2707,7 +2804,7 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) #define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1))
/* Two macros to help evaluate the number of rows or columns in each /* Two macros to help evaluate the number of rows or columns in each
* pass. This is expressed as a shift - effectively log2 of the number or * pass. This is expressed as a shift - effectively 3-log2 of the number or
* rows or columns in each 8x8 tile of the original image. * rows or columns in each 8x8 tile of the original image.
*/ */
#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) #define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3)
@ -2747,6 +2844,25 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
#define PNG_COL_IN_INTERLACE_PASS(x, pass) \ #define PNG_COL_IN_INTERLACE_PASS(x, pass) \
((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1) ((PNG_PASS_MASK(pass,1) >> ((x)&7)) & 1)
/* Whether the pass is in the image at all, taking into account the full image
* width and height, evaluates 'pass' lots of times, but width and height at
* most once each.
*/
#define PNG_PASS_IN_IMAGE(width, height, pass)\
((height) > PNG_PASS_START_ROW(pass) && (width) > PNG_PASS_START_COL(pass))
/* A macro to find the last pass (in the range 0 to 6) given an image width and
* height. Then two macros two find whether a given image row or column which
* is prsent in the pass is the last row or column in the pass. Note that these
* macros return 'true' for earlier rows or columns of the image that are *not*
* in the pass.
*/
#define PNG_LAST_PASS(width, height) ((height) > 1 ? 6 : ((width) > 1 ? 5 : 0))
#define PNG_LAST_PASS_ROW(y, pass, height)\
((y) + PNG_PASS_ROW_OFFSET(pass) >= (height))
#define PNG_LAST_PASS_COL(x, pass, width)\
((x) + PNG_PASS_COL_OFFSET(pass) >= (width))
#ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED #ifdef PNG_READ_COMPOSITE_NODIV_SUPPORTED
/* With these routines we avoid an integer divide, which will be slower on /* With these routines we avoid an integer divide, which will be slower on
* most machines. However, it does take more operations than the corresponding * most machines. However, it does take more operations than the corresponding
@ -2802,10 +2918,17 @@ PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr,
/* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ /* Place a 32-bit number into a buffer in PNG byte order (big-endian). */
#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i));
#endif
#ifdef PNG_SAVE_INT_32_SUPPORTED /* This becomes a macro in 1.7 because the old implementation was wrong; it
PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); * failed to do the cast. ANSI C requires the cast to convert a negative number
#endif * to the 2's complement form, so this just works:
*/
#define png_save_int_32(b, i) png_save_uint_32(b, i);
#endif /* WRITE_INT_FUNCTIONS */
/* Apps that used this will use the macro in 1.7. */
PNG_REMOVED(206, void, png_save_int_32, (png_bytep buf, png_int_32 i),
PNG_DEPRECATED)
/* Place a 16-bit number into a buffer in PNG byte order. /* Place a 16-bit number into a buffer in PNG byte order.
* The parameter is declared unsigned int, not png_uint_16, * The parameter is declared unsigned int, not png_uint_16,
@ -2850,12 +2973,79 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
PNG_EXPORT(242, void, png_set_check_for_invalid_index, PNG_EXPORT(242, void, png_set_check_for_invalid_index,
(png_structrp png_ptr, int allowed)); (png_structrp png_ptr, int enabled_if_greater_than_0));
# ifdef PNG_GET_PALETTE_MAX_SUPPORTED /* By default the check is enabled on both read and write, passing a value
* which is 0 or negative disables the check. Disabling the check also
* prevents the following API from working.
*/
#endif /* CHECK_FOR_INVALID_INDEX */
#ifdef PNG_GET_PALETTE_MAX_SUPPORTED
PNG_EXPORT(243, int, png_get_palette_max, (png_const_structrp png_ptr, PNG_EXPORT(243, int, png_get_palette_max, (png_const_structrp png_ptr,
png_const_inforp info_ptr)); png_const_inforp info_ptr));
# endif /* The info_ptr is not used, it may be NULL in 1.7.0 (not in earlier
#endif /* CHECK_FOR_INVALID_INDEX */ * versions). If the information is not available because
* png_set_check_for_invalid_index disabled the check this API returns -1.
* Valid results can only be obtained after the complete image has been read,
* though it may be called at any time to get the result so far.
*/
#endif /* GET_PALETTE_MAX */
/* Memory format options; these return information about the layout of the
* transformed row using the Simplified API PNG_FORMAT_ values (see below for
* the #defines).
*
* These are only relevant if read or write transforms are supported; these
* may cause the memory format of pixel data to differ from that used in the
* PNG file itself. Nevertheless the APIs are supported regardless of whether
* transforms are applied; use these to consistently and safely determine the
* layout of the image in memory.
*
* Some of the same information can be obtained from png_info, however this
* does not record whether the byte or bit formats have been changed.
*/
PNG_EXPORT(245, unsigned int, png_memory_format, (png_structrp png_ptr));
/* The in-memory format as a bitmask of PNG_FORMAT_FLAG_ values. All the
* flags listed below are used. If PNG_FORMAT_FLAG_INVALID is set the
* following caveats apply to the interpretation of PNG_FORMAT_FLAG_LINEAR:
*
* The gamma may differ from the sRGB (!LINEAR) or 1.0 (LINEAR). Call
* png_memory_gamma to find the correct value.
*
* The channel depth may differ from 8 (!LINEAR) or 16 (LINEAR). Call
* png_memory_channel_depth to find the correct value.
*
* It is only valid to call these APIS *after* either png_read_update_info
* or png_start_read_image on read or after the first row of an image has
* been written on write.
*
* To find the number of channels in each pixel from the returned value,
* 'fmt' use:
*
* PNG_FORMAT_CHANNELS(fmt)
*/
PNG_EXPORT(246, unsigned int, png_memory_channel_depth, (png_structrp png_ptr));
/* The actual depth of each channel in the image, to determine the full pixel
* depth (in bits) use:
*
* png_memory_channel_depth(pp) * PNG_FORMAT_CHANNELS(fmt)
*/
#ifdef PNG_GAMMA_SUPPORTED
PNG_EXPORT(247, png_fixed_point, png_memory_gamma, (png_structrp png_ptr));
/* The actual gamma of the image data, scaled by 100,000. This is the
* encoding gamma, e.g. 1/2.2 for sRGB. If the gamma is unknown this will
* return 0.
*
* On write this invariably returns 0; libpng does not change the gamma of
* the data on write.
*
* Note that this is not always the exact inverse of the 'screen gamma'
* passed to png_set_gamma; internal optimizations remove attempts to make
* small changes to the gamma value. This function returns the actual
* output value.
*/
#endif /* GAMMA */
/******************************************************************************* /*******************************************************************************
* Section 5: SIMPLIFIED API * Section 5: SIMPLIFIED API
@ -3015,20 +3205,79 @@ typedef struct
#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ #define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */
#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2 byte channels else 1 byte */ #define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2 byte channels else 1 byte */
#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ #define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */
#define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */
#define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */
/* other bits RESERVED */
#ifdef PNG_FORMAT_BGR_SUPPORTED /* The PNG color type value can be derived from a format which repesents a valid
# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */ * PNG format using the following macro. Note that if any of the non-PNG
#endif * format elements are use, such as BGR or AFIRST, the color type value that
* results does represent the number of channels in the format but may not
* represent their order or encoding.
*
* NOTE: the format can encode illegal PNG formats, such as a colormap with
* alpha or without color; these are legal simplified API formats which produce
* data that cannot be represented as PNG regardless of channel order or
* encoding.
*
* The macro below is the bit shift version, a multiplicative version which only
* evaluates 'f' once is:
*
* ((((((((f) * 0x111) & 0x128) * 0x3) & 0x130) * 0x5) >> 6) & 0x7)
*/
#define PNG_COLOR_TYPE_FROM_FORMAT(f)\
((((f) & (!((f) & PNG_FORMAT_FLAG_AFILLER))) << 2) |\
(((f) & PNG_FORMAT_FLAG_COLOR) ) |\
(((f) & PNG_FORMAT_FLAG_COLORMAP) >> 3))
#ifdef PNG_FORMAT_AFIRST_SUPPORTED /* The inverse: note that PNG_FORMAT_FLAG_LINEAR is not set by this macro and
# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ * that there is no handling for a 'filler' channel, consequently the macro must
#endif * only be used on genuine PNG color types, not the result of png_get_color_type
* after transforms have been applied to the original PNG data.
*/
#define PNG_FORMAT_FROM_COLOR_TYPE(c)\
((((c) & PNG_COLOR_MASK_ALPHA) >> 2) |\
(((c) & PNG_COLOR_MASK_COLOR) ) |\
(((c) & PNG_COLOR_MASK_PALETTE) << 3))
/* The following flags are not used by the simplified API but may be returned
* by png_memory_format. Presence of any of these flags means that the values
* in the image (in memory) cannot be handled 'normally'.
*/
#define PNG_FORMAT_FLAG_AFILLER 0x40U /* The 'alpha' channel is a filler:
* PNG_FORMAT_FLAG_ALPHA is set however the value in the alpha channel
* is not an alpha value and (therefore) cannot be used for alpha
* computations, it is just a filler value. PNG_COLOR_TYPE_FROM_FORMAT
* will return a color type *without* PNG_COLOR_MASK_ALPHA, however
* PNG_FORMAT_CHANNELS will return the correct number, including the
* filler channel.
*/
#define PNG_FORMAT_FLAG_SWAPPED 0x80U /* bytes or bits swapped:
* When the bit depth is 16 this means that the bytes within the
* components have been swapped, when the bit depth is less than 8
* it means the pixels within the bytes have been swapped. It should
* not be set for 8-bit compononents (it is meaningless). */
#define PNG_FORMAT_FLAG_RANGE 0x100U /* component range not 0..bit-depth:
* Low-bit-depth grayscale components have been unpacked into bytes
* without scaling, or RGB[A] pixels have been shifted back to the
* significant-bit range from the sBIT chunk or channels (currently
* alpha or gray) have been inverted. */
#define PNG_FORMAT_FLAG_INVALID 0x8000U /* Invalid simplified API channel depth:
* For single channel grayscale and palette indexed image data PNG
* supports bit depths of 1, 2 or 4 bits per pixel (and per channel)
* packed into bytes. The simplified API macros will not work with
* these formats (the simplified API always uses 8 or 16-bit channels).
* In the simplified API 'linear' images always have 16-bit channels
* and non-linear images are always sRGB encoded. If the INVALID flag
* is set then this may not be true; it is necessary to check the
* memory format bit-depth and gamma separately.
*/
/* Commonly used formats have predefined macros. /* Commonly used formats have predefined macros.
* *
* First the single byte (sRGB) formats: * First the single byte (sRGB) formats:
*/ */
#define PNG_FORMAT_GRAY 0 #define PNG_FORMAT_GRAY 0U
#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA #define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA
#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) #define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST)
#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR #define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR
@ -3119,6 +3368,12 @@ typedef struct
* color-mapped image. * color-mapped image.
*/ */
#define PNG_FORMAT_CHANNELS(fmt) PNG_IMAGE_PIXEL_CHANNELS(fmt)
/* Synonym for the above for use with the result of png_get_memory_format.
* This exists to avoid confusion with the PNG_IMAGE_ macros which do not
* work on all possible results of png_get_memory_format.
*/
#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\ #define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\
PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt)
/* The size, in bytes, of each component in a pixel; 1 for a color-mapped /* The size, in bytes, of each component in a pixel; 1 for a color-mapped
@ -3324,7 +3579,14 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
* to do this in user mode, in which case it is necessary to discover * to do this in user mode, in which case it is necessary to discover
* the capabilities in an OS specific way. Such capabilities are * the capabilities in an OS specific way. Such capabilities are
* listed here when libpng has support for them and must be turned * listed here when libpng has support for them and must be turned
* ON by the application if present. * ON by the application if present. Check pnglibconf.h for options
* appropriate to your hardware.
*
* In general 'PNG_EXTENSIONS' controls hardware optimizations; these
* are not supported parts of libpng and, if there are problems with
* them, bugs should be ported to the implementers. Depending on the
* configuration it may not be possible to disable extensions at run
* time.
* *
* SOFTWARE: sometimes software optimizations actually result in performance * SOFTWARE: sometimes software optimizations actually result in performance
* decrease on some architectures or systems, or with some sets of * decrease on some architectures or systems, or with some sets of
@ -3332,9 +3594,7 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
* selected at run time. * selected at run time.
*/ */
#ifdef PNG_SET_OPTION_SUPPORTED #ifdef PNG_SET_OPTION_SUPPORTED
#ifdef PNG_ARM_NEON_API_SUPPORTED #define PNG_EXTENSIONS 0 /* BOTH: enable or disable extensions */
# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */
#endif
#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ #define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */
#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ #define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */
#define PNG_OPTION_NEXT 6 /* Next option - numbers must be even */ #define PNG_OPTION_NEXT 6 /* Next option - numbers must be even */
@ -3347,23 +3607,102 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
int onoff)); int onoff));
#endif #endif /* SET_OPTION */
/* Support for software run-time settings.
*
* These settings allow tuning of the parameters used internally by libpng to
* achieve either greater performance, lower memory utilization or greater
* accuracy in image processing operations.
*
* The parameter is a single png_int_32, the result is the previous setting or
* 0x8000000 if the setting is not supported..
*/
#ifdef PNG_SETTING_SUPPORTED
PNG_EXPORT(248, png_int_32, png_setting, (png_structrp png_ptr, int setting,
png_int_32 value));
#define PNG_UNSUPPORTED_SETTING 0x80000000
/* Available settings: */
#define PNG_GAMMA_MINIMUM 1
/* SETTING: threshold below which gamma correction is not done, the default
* (set when the library is built) is PNG_GAMMA_THRESHOLD_FIXED, the
* parameter is a png_fixed_point number, the difference from PNG_FP_1 above
* which gamma correction will be performed.
*
* The value '153' is sufficient to maintain 1% accuracy in 16-bit linear
* calculations over a 655:1 range; over the maximum range possible with the
* 16-bit linear representation. Reasonable values are:
*
* 0: always do gamma correction, even if the gamma values are
* identical. The only point to this is to avoid a bug in the
* optimized (no gamma correction) code path, or for testing.
* 2: always do gamma correction if there is any significant
* difference. Notice that '1' will result in gamma correction in
* many cases when the screen gamma is the inverse of the encoding
* gamma because of inaccuracies in the representation of gamma.
* 153: do gamma correction if it is needed to maintain the accuracy of
* 16-bit linear calculations at 1% or below.
* 216: maintain 1% accuracy over a 100:1 dynamic range in 16-bit linear
* calculations. This matches the widely accepted numbers for human
* perception of differences within an image, however that doesn't
* mean that such high accuracy is required to avoid artefacts; such
* accuracy (such a low number) is only required if versions of the
* same image with and without gamma correction are to be compared
* visually.
* 5000: this is the default from libpng 1.6 and earlier. Using this
* produces changes in image contrast that are visible when suitable
* images are compared side-by-side however they are not obvious and
* it is inconceivable that a user would notice the change unless
* the user was very familiar with the image and the viewing
* environment.
*
* Values between 216 and 5000 produce varying very small changes in image
* contrast. Values above 10,000 (10%) produce noticeable increase or
* decrease in contrast which will probably change how the image is
* perceived.
*/
#if 0 /*NYI*/
#define PNG_GAMMA_ACCURACY 2
/* SETTING: controls the accuracy of the gamma calculations when the results
* are cached. The default is PNG_DEFAULT_GAMMA_ACCURACY. The number is 100
* times the number of bits, 'b', used in the internal tables when the input
* is linear, permitted values are 0..1600 however '0' causes the caching to
* be skipped entirely (so gives maximum accuracy with no caching!)
*
* The accuracy in the linear domain for a value 'a' is:
*
* +/-(.5/2^a)
*
* so for the default-default of 665 this means the accuracy is +/-0.5% and
* this ensures that almost-equal input values do not differ by more than 1%
* in the output, meeting the accepted requirement for human vision.
*
* The default value has no effect on input narrower than 16 bits. For n-bit
* input the total table size is ((n-v)+1)*(2^v), where 'v' is a/gamma and
* 'gamma' is the gamma encoding of the input:
*
* n a gamma 'v' table size
* 8 6.65 .45455 14.6 256
* 16 6.65 .45455 14.6 65536
* 16 6.65 1.0 6.65 1280
* 16 6 1.0 6 704
* 16 5 1.0 5 384
*/
#endif /*NYI*/
#endif /* SETTING */
/******************************************************************************* /*******************************************************************************
* END OF HARDWARE OPTIONS * END OF HARDWARE OPTIONS
******************************************************************************/ ******************************************************************************/
/* Maintainer: Put new public prototypes here ^, in libpng.3, and project
* defs
*/
/* The last ordinal number (this is the *last* one already used; the next /* The last ordinal number (this is the *last* one already used; the next
* one to use is one more than this.) Maintainer, remember to add an entry to * one to use is one more than this.) Maintainer, remember to add an entry to
* scripts/symbols.def as well. * scripts/symbols.def as well.
*/ */
#ifdef PNG_EXPORT_LAST_ORDINAL #ifdef PNG_EXPORT_LAST_ORDINAL
PNG_EXPORT_LAST_ORDINAL(244); PNG_EXPORT_LAST_ORDINAL(248);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -36,13 +36,13 @@
/* These settings control the formatting of messages in png.c and pngerror.c */ /* These settings control the formatting of messages in png.c and pngerror.c */
/* Moved to pngdebug.h at 1.5.0 */ /* Moved to pngdebug.h at 1.5.0 */
# ifndef PNG_LITERAL_SHARP # ifndef PNG_LITERAL_SHARP
# define PNG_LITERAL_SHARP 0x23 # define PNG_LITERAL_SHARP 0x23U
# endif # endif
# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET # ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET
# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b # define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5bU
# endif # endif
# ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET # ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET
# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d # define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5dU
# endif # endif
# ifndef PNG_STRING_NEWLINE # ifndef PNG_STRING_NEWLINE
# define PNG_STRING_NEWLINE "\n" # define PNG_STRING_NEWLINE "\n"

View File

@ -366,8 +366,7 @@ png_benign_error(png_const_structrp png_ptr, png_const_charp error_message)
if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0) if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
{ {
# ifdef PNG_READ_SUPPORTED # ifdef PNG_READ_SUPPORTED
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && if (png_ptr->read_struct && png_ptr->chunk_name != 0)
png_ptr->chunk_name != 0)
png_chunk_warning(png_ptr, error_message); png_chunk_warning(png_ptr, error_message);
else else
# endif # endif
@ -377,8 +376,7 @@ png_benign_error(png_const_structrp png_ptr, png_const_charp error_message)
else else
{ {
# ifdef PNG_READ_SUPPORTED # ifdef PNG_READ_SUPPORTED
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && if (png_ptr->read_struct && png_ptr->chunk_name != 0)
png_ptr->chunk_name != 0)
png_chunk_error(png_ptr, error_message); png_chunk_error(png_ptr, error_message);
else else
# endif # endif
@ -421,10 +419,14 @@ png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
#if defined(PNG_WARNINGS_SUPPORTED) || \ #if defined(PNG_WARNINGS_SUPPORTED) || \
(defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)) (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED))
/* These utilities are used internally to build an error message that relates /* These utilities are used internally to build an error message that relates
* to the current chunk. The chunk name comes from png_ptr->chunk_name, * to the current chunk. The chunk name comes from png_ptr->chunk_name unless
* which is used to prefix the message. The message is limited in length * png_ptr->zowner is set in which case that is used in preference. This is
* to 63 bytes. The name characters are output as hex digits wrapped in [] * used to prefix the message. The message is limited in length to 63 bytes.
* if the character is invalid. * The name characters are output as hex digits wrapped in [] if the character
* is invalid.
*
* Using 'zowner' means that IDAT errors at the end of the IDAT stream are still
* reported as from the IDAT chunks.
*/ */
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
static PNG_CONST char png_digit[16] = { static PNG_CONST char png_digit[16] = {
@ -436,9 +438,12 @@ static void /* PRIVATE */
png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
error_message) error_message)
{ {
png_uint_32 chunk_name = png_ptr->chunk_name; png_uint_32 chunk_name = png_ptr->zowner;
int iout = 0, ishift = 24; int iout = 0, ishift = 24;
if (chunk_name == 0)
chunk_name = png_ptr->chunk_name;
while (ishift >= 0) while (ishift >= 0)
{ {
int c = (int)(chunk_name >> ishift) & 0xff; int c = (int)(chunk_name >> ishift) & 0xff;
@ -530,17 +535,14 @@ png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp
#endif /* READ */ #endif /* READ */
void /* PRIVATE */ void /* PRIVATE */
png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error) (png_chunk_report)(png_const_structrp png_ptr, png_const_charp message,
int error)
{ {
# ifndef PNG_WARNINGS_SUPPORTED
PNG_UNUSED(message)
# endif
/* This is always supported, but for just read or just write it /* This is always supported, but for just read or just write it
* unconditionally does the right thing. * unconditionally does the right thing.
*/ */
# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) # if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) if (png_ptr->read_struct)
# endif # endif
# ifdef PNG_READ_SUPPORTED # ifdef PNG_READ_SUPPORTED
@ -548,13 +550,16 @@ png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
if (error < PNG_CHUNK_ERROR) if (error < PNG_CHUNK_ERROR)
png_chunk_warning(png_ptr, message); png_chunk_warning(png_ptr, message);
else else if (error < PNG_CHUNK_FATAL)
png_chunk_benign_error(png_ptr, message); png_chunk_benign_error(png_ptr, message);
else
png_chunk_error(png_ptr, message);
} }
# endif # endif
# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED) # if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0) else if (!png_ptr->read_struct)
# endif # endif
# ifdef PNG_WRITE_SUPPORTED # ifdef PNG_WRITE_SUPPORTED
@ -562,10 +567,17 @@ png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
if (error < PNG_CHUNK_WRITE_ERROR) if (error < PNG_CHUNK_WRITE_ERROR)
png_app_warning(png_ptr, message); png_app_warning(png_ptr, message);
else else if (error < PNG_CHUNK_FATAL)
png_app_error(png_ptr, message); png_app_error(png_ptr, message);
else
png_error(png_ptr, message);
} }
# endif # endif
# ifndef PNG_ERROR_TEXT_SUPPORTED
PNG_UNUSED(message)
# endif
} }
#ifdef PNG_ERROR_TEXT_SUPPORTED #ifdef PNG_ERROR_TEXT_SUPPORTED
@ -881,7 +893,7 @@ png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
if (png_ptr != NULL) if (png_ptr != NULL)
{ {
png_ptr->flags &= png_ptr->flags &=
((~(PNG_FLAG_STRIP_ERROR_NUMBERS | ((PNG_BIC_MASK(PNG_FLAG_STRIP_ERROR_NUMBERS |
PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode);
} }
} }
@ -1106,8 +1118,8 @@ affirm_text(png_charp buffer, size_t bufsize,
#endif /* AFFIRM_TEXT */ #endif /* AFFIRM_TEXT */
PNG_FUNCTION(void, png_affirm,(png_const_structrp png_ptr, PNG_FUNCTION(void,png_affirm,(png_const_structrp png_ptr,
param_deb(png_const_charp condition) unsigned int position), PNG_NORETURN) param_deb(png_const_charp condition) unsigned int position),PNG_NORETURN)
{ {
# if PNG_AFFIRM_TEXT # if PNG_AFFIRM_TEXT
char buffer[512]; char buffer[512];
@ -1154,6 +1166,17 @@ PNG_FUNCTION(void, png_affirm,(png_const_structrp png_ptr,
/* The character/byte checking APIs. These do their own calls to png_affirm /* The character/byte checking APIs. These do their own calls to png_affirm
* because the caller provides the position. * because the caller provides the position.
*/ */
unsigned int /* PRIVATE */
png_bit_affirm(png_const_structrp png_ptr, unsigned int position,
unsigned int u, unsigned int bits)
{
/* The following avoids overflow errors even if 'bits' is 16 or 32: */
if (u <= (1U << bits)-1U)
return u;
png_affirm(png_ptr, param_deb("(bit field) range") position);
}
char /* PRIVATE */ char /* PRIVATE */
png_char_affirm(png_const_structrp png_ptr, unsigned int position, int c) png_char_affirm(png_const_structrp png_ptr, unsigned int position, int c)
{ {

View File

@ -27,16 +27,18 @@ png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr,
return(0); return(0);
} }
png_size_t PNGAPI png_alloc_size_t PNGAPI
png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr) png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr)
{ {
if (png_ptr != NULL && info_ptr != NULL) if (png_ptr != NULL && info_ptr != NULL)
return(info_ptr->rowbytes); return png_calc_rowbytes(png_ptr,
PNG_FORMAT_CHANNELS(info_ptr->format) * info_ptr->bit_depth,
info_ptr->width);
return(0); return 0;
} }
#ifdef PNG_INFO_IMAGE_SUPPORTED #ifdef PNG_READ_PNG_SUPPORTED
png_bytepp PNGAPI png_bytepp PNGAPI
png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr) png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr)
{ {
@ -80,7 +82,8 @@ png_byte PNGAPI
png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr) png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
{ {
if (png_ptr != NULL && info_ptr != NULL) if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->color_type; return png_check_byte(png_ptr,
PNG_COLOR_TYPE_FROM_FORMAT(info_ptr->format));
return (0); return (0);
} }
@ -317,7 +320,7 @@ png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
static png_uint_32 static png_uint_32
ppi_from_ppm(png_uint_32 ppm) ppi_from_ppm(png_uint_32 ppm)
{ {
#if 0 #if 0 /*NOT USED*/
/* The conversion is *(2.54/100), in binary (32 digits): /* The conversion is *(2.54/100), in binary (32 digits):
* .00000110100000001001110101001001 * .00000110100000001001110101001001
*/ */
@ -477,7 +480,7 @@ png_byte PNGAPI
png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr) png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr)
{ {
if (png_ptr != NULL && info_ptr != NULL) if (png_ptr != NULL && info_ptr != NULL)
return(info_ptr->channels); return png_check_byte(png_ptr, PNG_FORMAT_CHANNELS(info_ptr->format));
return (0); return (0);
} }
@ -822,7 +825,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
*bit_depth = info_ptr->bit_depth; *bit_depth = info_ptr->bit_depth;
if (color_type != NULL) if (color_type != NULL)
*color_type = info_ptr->color_type; *color_type = PNG_COLOR_TYPE_FROM_FORMAT(info_ptr->format);
if (compression_type != NULL) if (compression_type != NULL)
*compression_type = info_ptr->compression_type; *compression_type = info_ptr->compression_type;
@ -833,16 +836,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
if (interlace_type != NULL) if (interlace_type != NULL)
*interlace_type = info_ptr->interlace_type; *interlace_type = info_ptr->interlace_type;
/* This is redundant if we can be sure that the info_ptr values were all return 1;
* assigned in png_set_IHDR(). We do the check anyhow in case an
* application has ignored our advice not to mess with the members
* of info_ptr directly.
*/
png_check_IHDR(png_ptr, info_ptr->width, info_ptr->height,
info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
info_ptr->compression_type, info_ptr->filter_type);
return (1);
} }
#ifdef PNG_oFFs_SUPPORTED #ifdef PNG_oFFs_SUPPORTED
@ -1080,7 +1074,7 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
{ {
png_debug1(1, "in %s retrieval function", "tRNS"); png_debug1(1, "in %s retrieval function", "tRNS");
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) if ((info_ptr->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
{ {
if (trans_alpha != NULL) if (trans_alpha != NULL)
{ {
@ -1092,7 +1086,7 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
*trans_color = &(info_ptr->trans_color); *trans_color = &(info_ptr->trans_color);
} }
else /* if (info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) */ else /* if (info_ptr->format not colormapped */
{ {
if (trans_color != NULL) if (trans_color != NULL)
{ {
@ -1132,7 +1126,7 @@ png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr,
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
png_byte PNGAPI png_byte PNGAPI
png_get_rgb_to_gray_status (png_const_structrp png_ptr) png_get_rgb_to_gray_status(png_const_structrp png_ptr)
{ {
if (png_ptr) if (png_ptr)
return png_ptr->rgb_to_gray_status; return png_ptr->rgb_to_gray_status;
@ -1157,7 +1151,7 @@ png_get_compression_buffer_size(png_const_structrp png_ptr)
return 0; return 0;
#ifdef PNG_WRITE_SUPPORTED #ifdef PNG_WRITE_SUPPORTED
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) if (png_ptr->read_struct)
#endif #endif
{ {
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
@ -1217,18 +1211,4 @@ png_get_io_chunk_type (png_const_structrp png_ptr)
return png_ptr->chunk_name; return png_ptr->chunk_name;
} }
#endif /* IO_STATE */ #endif /* IO_STATE */
#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
# ifdef PNG_GET_PALETTE_MAX_SUPPORTED
int PNGAPI
png_get_palette_max(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return png_ptr->num_palette_max;
return (-1);
}
# endif
#endif
#endif /* READ || WRITE */ #endif /* READ || WRITE */

View File

@ -11,7 +11,7 @@
* and license in png.h * and license in png.h
*/ */
/* png_info is a structure that holds the information in a PNG file so /* png_info is a structure that holds the information in a PNG file so
* that the application can find out the characteristics of the image. * that the application can find out the characteristics of the image.
* If you are reading the file, this structure will tell you what is * If you are reading the file, this structure will tell you what is
* in the PNG file. If you are writing the file, fill in the information * in the PNG file. If you are writing the file, fill in the information
@ -57,25 +57,17 @@ struct png_info_def
/* The following are necessary for every PNG file */ /* The following are necessary for every PNG file */
png_uint_32 width; /* width of image in pixels (from IHDR) */ png_uint_32 width; /* width of image in pixels (from IHDR) */
png_uint_32 height; /* height of image in pixels (from IHDR) */ png_uint_32 height; /* height of image in pixels (from IHDR) */
png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */ unsigned int valid; /* valid chunk data (see PNG_INFO_ in png.h) */
png_size_t rowbytes; /* bytes needed to hold an untransformed row */
png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */
png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */ unsigned int num_palette:9; /* number of color entries in "palette" (PLTE) */
png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ unsigned int num_trans:9; /* number of transparent palette color (tRNS) */
png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ unsigned int bit_depth:6; /* 1, 2, 4, 8, 16 or 32 bits/channel */
png_byte color_type; /* see PNG_COLOR_TYPE_ below (from IHDR) */ unsigned int format:PNG_RF_BITS; /* row format; see png_struct.h */
/* The following three should have been named *_method not *_type */ /* The following three should have been named *_method not *_type */
png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */ png_byte compression_type; /* must be PNG_COMPRESSION_TYPE_BASE (IHDR) */
png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */ png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
/* The following are set by png_set_IHDR, called from the application on
* write, but the are never actually used by the write code.
*/
png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */
png_byte pixel_depth; /* number of bits per pixel */
png_byte spare_byte; /* to align the data, and for future use */
#ifdef PNG_READ_SUPPORTED #ifdef PNG_READ_SUPPORTED
/* This is never set during write */ /* This is never set during write */
png_byte signature[8]; /* magic bytes read by libpng from start of file */ png_byte signature[8]; /* magic bytes read by libpng from start of file */

1557
pngpread.c

File diff suppressed because it is too large Load Diff

1357
pngpriv.h

File diff suppressed because it is too large Load Diff

1273
pngread.c

File diff suppressed because it is too large Load Diff

View File

@ -34,11 +34,11 @@ png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length)
{ {
png_debug1(4, "reading %d bytes", (int)length); png_debug1(4, "reading %d bytes", (int)length);
if (png_ptr->read_data_fn != NULL) if (png_ptr->rw_data_fn != NULL)
(*(png_ptr->read_data_fn))(png_ptr, data, length); png_ptr->rw_data_fn(png_ptr, data, length);
else else
png_error(png_ptr, "Call to NULL read function"); png_app_error(png_ptr, "No read function");
} }
#ifdef PNG_STDIO_SUPPORTED #ifdef PNG_STDIO_SUPPORTED
@ -63,7 +63,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
if (check != length) if (check != length)
png_error(png_ptr, "Read Error"); png_error(png_ptr, "Read Error");
} }
#endif #endif /* STDIO */
/* This function allows the application to supply a new input function /* This function allows the application to supply a new input function
* for libpng if standard C streams aren't being used. * for libpng if standard C streams aren't being used.
@ -91,31 +91,19 @@ png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr,
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
png_ptr->io_ptr = io_ptr; if (!png_ptr->read_struct)
#ifdef PNG_STDIO_SUPPORTED
if (read_data_fn != NULL)
png_ptr->read_data_fn = read_data_fn;
else
png_ptr->read_data_fn = png_default_read_data;
#else
png_ptr->read_data_fn = read_data_fn;
#endif
#ifdef PNG_WRITE_SUPPORTED
/* It is an error to write to a read device */
if (png_ptr->write_data_fn != NULL)
{ {
png_ptr->write_data_fn = NULL; png_app_error(png_ptr, "cannot set a read function on a write struct");
png_warning(png_ptr, return;
"Can't set both read_data_fn and write_data_fn in the"
" same structure");
} }
#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED if (read_data_fn == NULL)
png_ptr->output_flush_fn = NULL; {
#endif png_app_error(png_ptr, "API change: png_set_read_fn requires a function");
return;
}
png_ptr->io_ptr = io_ptr;
png_ptr->rw_data_fn = read_data_fn;
} }
#endif /* READ */ #endif /* READ */

11200
pngrtran.c

File diff suppressed because it is too large Load Diff

3977
pngrutil.c

File diff suppressed because it is too large Load Diff

180
pngset.c
View File

@ -164,8 +164,6 @@ void PNGAPI
png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr, png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_uint_16p hist) png_const_uint_16p hist)
{ {
int i;
png_debug1(1, "in %s storage function", "hIST"); png_debug1(1, "in %s storage function", "hIST");
if (png_ptr == NULL || info_ptr == NULL) if (png_ptr == NULL || info_ptr == NULL)
@ -197,8 +195,12 @@ png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
info_ptr->free_me |= PNG_FREE_HIST; info_ptr->free_me |= PNG_FREE_HIST;
{
unsigned int i;
for (i = 0; i < info_ptr->num_palette; i++) for (i = 0; i < info_ptr->num_palette; i++)
info_ptr->hist[i] = hist[i]; info_ptr->hist[i] = hist[i];
}
info_ptr->valid |= PNG_INFO_hIST; info_ptr->valid |= PNG_INFO_hIST;
} }
@ -217,32 +219,16 @@ png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
info_ptr->width = width; info_ptr->width = width;
info_ptr->height = height; info_ptr->height = height;
info_ptr->bit_depth = png_check_byte(png_ptr, bit_depth); info_ptr->bit_depth = png_check_bits(png_ptr, bit_depth, 6);
info_ptr->color_type = png_check_byte(png_ptr, color_type); info_ptr->format = png_check_bits(png_ptr,
PNG_FORMAT_FROM_COLOR_TYPE(color_type), PNG_RF_BITS);
info_ptr->compression_type = png_check_byte(png_ptr, compression_type); info_ptr->compression_type = png_check_byte(png_ptr, compression_type);
info_ptr->filter_type = png_check_byte(png_ptr, filter_type); info_ptr->filter_type = png_check_byte(png_ptr, filter_type);
info_ptr->interlace_type = png_check_byte(png_ptr, interlace_type); info_ptr->interlace_type = png_check_byte(png_ptr, interlace_type);
png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height, png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, info_ptr->bit_depth, color_type, info_ptr->interlace_type,
info_ptr->compression_type, info_ptr->filter_type); info_ptr->compression_type, info_ptr->filter_type);
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
info_ptr->channels = 1;
else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
info_ptr->channels = 3;
else
info_ptr->channels = 1;
if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
info_ptr->channels++;
info_ptr->pixel_depth = png_check_byte(png_ptr, info_ptr->channels *
info_ptr->bit_depth);
info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
} }
#ifdef PNG_oFFs_SUPPORTED #ifdef PNG_oFFs_SUPPORTED
@ -523,13 +509,12 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH)
{ {
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) if ((info_ptr->format == PNG_FORMAT_FLAG_COLORMAP) != 0)
png_error(png_ptr, "Invalid palette length"); png_chunk_error(png_ptr, "Invalid palette length");
else else
{ {
png_warning(png_ptr, "Invalid palette length"); png_chunk_report(png_ptr, "Invalid palette length", PNG_CHUNK_ERROR);
return; return;
} }
} }
@ -538,11 +523,9 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
(num_palette == 0 (num_palette == 0
# ifdef PNG_MNG_FEATURES_SUPPORTED # ifdef PNG_MNG_FEATURES_SUPPORTED
&& (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
# endif # endif /* MNG_FEATURES */
)) ))
{
png_error(png_ptr, "Invalid palette"); png_error(png_ptr, "Invalid palette");
}
/* It may not actually be necessary to set png_ptr->palette here; /* It may not actually be necessary to set png_ptr->palette here;
* we do it for backward compatibility with the way the png_handle_tRNS * we do it for backward compatibility with the way the png_handle_tRNS
@ -563,8 +546,8 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
if (num_palette > 0) if (num_palette > 0)
memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color))); memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
info_ptr->palette = png_ptr->palette; info_ptr->palette = png_ptr->palette;
info_ptr->num_palette = png_ptr->num_palette = info_ptr->num_palette = png_ptr->num_palette = png_check_bits(png_ptr,
png_check_u16(png_ptr, num_palette); num_palette, 9);
info_ptr->free_me |= PNG_FREE_PLTE; info_ptr->free_me |= PNG_FREE_PLTE;
@ -647,7 +630,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
*/ */
{ {
int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name, int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
proflen, profile, info_ptr->color_type); proflen, profile, (info_ptr->format & PNG_FORMAT_FLAG_COLOR) != 0);
png_colorspace_sync_info(png_ptr, info_ptr); png_colorspace_sync_info(png_ptr, info_ptr);
@ -730,6 +713,11 @@ png_set_text_2(png_structrp png_ptr, png_inforp info_ptr,
int max_text; int max_text;
png_textp new_text = NULL; png_textp new_text = NULL;
/* The code below goes horribly wrong if old_num_text ever ends up
* negative, so:
*/
affirm(old_num_text >= 0);
/* Calculate an appropriate max_text, checking for overflow. */ /* Calculate an appropriate max_text, checking for overflow. */
max_text = old_num_text; max_text = old_num_text;
if (num_text <= INT_MAX - max_text) if (num_text <= INT_MAX - max_text)
@ -908,17 +896,30 @@ png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
{ {
png_debug1(1, "in %s storage function", "tIME"); png_debug1(1, "in %s storage function", "tIME");
if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL || if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL)
(png_ptr->mode & PNG_WROTE_tIME) != 0)
return; return;
/* It is valid to do set the tIME chunk after the IDAT has been written, but
* not if one has already been written. This was ignored before - the
* previous time was used - this is a bad thing.
*/
if ((info_ptr->valid & PNG_INFO_tIME) != 0 /* Changing a time chunk */ &&
(png_ptr->mode & PNG_HAVE_IHDR) != 0 /* after writing started */)
{
/* So it can be *set* but it can't be *changed* after the info before PLTE
* has been written. (Note that putting tIME into an unknown chunk
* currently gets round this; to be fixed.)
*/
png_app_error(png_ptr, "cannot change tIME after writing starts");
return;
}
if (mod_time->month == 0 || mod_time->month > 12 || if (mod_time->month == 0 || mod_time->month > 12 ||
mod_time->day == 0 || mod_time->day > 31 || mod_time->day == 0 || mod_time->day > 31 ||
mod_time->hour > 23 || mod_time->minute > 59 || mod_time->hour > 23 || mod_time->minute > 59 ||
mod_time->second > 60) mod_time->second > 60)
{ {
png_warning(png_ptr, "Ignoring invalid time value"); png_app_error(png_ptr, "Ignoring invalid time value");
return; return;
} }
@ -937,11 +938,11 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
if (png_ptr == NULL || info_ptr == NULL) if (png_ptr == NULL || info_ptr == NULL)
return; return;
if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) if ((info_ptr->format & PNG_FORMAT_FLAG_ALPHA) != 0)
png_chunk_report(png_ptr, png_chunk_report(png_ptr,
"png_set_tRNS: invalid on PNG with alpha channel", PNG_CHUNK_ERROR); "png_set_tRNS: invalid on PNG with alpha channel", PNG_CHUNK_ERROR);
else if (info_ptr->color_type & PNG_COLOR_MASK_PALETTE) else if ((info_ptr->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
{ {
int max_num; int max_num;
@ -949,7 +950,7 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
/* Do this just in case the old data was not owned by libpng: */ /* Do this just in case the old data was not owned by libpng: */
info_ptr->valid &= ~PNG_INFO_tRNS; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_tRNS);
info_ptr->trans_alpha = NULL; info_ptr->trans_alpha = NULL;
info_ptr->num_trans = 0; info_ptr->num_trans = 0;
@ -988,7 +989,7 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
memcpy(info_ptr->trans_alpha, trans_alpha, memcpy(info_ptr->trans_alpha, trans_alpha,
(unsigned)/*SAFE*/num_trans); (unsigned)/*SAFE*/num_trans);
info_ptr->valid |= PNG_INFO_tRNS; info_ptr->valid |= PNG_INFO_tRNS;
info_ptr->num_trans = png_check_u16(png_ptr, num_trans); info_ptr->num_trans = png_check_bits(png_ptr, num_trans, 9);
} }
} }
@ -997,19 +998,18 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
/* Invalidate any prior transparent color and set num_trans. It is not /* Invalidate any prior transparent color and set num_trans. It is not
* used internally in this case but png_get_tRNS still returns it. * used internally in this case but png_get_tRNS still returns it.
*/ */
info_ptr->valid &= ~PNG_INFO_tRNS; info_ptr->valid &= PNG_BIC_MASK(PNG_INFO_tRNS);
info_ptr->num_trans = 0; /* for png_get_tRNS */ info_ptr->num_trans = 0; /* for png_get_tRNS */
if (trans_color != NULL && info_ptr->bit_depth < 16) if (trans_color != NULL && info_ptr->bit_depth < 16)
{ {
unsigned int sample_max = (1U << info_ptr->bit_depth) - 1U; unsigned int sample_max = (1U << info_ptr->bit_depth) - 1U;
if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY && if (!(info_ptr->format & PNG_FORMAT_FLAG_COLOR) ?
trans_color->gray <= sample_max) || trans_color->gray <= sample_max :
(info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
trans_color->red <= sample_max && trans_color->red <= sample_max &&
trans_color->green <= sample_max && trans_color->green <= sample_max &&
trans_color->blue <= sample_max)) trans_color->blue <= sample_max)
{ {
info_ptr->trans_color = *trans_color; info_ptr->trans_color = *trans_color;
info_ptr->valid |= PNG_INFO_tRNS; info_ptr->valid |= PNG_INFO_tRNS;
@ -1135,7 +1135,7 @@ check_location(png_const_structrp png_ptr, int location)
* change; previously the app had to use the * change; previously the app had to use the
* png_set_unknown_chunk_location API below for each chunk. * png_set_unknown_chunk_location API below for each chunk.
*/ */
if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0) if (location == 0 && !png_ptr->read_struct)
{ {
/* Write struct, so unknown chunks come from the app */ /* Write struct, so unknown chunks come from the app */
png_app_warning(png_ptr, png_app_warning(png_ptr,
@ -1179,18 +1179,16 @@ png_set_unknown_chunks(png_structrp png_ptr,
* code) but may be meaningless if the read or write handling of unknown * code) but may be meaningless if the read or write handling of unknown
* chunks is not compiled in. * chunks is not compiled in.
*/ */
# if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \ # ifndef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
defined(PNG_READ_SUPPORTED) if (png_ptr->read_struct)
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
{ {
png_app_error(png_ptr, "no unknown chunk support on read"); png_app_error(png_ptr, "no unknown chunk support on read");
return; return;
} }
# endif # endif
# if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \ # ifndef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
defined(PNG_WRITE_SUPPORTED) if (!png_ptr->read_struct)
if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
{ {
png_app_error(png_ptr, "no unknown chunk support on write"); png_app_error(png_ptr, "no unknown chunk support on write");
@ -1209,9 +1207,7 @@ png_set_unknown_chunks(png_structrp png_ptr,
if (np == NULL) if (np == NULL)
{ {
png_chunk_report(png_ptr, "too many unknown chunks", png_chunk_report(png_ptr, "too many unknown chunks", PNG_CHUNK_ERROR);
PNG_CHUNK_WRITE_ERROR);
return; return;
} }
@ -1244,7 +1240,7 @@ png_set_unknown_chunks(png_structrp png_ptr,
if (np->data == NULL) if (np->data == NULL)
{ {
png_chunk_report(png_ptr, "unknown chunk: out of memory", png_chunk_report(png_ptr, "unknown chunk: out of memory",
PNG_CHUNK_WRITE_ERROR); PNG_CHUNK_ERROR);
/* But just skip storing the unknown chunk */ /* But just skip storing the unknown chunk */
continue; continue;
} }
@ -1293,24 +1289,9 @@ png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
} }
#endif /* STORE_UNKNOWN_CHUNKS */ #endif /* STORE_UNKNOWN_CHUNKS */
#ifdef PNG_MNG_FEATURES_SUPPORTED
png_uint_32 PNGAPI
png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
{
png_debug(1, "in png_permit_mng_features");
if (png_ptr == NULL)
return 0;
png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
return png_ptr->mng_features_permitted;
}
#endif
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
static unsigned int static unsigned int
add_one_chunk(png_const_structrp png_ptr, png_bytep list, unsigned int count, add_one_chunk(png_structrp png_ptr, png_bytep list, unsigned int count,
png_const_bytep add, int keep) png_const_bytep add, int keep)
{ {
unsigned int i; unsigned int i;
@ -1322,8 +1303,8 @@ add_one_chunk(png_const_structrp png_ptr, png_bytep list, unsigned int count,
{ {
if (memcmp(list, add, 4) == 0) if (memcmp(list, add, 4) == 0)
{ {
list[4] = png_check_byte(png_ptr, keep); list[4] = keep & 0x3;
png_cache_known_unknown(png_ptr, add, keep);
return count; return count;
} }
} }
@ -1333,10 +1314,10 @@ add_one_chunk(png_const_structrp png_ptr, png_bytep list, unsigned int count,
++count; ++count;
memcpy(list, add, 4); memcpy(list, add, 4);
list[4] = png_check_byte(png_ptr, keep); list[4] = png_check_byte(png_ptr, keep);
png_cache_known_unknown(png_ptr, add, keep);
} }
return count; return count;
PNG_UNUSEDRC(png_ptr)
} }
void PNGAPI void PNGAPI
@ -1349,16 +1330,27 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
/* To actually use IF_SAFE or ALWAYS on read it is necessary to have the
* read SAVE code enabled.
*/
if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST) if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
{ {
png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep"); png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
return; return;
} }
# ifndef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
/* This is only a warning; if the application handles the chunk with a
* read callback it may work fine.
*/
if (png_ptr->read_struct && keep >= PNG_HANDLE_CHUNK_IF_SAFE)
png_app_warning(png_ptr,
"png_set_keep_unknown_chunks: unsupported keep");
# endif
if (num_chunks_in <= 0) if (num_chunks_in <= 0)
{ {
png_ptr->unknown_default = keep; png_ptr->unknown_default = (unsigned)keep & 0x3;
/* '0' means just set the flags, so stop here */ /* '0' means just set the flags, so stop here */
if (num_chunks_in == 0) if (num_chunks_in == 0)
@ -1402,7 +1394,6 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
* which can be switched off. * which can be switched off.
*/ */
png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list"); png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
return; return;
} }
@ -1418,7 +1409,6 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
if (num_chunks + old_num_chunks > UINT_MAX/5) if (num_chunks + old_num_chunks > UINT_MAX/5)
{ {
png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks"); png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
return; return;
} }
@ -1511,7 +1501,7 @@ png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
} }
#endif #endif
#ifdef PNG_INFO_IMAGE_SUPPORTED #ifdef PNG_WRITE_PNG_SUPPORTED
void PNGAPI void PNGAPI
png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr, png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
png_bytepp row_pointers) png_bytepp row_pointers)
@ -1542,7 +1532,7 @@ png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
png_error(png_ptr, "invalid compression buffer size"); png_error(png_ptr, "invalid compression buffer size");
# ifdef PNG_SEQUENTIAL_READ_SUPPORTED # ifdef PNG_SEQUENTIAL_READ_SUPPORTED
if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0) if (png_ptr->read_struct)
{ {
png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */ png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
return; return;
@ -1550,7 +1540,7 @@ png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
# endif # endif
# ifdef PNG_WRITE_SUPPORTED # ifdef PNG_WRITE_SUPPORTED
if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0) if (!png_ptr->read_struct)
{ {
if (png_ptr->zowner != 0) if (png_ptr->zowner != 0)
{ {
@ -1596,7 +1586,7 @@ void PNGAPI
png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask) png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
{ {
if (png_ptr != NULL && info_ptr != NULL) if (png_ptr != NULL && info_ptr != NULL)
info_ptr->valid &= ~mask; info_ptr->valid &= PNG_BIC_MASK(mask);
} }
@ -1653,30 +1643,8 @@ png_set_benign_errors(png_structrp png_ptr, int allowed)
PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN; PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
else else
png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN | png_ptr->flags &= PNG_BIC_MASK(PNG_FLAG_BENIGN_ERRORS_WARN |
PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN); PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
} }
#endif /* BENIGN_ERRORS */ #endif /* BENIGN_ERRORS */
#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
/* Whether to report invalid palette index; added at libng-1.5.10.
* It is possible for an indexed (color-type==3) PNG file to contain
* pixels with invalid (out-of-range) indexes if the PLTE chunk has
* fewer entries than the image's bit-depth would allow. We recover
* from this gracefully by filling any incomplete palette with zeros
* (opaque black). By default, when this occurs libpng will issue
* a benign error. This API can be used to override that behavior.
*/
void PNGAPI
png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
{
png_debug(1, "in png_set_check_for_invalid_index");
if (allowed > 0)
png_ptr->num_palette_max = 0;
else
png_ptr->num_palette_max = -1;
}
#endif
#endif /* READ || WRITE */ #endif /* READ || WRITE */

View File

@ -130,19 +130,228 @@ typedef struct png_colorspace
typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp; typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
/* General flags for the 'flags' field */ /* General flags for the 'flags' field */
#define PNG_COLORSPACE_HAVE_GAMMA 0x0001 #define PNG_COLORSPACE_HAVE_GAMMA 0x0001U
#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002 #define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002U
#define PNG_COLORSPACE_HAVE_INTENT 0x0004 #define PNG_COLORSPACE_HAVE_INTENT 0x0004U
#define PNG_COLORSPACE_FROM_gAMA 0x0008 #define PNG_COLORSPACE_FROM_gAMA 0x0008U
#define PNG_COLORSPACE_FROM_cHRM 0x0010 #define PNG_COLORSPACE_FROM_cHRM 0x0010U
#define PNG_COLORSPACE_FROM_sRGB 0x0020 #define PNG_COLORSPACE_FROM_sRGB 0x0020U
#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040 #define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040U
#define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */ #define PNG_COLORSPACE_MATCHES_sRGB 0x0080U /* exact match on profile */
#define PNG_COLORSPACE_RGB_TO_GRAY_SET 0x0100 /* user specified coeffs */ #define PNG_COLORSPACE_RGB_TO_GRAY_SET 0x0100U /* user specified coeffs */
#define PNG_COLORSPACE_INVALID 0x8000 #define PNG_COLORSPACE_INVALID 0x8000U
#define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags)) #define PNG_COLORSPACE_CANCEL(flags) (0xffffU - (flags))
#endif /* COLORSPACE || GAMMA */ #endif /* COLORSPACE || GAMMA */
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
/***************************** READ and WRITE TRANSFORMS ***********************
* These structures are used in pngrtran.c, pngwtran.c and pngtrans.c to hold
* information about transforms in progress. This mechanism was introduced in
* libpng 1.7.0 to ensure reliable transform code and to fix multiple bugs in
* the pre-1.7 transform handling.
*
* Prior to 1.7.0 the internal transform routines took a png_row_infop, like the
* user transform function, but without the png_ptr because it was never used.
* In 1.7.0 a separate internal structure is used in place of this to allow both
* future development to change the structure.
*
* The values in this structure will normally be changed by transformation
* implementations.
***************************** READ and WRITE TRANSFORMS **********************/
typedef struct
{
png_structp png_ptr; /* png_struct for error handling and some
* transform parameters. May be aliased.
*/
png_const_voidp sp; /* Source; the input row. */
png_voidp dp; /* Output buffer for the transformed row,
* this may be the same as sp.
*/
/* If the row is changed the tranform routine must write the result to
* dp[] and set sp to dp, otherwise it must not write to dp and must leave
* sp unchanged. dp[] and sp[] are both 'malloc' aligned; i.e. they have
* the system alignment, so the data can be read as any valid ANSI-C
* type.
*/
png_uint_32 width; /* width of row */
# ifdef PNG_READ_GAMMA_SUPPORTED
png_fixed_point gamma; /* Current gamma of the row data */
/* When a row is being transformed this contains the current gamma of the
* data if known. During initialization the value is used to accumulate
* information for png_struct::row_gamma in the first step,
* PNG_TC_INIT_FORMAT, then used to insert the correct gamma transforms
* during PNG_TC_INIT_FINAL. The field is only used on read; write
* transforms do not modify the gamma of the data.
*/
# endif
unsigned int format; /* As pngstruct::row_format below */
unsigned int range; /* Count of range transforms */
# define PNG_TC_CHANNELS(tc) PNG_FORMAT_CHANNELS((tc).format)
unsigned int bit_depth; /* bit depth of row */
png_byte sBIT_R;
png_byte sBIT_G;
png_byte sBIT_B;
png_byte sBIT_A; /* Signnificant bits in the row channels. */
/* The above four values are initially set to the number of bits significant
* in the input PNG data, R/G/B are set to the same (gray) value for
* grayscale input. All values are set to the bit depth if there is no sBIT
* chunk, if there is no alpha channel sBIT_A is set to the bit depth.
*
* When any potentially spurious bits have been cleared PNG_INFO_sBIT will be
* set in invalid_info. From this point on the above values record the
* approximate number of bits of accuracy in the channels and the lower bits
* should be preserved; they potentially contain useful information.
*/
# define PNG_TC_PIXEL_DEPTH(tc) (PNG_TC_CHANNELS(tc) * (tc).bit_depth)
# define PNG_TC_ROWBYTES(tc) PNG_ROWBYTES(PNG_TC_PIXEL_DEPTH(tc), (tc).width)
unsigned int invalid_info; /* PNG_INFO_* for invalidated chunks */
unsigned int cost; /* Cache cost */
# define PNG_CACHE_COST_LIMIT 0x100U
/* This is a runtime structure, so size doesn't matter much, and it helps
* code reliability to use real member names here. Feel free to experiment
* with integer values rather than bitfields.
*/
unsigned int init :2; /* 0 for processing, non zero for init: */
# define PNG_TC_INIT_FORMAT 0x01U /* Initialization step 1: just set 'format',
* 'bit_depth' and 'gamma' to the output
* values iff the transform corresponds to
* a user requested change to those values.
*/
# define PNG_TC_INIT_FINAL 0x03U /* Initialization step 2; set the 'format'
* 'bit_depth' and 'gamma' to the values the
* transform will actually produce (which
* need not be the same as the above).
*/
/* During initialization 'init' must be set and sp and dp may be NULL. If
* neither flag is set sp and dp must be non-NULL.
*
* When the transform runs it must update 'format', 'bit_depth' and 'gamma'
* to the values previously reported during PNG_TC_INIT_FINAL; not doing so
* may result in an affirm from a later transform.
*/
unsigned int caching :1; /* The color values are being used to
* generate a cache of the transforms.
*/
unsigned int palette :1; /* The values come from a PNG palette and
* the palette will not be expanded. The
* CACHE flag must be set too. A
* transform which causes the palette to
* be expanded must clear this flag.
*/
#if 0 /* NYI */
unsigned int interchannel:1; /* Set by a transform that combines two or
* more channels together; for example
* alpha composition or RGB to gray.
*/
#endif /* NYI */
unsigned int channel_add :1; /* A channel (alpha/filler) was added */
unsigned int strip_alpha :1; /* Set if the alpha channel will be
* stripped on read, this also prevents
* the tRNS chunk being expanded. Only
* some transforms check this, depending
* on the handling order and checks in
* pre-1.7 versions.
*/
unsigned int expand_tRNS :1; /* Set if the tRNS chunk should be
* expanded (ignored if read_strip_alpha
* is set). If this is *not* set
* transforms which do not use alpha/tRNS
* but would invalidate it (such as
* simple gamma correction) will simply
* mark the tRNS info as invalid.
*/
unsigned int transparent_alpha :1; /* Indicates that the alpha channel
* consists entirely of opaque (1.0 alpha)
* or completely transparent (0.0 alpha)
* pixels. Set when tRNS is expanded to
* alpha.
*/
unsigned int optimized_alpha :1; /* Meaningful only when bit_depth is
* 16 and gamma is 1 or unknown (0).
* Indicates that pixels which are opaque
* (alpha 1.0) have not been expanded to
* 16-bit linear; instead these pixels
* are encoded in the final format in
* png_struct::row_bit_depth and
* png_struct::row_gamma. This will
* invariably match the file format.
*/
} png_transform_control, *png_transform_controlp;
typedef const png_transform_control *png_const_transform_controlp;
typedef const png_row_info *png_const_row_infop;
typedef struct png_transform *png_transformp; /* Forward declaration */
typedef void (*png_transform_free_fn)(/* Function to free a transform */
png_const_structrp png_ptr,
png_transformp transform); /* pointer to this transform */
/* This function need not exist in a transform, it must free all the data
* allocated within the transform but not the transform itself. It is called
* from png_transform_free.
*/
typedef void (*png_transform_fn)(/* Function to implement a transform */
png_transformp *transform, /* pointer to this transform */
png_transform_controlp control); /* row information */
/* The transform function has two modes of operation:
*
* 1) Initialization. The list of transforms is processed from the start to
* the end and each function is called with one of hte PNG_TC_INIT_ flags
* set in control->flags, control->dp and control->sp may be NULL.
*
* For read the control structure contains the input row format and bit
* depth, the transform function changes this to represent what the
* transform will produce when it runs.
*
* For write the control structure contains the *required* output format
* and bit depth. The transform function changes this to the values that
* it needs to produce the required values.
*
* In both cases the transform function may update the 'fn' function to a
* new function to perform the desired transform; this allows considerable
* optimization on multi-row images.
*
* In both cases the caller considers the pixel bit depth changes and
* records the maximum required so that it can allocate a suitably sized
* buffer.
*
* 2) Execution.
*
* In the read case the transforms are processed in the stored order and
* must transform the row data appropriately *and* update the bit depth
* and format as before.
*
* In the write case the transforms are called in the reverse order and
* the input bit depth and format should match the required values.
*
* It is valid during initialization for the transform function to push
* another transform into the list in either the read or the write case if
* the transform cannot handle (read) or produce (write) the required format. * The transform pushes another transform into the list ahead of itself (at
* *transform) and runs that initialization; when control is returned to the
* caller the caller will re-run the transform initialization.
*
* It is also valid (during initialization) to push new transforms onto the
* list, just so long as the order of the transform is greater than the
* current transform (so that the caller will still call the new transform
* initialization.)
*
* In the write case the user transform callback might still end up producing
* an unexpected format, but at present this is unavoidable; the libpng API
* is extremely inconsistent in how a user transform reports the changes it
* made.
*
* TODO: fix this, probably with an API change in 1.7.0
*/
typedef struct png_transform /* Linked list of transform functions */
{
png_transformp next; /* Next transform in the list */
png_transform_fn fn; /* Function to implement the transform */
png_transform_free_fn free; /* Free allocated data, normally NULL */
unsigned int order; /* Order of the transform in the list. */
unsigned int size; /* Size of this structure (max 65535) */
png_uint_32 args; /* Optional transform arguments. */
} png_transform;
#endif /* TRANSFORM_MECH */
struct png_struct_def struct png_struct_def
{ {
/* Rearranged in libpng 1.7 to attempt to lessen padding; in general /* Rearranged in libpng 1.7 to attempt to lessen padding; in general
@ -165,50 +374,223 @@ struct png_struct_def
* and faster. * and faster.
*/ */
png_colorp palette; /* palette from the input file */ png_colorp palette; /* palette from the input file */
#ifdef PNG_READ_tRNS_SUPPORTED
png_bytep trans_alpha; /* alpha values for paletted files */ png_bytep trans_alpha; /* alpha values for paletted files */
size_t rowbytes; /* size of row in bytes */
size_t info_rowbytes; /* cache of updated row bytes */
png_uint_32 width; /* width of image in pixels */
png_uint_32 height; /* height of image in pixels */
png_uint_32 num_rows; /* number of rows in current pass */
/* TODO: usr_width is used in write, iwidth is used in read, the two fields
* could be made one.
*/
png_uint_32 usr_width; /* width of row at start of write */
png_uint_32 iwidth; /* width of current interlaced row in pixels */
png_uint_32 row_number; /* current row in interlace pass */
png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */
png_uint_32 crc; /* current chunk CRC value */
png_uint_32 mode; /* tells us where we are in the PNG file */
png_uint_32 flags; /* flags indicating various things to libpng */
png_uint_32 transformations;/* which transformations to perform */
png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */
png_uint_32 free_me; /* items libpng is responsible for freeing */
unsigned int maximum_pixel_depth; /* pixel depth used for the row buffers */
#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
int num_palette_max; /* maximum palette index found in IDAT */
#endif #endif
png_uint_16 num_palette; /* number of color entries in palette */ png_uint_32 width; /* width of image in pixels */
png_uint_16 num_trans; /* number of transparency values */ png_uint_32 height; /* height of image in pixels */
png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */
png_uint_32 chunk_length; /* Length (possibly remaining) in said chunk. */
png_uint_32 crc; /* current chunk CRC value */
png_uint_32 free_me; /* items libpng is responsible for freeing */
unsigned int flags; /* flags (should be bit fields) */
unsigned int mode :6; /* where we are in the PNG file */
unsigned int read_struct :1; /* this is a read (not write) struct */
unsigned int num_palette :9; /* number of color entries in palette */
#ifdef PNG_READ_tRNS_SUPPORTED
unsigned int num_trans :9; /* number of transparency values */
unsigned int transparent_palette :1; /* if they are all 0 or 255 */
#endif /* READ_tRNS */
#ifdef PNG_GET_PALETTE_MAX_SUPPORTED
unsigned int palette_index_max :9; /* maximum palette index found in IDAT */
#endif /* GET_PALETTE_MAX */
#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
unsigned int palette_index_check_disabled :1; /* defaults to 0, 'enabled' */
unsigned int palette_index_check_issued :1; /* error message output */
#endif /* CHECK_FOR_INVALID_INDEX */
#ifdef PNG_READ_tRNS_SUPPORTED
png_color_16 trans_color; /* transparent color for non-paletted files */
#endif /* READ_tRNS */
#ifdef PNG_READ_sBIT_SUPPORTED
png_color_8 sig_bit; /* significant bits in each channel */
#endif /* READ_sBIT */
/* Single byte values, typically used either to save space or to hold 1-byte /* Single byte values, typically used either to save space or to hold 1-byte
* values from the PNG chunk specifications. * values from the PNG chunk specifications.
*/ */
png_byte compression_type; /* file compression type (always 0) */ png_byte compression_type; /* file compression type (always 0) */
png_byte filter; /* file filter type (always 0) */ png_byte filter_method; /* file filter type (only non-0 with MNG) */
png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */ png_byte interlaced; /* PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
png_byte pass; /* current interlace pass (0 - 6) */
png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */
png_byte color_type; /* color type of file */ png_byte color_type; /* color type of file */
png_byte bit_depth; /* bit depth of file */ png_byte bit_depth; /* bit depth of file */
png_byte pixel_depth; /* number of bits per pixel */ png_byte sig_bytes; /* magic bytes read/written at start of file */
png_byte channels; /* number of channels in file */
png_byte sig_bytes; /* magic bytes read/written from start of file */ /* Options */
png_byte transformed_pixel_depth; #ifdef PNG_SET_OPTION_SUPPORTED
/* pixel depth after read/write transforms */ png_byte options; /* On/off state (up to 4 options) */
#endif
#ifdef PNG_READ_SUPPORTED
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
/* The png_struct colorspace structure is only required on read - on write it
* is in (just) the info_struct.
*/
png_colorspace colorspace;
#endif
#endif /* READ */
/* Transform handling */
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
png_transformp transform_list; /* List of transformation to perform. */
#endif
/* ROW BUFFERS and CONTROL
*
* Members used for image row compression (write) or decompression (read).
* filter byte (which is in next_filter.) All fields are only used during
* IDAT processing and start of 0.
*/
png_bytep row_buffer; /* primary row buffer */
#if defined(PNG_WRITE_FILTER_SUPPORTED) || defined(PNG_READ_SUPPORTED)
png_bytep alt_buffer; /* if two row buffers needed */
#endif
#ifdef PNG_WRITE_FILTER_SUPPORTED
png_bytep write_row[2]; /* Two rows to test filers */
#endif
png_alloc_size_t row_allocated_bytes; /* Total amount allocated */
png_uint_32 row_number; /* current row in pass */
#ifdef PNG_READ_GAMMA_SUPPORTED
png_fixed_point row_gamma; /* Gamma of final output */
#if 0 /* NYI */
unsigned int gamma_accuracy;
/* LINEAR gamma cache table size (in bits) times 100; for non-linear
* tables the value used is gamma_accuracy/gamma where 'gamma' is the
* encoding value of the data (typically less than 1).
*
* default: PNG_DEFAULT_GAMMA_ACCURACY (665)
*/
#endif /* NYI */
png_uint_16 gamma_threshold;
/* Gamma threshold value as a fixed-point value in the range 0..1; the
* threshold at or below which gamma correction is skipped. '0' forces
* gamma correction even when there is none because the input and output
* gammas are equal.
*
* default: PNG_GAMMA_THRESHOLD_FIXED (153)
*/
#endif /* READ_GAMMA */
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
unsigned int invalid_info; /* PNG_INFO_* for invalidated chunks */
#endif /* READ_TRANSFORMS */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
unsigned int read_started :1; /* at least one call to png_read_row */
#endif
unsigned int do_interlace :1; /* libpng handles the interlace */
unsigned int pass :3; /* current (interlace) pass (0 - 6) */
/* The next two fields are just used by the IDAT process functions to store
* the state of IDAT processing; they should not be altered or used by other
* functions.
*/
unsigned int prev_in_alt :1; /* previous row is stored in alt_buffer */
unsigned int row_state :2; /* state of row parsing (internal) */
# define PNG_RF_BITS 9 /* Number of bits required for the row format (below) */
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
/* The following fields describe the format of the user row; the output on
* read or the input on write, and give the maximum pixel depth, which
* controls the row buffer allocation size (row_allocated_bytes) above.
*/
unsigned int row_range :3; /* range error count */
unsigned int row_bit_depth :6; /* bits per channel (up to 32) */
unsigned int row_format:PNG_RF_BITS;/* format of output(R)/input(W) row: */
/* PNG_FORMAT_FLAG_ALPHA 0x01U format with an alpha channel
* PNG_FORMAT_FLAG_COLOR 0x02U color format: otherwise grayscale
* PNG_FORMAT_FLAG_LINEAR 0x04U NOT used (informational)
* PNG_FORMAT_FLAG_COLORMAP 0x08U image data is color-mapped
* PNG_FORMAT_FLAG_BGR 0x10U BGR colors, else order is RGB
* PNG_FORMAT_FLAG_AFIRST 0x20U alpha channel comes first *
* PNG_FORAMT_FLAG_AFILLER 0x40U The 'alpha' channel is a filler:
* PNG_FORMAT_FLAG_ALPHA is set however the value in the alpha channel
* is not an alpha value and (therefore) cannot be used for alpha
* computations, it is just a filler value. PNG_COLOR_TYPE_FROM_FORMAT
* will return a color type *without* PNG_COLOR_MASK_ALPHA, however
* PNG_FORMAT_CHANNELS will return the correct number, including the
* filler channel.
* PNG_FORMAT_FLAG_SWAPPED 0x80U bytes or bits swapped:
* When the bit depth is 16 this means that the bytes within the
* components have been swapped, when the bit depth is less than 8
* it means the pixels within the bytes have been swapped. It should
* not be set for 8-bit compononents (it is meaningless).
* PNG_FORMAT_FLAG_RANGE 0x100U component range not 0..bit-depth:
* Low-bit-depth grayscale components have been unpacked into bytes
* without scaling, or RGB[A] pixels have been shifted back to the
* significant-bit range from the sBIT chunk or channels (currently
* alpha or gray) have been inverted.
* PNG_FORMAT_FLAG_INVALID NOT STORED HERE
*/
unsigned int row_max_pixel :8; /* maximum pixel depth used */
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
unsigned int info_format:PNG_RF_BITS;
/* This field is used to validate the png_info used to write the
* IHDR. This is a new check in 1.7.0; previously it was possible to pass
* a png_info from a png_read with the read tranform information in the
* format having manually removed the required transforms from the rows
* passed to png_write_row.
*/
#endif /* WRITE_TRANSFORMS */
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
unsigned int write_invert_alpha :1;
/* This indicates the png_set_invert_alpha was called, it is used by the
* write code to implement the transform without needing to run the whole
* transform mechanism on the PNG palette data.
*/
#endif /* WRITE_INVERT_ALPHA */
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
unsigned int rgb_to_gray_status :1;
/* If set an RGB pixel was encountered by the RGB to gray transform
* wherein !(r==g==b).
*/
#endif /* RGB_TO_GRAY */
#endif /* TRANFORM_MECH */
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_FILTER_SUPPORTED)
png_byte next_filter; /* Filter byte for upcoming row (read or
* filters+masks to try (write, if WRITE_FILTER is
* supported).
*/
#endif
#ifdef PNG_READ_SUPPORTED
/* These, and IDAT_read_size below, control how much input and output (at
* most) is available to zlib.
*/
png_alloc_size_t read_buffer_size; /* current size of the buffer */
#endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
uInt IDAT_read_size; /* limit on read buffer size for IDAT */
#endif
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
int zlib_text_level; /* holds zlib compression level */
int zlib_text_method; /* holds zlib compression method */
int zlib_text_window_bits; /* holds zlib compression window bits */
int zlib_text_mem_level; /* holds zlib compression memory level */
int zlib_text_strategy; /* holds zlib compression strategy */
#endif
#ifdef PNG_WRITE_SUPPORTED
int zlib_level; /* holds zlib compression level */
int zlib_method; /* holds zlib compression method */
int zlib_window_bits; /* holds zlib compression window bits */
int zlib_mem_level; /* holds zlib compression memory level */
int zlib_strategy; /* holds zlib compression strategy */
int zlib_set_level; /* Actual values set into the zstream on write */
int zlib_set_method;
int zlib_set_window_bits;
int zlib_set_mem_level;
int zlib_set_strategy;
png_compression_bufferp zbuffer_list; /* Created on demand during write */
uInt zbuffer_size; /* size of the actual zlib buffer */
#endif
/* ERROR HANDLING */ /* ERROR HANDLING */
#ifdef PNG_SETJMP_SUPPORTED #ifdef PNG_SETJMP_SUPPORTED
@ -233,26 +615,30 @@ struct png_struct_def
/* IO and BASIC READ/WRITE SUPPORT */ /* IO and BASIC READ/WRITE SUPPORT */
png_voidp io_ptr; /* user supplied data for IO callbacks */ png_voidp io_ptr; /* user supplied data for IO callbacks */
png_rw_ptr rw_data_fn; /* read/write some bytes (must succeed) */
#ifdef PNG_READ_SUPPORTED #ifdef PNG_READ_SUPPORTED
png_rw_ptr read_data_fn; /* read some bytes (must succeed) */
png_read_status_ptr read_row_fn; /* called after each row is decoded */ png_read_status_ptr read_row_fn; /* called after each row is decoded */
png_bytep read_buffer; /* buffer for reading chunk data */ png_bytep read_buffer; /* buffer for reading chunk data */
/* During read the following array is set up to point to the appropriate /* During read the following array is set up to point to the appropriate
* un-filter function, this allows per-image and per-processor optimization. * un-filter function, this allows per-image and per-processor optimization.
*/ */
void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_alloc_size_t row_bytes,
png_bytep row, png_const_bytep prev_row); unsigned int bpp, png_bytep row, png_const_bytep prev_row);
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
/* The png_struct colorspace structure is only required on read - on write it
* is in (just) the info_struct.
*/
png_colorspace colorspace;
#endif
#endif /* READ */ #endif /* READ */
#ifdef PNG_WRITE_SUPPORTED
png_write_status_ptr write_row_fn; /* called after each row is encoded */
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_flush_ptr output_flush_fn; /* Function for flushing output */
png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */
png_uint_32 flush_rows; /* number of rows written since last flush */
#endif
#endif /* WRITE */
#ifdef PNG_SET_USER_LIMITS_SUPPORTED #ifdef PNG_SET_USER_LIMITS_SUPPORTED
png_uint_32 user_width_max; /* Maximum width on read */ png_uint_32 user_width_max; /* Maximum width on read */
png_uint_32 user_height_max; /* Maximum height on read */ png_uint_32 user_height_max; /* Maximum height on read */
@ -282,72 +668,25 @@ struct png_struct_def
png_bytep save_buffer_ptr; /* current location in save_buffer */ png_bytep save_buffer_ptr; /* current location in save_buffer */
png_bytep save_buffer; /* buffer for previously read data */ png_bytep save_buffer; /* buffer for previously read data */
png_bytep current_buffer_ptr; /* current location in current_buffer */ png_bytep current_buffer_ptr; /* current location in current_buffer */
png_bytep current_buffer; /* buffer for recently used data */
size_t save_buffer_size; /* amount of data now in save_buffer */ size_t save_buffer_size; /* amount of data now in save_buffer */
size_t save_buffer_max; /* total size of save_buffer */ size_t save_buffer_max; /* total size of save_buffer */
size_t buffer_size; /* total amount of available input data */
size_t current_buffer_size; /* amount of data now in current_buffer */ size_t current_buffer_size; /* amount of data now in current_buffer */
size_t buffer_size; /* total amount of available input data */
png_uint_32 push_length; /* size of current input chunk */ unsigned int process_mode :8;
png_uint_32 skip_length; /* bytes to skip in input data */ /* This is one or two four bit codes describing the current state of the
* 'push' reader. Normally the low four bits are a state code, however in
int process_mode; /* what push library is currently doing */ * some cases this may be pushed to the top four bits and replaced by a
int cur_palette; /* current push library palette index */ * different temporary state code. The value is, in effect, a two entry
#endif * stack.
*/
#ifdef PNG_WRITE_SUPPORTED #endif /* PROGRESSIVE_READ */
png_rw_ptr write_data_fn;/* write some bytes (must succeed) */
png_write_status_ptr write_row_fn; /* called after each row is encoded */
#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_flush_ptr output_flush_fn; /* Function for flushing output */
png_uint_32 flush_dist; /* how many rows apart to flush, 0 - no flush */
png_uint_32 flush_rows; /* number of rows written since last flush */
#endif
#ifdef PNG_WRITE_SUPPORTED
png_byte usr_bit_depth; /* bit depth of users row */
png_byte usr_channels; /* channels at start of write */
#endif
#ifdef PNG_IO_STATE_SUPPORTED #ifdef PNG_IO_STATE_SUPPORTED
png_uint_32 io_state; /* tells the app read/write progress */ png_uint_32 io_state; /* tells the app read/write progress */
#endif #endif
/* ROW BUFFERS
*
* Members that hold pointers to the decompressed image rows.
*/
png_bytep row_buf; /* buffer to save current (unfiltered) row.
* While reading, this is a pointer into
* big_row_buf; while writing it is separately
* allocated.
*/
#if defined(PNG_WRITE_FILTER_SUPPORTED) || defined(PNG_READ_SUPPORTED)
png_bytep prev_row; /* buffer to save previous (unfiltered) row.
* While reading this is a pointer into
* big_prev_row; while writing it is separately
* allocated if needed.
*/
#endif
#ifdef PNG_READ_SUPPORTED
/* The row_buf and prev_row pointers are misaligned so that the start of the
* row - after the filter byte - is aligned, the 'big_' pointers record the
* original allocated pointer. These are only used while reading.
*/
png_bytep big_row_buf;
png_bytep big_prev_row;
size_t big_row_buf_size; /* Actual size of both */
#endif
#ifdef PNG_WRITE_FILTER_SUPPORTED
png_bytep try_row; /* buffer to save trial row when filtering */
png_bytep tst_row; /* buffer to save best trial row when filtering */
#endif
/* UNKNOWN CHUNK HANDLING */ /* UNKNOWN CHUNK HANDLING */
/* TODO: this is excessively complicated, there are multiple ways of doing /* TODO: this is excessively complicated, there are multiple ways of doing
* the same thing. It should be cleaned up, possibly by finding out which * the same thing. It should be cleaned up, possibly by finding out which
@ -366,183 +705,45 @@ struct png_struct_def
/* This is called back from the unknown chunk handling */ /* This is called back from the unknown chunk handling */
png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
#endif #endif
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
/* Temporary storage for unknown chunk that the library doesn't recognize, #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
* used while reading the chunk. png_uint_32 known_unknown; /* Bit mask of known chunks to be treated as
* unknown in the read code.
*/ */
png_unknown_chunk unknown_chunk; #ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
#endif png_uint_32 save_unknown; /* Whether to save or skip these chunks:
* 'save' is 'known & save', 'skip' is
* 'known & ~save'.
*/
# define png_IDATs_skipped(pp) (((pp)->known_unknown & ~(pp)->save_unknown)&1U)
#else
# define png_IDATs_skipped(pp) ((pp)->known_unknown & 1U)
#endif /* !SAVE_UNKNOWN_CHUNKS */
#endif /* HANDLE_AS_UNKNOWN */
#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name
* followed by a PNG_HANDLE_* byte */ * followed by a PNG_HANDLE_* byte */
int unknown_default; /* As PNG_HANDLE_* */ unsigned int unknown_default :2; /* As PNG_HANDLE_* */
unsigned int num_chunk_list; /* Number of entries in the list */ unsigned int num_chunk_list; /* Number of entries in the list */
#endif #endif
/* USER TRANSFORM SUPPORT */
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
png_user_transform_ptr read_user_transform_fn; /* user read transform */
#endif
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
png_user_transform_ptr write_user_transform_fn; /* user write transform */
#endif
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
png_voidp user_transform_ptr; /* user supplied data for the above */
png_byte user_transform_depth; /* bit depth of user transformed pixels */
png_byte user_transform_channels; /* channels in user transformed pixels */
#endif
/* READ TRANSFORM SUPPORT
*
* Quite a lot of things can be done to the original image data on read, and
* most of these are configurable. The data required by the configurable
* read transforms should be stored here. The png_color_16 and png_color_8
* structures have low alignment requirements and odd sizes, so may cause
* misalignment when present. Member alignment is as follows:
*
* png_color_16 png_uint_16
* png_color_8 png_byte
*/
/* GAMMA/BACKGROUND/ALPHA-MODE/RGB-TO-GRAY/tRNS/sBIT
*
* These things are all interrelated because they need some or all of the
* gamma tables. Some attempt has been made below to order these members by
* size, so that as little padding as possible is required.
*/
#ifdef PNG_READ_GAMMA_SUPPORTED
png_bytep gamma_table; /* gamma table for 8-bit depth files */
png_uint_16p gamma_16_table; /* gamma table for 16-bit depth files */
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
defined(PNG_READ_ALPHA_MODE_SUPPORTED) ||\
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
png_bytep gamma_from_1; /* converts from 1.0 to screen */
png_uint_16p gamma_to_1; /* converts from file to 1.0 */
png_uint_16p gamma_16_from_1; /* converts from 1.0 to screen */
png_uint_16p gamma_16_to_1; /* converts from file to 1.0 */
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
#endif /* READ_GAMMA */
/* Integer values */
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
defined(PNG_READ_ALPHA_MODE_SUPPORTED)
png_fixed_point background_gamma;
#endif
#ifdef PNG_READ_GAMMA_SUPPORTED
png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */
int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */
#endif
/* png_color_16 */
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
defined(PNG_READ_ALPHA_MODE_SUPPORTED)
png_color_16 background; /* background color in screen gamma space */
png_color_16 background_1; /* background normalized to gamma 1.0 */
#endif
#if defined(PNG_READ_tRNS_SUPPORTED) || \
defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_EXPAND_SUPPORTED)
png_color_16 trans_color; /* transparent color for non-paletted files */
#endif
/* png_uint_16 */
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
png_uint_16 rgb_to_gray_red_coeff;
png_uint_16 rgb_to_gray_green_coeff;
/* The blue coefficient is calculated from the above */
#endif
/* png_color_8 */
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_sBIT_SUPPORTED)
png_color_8 sig_bit; /* significant bits in each available channel */
#endif
/* png_byte */
#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
defined(PNG_READ_ALPHA_MODE_SUPPORTED)
png_byte background_gamma_type;
#endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
png_byte rgb_to_gray_status;
#endif
/* SHIFT - both READ_SHIFT and WRITE_SHIFT */
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
png_color_8 shift; /* shift for significant bit tranformation */
#endif
/* FILLER SUPPORT (pixel expansion or read, contraction on write) */
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
png_uint_16 filler; /* filler bytes for pixel expansion */
#endif
/* QUANTIZE (convert to color-mapped) */
#ifdef PNG_READ_QUANTIZE_SUPPORTED
png_bytep palette_lookup; /* lookup table for quantizing */
png_bytep quantize_index; /* index translation for palette files */
png_bytep quantize_sort; /* working sort array */
png_bytep index_to_palette; /* where the original index currently is in the
* palette
*/
png_bytep palette_to_index; /* which original index points to this palette
* color
*/
#endif
/* MNG SUPPORT */
#ifdef PNG_MNG_FEATURES_SUPPORTED
png_uint_32 mng_features_permitted;
png_byte filter_type;
#endif
/* Options */
#ifdef PNG_SET_OPTION_SUPPORTED
png_byte options; /* On/off state (up to 4 options) */
#endif
/* COMPRESSION AND DECOMPRESSION SUPPORT. /* COMPRESSION AND DECOMPRESSION SUPPORT.
* *
* zlib expects a 'zstream' as the fundamental control structure, it allows * zlib expects a 'zstream' as the fundamental control structure, it allows
* all the parameters to be passed as one pointer. * all the parameters to be passed as one pointer.
*/ */
png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */
z_stream zstream; /* decompression structure */ z_stream zstream; /* decompression structure */
unsigned int zstream_ended:1; /* no more zlib output available */
unsigned int zstream_error:1; /* zlib error message has been output */
unsigned int zstream_eod :1; /* all the required uncompressed data has been
* received; set by the zstream using code for
* its own purposes. */
#ifdef PNG_READ_SUPPORTED /* MNG SUPPORT */
/* These, and IDAT_read_size below, control how much input and output (at #ifdef PNG_MNG_FEATURES_SUPPORTED
* most) is available to zlib. unsigned int mng_features_permitted :3;
*/
png_uint_32 idat_size; /* current IDAT size for read */
png_alloc_size_t read_buffer_size; /* current size of the buffer */
#endif
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
int zlib_text_level; /* holds zlib compression level */
int zlib_text_method; /* holds zlib compression method */
int zlib_text_window_bits; /* holds zlib compression window bits */
int zlib_text_mem_level; /* holds zlib compression memory level */
int zlib_text_strategy; /* holds zlib compression strategy */
#endif
#ifdef PNG_WRITE_SUPPORTED
int zlib_level; /* holds zlib compression level */
int zlib_method; /* holds zlib compression method */
int zlib_window_bits; /* holds zlib compression window bits */
int zlib_mem_level; /* holds zlib compression memory level */
int zlib_strategy; /* holds zlib compression strategy */
int zlib_set_level; /* Actual values set into the zstream on write */
int zlib_set_method;
int zlib_set_window_bits;
int zlib_set_mem_level;
int zlib_set_strategy;
png_compression_bufferp zbuffer_list; /* Created on demand during write */
uInt zbuffer_size; /* size of the actual zlib buffer */
#endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
uInt IDAT_read_size; /* limit on read buffer size for IDAT */
#endif #endif
}; };
#endif /* PNGSTRUCT_H */ #endif /* PNGSTRUCT_H */

View File

@ -101,6 +101,10 @@ typedef FILE * png_FILE_p;
# define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */ # define SINGLE_ROWBUF_ALLOC /* Makes buffer overruns easier to nail */
#endif #endif
#ifndef PNG_UNUSED
# define PNG_UNUSED(param) (void)param;
#endif
/* Turn on CPU timing /* Turn on CPU timing
#define PNGTEST_TIMING #define PNGTEST_TIMING
*/ */
@ -185,16 +189,14 @@ write_row_callback(png_structp png_ptr, png_uint_32 row_number, int pass)
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
/* Example of using user transform callback (we don't transform anything, /* Example of using a user transform callback (doesn't do anything at present).
* but merely examine the row filters. We set this to 256 rather than
* 5 in case illegal filter values are present.)
*/ */
static png_uint_32 filters_used[256];
static void PNGCBAPI static void PNGCBAPI
count_filters(png_structp png_ptr, png_row_infop row_info, png_bytep data) read_user_callback(png_structp png_ptr, png_row_infop row_info, png_bytep data)
{ {
if (png_ptr != NULL && row_info != NULL) PNG_UNUSED(png_ptr)
++filters_used[*(data - 1)]; PNG_UNUSED(row_info)
PNG_UNUSED(data)
} }
#endif #endif
@ -805,6 +807,8 @@ pngtest_check_text_support(png_const_structp png_ptr, png_textp text_ptr,
case PNG_TEXT_COMPRESSION_zTXt: case PNG_TEXT_COMPRESSION_zTXt:
# ifndef PNG_WRITE_zTXt_SUPPORTED # ifndef PNG_WRITE_zTXt_SUPPORTED
++unsupported_chunks; ++unsupported_chunks;
/* In libpng 1.7 this now does an app-error, so stop it: */
text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
# endif # endif
break; break;
@ -812,6 +816,7 @@ pngtest_check_text_support(png_const_structp png_ptr, png_textp text_ptr,
case PNG_ITXT_COMPRESSION_zTXt: case PNG_ITXT_COMPRESSION_zTXt:
# ifndef PNG_WRITE_iTXt_SUPPORTED # ifndef PNG_WRITE_iTXt_SUPPORTED
++unsupported_chunks; ++unsupported_chunks;
text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE;
# endif # endif
break; break;
@ -1000,14 +1005,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
} }
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
{ png_set_read_user_transform_fn(read_ptr, read_user_callback);
int i;
for (i = 0; i<256; i++)
filters_used[i] = 0;
png_set_read_user_transform_fn(read_ptr, count_filters);
}
#endif #endif
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
zero_samples = 0; zero_samples = 0;
@ -1054,7 +1052,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
{ {
png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth,
color_type, interlace_type, compression_type, filter_type); color_type, interlace_type, compression_type, filter_type);
#ifndef PNG_READ_INTERLACING_SUPPORTED
/* num_pass will not be set below, set it here if the image is /* num_pass will not be set below, set it here if the image is
* interlaced: what happens is that write interlacing is *not* turned * interlaced: what happens is that write interlacing is *not* turned
* on an the partial interlaced rows are written directly. * on an the partial interlaced rows are written directly.
@ -1073,7 +1070,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_error(read_ptr, "invalid interlace type"); png_error(read_ptr, "invalid interlace type");
/*NOT REACHED*/ /*NOT REACHED*/
} }
#endif
} }
} }
#ifdef PNG_FIXED_POINT_SUPPORTED #ifdef PNG_FIXED_POINT_SUPPORTED
@ -1366,7 +1362,8 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
#endif /* SINGLE_ROWBUF_ALLOC */ #endif /* SINGLE_ROWBUF_ALLOC */
pngtest_debug("Writing row data"); pngtest_debug("Writing row data");
#ifdef PNG_READ_INTERLACING_SUPPORTED #if defined(PNG_READ_DEINTERLACE_SUPPORTED) &&\
defined(PNG_WRITE_INTERLACING_SUPPORTED)
num_pass = png_set_interlace_handling(read_ptr); num_pass = png_set_interlace_handling(read_ptr);
if (png_set_interlace_handling(write_ptr) != num_pass) if (png_set_interlace_handling(write_ptr) != num_pass)
png_error(write_ptr, "png_set_interlace_handling: inconsistent num_pass"); png_error(write_ptr, "png_set_interlace_handling: inconsistent num_pass");
@ -1570,7 +1567,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
} }
# ifdef PNG_WRITE_SUPPORTED # ifdef PNG_WRITE_SUPPORTED
/* If there we no write support nothing was written! */ /* If there is no write support nothing was written! */
else if (unsupported_chunks > 0) else if (unsupported_chunks > 0)
{ {
fprintf(STDERR, "\n %s: unsupported chunks (%d)%s", fprintf(STDERR, "\n %s: unsupported chunks (%d)%s",
@ -1817,21 +1814,12 @@ main(int argc, char *argv[])
kerror = test_one_file(argv[i], outname); kerror = test_one_file(argv[i], outname);
if (kerror == 0) if (kerror == 0)
{ {
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
int k;
#endif
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
fprintf(STDERR, "\n PASS (%lu zero samples)\n", fprintf(STDERR, "\n PASS (%lu zero samples)\n",
(unsigned long)zero_samples); (unsigned long)zero_samples);
#else #else
fprintf(STDERR, " PASS\n"); fprintf(STDERR, " PASS\n");
#endif #endif
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
for (k = 0; k<256; k++)
if (filters_used[k] != 0)
fprintf(STDERR, " Filter %d was used %lu times\n",
k, (unsigned long)filters_used[k]);
#endif
#ifdef PNG_TIME_RFC1123_SUPPORTED #ifdef PNG_TIME_RFC1123_SUPPORTED
if (tIME_chunk_present != 0) if (tIME_chunk_present != 0)
fprintf(STDERR, " tIME = %s\n", tIME_string); fprintf(STDERR, " tIME = %s\n", tIME_string);
@ -1908,21 +1896,12 @@ main(int argc, char *argv[])
{ {
if (verbose == 1 || i == 2) if (verbose == 1 || i == 2)
{ {
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
int k;
#endif
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
fprintf(STDERR, "\n PASS (%lu zero samples)\n", fprintf(STDERR, "\n PASS (%lu zero samples)\n",
(unsigned long)zero_samples); (unsigned long)zero_samples);
#else #else
fprintf(STDERR, " PASS\n"); fprintf(STDERR, " PASS\n");
#endif #endif
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
for (k = 0; k<256; k++)
if (filters_used[k] != 0)
fprintf(STDERR, " Filter %d was used %lu times\n",
k, (unsigned long)filters_used[k]);
#endif
#ifdef PNG_TIME_RFC1123_SUPPORTED #ifdef PNG_TIME_RFC1123_SUPPORTED
if (tIME_chunk_present != 0) if (tIME_chunk_present != 0)
fprintf(STDERR, " tIME = %s\n", tIME_string); fprintf(STDERR, " tIME = %s\n", tIME_string);

4256
pngtrans.c

File diff suppressed because it is too large Load Diff

View File

@ -34,12 +34,11 @@ void /* PRIVATE */
png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length)
{ {
/* NOTE: write_data_fn must not change the buffer! */ /* NOTE: write_data_fn must not change the buffer! */
if (png_ptr->write_data_fn != NULL ) if (png_ptr->rw_data_fn != NULL )
(*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data), png_ptr->rw_data_fn(png_ptr, png_constcast(png_bytep, data), length);
length);
else else
png_error(png_ptr, "Call to NULL write function"); png_app_error(png_ptr, "No write function");
} }
#ifdef PNG_STDIO_SUPPORTED #ifdef PNG_STDIO_SUPPORTED
@ -56,7 +55,7 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); check = fwrite(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));
if (check != length) if (check != length)
png_error(png_ptr, "Write Error"); png_error(png_ptr, "Write Error");
@ -72,20 +71,17 @@ void /* PRIVATE */
png_flush(png_structrp png_ptr) png_flush(png_structrp png_ptr)
{ {
if (png_ptr->output_flush_fn != NULL) if (png_ptr->output_flush_fn != NULL)
(*(png_ptr->output_flush_fn))(png_ptr); png_ptr->output_flush_fn(png_ptr);
} }
# ifdef PNG_STDIO_SUPPORTED # ifdef PNG_STDIO_SUPPORTED
void PNGCBAPI void PNGCBAPI
png_default_flush(png_structp png_ptr) png_default_flush(png_structp png_ptr)
{ {
png_FILE_p io_ptr;
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr)); fflush(png_voidcast(png_FILE_p, (png_ptr->io_ptr)));
fflush(io_ptr);
} }
# endif # endif
#endif #endif
@ -126,44 +122,26 @@ png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr,
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
if (png_ptr->read_struct)
{
png_app_error(png_ptr, "cannot set a write function on a read struct");
return;
}
if (write_data_fn == NULL)
{
png_app_error(png_ptr,
"API change: png_set_write_fn requires a function");
return;
}
png_ptr->io_ptr = io_ptr; png_ptr->io_ptr = io_ptr;
png_ptr->rw_data_fn = write_data_fn;
#ifdef PNG_STDIO_SUPPORTED # ifdef PNG_WRITE_FLUSH_SUPPORTED
if (write_data_fn != NULL)
png_ptr->write_data_fn = write_data_fn;
else
png_ptr->write_data_fn = png_default_write_data;
#else
png_ptr->write_data_fn = write_data_fn;
#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
# ifdef PNG_STDIO_SUPPORTED
if (output_flush_fn != NULL) if (output_flush_fn != NULL)
png_ptr->output_flush_fn = output_flush_fn; png_ptr->output_flush_fn = output_flush_fn;
else
png_ptr->output_flush_fn = png_default_flush;
# else # else
png_ptr->output_flush_fn = output_flush_fn;
# endif
#else
PNG_UNUSED(output_flush_fn) PNG_UNUSED(output_flush_fn)
#endif /* WRITE_FLUSH */ # endif /* WRITE_FLUSH */
#ifdef PNG_READ_SUPPORTED
/* It is an error to read while writing a png file */
if (png_ptr->read_data_fn != NULL)
{
png_ptr->read_data_fn = NULL;
png_warning(png_ptr,
"Can't set both read_data_fn and write_data_fn in the"
" same structure");
}
#endif
} }
#endif /* WRITE */ #endif /* WRITE */

1306
pngwrite.c

File diff suppressed because it is too large Load Diff

View File

@ -14,38 +14,259 @@
#include "pngpriv.h" #include "pngpriv.h"
#define PNG_SRC_FILE PNG_SRC_FILE_pngwtran #define PNG_SRC_FILE PNG_SRC_FILE_pngwtran
#ifdef PNG_WRITE_SUPPORTED #ifdef PNG_WRITE_INTERLACING_SUPPORTED
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED /* Pick out the correct pixels for the interlace pass.
* The basic idea here is to go through the row with a source
#ifdef PNG_WRITE_PACK_SUPPORTED * pointer and a destination pointer (sp and dp), and copy the
/* Pack pixels into bytes. Get the true bit depth from png_ptr. The * correct pixels for the pass. As the row gets compacted,
* row_info bit depth should be 8 (one pixel per byte). The channels * sp will always be >= dp, so we should never overwrite anything.
* should be 1 (this only happens on grayscale and paletted images). * See the default: case for the easiest code to understand.
*/ */
static void static void
png_do_pack(png_transform_controlp row_info, png_bytep row) png_do_write_interlace_lbd(png_transformp *transform, png_transform_controlp tc)
{ {
const png_const_structrp png_ptr = tc->png_ptr;
const unsigned int pass = png_ptr->pass;
const png_uint_32 row_width = tc->width;
const png_uint_32 output_width = PNG_PASS_COLS(row_width, pass);
png_uint_32 i = PNG_PASS_START_COL(pass);
png_debug(1, "in png_do_write_interlace");
debug(!tc->init);
/* The data can be used in place (tc->sp) if the width isn't changed or
* the first pixel in the output is the first in the input and there is
* only one pixel in the output; this covers the last pass (PNG pass 7,
* libpng 6) and PNG passes 1, 3 and 5 with narrow images.
*/
tc->width = output_width;
if (row_width != output_width && (output_width != 1 || i > 0))
{
/* For passes before the last the pixels must be picked from the input
* row (tc->sp) and placed into the output row (tc->dp).
*/
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_bytep dp = png_voidcast(png_bytep, tc->dp);
const unsigned int inc = PNG_PASS_COL_OFFSET(pass);
unsigned int B = (*transform)->args & 0x3; /* 0, 1 or 2 */
/* The row data will be moved, so do this now before 'dp' is advanced:
*/
tc->sp = dp;
/* For pixels less than one byte wide the correct pixels have to be
* extracted from the input bytes. Because we are reading data in
* the application memory format we cannot rely on the PNG big
* endian order. Notice that this was apparently broken before
* 1.7.0.
*
* In libpng 1.7.0 libpng uses a classic bit-pump to optimize the
* extraction. In all passes before the last (6/7) no two pixels
* are adjacent in the input, so we are always extracting 1 bit.
* At present the code uses an 8-bit buffer to avoid coding for
* different byte sexes, but this could easily be changed.
*
* 'i' is the bit-index of bit in the input (sp[]), so,
* considering the 1-bit per pixel case, sp[i>>3] is the byte
* and the bit is bit (i&7) (0 lowest) on swapped (little endian)
* data or 7-(i&7) on PNG default (big-endian) data.
*
* Define these macros, where:
*
* B: the log2 bit depth (0, 1, 2 for 1bpp, 2bpp or 4bpp) of
* the data; this should be a constant.
* sp: the source pointer (sp) (a png_const_bytep)
* i: the pixel index in the input (png_uint_32)
* j: the bit index in the output (unsigned int)
*
* Unlike 'i', 'j' is interpreted directly; for LSB bytes it counts
* up, for MSB it counts down.
*
* NOTE: this could all be expanded to eliminate the code below by
* the time honoured copy'n'paste into three separate functions. This
* might be worth doing in the future.
*/
# define PIXEL_MASK ((1U << (1<<B))-1U)
# define BIT_MASK ((1U << (3-(B)))-1U) /* within a byte */
# define SP_BYTE (sp[i>>(3-(B))]) /* byte to use */
# define SP_OFFSET_LSB ((BIT_MASK & i) << (B))
# define SP_OFFSET_MSB ((BIT_MASK & ~i) << (B))
# define SP_PIXEL(sex) ((SP_BYTE >> SP_OFFSET_ ## sex) & PIXEL_MASK)
{
unsigned int j;
unsigned int d;
# ifdef PNG_WRITE_PACKSWAP_SUPPORTED
if (tc->format & PNG_FORMAT_FLAG_SWAPPED)
for (j = 0, d = 0; i < row_width; i += inc)
{ /* little-endian */
d |= SP_PIXEL(LSB) << j;
j += 1<<B;
if (j == 8) *dp++ = png_check_byte(png_ptr, d), j = 0, d = 0;
}
else
# endif /* WRITE_PACKSWAP */
for (j = 8, d = 0; i < row_width; i += inc)
{ /* big-endian */
j -= 1<<B;
d |= SP_PIXEL(MSB) << j;
if (j == 0) *dp++ = png_check_byte(png_ptr, d), j = 8, d = 0;
}
/* The end condition: if j is not 0 the last byte was not
* written:
*/
if (j != 0) *dp = png_check_byte(png_ptr, d);
}
# undef PIXEL_MASK
# undef BIT_MASK
# undef SP_BYTE
# undef SP_OFFSET_MSB
# undef SP_OFFSET_LSB
# undef SP_PIXEL
}
/* The transform is removed on the last pass. It can be removed earlier
* in other cases if the row width (the image width) is only 1, however
* this does not seem worth the overhead to check; PNG pass 5(4) happens
* if there are just three rows.
*/
else /* the source can be used in place */ if (pass == 6)
(*transform)->fn = NULL; /* remove me to caller */
}
static void
png_do_write_interlace_byte(png_transformp *transform,
png_transform_controlp tc)
{
const png_const_structrp png_ptr = tc->png_ptr;
const unsigned int pass = png_ptr->pass;
const png_uint_32 row_width = tc->width;
const png_uint_32 output_width = PNG_PASS_COLS(row_width, pass);
png_uint_32 i = PNG_PASS_START_COL(pass);
png_debug(1, "in png_do_write_interlace");
debug(!tc->init);
/* The data can be used in place (tc->sp) if the width isn't changed or
* the first pixel in the output is the first in the input and there is
* only one pixel in the output; this covers the last pass (PNG pass 7,
* libpng 6) and PNG passes 1, 3 and 5 with narrow images.
*/
tc->width = output_width;
if (row_width != output_width && (output_width != 1 || i > 0))
{
/* For passes before the last the pixels must be picked from the input
* row (tc->sp) and placed into the output row (tc->dp).
*/
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_bytep dp = png_voidcast(png_bytep, tc->dp);
const unsigned int inc = PNG_PASS_COL_OFFSET(pass);
unsigned int cbytes = (*transform)->args;
/* The row data will be moved, so do this now before 'dp' is advanced:
*/
tc->sp = dp;
/* Loop through the input copying each pixel to the correct place
* in the output. Note that the loop may be executed 0 times if
* this is called on a narrow image that does not contain this
* pass.
*/
for (sp += i * cbytes; i < row_width;
i += inc, sp += inc * cbytes, dp += cbytes)
if (dp != sp) /* cannot happen in practice */
memcpy(dp, sp, cbytes);
}
/* The transform is removed on the last pass. It can be removed earlier
* in other cases if the row width (the image width) is only 1, however
* this does not seem worth the overhead to check; PNG pass 5(4) happens
* if there are just three rows.
*/
else /* the source can be used in place */ if (pass == 6)
(*transform)->fn = NULL; /* remove me to caller */
}
static void
png_init_write_interlace(png_transformp *transform, png_transform_controlp tc)
{
# define png_ptr (tc->png_ptr)
png_debug(1, "in png_do_write_interlace");
debug(tc->init);
/* Do nothing on PNG_TC_INIT_FORMAT because we don't change the format, bit
* depth or gamma of the data.
*/
if (tc->init == PNG_TC_INIT_FINAL)
{
png_transformp tf = *transform;
unsigned int pixel_depth = PNG_TC_PIXEL_DEPTH(*tc);
png_uint_16 B = 0;
switch (pixel_depth)
{
case 4: /* B == 2 */
++B;
/* FALL THROUGH */
case 2: /* B == 1 */
++B;
/* FALL THROUGH */
case 1: /* B == 0 */
/* This is the low bit depth case: */
tf->args = B;
tf->fn = png_do_write_interlace_lbd;
break;
default:
affirm((pixel_depth & 7) == 0);
pixel_depth >>= 3;
affirm(pixel_depth > 0 && pixel_depth <= 8);
tf->args = pixel_depth & 0xf;
tf->fn = png_do_write_interlace_byte;
break;
}
}
# undef png_ptr
}
void /* PRIVATE */
png_set_write_interlace(png_structrp png_ptr)
{
/* This is checked in the caller: */
debug(png_ptr->interlaced == PNG_INTERLACE_ADAM7);
png_add_transform(png_ptr, 0, png_init_write_interlace, PNG_TR_INTERLACE);
}
#endif /* WRITE_INTERLACING */
#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes. */
static void
png_do_write_pack(png_transformp *transform, png_transform_controlp tc)
{
png_alloc_size_t rowbytes = PNG_TC_ROWBYTES(*tc);
png_const_bytep sp = png_voidcast(png_const_bytep, tc->sp);
png_const_bytep ep = png_upcast(png_const_bytep, tc->sp) + rowbytes;
png_bytep dp = png_voidcast(png_bytep, tc->dp);
png_debug(1, "in png_do_pack"); png_debug(1, "in png_do_pack");
# define png_ptr row_info->png_ptr # define png_ptr tc->png_ptr
/* The comment suggests the following must be true. switch ((*transform)->args)
* TODO: test this.
*/
affirm(row_info->bit_depth == 8 && row_info->channels == 1);
{
switch (png_ptr->bit_depth)
{ {
case 1: case 1:
{ {
png_const_bytep ep = row + png_transform_rowbytes(row_info);
png_bytep dp = row;
unsigned int mask = 0x80, v = 0; unsigned int mask = 0x80, v = 0;
while (row < ep) while (sp < ep)
{ {
if (*row++ != 0) if (*sp++ != 0)
v |= mask; v |= mask;
mask >>= 1; mask >>= 1;
@ -53,484 +274,105 @@ png_do_pack(png_transform_controlp row_info, png_bytep row)
if (mask == 0) if (mask == 0)
{ {
mask = 0x80; mask = 0x80;
*dp++ = (png_byte)/*SAFE*/v; *dp++ = PNG_BYTE(v);
v = 0; v = 0;
} }
} }
if (mask != 0x80) if (mask != 0x80)
*dp++ = (png_byte)/*SAFE*/v; *dp++ = PNG_BYTE(v);
row_info->bit_depth = 1;
break; break;
} }
case 2: case 2:
{ {
png_const_bytep ep = row + png_transform_rowbytes(row_info);
png_bytep dp = row;
unsigned int shift = 8, v = 0; unsigned int shift = 8, v = 0;
while (row < ep) while (sp < ep)
{ {
shift -= 2; shift -= 2;
v |= (*row++ & 0x3) << shift; v |= (*sp++ & 0x3) << shift;
if (shift == 0) if (shift == 0)
{ {
shift = 8; shift = 8;
*dp++ = png_check_byte(png_ptr, v); *dp++ = PNG_BYTE(v);
v = 0; v = 0;
} }
} }
if (shift != 8) if (shift != 8)
*dp++ = png_check_byte(png_ptr, v); *dp++ = PNG_BYTE(v);
row_info->bit_depth = 2;
break; break;
} }
case 4: case 4:
{ {
png_const_bytep ep = row + png_transform_rowbytes(row_info);
png_bytep dp = row;
unsigned int shift = 8, v = 0; unsigned int shift = 8, v = 0;
while (row < ep) while (sp < ep)
{ {
shift -= 4; shift -= 4;
v |= ((*row++ & 0xf) << shift); v |= ((*sp++ & 0xf) << shift);
if (shift == 0) if (shift == 0)
{ {
shift = 8; shift = 8;
*dp++ = png_check_byte(png_ptr, v); *dp++ = PNG_BYTE(v);
v = 0; v = 0;
} }
} }
if (shift != 8) if (shift != 8)
*dp++ = png_check_byte(png_ptr, v); *dp++ = PNG_BYTE(v);
row_info->bit_depth = 4;
break; break;
} }
default: default:
break; impossible("bit depth");
}
} }
if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0 &&
--(tc->range) == 0)
tc->format &= PNG_BIC_MASK(PNG_FORMAT_FLAG_RANGE);
tc->bit_depth = (*transform)->args;
tc->sp = tc->dp;
# undef png_ptr # undef png_ptr
} }
#endif
#ifdef PNG_WRITE_SHIFT_SUPPORTED
/* Shift pixel values to take advantage of whole range. Pass the
* true number of bits in bit_depth. The row should be packed
* according to row_info->bit_depth. Thus, if you had a row of
* bit depth 4, but the pixels only had values from 0 to 7, you
* would pass 3 as bit_depth, and this routine would translate the
* data to 0 to 15.
*
* NOTE: this is horrible complexity for no value. Once people suggested they
* were selling 16-bit displays with 5:6:5 bits spread R:G:B but so far as I
* could determine these displays produced intermediate grey (uncolored) colors,
* which is impossible with a true 5:6:5, so most likely 5:6:5 was marketing.
*/
static void
png_do_shift(png_transform_controlp row_info, png_bytep row)
{
png_debug(1, "in png_do_shift");
# define png_ptr row_info->png_ptr
if (!(row_info->flags & PNG_INDEXED) && (row_info->channels-1) <= 3)
{
png_const_color_8p bit_depth = &png_ptr->shift;
int shift_start[4], shift_dec[4];
int channels = 0;
if (row_info->channels == 3 || row_info->channels == 4)
{
shift_start[channels] = row_info->bit_depth - bit_depth->red;
shift_dec[channels] = bit_depth->red;
channels++;
shift_start[channels] = row_info->bit_depth - bit_depth->green;
shift_dec[channels] = bit_depth->green;
channels++;
shift_start[channels] = row_info->bit_depth - bit_depth->blue;
shift_dec[channels] = bit_depth->blue;
channels++;
}
else /* 1 or 2 channels */
{
shift_start[channels] = row_info->bit_depth - bit_depth->gray;
shift_dec[channels] = bit_depth->gray;
channels++;
}
if (row_info->channels == 2 || row_info->channels == 4)
{
shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
shift_dec[channels] = bit_depth->alpha;
channels++;
}
/* With low res depths, could only be grayscale, so one channel */
if (row_info->bit_depth < 8)
{
png_bytep bp = row;
png_size_t i;
unsigned int mask;
size_t row_bytes = png_transform_rowbytes(row_info);
affirm(row_info->channels == 1);
if (bit_depth->gray == 1 && row_info->bit_depth == 2)
mask = 0x55;
else if (row_info->bit_depth == 4 && bit_depth->gray == 3)
mask = 0x11;
else
mask = 0xff;
for (i = 0; i < row_bytes; i++, bp++)
{
int j;
unsigned int v, out;
v = *bp;
out = 0;
for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
{
if (j > 0)
out |= v << j;
else
out |= (v >> (-j)) & mask;
}
*bp = png_check_byte(png_ptr, out);
}
}
else if (row_info->bit_depth == 8)
{
png_bytep bp = row;
png_uint_32 i;
png_uint_32 istop = channels * row_info->width;
for (i = 0; i < istop; i++, bp++)
{
const unsigned int c = i%channels;
int j;
unsigned int v, out;
v = *bp;
out = 0;
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
{
if (j > 0)
out |= v << j;
else
out |= v >> (-j);
}
*bp = png_check_byte(png_ptr, out);
}
}
else
{
png_bytep bp;
png_uint_32 i;
png_uint_32 istop = channels * row_info->width;
for (bp = row, i = 0; i < istop; i++)
{
const unsigned int c = i%channels;
int j;
unsigned int value, v;
v = png_get_uint_16(bp);
value = 0;
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
{
if (j > 0)
value |= v << j;
else
value |= v >> (-j);
}
*bp++ = png_check_byte(png_ptr, value >> 8);
*bp++ = PNG_BYTE(value);
}
}
}
# undef png_ptr
}
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
static void
png_do_write_swap_alpha(png_transform_controlp row_info, png_bytep row)
{
png_debug(1, "in png_do_write_swap_alpha");
# define png_ptr row_info->png_ptr
{
if (row_info->channels == 4)
{
if (row_info->bit_depth == 8)
{
png_const_bytep ep = row + png_transform_rowbytes(row_info) - 4;
/* This converts from ARGB to RGBA */
while (row <= ep)
{
png_byte save = row[0];
row[0] = row[1];
row[1] = row[2];
row[2] = row[3];
row[3] = save;
row += 4;
}
debug(row == ep+4);
}
#ifdef PNG_WRITE_16BIT_SUPPORTED
else if (row_info->bit_depth == 16)
{
/* This converts from AARRGGBB to RRGGBBAA */
png_const_bytep ep = row + png_transform_rowbytes(row_info) - 8;
while (row <= ep)
{
png_byte s0 = row[0];
png_byte s1 = row[1];
memmove(row, row+2, 6);
row[6] = s0;
row[7] = s1;
row += 8;
}
debug(row == ep+8);
}
#endif /* WRITE_16BIT */
}
else if (row_info->channels == 2)
{
if (row_info->bit_depth == 8)
{
/* This converts from AG to GA */
png_const_bytep ep = row + png_transform_rowbytes(row_info) - 2;
/* This converts from ARGB to RGBA */
while (row <= ep)
{
png_byte save = *row;
*row = row[1], ++row;
*row++ = save;
}
debug(row == ep+2);
}
#ifdef PNG_WRITE_16BIT_SUPPORTED
else
{
/* This converts from AAGG to GGAA */
png_const_bytep ep = row + png_transform_rowbytes(row_info) - 4;
while (row <= ep)
{
png_byte save = row[0];
row[0] = row[2];
row[2] = save;
save = row[1];
row[1] = row[3];
row[3] = save;
row += 4;
}
debug(row == ep+4);
}
#endif /* WRITE_16BIT */
}
}
# undef png_ptr
}
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
static void
png_do_write_invert_alpha(png_transform_controlp row_info, png_bytep row)
{
png_debug(1, "in png_do_write_invert_alpha");
# define png_ptr row_info->png_ptr
{
if (row_info->channels == 4)
{
if (row_info->bit_depth == 8)
{
/* This inverts the alpha channel in RGBA */
png_const_bytep ep = row + png_transform_rowbytes(row_info) - 1;
row += 3; /* alpha channel */
while (row <= ep)
*row ^= 0xff, row += 4;
}
#ifdef PNG_WRITE_16BIT_SUPPORTED
else if (row_info->bit_depth == 16)
{
/* This inverts the alpha channel in RRGGBBAA */
png_const_bytep ep = row + png_transform_rowbytes(row_info) - 2;
row += 6;
while (row <= ep)
row[0] ^= 0xff, row[1] ^= 0xff, row += 8;
}
#endif /* WRITE_16BIT */
}
else if (row_info->channels == 2)
{
if (row_info->bit_depth == 8)
{
/* This inverts the alpha channel in GA */
png_const_bytep ep = row + png_transform_rowbytes(row_info) - 1;
++row;
while (row <= ep)
*row ^= 0xff, row += 2;
}
#ifdef PNG_WRITE_16BIT_SUPPORTED
else
{
/* This inverts the alpha channel in GGAA */
png_const_bytep ep = row + png_transform_rowbytes(row_info) - 2;
row += 2;
while (row <= ep)
row[0] ^= 0xff, row[1] ^= 0xff, row += 4;
}
#endif /* WRITE_16BIT */
}
}
# undef png_ptr
}
#endif
/* Transform the data according to the user's wishes. The order of
* transformations is significant.
*/
void /* PRIVATE */ void /* PRIVATE */
png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info_in) png_init_write_pack(png_transformp *transform, png_transform_controlp tc)
{ {
png_transform_control display; # define png_ptr tc->png_ptr
debug(tc->init);
# undef png_ptr
png_debug(1, "in png_do_write_transformations"); /* The init routine is called *forward* so the transform control we get has
* the required bit depth and the transform routine will increase it to 8
if (png_ptr == NULL) * bits per channel. The code doesn't really care how many channels there
return; * are, but the only way to get a channel depth of less than 8 is to have
* just one channel.
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
if (png_ptr->write_user_transform_fn != NULL)
(*(png_ptr->write_user_transform_fn)) /* User write transform
function */
(png_ptr, /* png_ptr */
row_info_in, /* row_info: */
/* png_uint_32 width; width of row */
/* png_size_t rowbytes; number of bytes in row */
/* png_byte color_type; color type of pixels */
/* png_byte bit_depth; bit depth of samples */
/* png_byte channels; number of channels (1-4) */
/* png_byte pixel_depth; bits per pixel (depth*channels) */
png_ptr->row_buf + 1); /* start of pixel data for row */
#endif
png_init_transform_control(png_ptr, &display, row_info_in);
#ifdef PNG_WRITE_FILLER_SUPPORTED
if ((png_ptr->transformations & PNG_FILLER) != 0)
png_do_strip_channel(&display, png_ptr->row_buf + 1,
!(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
#endif
#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
png_do_packswap(&display, png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_PACK_SUPPORTED
if ((png_ptr->transformations & PNG_PACK) != 0)
png_do_pack(&display, png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_SWAP_SUPPORTED
# ifdef PNG_16BIT_SUPPORTED
if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
png_do_swap(&display, png_ptr->row_buf + 1);
# endif
#endif
#ifdef PNG_WRITE_SHIFT_SUPPORTED
if ((png_ptr->transformations & PNG_SHIFT) != 0)
png_do_shift(&display, png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
png_do_write_swap_alpha(&display, png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
png_do_write_invert_alpha(&display, png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_BGR_SUPPORTED
if ((png_ptr->transformations & PNG_BGR) != 0)
png_do_bgr(&display, png_ptr->row_buf + 1);
#endif
#ifdef PNG_WRITE_INVERT_SUPPORTED
if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
png_do_invert(&display, png_ptr->row_buf + 1);
#endif
/* Clear the flags; they are irrelevant because the write code is
* reversing transformations to get PNG data but the shared transformation
* code assumes input PNG data. Only PNG_INDEXED is required.
*/ */
if ((display.flags & PNG_BAD_INDEX) != 0) if (tc->bit_depth < 8) /* else no packing/unpacking */
png_error(png_ptr, "palette data has out of range index"); {
if (tc->init == PNG_TC_INIT_FINAL)
{
(*transform)->fn = png_do_write_pack;
/* Record this for the backwards run: */
(*transform)->args = tc->bit_depth & 0xf;
}
display.flags &= PNG_INDEXED; if ((tc->format & PNG_FORMAT_FLAG_COLORMAP) == 0)
png_end_transform_control(row_info_in, &display); {
tc->range++;
tc->format |= PNG_FORMAT_FLAG_RANGE; /* forwards: backwards cancels */
}
tc->bit_depth = 8;
}
else /* the transform is not applicable */
(*transform)->fn = NULL;
} }
#endif /* WRITE_TRANSFORMS */ #endif /* WRITE_PACK */
#endif /* WRITE */

1127
pngwutil.c

File diff suppressed because it is too large Load Diff

39
scripts/chunkdesc.h Normal file
View File

@ -0,0 +1,39 @@
/* PNG CHUNK DESCRIPTIONS.
*
* If this list is changed in any way scripts/chunkhash.c must be rebuilt and
* run to regenerate the lookup functions for the tables described from this
* list.
*
* IDAT MUST be first in the list; it must have index '0'. The order of the
* remaining chunks comes from section 5.6 "Chunk ordering" in the ISO spec
* plus the ordering rules in the PNG extensions documnet.
*
* Keep PNG_CHUNK_BEGIN and PNG_CHUNK_END at the beginning and end.
*/
PNG_CHUNK_BEGIN(IDAT, 73, 68, 65, 84, within_IDAT, after_start)
PNG_CHUNK( IHDR, 73, 72, 68, 82, before_start, at_start)
PNG_CHUNK( cHRM, 99, 72, 82, 77, before_PLTE, after_start)
PNG_CHUNK( gAMA, 103, 65, 77, 65, before_PLTE, after_start)
PNG_CHUNK( iCCP, 105, 67, 67, 80, before_PLTE, after_start)
PNG_CHUNK( sBIT, 115, 66, 73, 84, before_PLTE, after_start)
PNG_CHUNK( sRGB, 115, 82, 71, 66, before_PLTE, after_start)
PNG_CHUNK( PLTE, 80, 76, 84, 69, before_PLTE, after_start)
PNG_CHUNK( bKGD, 98, 75, 71, 68, before_IDAT, after_PLTE)
PNG_CHUNK( hIST, 104, 73, 83, 84, before_IDAT, after_PLTE)
PNG_CHUNK( tRNS, 116, 82, 78, 83, before_IDAT, after_PLTE)
PNG_CHUNK( oFFs, 111, 70, 70, 115, before_IDAT, after_start)
PNG_CHUNK( pCAL, 112, 67, 65, 76, before_IDAT, after_start)
PNG_CHUNK( sCAL, 115, 67, 65, 76, before_IDAT, after_start)
PNG_CHUNK( sTER, 115, 84, 69, 82, before_IDAT, after_start)
PNG_CHUNK( pHYs, 112, 72, 89, 115, before_IDAT, after_start)
PNG_CHUNK( sPLT, 115, 80, 76, 84, before_IDAT, after_start)
PNG_CHUNK( tIME, 116, 73, 77, 69, before_end, after_start)
PNG_CHUNK( iTXt, 105, 84, 88, 116, before_end, after_start)
PNG_CHUNK( tEXt, 116, 69, 88, 116, before_end, after_start)
PNG_CHUNK( zTXt, 122, 84, 88, 116, before_end, after_start)
PNG_CHUNK( fRAc, 102, 82, 65, 99, before_end, after_start)
PNG_CHUNK( gIFg, 103, 73, 70, 103, before_end, after_start)
PNG_CHUNK( gIFt, 103, 73, 70, 116, before_end, after_start)
PNG_CHUNK( gIFx, 103, 73, 70, 120, before_end, after_start)
PNG_CHUNK( dSIG, 100, 83, 73, 71, before_end, after_start)
PNG_CHUNK_END( IEND, 73, 69, 78, 68, before_end, after_IDAT)

245
scripts/chunkhash.c Normal file
View File

@ -0,0 +1,245 @@
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdint.h>
#include "pnglibconf.h.prebuilt"
#include "../pngpriv.h"
static const struct
{
png_uint_32 name;
}
png_known_chunks[] =
/* See scripts/chunkdesc.h for how this works: */
#define PNG_CHUNK_END(n, c1, c2, c3, c4, before, after)\
{ png_ ##n }
#define PNG_CHUNK(n, c1, c2, c3, c4, before, after)\
PNG_CHUNK_END(n, c1, c2, c3, c4, before, after),
#define PNG_CHUNK_BEGIN(n, c1, c2, c3, c4, before, after)\
PNG_CHUNK_END(n, c1, c2, c3, c4, before, after),
{
# include "chunkdesc.h"
};
#define C_KNOWN ((sizeof png_known_chunks)/(sizeof png_known_chunks[0]))
static unsigned int
index_of(png_uint_32 name)
{
unsigned int i;
if (name == 0)
return 0;
for (i=0; i<C_KNOWN; ++i) if (png_known_chunks[i].name == name) return i;
assert("not reached" && 0);
}
static unsigned int bitorder[32];
#define PNG_CHUNK_HASH(n,shift,s1,s2,s3,s4,s5)\
(0x3f & (((n += n >> shift),n += n >> s1),n += n >> s2))
inline unsigned int hash(png_uint_32 name, unsigned int shift, unsigned int s1,
unsigned int s2, unsigned int s3, unsigned int s4, unsigned int s5)
{
/* Running the search gives (shift,s1,s2) (2,8,16) */
//return PNG_CHUNK_HASH(name, shift, s1, s2, s3, s4, s5);
name += name >> shift;
name += name >> s1;
name += name >> s2;
//name += name >> s3;
return 0x3f & name;
/*return 0x3f & ((name) + (
((name >> bitorder[s1]) & 0x01) +
((name >> (bitorder[s2]-1)) & 0x02) +
((name >> (bitorder[s3]-2)) & 0x04) +
((name >> (bitorder[s4]-3)) & 0x08) +
((name >> (bitorder[s5]-4)) & 0x10)));*/
}
int main(void) {
unsigned int s1 = 0, s2 = 0, s3 = 0, s4 = 0, s5 = 0;
unsigned int shift = 0;
png_uint_32 mask;
unsigned int bitcount;
unsigned int mineq;
png_uint_32 sarray;
unsigned int shift_save;
png_uint_32 reverse_index_save[64];
assert(C_KNOWN <= 64);
/* Check IDAT: */
assert(index_of(png_IDAT) == 0);
/* Build a mask of all the bits that differ in at least one of the known
* names.
*/
{
png_uint_32 set, unset;
int i;
for (i=0, set=unset=0; i<C_KNOWN; ++i)
{
set |= png_known_chunks[i].name;
unset |= ~png_known_chunks[i].name;
}
mask = set ^ ~unset;
}
//printf("C_KNOWN = %lu, 0x%.8x\n", C_KNOWN, mask);
assert(mask == 0x3f1f1f3f);
/* Print the bit array */
{
unsigned int i;
unsigned int ones[32];
memset(ones, 0, sizeof ones);
for (i=0; i<C_KNOWN; ++i)
{
png_uint_32 name = png_known_chunks[i].name;
int j, k;
char s[5], b[33];
PNG_CSTRING_FROM_CHUNK(s, name);
for (j=k=0; j<32; ++j)
{
if ((name >> j) & 1)
++ones[j];
if ((mask >> (31-j)) & 1)
b[k++] = ((name >> (31-j)) & 1) ? 'o' : ' ';
}
b[k] = 0;
//printf("%s: %s\n", s, b);
}
memset(bitorder, 0, sizeof bitorder);
bitcount = 0;
for (i=0; i<C_KNOWN; ++i) if (((C_KNOWN-i) & 1) == 0)
{
unsigned int lo = (C_KNOWN - i)>>1;
unsigned int hi = (C_KNOWN + i)>>1;
int j;
for (j=0; j<32; ++j) if (ones[j] == lo || ones[j] == hi)
{
//printf(" %2d,", j);
bitorder[bitcount++] = j;
}
}
//printf("\nbitcount=%u, C_KNOWN=%lu\n", bitcount, C_KNOWN);
}
/* s? are masks to exclude bits from the hash, one for each byte: */
mineq = C_KNOWN;
sarray = 0;
for (shift=0; shift<32; ++shift)
for (s1=0; s1<32; ++s1)
for (s2=s1+1; s2<32; ++s2)
//for (s3=s2+1; s3<32; ++s3)
//for (s4=s3+1; s4<bitcount; ++s4)
//for (s5=s4+1; s5<bitcount; ++s5)
{
int i, eq;
png_uint_32 reverse_index[64];
memset(reverse_index, 0, sizeof reverse_index);
for (i=eq=0; i<C_KNOWN; ++i)
{
png_uint_32 name = png_known_chunks[i].name;
unsigned int h = hash(name, shift, s1, s2, s3, s4, s5);
if (reverse_index[h] == 0)
reverse_index[h] = name;
else
++eq;
}
if (eq == 0)
{
/* Print the LUT: */
printf("static const png_byte png_chunk_lut[64] =\n{ \n ");
for (i=0; i<63; ++i)
{
printf("%2u, ", index_of(reverse_index[i]));
if ((i+1 & 0xf) == 0) printf("\n ");
}
printf("%2u\n};\n\n", index_of(reverse_index[63]));
//printf("hash: %u, %u, %u, %u, %u, %u\n", shift, s1, s2, s3, s4, s5);
printf("#define PNG_CHUNK_HASH(n)\\\n png_chunk_lut[0x3f &"
" (((n += n >> %u),n += n >> %u),n += n >> %u)]\n\n",
shift, s1, s2);
printf("static png_byte\n"
"png_chunk_index(png_uint_32 name)\n"
"{\n"
" name += name >> %u;\n"
" name += name >> %u;\n"
" name += name >> %u;\n"
" return png_chunk_lut[name & 0x3f];\n"
"}\n", shift, s1, s2);
return 0;
}
if (eq < mineq)
{
mineq = eq;
sarray = s1 + bitcount * (s2 + bitcount * (s3 + bitcount *
(s4 + bitcount *s5)));
memcpy(reverse_index_save, reverse_index, sizeof reverse_index_save);
shift_save = shift;
}
}
s1 = sarray % bitcount;
s2 = (sarray / bitcount) % bitcount;
s3 = (sarray / bitcount / bitcount) % bitcount;
s4 = (sarray / bitcount / bitcount / bitcount) % bitcount;
s5 = (sarray / bitcount / bitcount / bitcount / bitcount) % bitcount;
printf("best: %u clashes with bits: %u, %u, %u, %u, %u, %u\n",
mineq, shift_save, s1, s2, s3, s4, s5);
{
int i;
png_uint_32 reverse_index[64];
memset(reverse_index, 0, sizeof reverse_index);
for (i=0; i<C_KNOWN; ++i)
{
png_uint_32 name = png_known_chunks[i].name;
unsigned int h = hash(name, shift_save, s1, s2, s3, s4, s5);
if (reverse_index[h] == 0)
reverse_index[h] = name;
else
{
char n1[5], n2[5];
PNG_CSTRING_FROM_CHUNK(n1, reverse_index[h]);
PNG_CSTRING_FROM_CHUNK(n2, name);
printf("%d <- %s and %s\n", h, n1, n2);
}
}
}
return 1;
}

View File

@ -48,7 +48,7 @@ file pnglibconf.h scripts/pnglibconf.dfa PNGLCONF_H
# and chunk, should not be used in this file because they force the # and chunk, should not be used in this file because they force the
# relevant options on or off. # relevant options on or off.
#---------------------------------------------------------------------- #-------------------------------------------------------------------------------
# The following setting, option and chunk values can all be changed # The following setting, option and chunk values can all be changed
# while building libpng: # while building libpng:
@ -64,35 +64,10 @@ file pnglibconf.h scripts/pnglibconf.dfa PNGLCONF_H
# decoding but does change the libpng API because some chunks # decoding but does change the libpng API because some chunks
# will be ignored. # will be ignored.
# #
# There are three ways of disabling features, in no particular order: # There are three ways of disabling features, in order of power:
# #
# 1) Create 'pngusr.h', enter the required private build information # 1) Write a new '.dfa' file (say 'user.dfa') and in this file
# detailed below and #define PNG_NO_<option> for each option you # provide override values for setting entries and turn options or
# don't want in that file in that file. You can also turn on options
# using PNG_<option>_SUPPORTED. When you have finished rerun
# configure and rebuild pnglibconf.h file with -DPNG_USER_CONFIG:
#
# make clean
# CPPFLAGS='-DPNG_USER_CONFIG' ./configure
# make pnglibconf.h
#
# pngusr.h is only used during the creation of pnglibconf.h, but it
# is safer to ensure that -DPNG_USER_CONFIG is specified throughout
# the build by changing the CPPFLAGS passed to the initial ./configure
#
# 2) Add definitions of the settings you want to change to
# CPPFLAGS; for example:
#
# -DPNG_DEFAULT_READ_MACROS=0
#
# (This would change the default to *not* use read macros.) Be
# very careful to change only settings that don't alter the API
# because this approach bypasses the private build checking. You
# can also change settings from pngpriv.h (read pngpriv.h) safely
# without API changes. Do that in the same way.
#
# 3) Write a new '.dfa' file (say 'pngusr.dfa') and in this file
# provide override values for setting entries and turn option or
# chunk values explicitly 'on' or 'off': # chunk values explicitly 'on' or 'off':
# #
# setting FOO default VALUE # setting FOO default VALUE
@ -104,9 +79,90 @@ file pnglibconf.h scripts/pnglibconf.dfa PNGLCONF_H
# Look at the builds below contrib/pngminim for some extreme examples # Look at the builds below contrib/pngminim for some extreme examples
# of how this can be used. # of how this can be used.
# #
# Don't edit this file unless you are contributing a patch to # When you set an option 'off' it will be off; if this is impossible you
# libpng and need new or modified options/settings. # will get an error when you build pnglibconf.h. If you just want to
#---------------------------------------------------------------------- # set something off or on if it can be use 'disabled' or 'enabled' instead.
#
# The distributed file "user.dfa" is already included in a configure build
# and you can edit this in place if you are prepared to modify the source.
#
# 2) Create 'pngusr.h', enter the required private build information
# detailed below and #define PNG_NO_<option> for each option you
# want disabled. You can also enable options using PNG_<option>_SUPPORTED.
# When you have finished rerun configure and rebuild pnglibconf.h file with
# -DPNG_USER_CONFIG:
#
# make clean
# CPPFLAGS='-DPNG_USER_CONFIG' ./configure
# make pnglibconf.h
#
# pngusr.h is only used during the creation of pnglibconf.h, but it
# is safer to ensure that -DPNG_USER_CONFIG is specified throughout
# the build by changing the CPPFLAGS passed to the initial ./configure
#
# 3) Add definitions of the settings you want to change to
# CPPFLAGS; for example:
#
# -DPNG_DEFAULT_READ_MACROS=0
# -DPNG_NO_WRITE
# -DPNG_NO_GET_PALETTE_MAX -DPNG_READ_GET_PALETTE_MAX_SUPPORTED=
#
# As with #defines in pngusr.h these macro settings 'disable' or 'enable' and
# option and they get frozen in pnglibconf.h; read pnglibconf.h to see what
# (if anything) changed.
#
# IMPORTANT: when you pass this to the C compiler:
#
# -DPNG_foo_SUPPORTED
#
# it is the same as this #define:
#
# #define PNG_foo_SUPPORTED 1
#
# HOWEVER the macro will be recorded in pnglibconf.h as:
#
# #define PNG_foo_SUPPORTED
#
# To avoid confusion use -DPNG_foo_SUPPORTED= on the command line, which does
# the same thing as the #define.
#
# SUMMARY:
# These lines/macro settings are equivalent:
#
# To 'enable' an option; it will be on if its dependencies are satisfied
#
# -DPNG_foo_SUPPORTED= on the CC command line
# #define PNG_foo_SUPPORTED in pngusr.h
# option foo enabled in user.dfa
#
# To 'disable' an option; it will be off unless something below enables it:
#
# -DPNG_NO_foo on the CC command line
# #define PNG_NO_foo in pngusr.h
# option foo disabled in user.dfa
#
# To force an option on; the build of pnglibconf.h will fail if it has
# unsatisfied dependencies:
#
# option foo on in user.dfa
#
# To force an option off; there is no way to turn it back on, the build of
# pnglibconf.h will fail if it is required:
#
# option foo off in user.dfa
#
# If you want to start with everything 'off' and just turn things on that are
# required (the recommended approach to building a minimal libpng) use user.dfa
# and start with:
#
# everything off in user.dfa
#
# This actually *disables* all the options so that they can be enabled either
# explicitly or as required by other options.
#
# Don't edit this file unless you are contributing a patch to # libpng
# and need new or modified options/settings.
#-------------------------------------------------------------------------------
# The following causes commented out #undef lines to be written to # The following causes commented out #undef lines to be written to
# pnglibconf.h; this can be stopped by logunsupported=0 in a later # pnglibconf.h; this can be stopped by logunsupported=0 in a later
@ -171,11 +227,19 @@ logunsupported = 1
# NONE # NONE
# Note that PNG_USER_CONFIG only has an effect when building # Settings for private builds. The following two are required:
# pnglibconf.h #
# 1) USER_PRIVATEBUILD: set to the name of the legal entity holding the
# copyright to the changes (even if the changes are only a local
# configuration!)
#
# 2) USER_BUG_REPORTS: set to the email to which bug reports relating to this
# private configuration should be sent.
#
# Note that PNG_USER_CONFIG only has an effect when building pnglibconf.h
setting USER_CONFIG setting USER_CONFIG
setting USER_PRIVATEBUILD setting USER_PRIVATEBUILD
setting USER_BUG_REPORTS
setting USER_DLLFNAME_POSTFIX setting USER_DLLFNAME_POSTFIX
setting USER_VERSIONINFO_COMMENTS setting USER_VERSIONINFO_COMMENTS
setting USER_VERSIONINFO_COMPANYNAME setting USER_VERSIONINFO_COMPANYNAME
@ -221,33 +285,12 @@ setting ZLIB_HEADER default <zlib.h>
# must be made by the user) # must be made by the user)
option SET_OPTION disabled option SET_OPTION disabled
# These options are specific to the ARM NEON hardware optimizations. At present # Run-time setting of parameters, enabled as required below
# these optimizations depend on GCC specific pre-processing of an assembler (.S) option SETTING disabled
# file so they probably won't work with other compilers.
# # To support hardware specific optimizations libpng can include a hardware
# ARM_NEON_OPT: unset: check at compile time (__ARM_NEON__ must be defined by # specific header at build time, this setting records the included header:
# the compiler, typically as a result of specifying setting EXTENSION_HEADER
# CC="gcc -mfpu=neon".)
# 0: disable (even if the CPU has a NEON FPU.)
# 1: check at run time (via ARM_NEON_{API,CHECK})
# 2: switch on unconditionally (inadvisable - instead pass
# -mfpu=neon to GCC in CC)
# When building libpng avoid using any setting other than '0'; '1' is
# set automatically when either 'API' or 'CHECK' are configured in,
# '2' should not be necessary as -mfpu=neon will achieve the same
# effect as well as applying NEON optimizations to the rest of the
# libpng code.
# NOTE: any setting other than '0' requires ALIGNED_MEMORY
# ARM_NEON_API: (PNG_ARM_NEON == 1) allow the optimization to be switched on
# with png_set_option
# ARM_NEON_CHECK: (PNG_ARM_NEON == 1) compile a run-time check to see if Neon
# extensions are supported. This is poorly supported and
# deprecated - use the png_set_option API.
setting ARM_NEON_OPT
option ARM_NEON_API disabled requires ALIGNED_MEMORY enables SET_OPTION,
sets ARM_NEON_OPT 1
option ARM_NEON_CHECK disabled requires ALIGNED_MEMORY,
sets ARM_NEON_OPT 1
# These settings configure the default compression level (0-9) and 'strategy'; # These settings configure the default compression level (0-9) and 'strategy';
# strategy is as defined by the implementors of zlib. It describes the input # strategy is as defined by the implementors of zlib. It describes the input
@ -325,7 +368,11 @@ option BENIGN_READ_ERRORS requires BENIGN_ERRORS
# Generic options - affect both read and write. # Generic options - affect both read and write.
option MNG_FEATURES # If you want this you need to switch on either the read or write transform
# mechanism, otherwise nothing will happen.
option MNG_FEATURES disabled enables TRANSFORM_MECH
option MNG_READ_FEATURES enables MNG_FEATURES
option MNG_WRITE_FEATURES enables MNG_FEATURES
# Arithmetic options, the first is the big switch that chooses between internal # Arithmetic options, the first is the big switch that chooses between internal
# floating and fixed point arithmetic implementations - it does not affect any # floating and fixed point arithmetic implementations - it does not affect any
@ -412,6 +459,14 @@ option SET_USER_LIMITS requires USER_LIMITS
# conformant, however the library that results is still non-standard. # conformant, however the library that results is still non-standard.
# See the comments above about how to change options and settings. # See the comments above about how to change options and settings.
# READ/WRITE tranform support
#
# The internal TRANSFORM_MECH options are used to turn on (or off) the required
# support code for the read and write transforms. They are off by default,
# switching them on is not a good idea. Switching them off will cause the build
# to fail if anything is left in which depends on the transform support.
option TRANSFORM_MECH disabled
# READ options # READ options
# #
# WARNING: in libpng 1.5 maintained configuration compatibility with earlier # WARNING: in libpng 1.5 maintained configuration compatibility with earlier
@ -427,7 +482,7 @@ option SET_USER_LIMITS requires USER_LIMITS
# to libpng 1.6; the new interfaces in 1.6 will take several years to become # to libpng 1.6; the new interfaces in 1.6 will take several years to become
# popular. # popular.
option READ enables READ_INTERLACING SET_OPTION option READ enables SET_OPTION
# Disabling READ_16BIT does not disable reading 16-bit PNG files, but it # Disabling READ_16BIT does not disable reading 16-bit PNG files, but it
# forces them to be chopped down to 8-bit, and disables any 16-bit # forces them to be chopped down to 8-bit, and disables any 16-bit
@ -438,11 +493,11 @@ option READ enables READ_INTERLACING SET_OPTION
option READ_16BIT requires READ enables 16BIT option READ_16BIT requires READ enables 16BIT
option READ_QUANTIZE requires READ
option READ_TRANSFORMS requires READ option READ_TRANSFORMS requires READ
= NO_READ_TRANSFORMS READ_TRANSFORMS_NOT_SUPPORTED = NO_READ_TRANSFORMS READ_TRANSFORMS_NOT_SUPPORTED
option READ_QUANTIZE requires READ_TRANSFORMS enables TRANFORM_MECH
# Read gamma handling. Gamma processing is a core part of libpng and many of # Read gamma handling. Gamma processing is a core part of libpng and many of
# the capabilities are dependent on libpng performing gamma correction. # the capabilities are dependent on libpng performing gamma correction.
# #
@ -458,37 +513,50 @@ option READ_TRANSFORMS requires READ
# If you handle gamma issues outside libpng then you do not need the libpng # If you handle gamma issues outside libpng then you do not need the libpng
# gamma processing; and it is an enormous waste of space. You just need to # gamma processing; and it is an enormous waste of space. You just need to
# remove the use of libpng APIs that depend on it. # remove the use of libpng APIs that depend on it.
option READ_GAMMA requires READ_TRANSFORMS, READ_gAMA, READ_sRGB option READ_GAMMA requires READ_TRANSFORMS, READ_gAMA, READ_sRGB,
enables TRANSFORM_MECH, READ_SCALE_16_TO_8, READ_EXPAND, SETTING
option READ_ALPHA_MODE requires READ_TRANSFORMS, READ_GAMMA option READ_ALPHA_MODE requires READ_TRANSFORMS, READ_GAMMA, READ_BACKGROUND
option READ_BACKGROUND requires READ_TRANSFORMS, READ_STRIP_ALPHA, READ_GAMMA option READ_BACKGROUND requires READ_TRANSFORMS, READ_STRIP_ALPHA, READ_GAMMA,
option READ_BGR requires READ_TRANSFORMS READ_tRNS enables TRANSFORM_MECH
option READ_EXPAND_16 requires READ_TRANSFORMS, READ_16BIT, READ_EXPAND option READ_BGR requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_EXPAND requires READ_TRANSFORMS option READ_EXPAND_16 requires READ_TRANSFORMS, READ_16BIT, READ_EXPAND,
option READ_FILLER requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_GRAY_TO_RGB requires READ_TRANSFORMS option READ_EXPAND requires READ_TRANSFORMS, READ_tRNS enables TRANSFORM_MECH
option READ_INVERT_ALPHA requires READ_TRANSFORMS option READ_FILLER requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_INVERT requires READ_TRANSFORMS option READ_GRAY_TO_RGB requires READ_TRANSFORMS, READ_EXPAND,
option READ_PACK requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_PACKSWAP requires READ_TRANSFORMS option READ_INVERT_ALPHA requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_RGB_TO_GRAY requires READ_TRANSFORMS, READ_GAMMA enables COLORSPACE option READ_INVERT requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_SCALE_16_TO_8 requires READ_TRANSFORMS option READ_PACK requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_SHIFT requires READ_TRANSFORMS option READ_PACKSWAP requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_STRIP_16_TO_8 requires READ_TRANSFORMS option READ_RGB_TO_GRAY requires READ_TRANSFORMS, READ_GAMMA,
option READ_STRIP_ALPHA requires READ_TRANSFORMS enables COLORSPACE, TRANSFORM_MECH, READ_SCALE_16_TO_8
option READ_SWAP_ALPHA requires READ_TRANSFORMS option READ_SCALE_16_TO_8 requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_SWAP requires READ_TRANSFORMS, READ_16BIT option READ_SHIFT requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_USER_TRANSFORM requires READ_TRANSFORMS option READ_STRIP_16_TO_8 requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_STRIP_ALPHA requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_SWAP_ALPHA requires READ_TRANSFORMS enables TRANSFORM_MECH
option READ_SWAP requires READ_TRANSFORMS, READ_16BIT enables TRANSFORM_MECH
option READ_USER_TRANSFORM requires READ_TRANSFORMS enables TRANSFORM_MECH
# You can define PNG_NO_PROGRESSIVE_READ if you don't do progressive reading.
option PROGRESSIVE_READ requires READ option PROGRESSIVE_READ requires READ
option SEQUENTIAL_READ requires READ option SEQUENTIAL_READ requires READ
# You can define PNG_NO_PROGRESSIVE_READ if you don't do progressive reading. # Added to 1.7.0: png_read_image now requires the deinterlace code
# This is not talking about interlacing capability! You'll still have option READ_IMAGE requires SEQUENTIAL_READ READ_DEINTERLACE
# interlacing unless you turn off the following which is required
# for PNG-compliant decoders. (In other words, do not do this - in # This is not talking about reading interlaced PNG files, it is talking about
# fact it can't be disabled from the command line!) # libpng support to 'widen' the interlaced passes to the full row width. If
#option READ_INTERLACING requires READ # you take the rows libpng provides and expand them yourself you do not need
# this code.
#
# READ_INTERLACING is for backward compatibility with older version of libpng;
# applications had to use this to see if they needed to do their own interlace
# handling.
option READ_INTERLACING disabled
option READ_DEINTERLACE requires READ enables READ_INTERLACING
option READ_COMPOSITE_NODIV requires READ option READ_COMPOSITE_NODIV requires READ
= NO_READ_COMPOSITE_NODIV NO_READ_COMPOSITED_NODIV = NO_READ_COMPOSITE_NODIV NO_READ_COMPOSITED_NODIV
@ -514,25 +582,22 @@ option WRITE_16BIT requires WRITE enables 16BIT
option WRITE_TRANSFORMS requires WRITE option WRITE_TRANSFORMS requires WRITE
= NO_WRITE_TRANSFORMS WRITE_TRANSFORMS_NOT_SUPPORTED = NO_WRITE_TRANSFORMS WRITE_TRANSFORMS_NOT_SUPPORTED
option WRITE_SHIFT requires WRITE_TRANSFORMS option WRITE_SHIFT requires WRITE_TRANSFORMS enables TRANSFORM_MECH
option WRITE_PACK requires WRITE_TRANSFORMS option WRITE_PACK requires WRITE_TRANSFORMS enables TRANSFORM_MECH
option WRITE_BGR requires WRITE_TRANSFORMS option WRITE_BGR requires WRITE_TRANSFORMS enables TRANSFORM_MECH
option WRITE_SWAP requires WRITE_TRANSFORMS, WRITE_16BIT option WRITE_SWAP requires WRITE_TRANSFORMS, WRITE_16BIT enables TRANSFORM_MECH
option WRITE_PACKSWAP requires WRITE_TRANSFORMS option WRITE_PACKSWAP requires WRITE_TRANSFORMS enables TRANSFORM_MECH
option WRITE_INVERT requires WRITE_TRANSFORMS option WRITE_INVERT requires WRITE_TRANSFORMS enables TRANSFORM_MECH
option WRITE_FILLER requires WRITE_TRANSFORMS option WRITE_FILLER requires WRITE_TRANSFORMS enables TRANSFORM_MECH
option WRITE_SWAP_ALPHA requires WRITE_TRANSFORMS option WRITE_SWAP_ALPHA requires WRITE_TRANSFORMS enables TRANSFORM_MECH
option WRITE_INVERT_ALPHA requires WRITE_TRANSFORMS option WRITE_INVERT_ALPHA requires WRITE_TRANSFORMS
option WRITE_USER_TRANSFORM requires WRITE_TRANSFORMS option WRITE_USER_TRANSFORM requires WRITE_TRANSFORMS enables TRANSFORM_MECH
# This is not required for PNG-compliant encoders, but can cause # This is not required for PNG-compliant encoders, but can cause
# trouble if left undefined # trouble if left undefined
option WRITE_INTERLACING requires WRITE enables TRANSFORM_MECH
option WRITE_INTERLACING requires WRITE # The following is no longer implemented:
# The following depends, internally, on WEIGHT_SHIFT and COST_SHIFT
# where are set below.
option WRITE_WEIGHTED_FILTER requires WRITE option WRITE_WEIGHTED_FILTER requires WRITE
option WRITE_FLUSH requires WRITE option WRITE_FLUSH requires WRITE
@ -568,9 +633,9 @@ option WRITE_ANCILLARY_CHUNKS requires WRITE
= NO_WRITE_ANCILLARY_CHUNKS WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED = NO_WRITE_ANCILLARY_CHUNKS WRITE_ANCILLARY_CHUNKS_NOT_SUPPORTED
# These options disable *all* the text chunks if turned off # These options disable *all* the text chunks if turned off
option TEXT disabled
option READ_TEXT requires READ_ANCILLARY_CHUNKS enables TEXT option READ_TEXT requires READ_ANCILLARY_CHUNKS enables TEXT disabled
option WRITE_TEXT requires WRITE_ANCILLARY_CHUNKS enables TEXT option WRITE_TEXT requires WRITE_ANCILLARY_CHUNKS enables TEXT disabled
# Moved to pnglibconf.h at libpng-1.5.0 # Moved to pnglibconf.h at libpng-1.5.0
# Feature support: in 1.4 this was in pngconf.h, but the following # Feature support: in 1.4 this was in pngconf.h, but the following
@ -647,11 +712,6 @@ setting sRGB_PROFILE_CHECKS default 2
option ALIGNED_MEMORY option ALIGNED_MEMORY
# Buggy compilers (e.g., gcc 2.7.2.2) need PNG_NO_POINTER_INDEXING
# See png[wr]util.c, normally this should always be *on*
option POINTER_INDEXING
# Other defines for things like memory and the like can go here. # Other defines for things like memory and the like can go here.
# BUILD TIME SETTINGS # BUILD TIME SETTINGS
@ -668,25 +728,68 @@ setting QUANTIZE_RED_BITS default 5
setting QUANTIZE_GREEN_BITS default 5 setting QUANTIZE_GREEN_BITS default 5
setting QUANTIZE_BLUE_BITS default 5 setting QUANTIZE_BLUE_BITS default 5
# This controls how fine the gamma correction becomes when you # LEGACY: this used to control the precision of 16-bit gamma operations when the
# are only interested in 8 bits anyway. Increasing this value # output was only 8 bits. It is left in for background compatibility but it
# results in more memory being used, and more pow() functions # does nothing.
# being called to fill in the gamma tables. Don't set this value
# less than 8, and even that may not work (I haven't tested it).
setting MAX_GAMMA_8 default 11 setting MAX_GAMMA_8 default 11
# This controls how much a difference in gamma we can tolerate before # This controls how much a difference in gamma libpng will ignore; if a gamma
# we actually start doing gamma conversion, it's a fixed point value, # convertion is greater than this it will be done, if less it will be skipped.
# so the default below is 0.05, meaning libpng ignores corrections in #
# the range 0.95 to 1.05 # Prior to 1.7.0 this value was somewhat large; 5%. In 1.7.0 it has been set to
# 1%. The logic for this is that human vision can perceive about a 1% change in
# luminance, so if a user were to compare an image with the correct gamma
# correction against the libpng output we would want libpng to be within 1% of
# the correct values for all pixel values x, [0..1], so:
#
# x
# --------------- = 1.01
# x^(1+threshold)
#
# x^-threshold = 1.01
# -threshold.log(x) = log(1.01)
#
# log(1.01)
# threshold = ---------
# -log(x)
#
# The threshold goes down as 'x' goes down. For linear 16-bit values the
# threshold is under 0.1% for the smallest value (1/65535), for linear 8-bit
# values it is under 1%. It gets considerably smaller for gamma encoded values.
#
# However it is pointless to place demands on one part of the pipeline that
# other parts cannot meet. The 1.7 pipeline uses 16-bit linear arithmetic,
# therefore 1% resolution is only met with a pixel value (x) of 100/65535. The
# corresponding value of 'threshold' is 0.15%, hence:
setting GAMMA_THRESHOLD_FIXED default 5000 setting GAMMA_THRESHOLD_FIXED default 153
# Scaling factor for filter heuristic weighting calculations # Internally libpng 1.7 uses a gamma table lookup to cache results. Because the
# LUT is excessively large for 16-bit linear values the algorithm uses a
# partitioned table (in fact it's a classic floating point LUT) to achieve a
# given accuracy in the calculations. Each table has 2^b entries, where b is
# the number of bits of the value used to index the LUT. The table is indexed
# by the high bits [2..2+b] (where '1' is the highest bit) of the value, so the
# accuracy in the linear case is (worst case) 1/(1+1/2^b).
#
# IN FACT a 'b' of 6 is almost certainly adequate; accuracy of 1/64, HOWEVER,
# received wisdom is that 1% accuracy is required (show me a paper that proves
# this by experiment; the only information I have found suggests to me that 1/60
# is the peak possible for a typical human being.)
#
# The default table size is controlled by the following option, this is the
# number of bits in the table for *linear* input multiplied by 100, so the
# default is 6.65 and 2^6.65 is just over 100, giving the desired .5% accuracy
# in the linear domain. When the input is not linear an appropriate adjustment
# is made by dividing the value by the encoding gamma; much more accuracy is
# required from the gamma encoded input to give +/-.5% accuracy in the linear
# domain. Note that the default exceeds the accuracy of 8-bit gamma encoded
# values, but that is because 8-bit gamma encoded values are not sufficiently
# accurate to represent the 1% over 100:1 range assumed for human vision
# (9-bits to represent 463 values, are required).
setting WEIGHT_SHIFT default 8 setting DEFAULT_GAMMA_ACCURACY default 665
setting COST_SHIFT default 3
# Precision to use when converting a floating point value to a PNG # Precision to use when converting a floating point value to a PNG
# extension format string in an sCAL chunk (only relevant if the # extension format string in an sCAL chunk (only relevant if the
@ -738,7 +841,7 @@ chunk cHRM enables COLORSPACE
chunk gAMA enables GAMMA chunk gAMA enables GAMMA
chunk hIST chunk hIST
chunk iCCP enables COLORSPACE, GAMMA chunk iCCP enables COLORSPACE, GAMMA
chunk iTXt enables TEXT chunk iTXt
chunk oFFs chunk oFFs
chunk pCAL chunk pCAL
chunk pHYs chunk pHYs
@ -746,10 +849,18 @@ chunk sBIT
chunk sCAL chunk sCAL
chunk sPLT chunk sPLT
chunk sRGB enables COLORSPACE, GAMMA, SET_OPTION chunk sRGB enables COLORSPACE, GAMMA, SET_OPTION
chunk tEXt requires TEXT chunk tEXt
chunk tIME chunk tIME
chunk tRNS chunk tRNS
chunk zTXt enables TEXT chunk zTXt
# Text handling; add enable options to the read/write possibilities:
option READ_tEXt enables READ_TEXT
option READ_zTXt enables READ_TEXT
option READ_iTXt enables READ_TEXT
option WRITE_tEXt enables WRITE_TEXT
option WRITE_zTXt enables WRITE_TEXT
option WRITE_iTXt enables WRITE_TEXT
# This only affects support of the optional PLTE chunk in RGB and RGBA # This only affects support of the optional PLTE chunk in RGB and RGBA
# images. Notice that READ_ANCILLARY_CHUNKS therefore disables part # images. Notice that READ_ANCILLARY_CHUNKS therefore disables part
@ -768,14 +879,14 @@ option UNKNOWN_CHUNKS
# otherwise they are skipped. If the write option is turned on unknown chunks # otherwise they are skipped. If the write option is turned on unknown chunks
# set by png_set_unknown_chunks will be written otherwise it is an error to call # set by png_set_unknown_chunks will be written otherwise it is an error to call
# that API on a write struct. # that API on a write struct.
option WRITE_UNKNOWN_CHUNKS requires WRITE requires UNKNOWN_CHUNKS option WRITE_UNKNOWN_CHUNKS requires WRITE UNKNOWN_CHUNKS
option WRITE_UNKNOWN_CHUNKS enables STORE_UNKNOWN_CHUNKS option WRITE_UNKNOWN_CHUNKS enables STORE_UNKNOWN_CHUNKS
# The first way to read user chunks is to have libpng save them for a later call # The first way to read user chunks is to have libpng save them for a later call
# to png_get_unknown_chunks, the application must call # to png_get_unknown_chunks, the application must call
# png_set_keep_unknown_chunks to cause this to actually happen (see png.h) # png_set_keep_unknown_chunks to cause this to actually happen (see png.h)
option SAVE_UNKNOWN_CHUNKS requires READ requires SET_UNKNOWN_CHUNKS option SAVE_UNKNOWN_CHUNKS requires READ SET_UNKNOWN_CHUNKS HANDLE_AS_UNKNOWN
option SAVE_UNKNOWN_CHUNKS enables READ_UNKNOWN_CHUNKS, STORE_UNKNOWN_CHUNKS option SAVE_UNKNOWN_CHUNKS enables READ_UNKNOWN_CHUNKS STORE_UNKNOWN_CHUNKS
# The second approach is to use an application provided callback to process the # The second approach is to use an application provided callback to process the
# chunks, the callback can either handle the chunk entirely itself or request # chunks, the callback can either handle the chunk entirely itself or request
@ -807,11 +918,11 @@ option READ_USER_CHUNKS enables READ_UNKNOWN_CHUNKS, USER_CHUNKS
# This option no longer affects the write code. It can be safely disabled and # This option no longer affects the write code. It can be safely disabled and
# will prevent applications stopping libpng reading known chunks. # will prevent applications stopping libpng reading known chunks.
option SET_UNKNOWN_CHUNKS requires UNKNOWN_CHUNKS option SET_UNKNOWN_CHUNKS requires UNKNOWN_CHUNKS
option HANDLE_AS_UNKNOWN requires SET_UNKNOWN_CHUNKS option HANDLE_AS_UNKNOWN requires SET_UNKNOWN_CHUNKS READ
# The following options are derived from the above and should not be turned on # The following options are derived from the above and should not be turned on
# explicitly. # explicitly.
option READ_UNKNOWN_CHUNKS requires UNKNOWN_CHUNKS disabled option READ_UNKNOWN_CHUNKS requires READ UNKNOWN_CHUNKS disabled
option STORE_UNKNOWN_CHUNKS requires UNKNOWN_CHUNKS disabled option STORE_UNKNOWN_CHUNKS requires UNKNOWN_CHUNKS disabled
option CONVERT_tIME requires WRITE_ANCILLARY_CHUNKS option CONVERT_tIME requires WRITE_ANCILLARY_CHUNKS
@ -823,11 +934,6 @@ option CONVERT_tIME requires WRITE_ANCILLARY_CHUNKS
option WRITE_FILTER requires WRITE option WRITE_FILTER requires WRITE
option SAVE_INT_32 disabled
# png_save_int_32 is required internally for writing the ancillary chunks oFFs
# and pCAL and for both reading and writing iCCP (for the generation/checking of
# the corresponding cHRM/gAMA chunks) if full ICC is supported.
# added at libpng-1.5.4 # added at libpng-1.5.4
option WRITE_OPTIMIZE_CMF requires WRITE option WRITE_OPTIMIZE_CMF requires WRITE
@ -837,10 +943,6 @@ option READ_iCCP enables READ_COMPRESSED_TEXT
option READ_iTXt enables READ_COMPRESSED_TEXT option READ_iTXt enables READ_COMPRESSED_TEXT
option READ_zTXt enables READ_COMPRESSED_TEXT option READ_zTXt enables READ_COMPRESSED_TEXT
option WRITE_oFFs enables SAVE_INT_32
option WRITE_pCAL enables SAVE_INT_32
option WRITE_cHRM enables SAVE_INT_32
option WRITE_COMPRESSED_TEXT disabled option WRITE_COMPRESSED_TEXT disabled
option WRITE_iCCP enables WRITE_COMPRESSED_TEXT option WRITE_iCCP enables WRITE_COMPRESSED_TEXT
option WRITE_iTXt enables WRITE_COMPRESSED_TEXT option WRITE_iTXt enables WRITE_COMPRESSED_TEXT
@ -849,21 +951,35 @@ option WRITE_zTXt enables WRITE_COMPRESSED_TEXT
# Turn this off to disable png_read_png() and png_write_png() and # Turn this off to disable png_read_png() and png_write_png() and
# leave the row_pointers member out of the info structure. # leave the row_pointers member out of the info structure.
option INFO_IMAGE option INFO_IMAGE disabled
option READ_PNG requires SEQUENTIAL_READ READ_TRANSFORMS enables INFO_IMAGE
option WRITE_PNG requires WRITE WRITE_TRANSFORMS enables INFO_IMAGE
# added at libpng-1.5.10 # There are four options here, two each for read and write. By default they are
# Turn this off to disable warning about invalid palette index and # all switched on.
# leave the num_palette_max member out of the png structure. #
# 1) {READ,WRITE}_CHECK_FOR_INVALID_INDEX: checks PNG colormap data on read or
# write to ensure it does not contain out-of-range palette index values.
# Disabled by -DPNG_NO_CHECK_FOR_INVALID_INDEX
#
# 2) {READ,WRITE}_GET_PALETTE_MAX: returns the largest pixel value in a
# color mapped PNG. Disbaled by -DPNG_NO_GET_PALETTE_MAX
#
# All of this stuff can be removed by "option PALETTE_MAX off" but using
# -DPNG_NO_ defines on the command line just sets the relevant option to
# "disabled", so if you want to *disable* just READ_CHECK_FOR_INVALID_INDEX (for
# example) you need both -DPNG_NO_CHECK_FOR_INVALID_INDEX *and*
# -DPNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
option PALETTE_MAX disabled enables TRANSFORM_MECH
option CHECK_FOR_INVALID_INDEX enables READ_CHECK_FOR_INVALID_INDEX option CHECK_FOR_INVALID_INDEX,
option CHECK_FOR_INVALID_INDEX enables WRITE_CHECK_FOR_INVALID_INDEX enables READ_CHECK_FOR_INVALID_INDEX WRITE_CHECK_FOR_INVALID_INDEX
option READ_CHECK_FOR_INVALID_INDEX requires READ, CHECK_FOR_INVALID_INDEX option READ_CHECK_FOR_INVALID_INDEX requires READ disabled enables PALETTE_MAX
option WRITE_CHECK_FOR_INVALID_INDEX requires WRITE, CHECK_FOR_INVALID_INDEX option WRITE_CHECK_FOR_INVALID_INDEX requires WRITE disabled enables PALETTE_MAX
# added at libpng-1.5.15
option GET_PALETTE_MAX enables READ_GET_PALETTE_MAX WRITE_GET_PALETTE_MAX option GET_PALETTE_MAX enables READ_GET_PALETTE_MAX WRITE_GET_PALETTE_MAX
option READ_GET_PALETTE_MAX requires READ_CHECK_FOR_INVALID_INDEX disabled option READ_GET_PALETTE_MAX requires READ disabled enables PALETTE_MAX
option WRITE_GET_PALETTE_MAX requires WRITE_CHECK_FOR_INVALID_INDEX disabled option WRITE_GET_PALETTE_MAX requires WRITE disabled enables PALETTE_MAX
# Simplified API options (added at libpng-1.6.0) # Simplified API options (added at libpng-1.6.0)
# In libpng 1.6.8 the handling of these options was changed to used 'requires' # In libpng 1.6.8 the handling of these options was changed to used 'requires'
@ -880,7 +996,8 @@ option SIMPLIFIED_READ,
READ_EXPAND, READ_16BIT, READ_EXPAND_16, READ_SCALE_16_TO_8, READ_EXPAND, READ_16BIT, READ_EXPAND_16, READ_SCALE_16_TO_8,
READ_RGB_TO_GRAY, READ_ALPHA_MODE, READ_BACKGROUND, READ_STRIP_ALPHA, READ_RGB_TO_GRAY, READ_ALPHA_MODE, READ_BACKGROUND, READ_STRIP_ALPHA,
READ_FILLER, READ_SWAP, READ_PACK, READ_GRAY_TO_RGB, READ_GAMMA, READ_FILLER, READ_SWAP, READ_PACK, READ_GRAY_TO_RGB, READ_GAMMA,
READ_tRNS, READ_bKGD, READ_gAMA, READ_cHRM, READ_sRGB, READ_sBIT READ_tRNS, READ_bKGD, READ_gAMA, READ_cHRM, READ_sRGB, READ_sBIT,
READ_DEINTERLACE
# AFIRST and BGR read options: # AFIRST and BGR read options:
# Prior to libpng 1.6.8 these were disabled but switched on if the low level # Prior to libpng 1.6.8 these were disabled but switched on if the low level

View File

@ -18,8 +18,6 @@
/* options */ /* options */
#define PNG_16BIT_SUPPORTED #define PNG_16BIT_SUPPORTED
#define PNG_ALIGNED_MEMORY_SUPPORTED #define PNG_ALIGNED_MEMORY_SUPPORTED
/*#undef PNG_ARM_NEON_API_SUPPORTED*/
/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
#define PNG_BENIGN_ERRORS_SUPPORTED #define PNG_BENIGN_ERRORS_SUPPORTED
#define PNG_BENIGN_READ_ERRORS_SUPPORTED #define PNG_BENIGN_READ_ERRORS_SUPPORTED
/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ /*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
@ -43,7 +41,9 @@
#define PNG_INFO_IMAGE_SUPPORTED #define PNG_INFO_IMAGE_SUPPORTED
#define PNG_IO_STATE_SUPPORTED #define PNG_IO_STATE_SUPPORTED
#define PNG_MNG_FEATURES_SUPPORTED #define PNG_MNG_FEATURES_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED #define PNG_MNG_READ_FEATURES_SUPPORTED
#define PNG_MNG_WRITE_FEATURES_SUPPORTED
#define PNG_PALETTE_MAX_SUPPORTED
#define PNG_PROGRESSIVE_READ_SUPPORTED #define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_16BIT_SUPPORTED #define PNG_READ_16BIT_SUPPORTED
#define PNG_READ_ALPHA_MODE_SUPPORTED #define PNG_READ_ALPHA_MODE_SUPPORTED
@ -53,12 +53,14 @@
#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED #define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED #define PNG_READ_COMPOSITE_NODIV_SUPPORTED
#define PNG_READ_COMPRESSED_TEXT_SUPPORTED #define PNG_READ_COMPRESSED_TEXT_SUPPORTED
#define PNG_READ_DEINTERLACE_SUPPORTED
#define PNG_READ_EXPAND_16_SUPPORTED #define PNG_READ_EXPAND_16_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED #define PNG_READ_EXPAND_SUPPORTED
#define PNG_READ_FILLER_SUPPORTED #define PNG_READ_FILLER_SUPPORTED
#define PNG_READ_GAMMA_SUPPORTED #define PNG_READ_GAMMA_SUPPORTED
#define PNG_READ_GET_PALETTE_MAX_SUPPORTED #define PNG_READ_GET_PALETTE_MAX_SUPPORTED
#define PNG_READ_GRAY_TO_RGB_SUPPORTED #define PNG_READ_GRAY_TO_RGB_SUPPORTED
#define PNG_READ_IMAGE_SUPPORTED
#define PNG_READ_INTERLACING_SUPPORTED #define PNG_READ_INTERLACING_SUPPORTED
#define PNG_READ_INT_FUNCTIONS_SUPPORTED #define PNG_READ_INT_FUNCTIONS_SUPPORTED
#define PNG_READ_INVERT_ALPHA_SUPPORTED #define PNG_READ_INVERT_ALPHA_SUPPORTED
@ -66,6 +68,7 @@
#define PNG_READ_OPT_PLTE_SUPPORTED #define PNG_READ_OPT_PLTE_SUPPORTED
#define PNG_READ_PACKSWAP_SUPPORTED #define PNG_READ_PACKSWAP_SUPPORTED
#define PNG_READ_PACK_SUPPORTED #define PNG_READ_PACK_SUPPORTED
#define PNG_READ_PNG_SUPPORTED
#define PNG_READ_QUANTIZE_SUPPORTED #define PNG_READ_QUANTIZE_SUPPORTED
#define PNG_READ_RGB_TO_GRAY_SUPPORTED #define PNG_READ_RGB_TO_GRAY_SUPPORTED
#define PNG_READ_SCALE_16_TO_8_SUPPORTED #define PNG_READ_SCALE_16_TO_8_SUPPORTED
@ -97,10 +100,10 @@
#define PNG_READ_tIME_SUPPORTED #define PNG_READ_tIME_SUPPORTED
#define PNG_READ_tRNS_SUPPORTED #define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_zTXt_SUPPORTED #define PNG_READ_zTXt_SUPPORTED
#define PNG_SAVE_INT_32_SUPPORTED
#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED #define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_SEQUENTIAL_READ_SUPPORTED #define PNG_SEQUENTIAL_READ_SUPPORTED
#define PNG_SETJMP_SUPPORTED #define PNG_SETJMP_SUPPORTED
#define PNG_SETTING_SUPPORTED
#define PNG_SET_OPTION_SUPPORTED #define PNG_SET_OPTION_SUPPORTED
#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED #define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_SET_USER_LIMITS_SUPPORTED #define PNG_SET_USER_LIMITS_SUPPORTED
@ -114,6 +117,8 @@
#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED #define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_TEXT_SUPPORTED #define PNG_TEXT_SUPPORTED
#define PNG_TIME_RFC1123_SUPPORTED #define PNG_TIME_RFC1123_SUPPORTED
#define PNG_TRANFORM_MECH_SUPPORTED
#define PNG_TRANSFORM_MECH_SUPPORTED
#define PNG_UNKNOWN_CHUNKS_SUPPORTED #define PNG_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_USER_CHUNKS_SUPPORTED #define PNG_USER_CHUNKS_SUPPORTED
#define PNG_USER_LIMITS_SUPPORTED #define PNG_USER_LIMITS_SUPPORTED
@ -139,6 +144,7 @@
#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED #define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
#define PNG_WRITE_PACKSWAP_SUPPORTED #define PNG_WRITE_PACKSWAP_SUPPORTED
#define PNG_WRITE_PACK_SUPPORTED #define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_PNG_SUPPORTED
#define PNG_WRITE_SHIFT_SUPPORTED #define PNG_WRITE_SHIFT_SUPPORTED
#define PNG_WRITE_SUPPORTED #define PNG_WRITE_SUPPORTED
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED #define PNG_WRITE_SWAP_ALPHA_SUPPORTED
@ -186,9 +192,9 @@
/* settings */ /* settings */
#define PNG_ABORT { (abort()); } #define PNG_ABORT { (abort()); }
#define PNG_API_RULE 0 #define PNG_API_RULE 0
#define PNG_COST_SHIFT 3 #define PNG_DEFAULT_GAMMA_ACCURACY 665
#define PNG_DEFAULT_READ_MACROS 1 #define PNG_DEFAULT_READ_MACROS 1
#define PNG_GAMMA_THRESHOLD_FIXED 5000 #define PNG_GAMMA_THRESHOLD_FIXED 153
#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE #define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
#define PNG_INFLATE_BUF_SIZE 1024 #define PNG_INFLATE_BUF_SIZE 1024
#define PNG_MAX_GAMMA_8 11 #define PNG_MAX_GAMMA_8 11
@ -201,10 +207,9 @@
#define PNG_USER_CHUNK_MALLOC_MAX 8000000 #define PNG_USER_CHUNK_MALLOC_MAX 8000000
#define PNG_USER_HEIGHT_MAX 1000000 #define PNG_USER_HEIGHT_MAX 1000000
#define PNG_USER_WIDTH_MAX 1000000 #define PNG_USER_WIDTH_MAX 1000000
#define PNG_WEIGHT_SHIFT 8
#define PNG_ZBUF_SIZE 8192 #define PNG_ZBUF_SIZE 8192
#define PNG_ZLIB_HEADER <zlib.h> #define PNG_ZLIB_HEADER <zlib.h>
#define PNG_ZLIB_VERNUM 0 /* unknown */ #define PNG_ZLIB_VERNUM 0
#define PNG_Z_DEFAULT_COMPRESSION (-1) #define PNG_Z_DEFAULT_COMPRESSION (-1)
#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 #define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
#define PNG_Z_DEFAULT_STRATEGY 1 #define PNG_Z_DEFAULT_STRATEGY 1

View File

@ -204,7 +204,6 @@ EXPORTS
png_get_int_32 @203 png_get_int_32 @203
png_get_uint_31 @204 png_get_uint_31 @204
png_save_uint_32 @205 png_save_uint_32 @205
png_save_int_32 @206
png_save_uint_16 @207 png_save_uint_16 @207
png_set_gamma_fixed @208 png_set_gamma_fixed @208
png_set_filter_heuristics_fixed @209 png_set_filter_heuristics_fixed @209
@ -243,3 +242,7 @@ EXPORTS
png_set_check_for_invalid_index @242 png_set_check_for_invalid_index @242
png_get_palette_max @243 png_get_palette_max @243
png_set_option @244 png_set_option @244
png_memory_format @245
png_memory_channel_depth @246
png_memory_gamma @247
png_setting @248

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec ./pngimage --exhaustive --log "${srcdir}/contrib/pngsuite/"*.png exec ./pngimage --exhaustive --list-combos --log "${srcdir}/contrib/pngsuite/"*.png

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec ./pngimage --log "${srcdir}/contrib/pngsuite/"*.png exec ./pngimage --list-combos --log "${srcdir}/contrib/pngsuite/"*.png

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec ./pngunknown default=discard IDAT=save "${srcdir}/pngtest.png" exec ./pngunknown --strict default=discard IDAT=save "${srcdir}/pngtest.png"

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec ./pngunknown default=discard "${srcdir}/pngtest.png" exec ./pngunknown --strict default=discard "${srcdir}/pngtest.png"

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec ./pngunknown default=if-safe "${srcdir}/pngtest.png" exec ./pngunknown --strict default=if-safe "${srcdir}/pngtest.png"

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec ./pngunknown bKGD=save cHRM=save gAMA=save all=discard iCCP=save sBIT=save sRGB=save "${srcdir}/pngtest.png" exec ./pngunknown --strict bKGD=save cHRM=save gAMA=save all=discard iCCP=save sBIT=save sRGB=save "${srcdir}/pngtest.png"

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec ./pngunknown sTER=if-safe "${srcdir}/pngtest.png" exec ./pngunknown --strict sTER=if-safe "${srcdir}/pngtest.png"

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec ./pngunknown default=save "${srcdir}/pngtest.png" exec ./pngunknown --strict default=save "${srcdir}/pngtest.png"

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec ./pngunknown vpAg=if-safe "${srcdir}/pngtest.png" exec ./pngunknown --strict vpAg=if-safe "${srcdir}/pngtest.png"

View File

@ -1,2 +1,2 @@
#!/bin/sh #!/bin/sh
exec ./pngvalid --standard --progressive-read exec ./pngvalid --standard