Update libpng

This commit is contained in:
Luke Street 2020-10-21 00:40:02 -04:00 committed by Luke Street
parent e4d95e768c
commit ced84a1eb8
31 changed files with 5947 additions and 3252 deletions

View File

@ -1,8 +1,19 @@
if(NOT WIN32 AND NOT APPLE) # remove WIN32 when specter/freetype is gone if(NOT WIN32 AND NOT APPLE AND NOT NX) # remove WIN32 when specter/freetype is gone
find_library(PNG_LIB NAMES png libpng) find_library(PNG_LIB NAMES png libpng)
endif() endif()
if(NOT PNG_LIB) if(NOT PNG_LIB)
message(STATUS "Using HECL's built-in libpng") message(STATUS "Using HECL's built-in libpng")
if(NX)
set(INTRINSICS
arm/arm_init.c
arm/filter_neon.S
arm/filter_neon_intrinsics.c
arm/palette_neon_intrinsics.c)
else()
set(INTRINSICS
intel/filter_sse2_intrinsics.c
intel/intel_init.c)
endif()
add_library(png add_library(png
png.h png.h
pngconf.h pngconf.h
@ -26,7 +37,8 @@ add_library(png
pngwio.c pngwio.c
pngwrite.c pngwrite.c
pngwtran.c pngwtran.c
pngwutil.c) pngwutil.c
${INTRINSICS})
target_link_libraries(png PUBLIC ${ZLIB_LIBRARIES}) target_link_libraries(png PUBLIC ${ZLIB_LIBRARIES})
target_include_directories(png PUBLIC ${ZLIB_INCLUDE_DIR}) target_include_directories(png PUBLIC ${ZLIB_INCLUDE_DIR})
set(PNG_LIBRARIES png CACHE PATH "PNG libraries" FORCE) set(PNG_LIBRARIES png CACHE PATH "PNG libraries" FORCE)

View File

@ -1,15 +1,16 @@
README for libpng version 1.6.19 - November 12, 2015 (shared library 16.0) README for libpng version 1.6.37 - April 14, 2019
See the note about version numbers near the top of png.h =================================================
See the note about version numbers near the top of png.h.
See INSTALL for instructions on how to install libpng. See INSTALL for instructions on how to install libpng.
Libpng comes in several distribution formats. Get libpng-*.tar.gz or Libpng comes in several distribution formats. Get libpng-*.tar.gz or
libpng-*.tar.xz or if you want UNIX-style line endings in the text files, libpng-*.tar.xz or if you want UNIX-style line endings in the text
or lpng*.7z or lpng*.zip if you want DOS-style line endings. files, or lpng*.7z or lpng*.zip if you want DOS-style line endings.
Version 0.89 was the first official release of libpng. Don't let the Version 0.89 was the first official release of libpng. Don't let the
fact that it's the first release fool you. The libpng library has been in fact that it's the first release fool you. The libpng library has been
extensive use and testing since mid-1995. By late 1997 it had in extensive use and testing since mid-1995. By late 1997 it had
finally gotten to the stage where there hadn't been significant finally gotten to the stage where there hadn't been significant
changes to the API in some time, and people have a bad feeling about changes to the API in some time, and people have a bad feeling about
libraries with versions < 1.0. Version 1.0.0 was released in libraries with versions < 1.0. Version 1.0.0 was released in
@ -23,7 +24,7 @@ earlier versions if you are using a shared library. The type of the
png_uint_32, which will affect shared-library applications that use png_uint_32, which will affect shared-library applications that use
this function. this function.
To avoid problems with changes to the internals of png info_struct, To avoid problems with changes to the internals of the png info_struct,
new APIs have been made available in 0.95 to avoid direct application new APIs have been made available in 0.95 to avoid direct application
access to info_ptr. These functions are the png_set_<chunk> and access to info_ptr. These functions are the png_set_<chunk> and
png_get_<chunk> functions. These functions should be used when png_get_<chunk> functions. These functions should be used when
@ -60,94 +61,59 @@ the library action on the detection of chunk CRC errors. It is possible
to set different actions based on whether the CRC error occurred in a to set different actions based on whether the CRC error occurred in a
critical or an ancillary chunk. critical or an ancillary chunk.
The changes made to the library, and bugs fixed are based on discussions For a detailed description on using libpng, read libpng-manual.txt.
on the PNG-implement mailing list and not on material submitted For examples of libpng in a program, see example.c and pngtest.c. For
privately to Guy, Andreas, or Glenn. They will forward any good usage information and restrictions (what little they are) on libpng,
suggestions to the list. see png.h. For a description on using zlib (the compression library
used by libpng) and zlib's restrictions, see zlib.h
For a detailed description on using libpng, read libpng-manual.txt. For
examples of libpng in a program, see example.c and pngtest.c. For usage
information and restrictions (what little they are) on libpng, see
png.h. For a description on using zlib (the compression library used by
libpng) and zlib's restrictions, see zlib.h
I have included a general makefile, as well as several machine and I have included a general makefile, as well as several machine and
compiler specific ones, but you may have to modify one for your own needs. compiler specific ones, but you may have to modify one for your own
needs.
You should use zlib 1.0.4 or later to run this, but it MAY work with You should use zlib 1.0.4 or later to run this, but it MAY work with
versions as old as zlib 0.95. Even so, there are bugs in older zlib versions as old as zlib 0.95. Even so, there are bugs in older zlib
versions which can cause the output of invalid compression streams for versions which can cause the output of invalid compression streams for
some images. You will definitely need zlib 1.0.4 or later if you are some images.
taking advantage of the MS-DOS "far" structure allocation for the small
and medium memory models. You should also note that zlib is a
compression library that is useful for more things than just PNG files.
You can use zlib as a drop-in replacement for fread() and fwrite() if
you are so inclined.
zlib should be available at the same place that libpng is, or at zlib.net. You should also note that zlib is a compression library that is useful
for more things than just PNG files. You can use zlib as a drop-in
replacement for fread() and fwrite(), if you are so inclined.
zlib should be available at the same place that libpng is, or at
https://zlib.net.
You may also want a copy of the PNG specification. It is available You may also want a copy of the PNG specification. It is available
as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
these at http://www.libpng.org/pub/png/documents/ these at http://www.libpng.org/pub/png/pngdocs.html .
This code is currently being archived at libpng.sf.net in the This code is currently being archived at libpng.sourceforge.io in the
[DOWNLOAD] area, and at ftp://ftp.simplesystems.org. If you can't find it [DOWNLOAD] area, and at http://libpng.download/src .
in any of those places, e-mail me, and I'll help you find it.
I am not a lawyer, but I believe that the Export Control Classification This release, based in a large way on Glenn's, Guy's and Andreas'
Number (ECCN) for libpng is EAR99, which means not subject to export earlier work, was created and will be supported by myself and the PNG
controls or International Traffic in Arms Regulations (ITAR) because it
is open source, publicly available software, that does not contain any
encryption software. See the EAR, paragraphs 734.3(b)(3) and 734.7(b).
If you have any code changes, requests, problems, etc., please e-mail
them to me. Also, I'd appreciate any make files or project files,
and any modifications you needed to make to get libpng to compile,
along with a #define variable to tell what compiler/system you are on.
If you needed to add transformations to libpng, or wish libpng would
provide the image in a different way, drop me a note (and code, if
possible), so I can consider supporting the transformation.
Finally, if you get any warning messages when compiling libpng
(note: not zlib), and they are easy to fix, I'd appreciate the
fix. Please mention "libpng" somewhere in the subject line. Thanks.
This release was created and will be supported by myself (of course
based in a large way on Guy's and Andreas' earlier work), and the PNG
development group. development group.
Send comments/corrections/commendations to png-mng-implement at Send comments/corrections/commendations to png-mng-implement at
lists.sourceforge.net (subscription required; visit lists.sourceforge.net (subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement https://lists.sourceforge.net/lists/listinfo/png-mng-implement
to subscribe) or to glennrp at users.sourceforge.net to subscribe).
You can't reach Guy, the original libpng author, at the addresses Send general questions about the PNG specification to png-mng-misc
given in previous versions of this document. He and Andreas will at lists.sourceforge.net (subscription required; visit
read mail addressed to the png-implement list, however.
Please do not send general questions about PNG. Send them to
png-mng-misc at lists.sf.net (subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-misc to https://lists.sourceforge.net/lists/listinfo/png-mng-misc to
subscribe). If you have a question about something subscribe).
in the PNG specification that is related to using libpng, send it
to me. Send me any questions that start with "I was using libpng,
and ...". If in doubt, send questions to me. I'll bounce them
to others, if necessary.
Please do not send suggestions on how to change PNG. We have
been discussing PNG for twenty years now, and it is official and
finished. If you have suggestions for libpng, however, I'll
gladly listen. Even if your suggestion is not used immediately,
it may be used later.
Files in this distribution: Files in this distribution:
ANNOUNCE => Announcement of this version, with recent changes ANNOUNCE => Announcement of this version, with recent changes
AUTHORS => List of contributing authors
CHANGES => Description of changes between libpng versions CHANGES => Description of changes between libpng versions
KNOWNBUG => List of known bugs and deficiencies KNOWNBUG => List of known bugs and deficiencies
LICENSE => License to use and redistribute libpng LICENSE => License to use and redistribute libpng
README => This file README => This file
TODO => Things not implemented in the current library TODO => Things not implemented in the current library
Y2KINFO => Statement of Y2K compliance TRADEMARK => Trademark information
example.c => Example code for using libpng functions example.c => Example code for using libpng functions
libpng.3 => manual page for libpng (includes libpng-manual.txt) libpng.3 => manual page for libpng (includes libpng-manual.txt)
libpng-manual.txt => Description of libpng and its functions libpng-manual.txt => Description of libpng and its functions
@ -179,18 +145,25 @@ Files in this distribution:
pngwtran.c => Write data transformations pngwtran.c => Write data transformations
pngwutil.c => Write utility functions pngwutil.c => Write utility functions
arm => Contains optimized code for the ARM platform arm => Contains optimized code for the ARM platform
powerpc => Contains optimized code for the PowerPC platform
contrib => Contributions contrib => Contributions
arm-neon => Optimized code for ARM-NEON platform
powerpc-vsx => Optimized code for POWERPC-VSX platform
examples => Example programs examples => Example programs
gregbook => source code for PNG reading and writing, from gregbook => source code for PNG reading and writing, from
Greg Roelofs' "PNG: The Definitive Guide", Greg Roelofs' "PNG: The Definitive Guide",
O'Reilly, 1999 O'Reilly, 1999
libtests => Test programs libtests => Test programs
mips-msa => Optimized code for MIPS-MSA platform
pngminim => Minimal decoder, encoder, and progressive decoder pngminim => Minimal decoder, encoder, and progressive decoder
programs demonstrating use of pngusr.dfa programs demonstrating use of pngusr.dfa
pngminus => Simple pnm2png and png2pnm programs pngminus => Simple pnm2png and png2pnm programs
pngsuite => Test images pngsuite => Test images
testpngs
tools => Various tools tools => Various tools
visupng => Contains a MSVC workspace for VisualPng visupng => Contains a MSVC workspace for VisualPng
intel => Optimized code for INTEL-SSE2 platform
mips => Optimized code for MIPS platform
projects => Contains project files and workspaces for projects => Contains project files and workspaces for
building a DLL building a DLL
owatcom => Contains a WATCOM project for building libpng owatcom => Contains a WATCOM project for building libpng
@ -201,15 +174,10 @@ Files in this distribution:
scripts => Directory containing scripts for building libpng: scripts => Directory containing scripts for building libpng:
(see scripts/README.txt for the list of scripts) (see scripts/README.txt for the list of scripts)
Good luck, and happy coding. Good luck, and happy coding!
-Glenn Randers-Pehrson (current maintainer, since 1998) * Cosmin Truta (current maintainer, since 2018)
Internet: glennrp at users.sourceforge.net * Glenn Randers-Pehrson (former maintainer, 1998-2018)
* Andreas Eric Dilger (former maintainer, 1996-1997)
-Andreas Eric Dilger (former maintainer, 1996-1997) * Guy Eric Schalnat (original author and former maintainer, 1995-1996)
Internet: adilger at enel.ucalgary.ca (formerly of Group 42, Inc.)
Web: http://www-mddsp.enel.ucalgary.ca/People/adilger/
-Guy Eric Schalnat (original author and former maintainer, 1995-1996)
(formerly of Group 42, Inc)
Internet: gschal at infinet.com

136
hecl/extern/libpng/arm/arm_init.c vendored Normal file
View File

@ -0,0 +1,136 @@
/* arm_init.c - NEON optimised filter functions
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are
* called.
*/
#define _POSIX_SOURCE 1
#include "../pngpriv.h"
#ifdef PNG_READ_SUPPORTED
#if PNG_ARM_NEON_OPT > 0
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED /* Do run-time checks */
/* WARNING: it is strongly recommended that you do not build libpng with
* run-time checks for CPU features if at all possible. In the case of the ARM
* NEON instructions there is no processor-specific way of detecting the
* presence of the required support, therefore run-time detection is extremely
* OS specific.
*
* You may set the macro PNG_ARM_NEON_FILE to the file name of file containing
* a fragment of C source code which defines the png_have_neon function. There
* are a number of implementations in contrib/arm-neon, but the only one that
* has partial support is contrib/arm-neon/linux.c - a generic Linux
* implementation which reads /proc/cpufino.
*/
#ifndef PNG_ARM_NEON_FILE
# ifdef __linux__
# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
# endif
#endif
#ifdef PNG_ARM_NEON_FILE
#include <signal.h> /* for sig_atomic_t */
static int png_have_neon(png_structp png_ptr);
#include PNG_ARM_NEON_FILE
#else /* PNG_ARM_NEON_FILE */
# error "PNG_ARM_NEON_FILE undefined: no support for run-time ARM NEON checks"
#endif /* PNG_ARM_NEON_FILE */
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
#endif
void
png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
{
/* The switch statement is compiled in for ARM_NEON_API, the call to
* png_have_neon is compiled in for ARM_NEON_CHECK. If both are defined
* the check is only performed if the API has not set the NEON option on
* or off explicitly. In this case the check controls what happens.
*
* If the CHECK is not compiled in and the option is UNSET the behavior prior
* to 1.6.7 was to use the NEON code - this was a bug caused by having the
* wrong order of the 'ON' and 'default' cases. UNSET now defaults to OFF,
* as documented in png.h
*/
png_debug(1, "in png_init_filter_functions_neon");
#ifdef PNG_ARM_NEON_API_SUPPORTED
switch ((pp->options >> PNG_ARM_NEON) & 3)
{
case PNG_OPTION_UNSET:
/* Allow the run-time check to execute if it has been enabled -
* thus both API and CHECK can be turned on. If it isn't supported
* this case will fall through to the 'default' below, which just
* returns.
*/
#endif /* PNG_ARM_NEON_API_SUPPORTED */
#ifdef PNG_ARM_NEON_CHECK_SUPPORTED
{
static volatile sig_atomic_t no_neon = -1; /* not checked */
if (no_neon < 0)
no_neon = !png_have_neon(pp);
if (no_neon)
return;
}
#ifdef PNG_ARM_NEON_API_SUPPORTED
break;
#endif
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
#ifdef PNG_ARM_NEON_API_SUPPORTED
default: /* OFF or INVALID */
return;
case PNG_OPTION_ON:
/* Option turned on */
break;
}
#endif
/* IMPORTANT: any new external functions used here must be declared using
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
* 'prefix' option to configure works:
*
* ./configure --with-libpng-prefix=foobar_
*
* Verify you have got this right by running the above command, doing a build
* and examining pngprefix.h; it must contain a #define for every external
* function you add. (Notice that this happens automatically for the
* initialization function.)
*/
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
if (bpp == 3)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
png_read_filter_row_paeth3_neon;
}
else if (bpp == 4)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
png_read_filter_row_paeth4_neon;
}
}
#endif /* PNG_ARM_NEON_OPT > 0 */
#endif /* READ */

253
hecl/extern/libpng/arm/filter_neon.S vendored Normal file
View File

@ -0,0 +1,253 @@
/* filter_neon.S - NEON optimised filter functions
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2017 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* This is required to get the symbol renames, which are #defines, and the
* definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
*/
#define PNG_VERSION_INFO_ONLY
#include "../pngpriv.h"
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
#endif
#ifdef PNG_READ_SUPPORTED
/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for
* ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it
* only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h
* for the logic which sets PNG_USE_ARM_NEON_ASM:
*/
#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */
#if PNG_ARM_NEON_OPT > 0
#ifdef __ELF__
# define ELF
#else
# define ELF @
#endif
.arch armv7-a
.fpu neon
.macro func name, export=0
.macro endfunc
ELF .size \name, . - \name
.endfunc
.purgem endfunc
.endm
.text
/* Explicitly specifying alignment here because some versions of
* GAS don't align code correctly. This is harmless in correctly
* written versions of GAS.
*/
.align 2
.if \export
.global \name
.endif
ELF .type \name, STT_FUNC
.func \name
\name:
.endm
func png_read_filter_row_sub4_neon, export=1
ldr r3, [r0, #4] @ rowbytes
vmov.i8 d3, #0
1:
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
vadd.u8 d0, d3, d4
vadd.u8 d1, d0, d5
vadd.u8 d2, d1, d6
vadd.u8 d3, d2, d7
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
subs r3, r3, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_sub3_neon, export=1
ldr r3, [r0, #4] @ rowbytes
vmov.i8 d3, #0
mov r0, r1
mov r2, #3
mov r12, #12
vld1.8 {q11}, [r0], r12
1:
vext.8 d5, d22, d23, #3
vadd.u8 d0, d3, d22
vext.8 d6, d22, d23, #6
vadd.u8 d1, d0, d5
vext.8 d7, d23, d23, #1
vld1.8 {q11}, [r0], r12
vst1.32 {d0[0]}, [r1,:32], r2
vadd.u8 d2, d1, d6
vst1.32 {d1[0]}, [r1], r2
vadd.u8 d3, d2, d7
vst1.32 {d2[0]}, [r1], r2
vst1.32 {d3[0]}, [r1], r2
subs r3, r3, #12
bgt 1b
bx lr
endfunc
func png_read_filter_row_up_neon, export=1
ldr r3, [r0, #4] @ rowbytes
1:
vld1.8 {q0}, [r1,:128]
vld1.8 {q1}, [r2,:128]!
vadd.u8 q0, q0, q1
vst1.8 {q0}, [r1,:128]!
subs r3, r3, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_avg4_neon, export=1
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
1:
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
vhadd.u8 d0, d3, d16
vadd.u8 d0, d0, d4
vhadd.u8 d1, d0, d17
vadd.u8 d1, d1, d5
vhadd.u8 d2, d1, d18
vadd.u8 d2, d2, d6
vhadd.u8 d3, d2, d19
vadd.u8 d3, d3, d7
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
subs r12, r12, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_avg3_neon, export=1
push {r4,lr}
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
mov r0, r1
mov r4, #3
mov lr, #12
vld1.8 {q11}, [r0], lr
1:
vld1.8 {q10}, [r2], lr
vext.8 d5, d22, d23, #3
vhadd.u8 d0, d3, d20
vext.8 d17, d20, d21, #3
vadd.u8 d0, d0, d22
vext.8 d6, d22, d23, #6
vhadd.u8 d1, d0, d17
vext.8 d18, d20, d21, #6
vadd.u8 d1, d1, d5
vext.8 d7, d23, d23, #1
vld1.8 {q11}, [r0], lr
vst1.32 {d0[0]}, [r1,:32], r4
vhadd.u8 d2, d1, d18
vst1.32 {d1[0]}, [r1], r4
vext.8 d19, d21, d21, #1
vadd.u8 d2, d2, d6
vhadd.u8 d3, d2, d19
vst1.32 {d2[0]}, [r1], r4
vadd.u8 d3, d3, d7
vst1.32 {d3[0]}, [r1], r4
subs r12, r12, #12
bgt 1b
pop {r4,pc}
endfunc
.macro paeth rx, ra, rb, rc
vaddl.u8 q12, \ra, \rb @ a + b
vaddl.u8 q15, \rc, \rc @ 2*c
vabdl.u8 q13, \rb, \rc @ pa
vabdl.u8 q14, \ra, \rc @ pb
vabd.u16 q15, q12, q15 @ pc
vcle.u16 q12, q13, q14 @ pa <= pb
vcle.u16 q13, q13, q15 @ pa <= pc
vcle.u16 q14, q14, q15 @ pb <= pc
vand q12, q12, q13 @ pa <= pb && pa <= pc
vmovn.u16 d28, q14
vmovn.u16 \rx, q12
vbsl d28, \rb, \rc
vbsl \rx, \ra, d28
.endm
func png_read_filter_row_paeth4_neon, export=1
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
vmov.i8 d20, #0
1:
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
paeth d0, d3, d16, d20
vadd.u8 d0, d0, d4
paeth d1, d0, d17, d16
vadd.u8 d1, d1, d5
paeth d2, d1, d18, d17
vadd.u8 d2, d2, d6
paeth d3, d2, d19, d18
vmov d20, d19
vadd.u8 d3, d3, d7
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
subs r12, r12, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_paeth3_neon, export=1
push {r4,lr}
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
vmov.i8 d4, #0
mov r0, r1
mov r4, #3
mov lr, #12
vld1.8 {q11}, [r0], lr
1:
vld1.8 {q10}, [r2], lr
paeth d0, d3, d20, d4
vext.8 d5, d22, d23, #3
vadd.u8 d0, d0, d22
vext.8 d17, d20, d21, #3
paeth d1, d0, d17, d20
vst1.32 {d0[0]}, [r1,:32], r4
vext.8 d6, d22, d23, #6
vadd.u8 d1, d1, d5
vext.8 d18, d20, d21, #6
paeth d2, d1, d18, d17
vext.8 d7, d23, d23, #1
vld1.8 {q11}, [r0], lr
vst1.32 {d1[0]}, [r1], r4
vadd.u8 d2, d2, d6
vext.8 d19, d21, d21, #1
paeth d3, d2, d19, d18
vst1.32 {d2[0]}, [r1], r4
vmov d4, d19
vadd.u8 d3, d3, d7
vst1.32 {d3[0]}, [r1], r4
subs r12, r12, #12
bgt 1b
pop {r4,pc}
endfunc
#endif /* PNG_ARM_NEON_OPT > 0 */
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */
#endif /* READ */

View File

@ -0,0 +1,402 @@
/* filter_neon_intrinsics.c - NEON optimised filter functions
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2016 Glenn Randers-Pehrson
* Written by James Yu <james.yu at linaro.org>, October 2013.
* Based on filter_neon.S, written by Mans Rullgard, 2011.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#include "../pngpriv.h"
#ifdef PNG_READ_SUPPORTED
/* This code requires -mfpu=neon on the command line: */
#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
#if defined(_MSC_VER) && defined(_M_ARM64)
# include <arm64_neon.h>
#else
# include <arm_neon.h>
#endif
/* libpng row pointers are not necessarily aligned to any particular boundary,
* however this code will only work with appropriate alignment. arm/arm_init.c
* checks for this (and will not compile unless it is done). This code uses
* variants of png_aligncast to avoid compiler warnings.
*/
#define png_ptr(type,pointer) png_aligncast(type *,pointer)
#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer)
/* The following relies on a variable 'temp_pointer' being declared with type
* 'type'. This is written this way just to hide the GCC strict aliasing
* warning; note that the code is safe because there never is an alias between
* the input and output pointers.
*
* When compiling with MSVC ARM64, the png_ldr macro can't be passed directly
* to vst4_lane_u32, because of an internal compiler error inside MSVC.
* To avoid this compiler bug, we use a temporary variable (vdest_val) to store
* the result of png_ldr.
*/
#define png_ldr(type,pointer)\
(temp_pointer = png_ptr(type,pointer), *temp_pointer)
#if PNG_ARM_NEON_OPT > 0
void
png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes;
png_const_bytep pp = prev_row;
png_debug(1, "in png_read_filter_row_up_neon");
for (; rp < rp_stop; rp += 16, pp += 16)
{
uint8x16_t qrp, qpp;
qrp = vld1q_u8(rp);
qpp = vld1q_u8(pp);
qrp = vaddq_u8(qrp, qpp);
vst1q_u8(rp, qrp);
}
}
void
png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes;
uint8x16_t vtmp = vld1q_u8(rp);
uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp);
uint8x8x2_t vrp = *vrpt;
uint8x8x4_t vdest;
vdest.val[3] = vdup_n_u8(0);
png_debug(1, "in png_read_filter_row_sub3_neon");
for (; rp < rp_stop;)
{
uint8x8_t vtmp1, vtmp2;
uint32x2_t *temp_pointer;
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
vtmp2 = vext_u8(vrp.val[0], vrp.val[1], 6);
vdest.val[1] = vadd_u8(vdest.val[0], vtmp1);
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
vdest.val[2] = vadd_u8(vdest.val[1], vtmp2);
vdest.val[3] = vadd_u8(vdest.val[2], vtmp1);
vtmp = vld1q_u8(rp + 12);
vrpt = png_ptr(uint8x8x2_t, &vtmp);
vrp = *vrpt;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
rp += 3;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
rp += 3;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
rp += 3;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
rp += 3;
}
PNG_UNUSED(prev_row)
}
void
png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes;
uint8x8x4_t vdest;
vdest.val[3] = vdup_n_u8(0);
png_debug(1, "in png_read_filter_row_sub4_neon");
for (; rp < rp_stop; rp += 16)
{
uint32x2x4_t vtmp = vld4_u32(png_ptr(uint32_t,rp));
uint8x8x4_t *vrpt = png_ptr(uint8x8x4_t,&vtmp);
uint8x8x4_t vrp = *vrpt;
uint32x2x4_t *temp_pointer;
uint32x2x4_t vdest_val;
vdest.val[0] = vadd_u8(vdest.val[3], vrp.val[0]);
vdest.val[1] = vadd_u8(vdest.val[0], vrp.val[1]);
vdest.val[2] = vadd_u8(vdest.val[1], vrp.val[2]);
vdest.val[3] = vadd_u8(vdest.val[2], vrp.val[3]);
vdest_val = png_ldr(uint32x2x4_t, &vdest);
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
PNG_UNUSED(prev_row)
}
void
png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
png_bytep rp = row;
png_const_bytep pp = prev_row;
png_bytep rp_stop = row + row_info->rowbytes;
uint8x16_t vtmp;
uint8x8x2_t *vrpt;
uint8x8x2_t vrp;
uint8x8x4_t vdest;
vdest.val[3] = vdup_n_u8(0);
vtmp = vld1q_u8(rp);
vrpt = png_ptr(uint8x8x2_t,&vtmp);
vrp = *vrpt;
png_debug(1, "in png_read_filter_row_avg3_neon");
for (; rp < rp_stop; pp += 12)
{
uint8x8_t vtmp1, vtmp2, vtmp3;
uint8x8x2_t *vppt;
uint8x8x2_t vpp;
uint32x2_t *temp_pointer;
vtmp = vld1q_u8(pp);
vppt = png_ptr(uint8x8x2_t,&vtmp);
vpp = *vppt;
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
vtmp3 = vext_u8(vrp.val[0], vrp.val[1], 6);
vdest.val[1] = vhadd_u8(vdest.val[0], vtmp2);
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 6);
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
vtmp = vld1q_u8(rp + 12);
vrpt = png_ptr(uint8x8x2_t,&vtmp);
vrp = *vrpt;
vdest.val[2] = vhadd_u8(vdest.val[1], vtmp2);
vdest.val[2] = vadd_u8(vdest.val[2], vtmp3);
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
vdest.val[3] = vhadd_u8(vdest.val[2], vtmp2);
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
rp += 3;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
rp += 3;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
rp += 3;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
rp += 3;
}
}
void
png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes;
png_const_bytep pp = prev_row;
uint8x8x4_t vdest;
vdest.val[3] = vdup_n_u8(0);
png_debug(1, "in png_read_filter_row_avg4_neon");
for (; rp < rp_stop; rp += 16, pp += 16)
{
uint32x2x4_t vtmp;
uint8x8x4_t *vrpt, *vppt;
uint8x8x4_t vrp, vpp;
uint32x2x4_t *temp_pointer;
uint32x2x4_t vdest_val;
vtmp = vld4_u32(png_ptr(uint32_t,rp));
vrpt = png_ptr(uint8x8x4_t,&vtmp);
vrp = *vrpt;
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
vppt = png_ptr(uint8x8x4_t,&vtmp);
vpp = *vppt;
vdest.val[0] = vhadd_u8(vdest.val[3], vpp.val[0]);
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
vdest.val[1] = vhadd_u8(vdest.val[0], vpp.val[1]);
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
vdest.val[2] = vhadd_u8(vdest.val[1], vpp.val[2]);
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]);
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
vdest_val = png_ldr(uint32x2x4_t, &vdest);
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
}
static uint8x8_t
paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c)
{
uint8x8_t d, e;
uint16x8_t p1, pa, pb, pc;
p1 = vaddl_u8(a, b); /* a + b */
pc = vaddl_u8(c, c); /* c * 2 */
pa = vabdl_u8(b, c); /* pa */
pb = vabdl_u8(a, c); /* pb */
pc = vabdq_u16(p1, pc); /* pc */
p1 = vcleq_u16(pa, pb); /* pa <= pb */
pa = vcleq_u16(pa, pc); /* pa <= pc */
pb = vcleq_u16(pb, pc); /* pb <= pc */
p1 = vandq_u16(p1, pa); /* pa <= pb && pa <= pc */
d = vmovn_u16(pb);
e = vmovn_u16(p1);
d = vbsl_u8(d, b, c);
e = vbsl_u8(e, a, d);
return e;
}
void
png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
png_bytep rp = row;
png_const_bytep pp = prev_row;
png_bytep rp_stop = row + row_info->rowbytes;
uint8x16_t vtmp;
uint8x8x2_t *vrpt;
uint8x8x2_t vrp;
uint8x8_t vlast = vdup_n_u8(0);
uint8x8x4_t vdest;
vdest.val[3] = vdup_n_u8(0);
vtmp = vld1q_u8(rp);
vrpt = png_ptr(uint8x8x2_t,&vtmp);
vrp = *vrpt;
png_debug(1, "in png_read_filter_row_paeth3_neon");
for (; rp < rp_stop; pp += 12)
{
uint8x8x2_t *vppt;
uint8x8x2_t vpp;
uint8x8_t vtmp1, vtmp2, vtmp3;
uint32x2_t *temp_pointer;
vtmp = vld1q_u8(pp);
vppt = png_ptr(uint8x8x2_t,&vtmp);
vpp = *vppt;
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 3);
vtmp2 = vext_u8(vpp.val[0], vpp.val[1], 3);
vdest.val[1] = paeth(vdest.val[0], vtmp2, vpp.val[0]);
vdest.val[1] = vadd_u8(vdest.val[1], vtmp1);
vtmp1 = vext_u8(vrp.val[0], vrp.val[1], 6);
vtmp3 = vext_u8(vpp.val[0], vpp.val[1], 6);
vdest.val[2] = paeth(vdest.val[1], vtmp3, vtmp2);
vdest.val[2] = vadd_u8(vdest.val[2], vtmp1);
vtmp1 = vext_u8(vrp.val[1], vrp.val[1], 1);
vtmp2 = vext_u8(vpp.val[1], vpp.val[1], 1);
vtmp = vld1q_u8(rp + 12);
vrpt = png_ptr(uint8x8x2_t,&vtmp);
vrp = *vrpt;
vdest.val[3] = paeth(vdest.val[2], vtmp2, vtmp3);
vdest.val[3] = vadd_u8(vdest.val[3], vtmp1);
vlast = vtmp2;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[0]), 0);
rp += 3;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[1]), 0);
rp += 3;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[2]), 0);
rp += 3;
vst1_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2_t,&vdest.val[3]), 0);
rp += 3;
}
}
void
png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
png_bytep rp = row;
png_bytep rp_stop = row + row_info->rowbytes;
png_const_bytep pp = prev_row;
uint8x8_t vlast = vdup_n_u8(0);
uint8x8x4_t vdest;
vdest.val[3] = vdup_n_u8(0);
png_debug(1, "in png_read_filter_row_paeth4_neon");
for (; rp < rp_stop; rp += 16, pp += 16)
{
uint32x2x4_t vtmp;
uint8x8x4_t *vrpt, *vppt;
uint8x8x4_t vrp, vpp;
uint32x2x4_t *temp_pointer;
uint32x2x4_t vdest_val;
vtmp = vld4_u32(png_ptr(uint32_t,rp));
vrpt = png_ptr(uint8x8x4_t,&vtmp);
vrp = *vrpt;
vtmp = vld4_u32(png_ptrc(uint32_t,pp));
vppt = png_ptr(uint8x8x4_t,&vtmp);
vpp = *vppt;
vdest.val[0] = paeth(vdest.val[3], vpp.val[0], vlast);
vdest.val[0] = vadd_u8(vdest.val[0], vrp.val[0]);
vdest.val[1] = paeth(vdest.val[0], vpp.val[1], vpp.val[0]);
vdest.val[1] = vadd_u8(vdest.val[1], vrp.val[1]);
vdest.val[2] = paeth(vdest.val[1], vpp.val[2], vpp.val[1]);
vdest.val[2] = vadd_u8(vdest.val[2], vrp.val[2]);
vdest.val[3] = paeth(vdest.val[2], vpp.val[3], vpp.val[2]);
vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]);
vlast = vpp.val[3];
vdest_val = png_ldr(uint32x2x4_t, &vdest);
vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0);
}
}
#endif /* PNG_ARM_NEON_OPT > 0 */
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 1 (intrinsics) */
#endif /* READ */

View File

@ -0,0 +1,149 @@
/* palette_neon_intrinsics.c - NEON optimised palette expansion functions
*
* Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 2017-2018 Arm Holdings. All rights reserved.
* Written by Richard Townsend <Richard.Townsend@arm.com>, February 2017.
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#include "../pngpriv.h"
#if PNG_ARM_NEON_IMPLEMENTATION == 1
#if defined(_MSC_VER) && defined(_M_ARM64)
# include <arm64_neon.h>
#else
# include <arm_neon.h>
#endif
/* Build an RGBA8 palette from the separate RGB and alpha palettes. */
void
png_riffle_palette_neon(png_structrp png_ptr)
{
png_const_colorp palette = png_ptr->palette;
png_bytep riffled_palette = png_ptr->riffled_palette;
png_const_bytep trans_alpha = png_ptr->trans_alpha;
int num_trans = png_ptr->num_trans;
int i;
png_debug(1, "in png_riffle_palette_neon");
/* Initially black, opaque. */
uint8x16x4_t w = {{
vdupq_n_u8(0x00),
vdupq_n_u8(0x00),
vdupq_n_u8(0x00),
vdupq_n_u8(0xff),
}};
/* First, riffle the RGB colours into an RGBA8 palette.
* The alpha component is set to opaque for now.
*/
for (i = 0; i < 256; i += 16)
{
uint8x16x3_t v = vld3q_u8((png_const_bytep)(palette + i));
w.val[0] = v.val[0];
w.val[1] = v.val[1];
w.val[2] = v.val[2];
vst4q_u8(riffled_palette + (i << 2), w);
}
/* Fix up the missing transparency values. */
for (i = 0; i < num_trans; i++)
riffled_palette[(i << 2) + 3] = trans_alpha[i];
}
/* Expands a palettized row into RGBA8. */
int
png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info,
png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
{
png_uint_32 row_width = row_info->width;
const png_uint_32 *riffled_palette =
(const png_uint_32 *)png_ptr->riffled_palette;
const png_int_32 pixels_per_chunk = 4;
int i;
png_debug(1, "in png_do_expand_palette_rgba8_neon");
if (row_width < pixels_per_chunk)
return 0;
/* This function originally gets the last byte of the output row.
* The NEON part writes forward from a given position, so we have
* to seek this back by 4 pixels x 4 bytes.
*/
*ddp = *ddp - ((pixels_per_chunk * sizeof(png_uint_32)) - 1);
for (i = 0; i < row_width; i += pixels_per_chunk)
{
uint32x4_t cur;
png_bytep sp = *ssp - i, dp = *ddp - (i << 2);
cur = vld1q_dup_u32 (riffled_palette + *(sp - 3));
cur = vld1q_lane_u32(riffled_palette + *(sp - 2), cur, 1);
cur = vld1q_lane_u32(riffled_palette + *(sp - 1), cur, 2);
cur = vld1q_lane_u32(riffled_palette + *(sp - 0), cur, 3);
vst1q_u32((void *)dp, cur);
}
if (i != row_width)
{
/* Remove the amount that wasn't processed. */
i -= pixels_per_chunk;
}
/* Decrement output pointers. */
*ssp = *ssp - i;
*ddp = *ddp - (i << 2);
return i;
}
/* Expands a palettized row into RGB8. */
int
png_do_expand_palette_rgb8_neon(png_structrp png_ptr, png_row_infop row_info,
png_const_bytep row, png_bytepp ssp, png_bytepp ddp)
{
png_uint_32 row_width = row_info->width;
png_const_bytep palette = (png_const_bytep)png_ptr->palette;
const png_uint_32 pixels_per_chunk = 8;
int i;
png_debug(1, "in png_do_expand_palette_rgb8_neon");
if (row_width <= pixels_per_chunk)
return 0;
/* Seeking this back by 8 pixels x 3 bytes. */
*ddp = *ddp - ((pixels_per_chunk * sizeof(png_color)) - 1);
for (i = 0; i < row_width; i += pixels_per_chunk)
{
uint8x8x3_t cur;
png_bytep sp = *ssp - i, dp = *ddp - ((i << 1) + i);
cur = vld3_dup_u8(palette + sizeof(png_color) * (*(sp - 7)));
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 6)), cur, 1);
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 5)), cur, 2);
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 4)), cur, 3);
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 3)), cur, 4);
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 2)), cur, 5);
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 1)), cur, 6);
cur = vld3_lane_u8(palette + sizeof(png_color) * (*(sp - 0)), cur, 7);
vst3_u8((void *)dp, cur);
}
if (i != row_width)
{
/* Remove the amount that wasn't processed. */
i -= pixels_per_chunk;
}
/* Decrement output pointers. */
*ssp = *ssp - i;
*ddp = *ddp - ((i << 1) + i);
return i;
}
#endif /* PNG_ARM_NEON_IMPLEMENTATION */

View File

@ -0,0 +1,391 @@
/* filter_sse2_intrinsics.c - SSE2 optimized filter functions
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2016-2017 Glenn Randers-Pehrson
* Written by Mike Klein and Matt Sarett
* Derived from arm/filter_neon_intrinsics.c
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#include "../pngpriv.h"
#ifdef PNG_READ_SUPPORTED
#if PNG_INTEL_SSE_IMPLEMENTATION > 0
#include <immintrin.h>
/* Functions in this file look at most 3 pixels (a,b,c) to predict the 4th (d).
* They're positioned like this:
* prev: c b
* row: a d
* The Sub filter predicts d=a, Avg d=(a+b)/2, and Paeth predicts d to be
* whichever of a, b, or c is closest to p=a+b-c.
*/
static __m128i load4(const void* p) {
int tmp;
memcpy(&tmp, p, sizeof(tmp));
return _mm_cvtsi32_si128(tmp);
}
static void store4(void* p, __m128i v) {
int tmp = _mm_cvtsi128_si32(v);
memcpy(p, &tmp, sizeof(int));
}
static __m128i load3(const void* p) {
png_uint_32 tmp = 0;
memcpy(&tmp, p, 3);
return _mm_cvtsi32_si128(tmp);
}
static void store3(void* p, __m128i v) {
int tmp = _mm_cvtsi128_si32(v);
memcpy(p, &tmp, 3);
}
void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row,
png_const_bytep prev)
{
/* The Sub filter predicts each pixel as the previous pixel, a.
* There is no pixel to the left of the first pixel. It's encoded directly.
* That works with our main loop if we just say that left pixel was zero.
*/
size_t rb;
__m128i a, d = _mm_setzero_si128();
png_debug(1, "in png_read_filter_row_sub3_sse2");
rb = row_info->rowbytes;
while (rb >= 4) {
a = d; d = load4(row);
d = _mm_add_epi8(d, a);
store3(row, d);
row += 3;
rb -= 3;
}
if (rb > 0) {
a = d; d = load3(row);
d = _mm_add_epi8(d, a);
store3(row, d);
row += 3;
rb -= 3;
}
PNG_UNUSED(prev)
}
void png_read_filter_row_sub4_sse2(png_row_infop row_info, png_bytep row,
png_const_bytep prev)
{
/* The Sub filter predicts each pixel as the previous pixel, a.
* There is no pixel to the left of the first pixel. It's encoded directly.
* That works with our main loop if we just say that left pixel was zero.
*/
size_t rb;
__m128i a, d = _mm_setzero_si128();
png_debug(1, "in png_read_filter_row_sub4_sse2");
rb = row_info->rowbytes+4;
while (rb > 4) {
a = d; d = load4(row);
d = _mm_add_epi8(d, a);
store4(row, d);
row += 4;
rb -= 4;
}
PNG_UNUSED(prev)
}
void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row,
png_const_bytep prev)
{
/* The Avg filter predicts each pixel as the (truncated) average of a and b.
* There's no pixel to the left of the first pixel. Luckily, it's
* predicted to be half of the pixel above it. So again, this works
* perfectly with our loop if we make sure a starts at zero.
*/
size_t rb;
const __m128i zero = _mm_setzero_si128();
__m128i b;
__m128i a, d = zero;
png_debug(1, "in png_read_filter_row_avg3_sse2");
rb = row_info->rowbytes;
while (rb >= 4) {
__m128i avg;
b = load4(prev);
a = d; d = load4(row );
/* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
avg = _mm_avg_epu8(a,b);
/* ...but we can fix it up by subtracting off 1 if it rounded up. */
avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
_mm_set1_epi8(1)));
d = _mm_add_epi8(d, avg);
store3(row, d);
prev += 3;
row += 3;
rb -= 3;
}
if (rb > 0) {
__m128i avg;
b = load3(prev);
a = d; d = load3(row );
/* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
avg = _mm_avg_epu8(a,b);
/* ...but we can fix it up by subtracting off 1 if it rounded up. */
avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
_mm_set1_epi8(1)));
d = _mm_add_epi8(d, avg);
store3(row, d);
prev += 3;
row += 3;
rb -= 3;
}
}
void png_read_filter_row_avg4_sse2(png_row_infop row_info, png_bytep row,
png_const_bytep prev)
{
/* The Avg filter predicts each pixel as the (truncated) average of a and b.
* There's no pixel to the left of the first pixel. Luckily, it's
* predicted to be half of the pixel above it. So again, this works
* perfectly with our loop if we make sure a starts at zero.
*/
size_t rb;
const __m128i zero = _mm_setzero_si128();
__m128i b;
__m128i a, d = zero;
png_debug(1, "in png_read_filter_row_avg4_sse2");
rb = row_info->rowbytes+4;
while (rb > 4) {
__m128i avg;
b = load4(prev);
a = d; d = load4(row );
/* PNG requires a truncating average, so we can't just use _mm_avg_epu8 */
avg = _mm_avg_epu8(a,b);
/* ...but we can fix it up by subtracting off 1 if it rounded up. */
avg = _mm_sub_epi8(avg, _mm_and_si128(_mm_xor_si128(a,b),
_mm_set1_epi8(1)));
d = _mm_add_epi8(d, avg);
store4(row, d);
prev += 4;
row += 4;
rb -= 4;
}
}
/* Returns |x| for 16-bit lanes. */
static __m128i abs_i16(__m128i x) {
#if PNG_INTEL_SSE_IMPLEMENTATION >= 2
return _mm_abs_epi16(x);
#else
/* Read this all as, return x<0 ? -x : x.
* To negate two's complement, you flip all the bits then add 1.
*/
__m128i is_negative = _mm_cmplt_epi16(x, _mm_setzero_si128());
/* Flip negative lanes. */
x = _mm_xor_si128(x, is_negative);
/* +1 to negative lanes, else +0. */
x = _mm_sub_epi16(x, is_negative);
return x;
#endif
}
/* Bytewise c ? t : e. */
static __m128i if_then_else(__m128i c, __m128i t, __m128i e) {
#if PNG_INTEL_SSE_IMPLEMENTATION >= 3
return _mm_blendv_epi8(e,t,c);
#else
return _mm_or_si128(_mm_and_si128(c, t), _mm_andnot_si128(c, e));
#endif
}
void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row,
png_const_bytep prev)
{
/* Paeth tries to predict pixel d using the pixel to the left of it, a,
* and two pixels from the previous row, b and c:
* prev: c b
* row: a d
* The Paeth function predicts d to be whichever of a, b, or c is nearest to
* p=a+b-c.
*
* The first pixel has no left context, and so uses an Up filter, p = b.
* This works naturally with our main loop's p = a+b-c if we force a and c
* to zero.
* Here we zero b and d, which become c and a respectively at the start of
* the loop.
*/
size_t rb;
const __m128i zero = _mm_setzero_si128();
__m128i c, b = zero,
a, d = zero;
png_debug(1, "in png_read_filter_row_paeth3_sse2");
rb = row_info->rowbytes;
while (rb >= 4) {
/* It's easiest to do this math (particularly, deal with pc) with 16-bit
* intermediates.
*/
__m128i pa,pb,pc,smallest,nearest;
c = b; b = _mm_unpacklo_epi8(load4(prev), zero);
a = d; d = _mm_unpacklo_epi8(load4(row ), zero);
/* (p-a) == (a+b-c - a) == (b-c) */
pa = _mm_sub_epi16(b,c);
/* (p-b) == (a+b-c - b) == (a-c) */
pb = _mm_sub_epi16(a,c);
/* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
pc = _mm_add_epi16(pa,pb);
pa = abs_i16(pa); /* |p-a| */
pb = abs_i16(pb); /* |p-b| */
pc = abs_i16(pc); /* |p-c| */
smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
/* Paeth breaks ties favoring a over b over c. */
nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
c));
/* Note `_epi8`: we need addition to wrap modulo 255. */
d = _mm_add_epi8(d, nearest);
store3(row, _mm_packus_epi16(d,d));
prev += 3;
row += 3;
rb -= 3;
}
if (rb > 0) {
/* It's easiest to do this math (particularly, deal with pc) with 16-bit
* intermediates.
*/
__m128i pa,pb,pc,smallest,nearest;
c = b; b = _mm_unpacklo_epi8(load3(prev), zero);
a = d; d = _mm_unpacklo_epi8(load3(row ), zero);
/* (p-a) == (a+b-c - a) == (b-c) */
pa = _mm_sub_epi16(b,c);
/* (p-b) == (a+b-c - b) == (a-c) */
pb = _mm_sub_epi16(a,c);
/* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
pc = _mm_add_epi16(pa,pb);
pa = abs_i16(pa); /* |p-a| */
pb = abs_i16(pb); /* |p-b| */
pc = abs_i16(pc); /* |p-c| */
smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
/* Paeth breaks ties favoring a over b over c. */
nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
c));
/* Note `_epi8`: we need addition to wrap modulo 255. */
d = _mm_add_epi8(d, nearest);
store3(row, _mm_packus_epi16(d,d));
prev += 3;
row += 3;
rb -= 3;
}
}
void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row,
png_const_bytep prev)
{
/* Paeth tries to predict pixel d using the pixel to the left of it, a,
* and two pixels from the previous row, b and c:
* prev: c b
* row: a d
* The Paeth function predicts d to be whichever of a, b, or c is nearest to
* p=a+b-c.
*
* The first pixel has no left context, and so uses an Up filter, p = b.
* This works naturally with our main loop's p = a+b-c if we force a and c
* to zero.
* Here we zero b and d, which become c and a respectively at the start of
* the loop.
*/
size_t rb;
const __m128i zero = _mm_setzero_si128();
__m128i pa,pb,pc,smallest,nearest;
__m128i c, b = zero,
a, d = zero;
png_debug(1, "in png_read_filter_row_paeth4_sse2");
rb = row_info->rowbytes+4;
while (rb > 4) {
/* It's easiest to do this math (particularly, deal with pc) with 16-bit
* intermediates.
*/
c = b; b = _mm_unpacklo_epi8(load4(prev), zero);
a = d; d = _mm_unpacklo_epi8(load4(row ), zero);
/* (p-a) == (a+b-c - a) == (b-c) */
pa = _mm_sub_epi16(b,c);
/* (p-b) == (a+b-c - b) == (a-c) */
pb = _mm_sub_epi16(a,c);
/* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */
pc = _mm_add_epi16(pa,pb);
pa = abs_i16(pa); /* |p-a| */
pb = abs_i16(pb); /* |p-b| */
pc = abs_i16(pc); /* |p-c| */
smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb));
/* Paeth breaks ties favoring a over b over c. */
nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a,
if_then_else(_mm_cmpeq_epi16(smallest, pb), b,
c));
/* Note `_epi8`: we need addition to wrap modulo 255. */
d = _mm_add_epi8(d, nearest);
store4(row, _mm_packus_epi16(d,d));
prev += 4;
row += 4;
rb -= 4;
}
}
#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */
#endif /* READ */

52
hecl/extern/libpng/intel/intel_init.c vendored Normal file
View File

@ -0,0 +1,52 @@
/* intel_init.c - SSE2 optimized filter functions
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2016-2017 Glenn Randers-Pehrson
* Written by Mike Klein and Matt Sarett, Google, Inc.
* Derived from arm/arm_init.c
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#include "../pngpriv.h"
#ifdef PNG_READ_SUPPORTED
#if PNG_INTEL_SSE_IMPLEMENTATION > 0
void
png_init_filter_functions_sse2(png_structp pp, unsigned int bpp)
{
/* The techniques used to implement each of these filters in SSE operate on
* one pixel at a time.
* So they generally speed up 3bpp images about 3x, 4bpp images about 4x.
* They can scale up to 6 and 8 bpp images and down to 2 bpp images,
* but they'd not likely have any benefit for 1bpp images.
* Most of these can be implemented using only MMX and 64-bit registers,
* but they end up a bit slower than using the equally-ubiquitous SSE2.
*/
png_debug(1, "in png_init_filter_functions_sse2");
if (bpp == 3)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_sse2;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_sse2;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
png_read_filter_row_paeth3_sse2;
}
else if (bpp == 4)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_sse2;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_sse2;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
png_read_filter_row_paeth4_sse2;
}
/* No need optimize PNG_FILTER_VALUE_UP. The compiler should
* autovectorize.
*/
}
#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */
#endif /* PNG_READ_SUPPORTED */

View File

@ -1,10 +1,10 @@
/* png.c - location for general purpose libpng functions /* png.c - location for general purpose libpng functions
* *
* Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -14,7 +14,27 @@
#include "pngpriv.h" #include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */ /* Generate a compiler error if there is an old png.h in the search path. */
typedef png_libpng_version_1_6_19 Your_png_h_is_not_version_1_6_19; typedef png_libpng_version_1_6_37 Your_png_h_is_not_version_1_6_37;
#ifdef __GNUC__
/* The version tests may need to be added to, but the problem warning has
* consistently been fixed in GCC versions which obtain wide-spread release.
* The problem is that many versions of GCC rearrange comparison expressions in
* the optimizer in such a way that the results of the comparison will change
* if signed integer overflow occurs. Such comparisons are not permitted in
* ANSI C90, however GCC isn't clever enough to work out that that do not occur
* below in png_ascii_from_fp and png_muldiv, so it produces a warning with
* -Wextra. Unfortunately this is highly dependent on the optimizer and the
* machine architecture so the warning comes and goes unpredictably and is
* impossible to "fix", even were that a good idea.
*/
#if __GNUC__ == 7 && __GNUC_MINOR__ == 1
#define GCC_STRICT_OVERFLOW 1
#endif /* GNU 7.1.x */
#endif /* GNU */
#ifndef GCC_STRICT_OVERFLOW
#define GCC_STRICT_OVERFLOW 0
#endif
/* Tells libpng that we have already handled the first "num_bytes" bytes /* Tells libpng that we have already handled the first "num_bytes" bytes
* of the PNG file signature. If the PNG data is embedded into another * of the PNG file signature. If the PNG data is embedded into another
@ -51,7 +71,7 @@ png_set_sig_bytes(png_structrp png_ptr, int num_bytes)
* PNG signature (this is the same behavior as strcmp, memcmp, etc). * PNG signature (this is the same behavior as strcmp, memcmp, etc).
*/ */
int PNGAPI int PNGAPI
png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check)
{ {
png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
@ -116,7 +136,7 @@ png_reset_crc(png_structrp png_ptr)
* trouble of calculating it. * trouble of calculating it.
*/ */
void /* PRIVATE */ void /* PRIVATE */
png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, size_t length)
{ {
int need_crc = 1; int need_crc = 1;
@ -401,7 +421,7 @@ png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr)
* those cases where it does anything other than a memset. * those cases where it does anything other than a memset.
*/ */
PNG_FUNCTION(void,PNGAPI PNG_FUNCTION(void,PNGAPI
png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), png_info_init_3,(png_infopp ptr_ptr, size_t png_info_struct_size),
PNG_DEPRECATED) PNG_DEPRECATED)
{ {
png_inforp info_ptr = *ptr_ptr; png_inforp info_ptr = *ptr_ptr;
@ -458,7 +478,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
#ifdef PNG_TEXT_SUPPORTED #ifdef PNG_TEXT_SUPPORTED
/* Free text item num or (if num == -1) all text items */ /* Free text item num or (if num == -1) all text items */
if (info_ptr->text != 0 && if (info_ptr->text != NULL &&
((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0) ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0)
{ {
if (num != -1) if (num != -1)
@ -477,6 +497,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
png_free(png_ptr, info_ptr->text); png_free(png_ptr, info_ptr->text);
info_ptr->text = NULL; info_ptr->text = NULL;
info_ptr->num_text = 0; info_ptr->num_text = 0;
info_ptr->max_text = 0;
} }
} }
#endif #endif
@ -541,7 +562,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
#ifdef PNG_sPLT_SUPPORTED #ifdef PNG_sPLT_SUPPORTED
/* Free a given sPLT entry, or (if num == -1) all sPLT entries */ /* Free a given sPLT entry, or (if num == -1) all sPLT entries */
if (info_ptr->splt_palettes != 0 && if (info_ptr->splt_palettes != NULL &&
((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0) ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0)
{ {
if (num != -1) if (num != -1)
@ -571,7 +592,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
#endif #endif
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
if (info_ptr->unknown_chunks != 0 && if (info_ptr->unknown_chunks != NULL &&
((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0) ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0)
{ {
if (num != -1) if (num != -1)
@ -594,6 +615,26 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
} }
#endif #endif
#ifdef PNG_eXIf_SUPPORTED
/* Free any eXIf entry */
if (((mask & PNG_FREE_EXIF) & info_ptr->free_me) != 0)
{
# ifdef PNG_READ_eXIf_SUPPORTED
if (info_ptr->eXIf_buf)
{
png_free(png_ptr, info_ptr->eXIf_buf);
info_ptr->eXIf_buf = NULL;
}
# endif
if (info_ptr->exif)
{
png_free(png_ptr, info_ptr->exif);
info_ptr->exif = NULL;
}
info_ptr->valid &= ~PNG_INFO_eXIf;
}
#endif
#ifdef PNG_hIST_SUPPORTED #ifdef PNG_hIST_SUPPORTED
/* Free any hIST entry */ /* Free any hIST entry */
if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0) if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0)
@ -617,7 +658,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
/* Free any image bits attached to the info structure */ /* Free any image bits attached to the info structure */
if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0) if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0)
{ {
if (info_ptr->row_pointers != 0) if (info_ptr->row_pointers != NULL)
{ {
png_uint_32 row; png_uint_32 row;
for (row = 0; row < info_ptr->height; row++) for (row = 0; row < info_ptr->height; row++)
@ -684,7 +725,7 @@ png_init_io(png_structrp png_ptr, png_FILE_p fp)
void PNGAPI void PNGAPI
png_save_int_32(png_bytep buf, png_int_32 i) png_save_int_32(png_bytep buf, png_int_32 i)
{ {
png_save_uint_32(buf, i); png_save_uint_32(buf, (png_uint_32)i);
} }
# endif # endif
@ -695,7 +736,7 @@ png_save_int_32(png_bytep buf, png_int_32 i)
int PNGAPI int PNGAPI
png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
{ {
static PNG_CONST char short_months[12][4] = static const char short_months[12][4] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun", {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
@ -773,19 +814,14 @@ png_get_copyright(png_const_structrp png_ptr)
#ifdef PNG_STRING_COPYRIGHT #ifdef PNG_STRING_COPYRIGHT
return PNG_STRING_COPYRIGHT return PNG_STRING_COPYRIGHT
#else #else
# ifdef __STDC__
return PNG_STRING_NEWLINE \ return PNG_STRING_NEWLINE \
"libpng version 1.6.19 - November 12, 2015" PNG_STRING_NEWLINE \ "libpng version 1.6.37" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2015 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ "Copyright (c) 2018-2019 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
PNG_STRING_NEWLINE; PNG_STRING_NEWLINE;
# else
return "libpng version 1.6.19 - November 12, 2015\
Copyright (c) 1998-2015 Glenn Randers-Pehrson\
Copyright (c) 1996-1997 Andreas Dilger\
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
# endif
#endif #endif
} }
@ -900,7 +936,7 @@ png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name)
/* The code is the fifth byte after each four byte string. Historically this /* The code is the fifth byte after each four byte string. Historically this
* code was always searched from the end of the list, this is no longer * code was always searched from the end of the list, this is no longer
* necessary because the 'set' routine handles duplicate entries correcty. * necessary because the 'set' routine handles duplicate entries correctly.
*/ */
do /* num_chunk_list > 0, so at least one */ do /* num_chunk_list > 0, so at least one */
{ {
@ -1079,7 +1115,7 @@ png_colorspace_set_gamma(png_const_structrp png_ptr,
png_colorspacerp colorspace, png_fixed_point gAMA) png_colorspacerp colorspace, png_fixed_point gAMA)
{ {
/* Changed in libpng-1.5.4 to limit the values to ensure overflow can't /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
* occur. Since the fixed point representation is asymetrical it is * occur. Since the fixed point representation is asymmetrical it is
* possible for 1/gamma to overflow the limit of 21474 and this means the * possible for 1/gamma to overflow the limit of 21474 and this means the
* gamma value must be at least 5/100000 and hence at most 20000.0. For * gamma value must be at least 5/100000 and hence at most 20000.0. For
* safety the limits here are a little narrower. The values are 0.00016 to * safety the limits here are a little narrower. The values are 0.00016 to
@ -1871,12 +1907,12 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
*/ */
if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
return png_icc_profile_error(png_ptr, colorspace, "sRGB", return png_icc_profile_error(png_ptr, colorspace, "sRGB",
(unsigned)intent, "invalid sRGB rendering intent"); (png_alloc_size_t)intent, "invalid sRGB rendering intent");
if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&
colorspace->rendering_intent != intent) colorspace->rendering_intent != intent)
return png_icc_profile_error(png_ptr, colorspace, "sRGB", return png_icc_profile_error(png_ptr, colorspace, "sRGB",
(unsigned)intent, "inconsistent rendering intents"); (png_alloc_size_t)intent, "inconsistent rendering intents");
if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)
{ {
@ -1930,16 +1966,49 @@ png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
static const png_byte D50_nCIEXYZ[12] = static const png_byte D50_nCIEXYZ[12] =
{ 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d };
int /* PRIVATE */ static int /* bool */
png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, icc_check_length(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)
{ {
if (profile_length < 132) if (profile_length < 132)
return png_icc_profile_error(png_ptr, colorspace, name, profile_length, return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
"too short"); "too short");
return 1;
}
#ifdef PNG_READ_iCCP_SUPPORTED
int /* PRIVATE */
png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
png_const_charp name, png_uint_32 profile_length)
{
if (!icc_check_length(png_ptr, colorspace, name, profile_length))
return 0;
/* This needs to be here because the 'normal' check is in
* png_decompress_chunk, yet this happens after the attempt to
* png_malloc_base the required data. We only need this on read; on write
* the caller supplies the profile buffer so libpng doesn't allocate it. See
* the call to icc_check_length below (the write case).
*/
# ifdef PNG_SET_USER_LIMITS_SUPPORTED
else if (png_ptr->user_chunk_malloc_max > 0 &&
png_ptr->user_chunk_malloc_max < profile_length)
return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
"exceeds application limits");
# elif PNG_USER_CHUNK_MALLOC_MAX > 0
else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length)
return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
"exceeds libpng limits");
# else /* !SET_USER_LIMITS */
/* This will get compiled out on all 32-bit and better systems. */
else if (PNG_SIZE_MAX < profile_length)
return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
"exceeds system limits");
# endif /* !SET_USER_LIMITS */
return 1; return 1;
} }
#endif /* READ_iCCP */
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,
@ -1992,7 +2061,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
*/ */
/* Data checks (could be skipped). These checks must be independent of the /* Data checks (could be skipped). These checks must be independent of the
* version number; however, the version number doesn't accomodate changes in * version number; however, the version number doesn't accommodate changes in
* the header fields (just the known tags and the interpretation of the * the header fields (just the known tags and the interpretation of the
* data.) * data.)
*/ */
@ -2148,15 +2217,6 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
* being in range. All defined tag types have an 8 byte header - a 4 byte * being in range. All defined tag types have an 8 byte header - a 4 byte
* type signature then 0. * type signature then 0.
*/ */
if ((tag_start & 3) != 0)
{
/* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is
* only a warning here because libpng does not care about the
* alignment.
*/
(void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
"ICC profile tag start not a multiple of 4");
}
/* This is a hard error; potentially it can cause read outside the /* This is a hard error; potentially it can cause read outside the
* profile. * profile.
@ -2164,6 +2224,16 @@ png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
if (tag_start > profile_length || tag_length > profile_length - tag_start) if (tag_start > profile_length || tag_length > profile_length - tag_start)
return png_icc_profile_error(png_ptr, colorspace, name, tag_id, return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
"ICC profile tag outside profile"); "ICC profile tag outside profile");
if ((tag_start & 3) != 0)
{
/* CNHP730S.icc shipped with Microsoft Windows 64 violates this; it is
* only a warning here because libpng does not care about the
* alignment.
*/
(void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
"ICC profile tag start not a multiple of 4");
}
} }
return 1; /* success, maybe with warnings */ return 1; /* success, maybe with warnings */
@ -2353,7 +2423,6 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
return 0; /* no match */ return 0; /* no match */
} }
#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */
void /* PRIVATE */ void /* PRIVATE */
png_icc_set_sRGB(png_const_structrp png_ptr, png_icc_set_sRGB(png_const_structrp png_ptr,
@ -2362,12 +2431,11 @@ png_icc_set_sRGB(png_const_structrp png_ptr,
/* Is this profile one of the known ICC sRGB profiles? If it is, just set /* Is this profile one of the known ICC sRGB profiles? If it is, just set
* the sRGB information. * the sRGB information.
*/ */
#if PNG_sRGB_PROFILE_CHECKS >= 0
if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0) if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0)
#endif
(void)png_colorspace_set_sRGB(png_ptr, colorspace, (void)png_colorspace_set_sRGB(png_ptr, colorspace,
(int)/*already checked*/png_get_uint_32(profile+64)); (int)/*already checked*/png_get_uint_32(profile+64));
} }
#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */
#endif /* sRGB */ #endif /* sRGB */
int /* PRIVATE */ int /* PRIVATE */
@ -2378,13 +2446,13 @@ png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
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 (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 && color_type) != 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)
{ {
# ifdef PNG_sRGB_SUPPORTED # if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0
/* If no sRGB support, don't try storing sRGB information */ /* If no sRGB support, don't try storing sRGB information */
png_icc_set_sRGB(png_ptr, colorspace, profile, 0); png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
# endif # endif
@ -2496,7 +2564,7 @@ png_check_IHDR(png_const_structrp png_ptr,
error = 1; error = 1;
} }
if (png_gt(((width + 7) & (~7)), if (png_gt(((width + 7) & (~7U)),
((PNG_SIZE_MAX ((PNG_SIZE_MAX
- 48 /* big_row_buf hack */ - 48 /* big_row_buf hack */
- 1) /* filter byte */ - 1) /* filter byte */
@ -2633,7 +2701,7 @@ png_check_IHDR(png_const_structrp png_ptr,
#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) #if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
/* ASCII to fp functions */ /* ASCII to fp functions */
/* Check an ASCII formated floating point value, see the more detailed /* Check an ASCII formatted floating point value, see the more detailed
* comments in pngpriv.h * comments in pngpriv.h
*/ */
/* The following is used internally to preserve the sticky flags */ /* The following is used internally to preserve the sticky flags */
@ -2641,11 +2709,11 @@ png_check_IHDR(png_const_structrp png_ptr,
#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) #define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY))
int /* PRIVATE */ int /* PRIVATE */
png_check_fp_number(png_const_charp string, png_size_t size, int *statep, png_check_fp_number(png_const_charp string, size_t size, int *statep,
png_size_tp whereami) png_size_tp whereami)
{ {
int state = *statep; int state = *statep;
png_size_t i = *whereami; size_t i = *whereami;
while (i < size) while (i < size)
{ {
@ -2768,10 +2836,10 @@ PNG_FP_End:
/* The same but for a complete string. */ /* The same but for a complete string. */
int int
png_check_fp_string(png_const_charp string, png_size_t size) png_check_fp_string(png_const_charp string, size_t size)
{ {
int state=0; int state=0;
png_size_t char_index=0; size_t char_index=0;
if (png_check_fp_number(string, size, &state, &char_index) != 0 && if (png_check_fp_number(string, size, &state, &char_index) != 0 &&
(char_index == size || string[char_index] == 0)) (char_index == size || string[char_index] == 0))
@ -2798,7 +2866,7 @@ png_pow10(int power)
if (power < 0) if (power < 0)
{ {
if (power < DBL_MIN_10_EXP) return 0; if (power < DBL_MIN_10_EXP) return 0;
recip = 1, power = -power; recip = 1; power = -power;
} }
if (power > 0) if (power > 0)
@ -2823,8 +2891,16 @@ png_pow10(int power)
/* Function to format a floating point value in ASCII with a given /* Function to format a floating point value in ASCII with a given
* precision. * precision.
*/ */
#if GCC_STRICT_OVERFLOW
#pragma GCC diagnostic push
/* The problem arises below with exp_b10, which can never overflow because it
* comes, originally, from frexp and is therefore limited to a range which is
* typically +/-710 (log2(DBL_MAX)/log2(DBL_MIN)).
*/
#pragma GCC diagnostic warning "-Wstrict-overflow=2"
#endif /* GCC_STRICT_OVERFLOW */
void /* PRIVATE */ void /* PRIVATE */
png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size,
double fp, unsigned int precision) double fp, unsigned int precision)
{ {
/* We use standard functions from math.h, but not printf because /* We use standard functions from math.h, but not printf because
@ -2876,7 +2952,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
double test = png_pow10(exp_b10+1); double test = png_pow10(exp_b10+1);
if (test <= DBL_MAX) if (test <= DBL_MAX)
++exp_b10, base = test; {
++exp_b10; base = test;
}
else else
break; break;
@ -2890,7 +2968,10 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
* test on DBL_MAX above. * test on DBL_MAX above.
*/ */
fp /= base; fp /= base;
while (fp >= 1) fp /= 10, ++exp_b10; while (fp >= 1)
{
fp /= 10; ++exp_b10;
}
/* Because of the code above fp may, at this point, be /* Because of the code above fp may, at this point, be
* less than .1, this is ok because the code below can * less than .1, this is ok because the code below can
@ -2907,7 +2988,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
*/ */
if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */
{ {
czero = -exp_b10; /* PLUS 2 digits: TOTAL 3 */ czero = 0U-exp_b10; /* PLUS 2 digits: TOTAL 3 */
exp_b10 = 0; /* Dot added below before first output. */ exp_b10 = 0; /* Dot added below before first output. */
} }
else else
@ -2941,7 +3022,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
/* Rounding up to 10, handle that here. */ /* Rounding up to 10, handle that here. */
if (czero > 0) if (czero > 0)
{ {
--czero, d = 1; --czero; d = 1;
if (cdigits == 0) --clead; if (cdigits == 0) --clead;
} }
else else
@ -2955,7 +3036,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
else if (ch == 46) else if (ch == 46)
{ {
ch = *--ascii, ++size; ch = *--ascii; ++size;
/* Advance exp_b10 to '1', so that the /* Advance exp_b10 to '1', so that the
* decimal point happens after the * decimal point happens after the
* previous digit. * previous digit.
@ -2982,7 +3063,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
int ch = *--ascii; int ch = *--ascii;
if (ch == 46) if (ch == 46)
++size, exp_b10 = 1; {
++size; exp_b10 = 1;
}
/* Else lost a leading zero, so 'exp_b10' is /* Else lost a leading zero, so 'exp_b10' is
* still ok at (-1) * still ok at (-1)
@ -3018,21 +3101,26 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
*/ */
if (exp_b10 != (-1)) if (exp_b10 != (-1))
{ {
if (exp_b10 == 0) *ascii++ = 46, --size; if (exp_b10 == 0)
{
*ascii++ = 46; --size;
}
/* PLUS 1: TOTAL 4 */ /* PLUS 1: TOTAL 4 */
--exp_b10; --exp_b10;
} }
*ascii++ = 48, --czero; *ascii++ = 48; --czero;
} }
if (exp_b10 != (-1)) if (exp_b10 != (-1))
{ {
if (exp_b10 == 0) if (exp_b10 == 0)
*ascii++ = 46, --size; /* counted above */ {
*ascii++ = 46; --size; /* counted above */
}
--exp_b10; --exp_b10;
} }
*ascii++ = (char)(48 + (int)d), ++cdigits; *ascii++ = (char)(48 + (int)d); ++cdigits;
} }
} }
while (cdigits+czero < precision+clead && fp > DBL_MIN); while (cdigits+czero < precision+clead && fp > DBL_MIN);
@ -3040,11 +3128,11 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
/* The total output count (max) is now 4+precision */ /* The total output count (max) is now 4+precision */
/* Check for an exponent, if we don't need one we are /* Check for an exponent, if we don't need one we are
* done and just need to terminate the string. At * done and just need to terminate the string. At this
* this point exp_b10==(-1) is effectively if flag - it got * point, exp_b10==(-1) is effectively a flag: it got
* to '-1' because of the decrement after outputting * to '-1' because of the decrement, after outputting
* the decimal point above (the exponent required is * the decimal point above. (The exponent required is
* *not* -1!) * *not* -1.)
*/ */
if (exp_b10 >= (-1) && exp_b10 <= 2) if (exp_b10 >= (-1) && exp_b10 <= 2)
{ {
@ -3055,7 +3143,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
* zeros were *not* output, so this doesn't increase * zeros were *not* output, so this doesn't increase
* the output count. * the output count.
*/ */
while (--exp_b10 >= 0) *ascii++ = 48; while (exp_b10-- > 0) *ascii++ = 48;
*ascii = 0; *ascii = 0;
@ -3073,7 +3161,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
*/ */
size -= cdigits; size -= cdigits;
*ascii++ = 69, --size; /* 'E': PLUS 1 TOTAL 2+precision */ *ascii++ = 69; --size; /* 'E': PLUS 1 TOTAL 2+precision */
/* The following use of an unsigned temporary avoids ambiguities in /* The following use of an unsigned temporary avoids ambiguities in
* the signed arithmetic on exp_b10 and permits GCC at least to do * the signed arithmetic on exp_b10 and permits GCC at least to do
@ -3084,12 +3172,12 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
if (exp_b10 < 0) if (exp_b10 < 0)
{ {
*ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ *ascii++ = 45; --size; /* '-': PLUS 1 TOTAL 3+precision */
uexp_b10 = -exp_b10; uexp_b10 = 0U-exp_b10;
} }
else else
uexp_b10 = exp_b10; uexp_b10 = 0U+exp_b10;
cdigits = 0; cdigits = 0;
@ -3132,6 +3220,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
/* Here on buffer too small. */ /* Here on buffer too small. */
png_error(png_ptr, "ASCII conversion buffer too small"); png_error(png_ptr, "ASCII conversion buffer too small");
} }
#if GCC_STRICT_OVERFLOW
#pragma GCC diagnostic pop
#endif /* GCC_STRICT_OVERFLOW */
# endif /* FLOATING_POINT */ # endif /* FLOATING_POINT */
@ -3140,7 +3231,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
*/ */
void /* PRIVATE */ void /* PRIVATE */
png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
png_size_t size, png_fixed_point fp) size_t size, png_fixed_point fp)
{ {
/* Require space for 10 decimal digits, a decimal point, a minus sign and a /* Require space for 10 decimal digits, a decimal point, a minus sign and a
* trailing \0, 13 characters: * trailing \0, 13 characters:
@ -3151,9 +3242,11 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
/* Avoid overflow here on the minimum integer. */ /* Avoid overflow here on the minimum integer. */
if (fp < 0) if (fp < 0)
*ascii++ = 45, num = -fp; {
*ascii++ = 45; num = (png_uint_32)(-fp);
}
else else
num = fp; num = (png_uint_32)fp;
if (num <= 0x80000000) /* else overflowed */ if (num <= 0x80000000) /* else overflowed */
{ {
@ -3189,7 +3282,10 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
* then ndigits digits to first: * then ndigits digits to first:
*/ */
i = 5; i = 5;
while (ndigits < i) *ascii++ = 48, --i; while (ndigits < i)
{
*ascii++ = 48; --i;
}
while (ndigits >= first) *ascii++ = digits[--ndigits]; while (ndigits >= first) *ascii++ = digits[--ndigits];
/* Don't output the trailing zeros! */ /* Don't output the trailing zeros! */
} }
@ -3240,6 +3336,15 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
* the nearest .00001). Overflow and divide by zero are signalled in * the nearest .00001). Overflow and divide by zero are signalled in
* the result, a boolean - true on success, false on overflow. * the result, a boolean - true on success, false on overflow.
*/ */
#if GCC_STRICT_OVERFLOW /* from above */
/* It is not obvious which comparison below gets optimized in such a way that
* signed overflow would change the result; looking through the code does not
* reveal any tests which have the form GCC complains about, so presumably the
* optimizer is moving an add or subtract into the 'if' somewhere.
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic warning "-Wstrict-overflow=2"
#endif /* GCC_STRICT_OVERFLOW */
int int
png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
png_int_32 divisor) png_int_32 divisor)
@ -3354,6 +3459,9 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
return 0; return 0;
} }
#if GCC_STRICT_OVERFLOW
#pragma GCC diagnostic pop
#endif /* GCC_STRICT_OVERFLOW */
#endif /* READ_GAMMA || INCH_CONVERSIONS */ #endif /* READ_GAMMA || INCH_CONVERSIONS */
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
@ -3647,7 +3755,7 @@ png_log16bit(png_uint_32 x)
* of getting this accuracy in practice. * of getting this accuracy in practice.
* *
* To deal with this the following exp() function works out the exponent of the * To deal with this the following exp() function works out the exponent of the
* frational part of the logarithm by using an accurate 32-bit value from the * fractional part of the logarithm by using an accurate 32-bit value from the
* top four fractional bits then multiplying in the remaining bits. * top four fractional bits then multiplying in the remaining bits.
*/ */
static const png_uint_32 static const png_uint_32
@ -3862,18 +3970,18 @@ png_gamma_correct(png_structrp png_ptr, unsigned int value,
*/ */
static void static void
png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) unsigned int shift, png_fixed_point gamma_val)
{ {
/* Various values derived from 'shift': */ /* Various values derived from 'shift': */
PNG_CONST unsigned int num = 1U << (8U - shift); unsigned int num = 1U << (8U - shift);
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* CSE the division and work round wacky GCC warnings (see the comments /* CSE the division and work round wacky GCC warnings (see the comments
* in png_gamma_8bit_correct for where these come from.) * in png_gamma_8bit_correct for where these come from.)
*/ */
PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1); double fmax = 1.0 / (((png_int_32)1 << (16U - shift)) - 1);
#endif #endif
PNG_CONST unsigned int max = (1U << (16U - shift))-1U; unsigned int max = (1U << (16U - shift)) - 1U;
PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); unsigned int max_by_2 = 1U << (15U - shift);
unsigned int i; unsigned int i;
png_uint_16pp table = *ptable = png_uint_16pp table = *ptable =
@ -3939,10 +4047,10 @@ png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
*/ */
static void static void
png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) unsigned int shift, png_fixed_point gamma_val)
{ {
PNG_CONST unsigned int num = 1U << (8U - shift); unsigned int num = 1U << (8U - shift);
PNG_CONST unsigned int max = (1U << (16U - shift))-1U; unsigned int max = (1U << (16U - shift))-1U;
unsigned int i; unsigned int i;
png_uint_32 last; png_uint_32 last;
@ -4007,7 +4115,7 @@ png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
*/ */
static void static void
png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable, png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
PNG_CONST png_fixed_point gamma_val) png_fixed_point gamma_val)
{ {
unsigned int i; unsigned int i;
png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
@ -4091,9 +4199,9 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
/* Remove any existing table; this copes with multiple calls to /* Remove any existing table; this copes with multiple calls to
* png_read_update_info. The warning is because building the gamma tables * png_read_update_info. The warning is because building the gamma tables
* multiple times is a performance hit - it's harmless but the ability to call * multiple times is a performance hit - it's harmless but the ability to
* png_read_update_info() multiple times is new in 1.5.6 so it seems sensible * call png_read_update_info() multiple times is new in 1.5.6 so it seems
* to warn if the app introduces such a hit. * sensible to warn if the app introduces such a hit.
*/ */
if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL)
{ {
@ -4104,7 +4212,8 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
if (bit_depth <= 8) if (bit_depth <= 8)
{ {
png_build_8bit_table(png_ptr, &png_ptr->gamma_table, png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, png_ptr->screen_gamma > 0 ?
png_reciprocal2(png_ptr->colorspace.gamma,
png_ptr->screen_gamma) : PNG_FP_1); png_ptr->screen_gamma) : PNG_FP_1);
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
@ -4116,7 +4225,8 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
png_reciprocal(png_ptr->colorspace.gamma)); png_reciprocal(png_ptr->colorspace.gamma));
png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : png_ptr->screen_gamma > 0 ?
png_reciprocal(png_ptr->screen_gamma) :
png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
} }
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
@ -4147,8 +4257,8 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
* pow(iv, gamma). * pow(iv, gamma).
* *
* Thus the gamma table consists of up to 256 256-entry tables. The table * Thus the gamma table consists of up to 256 256-entry tables. The table
* is selected by the (8-gamma_shift) most significant of the low 8 bits of * is selected by the (8-gamma_shift) most significant of the low 8 bits
* the color value then indexed by the upper 8 bits: * of the color value then indexed by the upper 8 bits:
* *
* table[low bits][high 8 bits] * table[low bits][high 8 bits]
* *
@ -4181,8 +4291,8 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth)
/* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
* PNG_COMPOSE). This effectively smashed the background calculation for * PNG_COMPOSE). This effectively smashed the background calculation for
* 16-bit output because the 8-bit table assumes the result will be reduced * 16-bit output because the 8-bit table assumes the result will be
* to 8 bits. * reduced to 8 bits.
*/ */
if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
@ -4224,13 +4334,13 @@ 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; png_uint_32 mask = 3U << option;
int setting = (2 + (onoff != 0)) << option; png_uint_32 setting = (2U + (onoff != 0)) << option;
int current = png_ptr->options; png_uint_32 current = png_ptr->options;
png_ptr->options = (png_byte)(((current & ~mask) | setting) & 0xff); png_ptr->options = (png_uint_32)((current & ~mask) | setting);
return (current & mask) >> option; return (int)(current & mask) >> option;
} }
return PNG_OPTION_INVALID; return PNG_OPTION_INVALID;
@ -4242,7 +4352,7 @@ png_set_option(png_structrp png_ptr, int option, int onoff)
defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
/* sRGB conversion tables; these are machine generated with the code in /* sRGB conversion tables; these are machine generated with the code in
* contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the
* specification (see the article at http://en.wikipedia.org/wiki/SRGB) * specification (see the article at https://en.wikipedia.org/wiki/SRGB)
* is used, not the gamma=1/2.2 approximation use elsewhere in libpng. * is used, not the gamma=1/2.2 approximation use elsewhere in libpng.
* The sRGB to linear table is exact (to the nearest 16-bit linear fraction). * The sRGB to linear table is exact (to the nearest 16-bit linear fraction).
* The inverse (linear to sRGB) table has accuracies as follows: * The inverse (linear to sRGB) table has accuracies as follows:
@ -4478,8 +4588,7 @@ png_image_free(png_imagep image)
if (image != NULL && image->opaque != NULL && if (image != NULL && image->opaque != NULL &&
image->opaque->error_buf == NULL) image->opaque->error_buf == NULL)
{ {
/* Ignore errors here: */ png_image_free_function(image);
(void)png_safe_execute(image, png_image_free_function, image);
image->opaque = NULL; image->opaque = NULL;
} }
} }

View File

@ -1,31 +1,69 @@
/* png.h - header file for PNG reference library /* png.h - header file for PNG reference library
* *
* libpng version 1.6.19, November 12, 2015 * libpng version 1.6.37 - April 14, 2019
* *
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 2018-2019 Cosmin Truta
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license (See LICENSE, below) * This code is released under the libpng license. (See LICENSE, below.)
* *
* Authors and maintainers: * Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
* libpng versions 0.97, January 1998, through 1.6.19, November 12, 2015: Glenn * libpng versions 0.97, January 1998, through 1.6.35, July 2018:
* Glenn Randers-Pehrson
* libpng versions 1.6.36, December 2018, through 1.6.37, April 2019:
* Cosmin Truta
* See also "Contributing Authors", below. * See also "Contributing Authors", below.
*/ */
/* /*
* COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: * COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
* =========================================
* *
* If you modify libpng you may insert additional notices immediately following * PNG Reference Library License version 2
* this sentence. * ---------------------------------------
* *
* This code is released under the libpng license. * * Copyright (c) 1995-2019 The PNG Reference Library Authors.
* * Copyright (c) 2018-2019 Cosmin Truta.
* * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
* * Copyright (c) 1996-1997 Andreas Dilger.
* * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* libpng versions 1.0.7, July 1, 2000, through 1.6.19, November 12, 2015, are * The software is supplied "as is", without warranty of any kind,
* Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are * express or implied, including, without limitation, the warranties
* of merchantability, fitness for a particular purpose, title, and
* non-infringement. In no event shall the Copyright owners, or
* anyone distributing the software, be liable for any damages or
* other liability, whether in contract, tort or otherwise, arising
* from, out of, or in connection with the software, or the use or
* other dealings in the software, even if advised of the possibility
* of such damage.
*
* Permission is hereby granted to use, copy, modify, and distribute
* this software, or portions hereof, for any purpose, without fee,
* subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you
* must not claim that you wrote the original software. If you
* use this software in a product, an acknowledgment in the product
* documentation would be appreciated, but is not required.
*
* 2. Altered source versions must be plainly marked as such, and must
* not be misrepresented as being the original software.
*
* 3. This Copyright notice may not be removed or altered from any
* source or altered source distribution.
*
*
* PNG Reference Library License version 1 (for libpng 0.5 through 1.6.35)
* -----------------------------------------------------------------------
*
* libpng versions 1.0.7, July 1, 2000, through 1.6.35, July 15, 2018 are
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson, are
* derived from libpng-1.0.6, and are distributed according to the same * derived from libpng-1.0.6, and are distributed according to the same
* disclaimer and license as libpng-1.0.6 with the following individuals * disclaimer and license as libpng-1.0.6 with the following individuals
* added to the list of Contributing Authors: * added to the list of Contributing Authors:
@ -36,21 +74,28 @@
* Cosmin Truta * Cosmin Truta
* Gilles Vollant * Gilles Vollant
* James Yu * James Yu
* Mandar Sahastrabuddhe
* Google Inc.
* Vadim Barkov
* *
* and with the following additions to the disclaimer: * and with the following additions to the disclaimer:
* *
* There is no warranty against interference with your enjoyment of the * There is no warranty against interference with your enjoyment of
* library or against infringement. There is no warranty that our * the library or against infringement. There is no warranty that our
* efforts or the library will fulfill any of your particular purposes * efforts or the library will fulfill any of your particular purposes
* or needs. This library is provided with all faults, and the entire * or needs. This library is provided with all faults, and the entire
* risk of satisfactory quality, performance, accuracy, and effort is with * risk of satisfactory quality, performance, accuracy, and effort is
* the user. * with the user.
*
* Some files in the "contrib" directory and some configure-generated
* files that are distributed with libpng have other copyright owners, and
* are released under other open source licenses.
* *
* libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are * libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are
* Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from
* libpng-0.96, and are distributed according to the same disclaimer and * libpng-0.96, and are distributed according to the same disclaimer and
* license as libpng-0.96, with the following individuals added to the list * license as libpng-0.96, with the following individuals added to the
* of Contributing Authors: * list of Contributing Authors:
* *
* Tom Lane * Tom Lane
* Glenn Randers-Pehrson * Glenn Randers-Pehrson
@ -69,6 +114,9 @@
* Greg Roelofs * Greg Roelofs
* Tom Tanner * Tom Tanner
* *
* Some files in the "scripts" directory have other copyright owners,
* but are released under this license.
*
* libpng versions 0.5, May 1995, through 0.88, January 1996, are * libpng versions 0.5, May 1995, through 0.88, January 1996, are
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
@ -81,13 +129,14 @@
* Paul Schmidt * Paul Schmidt
* Tim Wegner * Tim Wegner
* *
* The PNG Reference Library is supplied "AS IS". The Contributing Authors * The PNG Reference Library is supplied "AS IS". The Contributing
* and Group 42, Inc. disclaim all warranties, expressed or implied, * Authors and Group 42, Inc. disclaim all warranties, expressed or
* including, without limitation, the warranties of merchantability and of * implied, including, without limitation, the warranties of
* fitness for any purpose. The Contributing Authors and Group 42, Inc. * merchantability and of fitness for any purpose. The Contributing
* assume no liability for direct, indirect, incidental, special, exemplary, * Authors and Group 42, Inc. assume no liability for direct, indirect,
* or consequential damages, which may result from the use of the PNG * incidental, special, exemplary, or consequential damages, which may
* Reference Library, even if advised of the possibility of such damage. * result from the use of the PNG Reference Library, even if advised of
* the possibility of such damage.
* *
* Permission is hereby granted to use, copy, modify, and distribute this * Permission is hereby granted to use, copy, modify, and distribute this
* source code, or portions hereof, for any purpose, without fee, subject * source code, or portions hereof, for any purpose, without fee, subject
@ -101,13 +150,22 @@
* 3. This Copyright notice may not be removed or altered from any * 3. This Copyright notice may not be removed or altered from any
* source or altered source distribution. * source or altered source distribution.
* *
* The Contributing Authors and Group 42, Inc. specifically permit, without * The Contributing Authors and Group 42, Inc. specifically permit,
* fee, and encourage the use of this source code as a component to * without fee, and encourage the use of this source code as a component
* supporting the PNG file format in commercial products. If you use this * to supporting the PNG file format in commercial products. If you use
* source code in a product, acknowledgment is not required but would be * this source code in a product, acknowledgment is not required but would
* appreciated. * be appreciated.
* *
* END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE.
*
* TRADEMARK
* =========
*
* The name "libpng" has not been registered by the Copyright owners
* as a trademark in any jurisdiction. However, because libpng has
* been distributed and maintained world-wide, continually since 1995,
* the Copyright owners claim "common-law trademark protection" in any
* jurisdiction where common-law trademark is recognized.
*/ */
/* /*
@ -120,12 +178,6 @@
* files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). * files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31).
*/ */
/*
* Libpng is OSI Certified Open Source Software. OSI Certified Open Source is
* a certification mark of the Open Source Initiative. OSI has not addressed
* the additional disclaimers inserted at version 1.0.7.
*/
/* /*
* The contributing authors would like to thank all those who helped * The contributing authors would like to thank all those who helped
* with testing, bug fixes, and patience. This wouldn't have been * with testing, bug fixes, and patience. This wouldn't have been
@ -179,23 +231,25 @@
* 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible)
* 1.0.7 1 10007 (still compatible) * 1.0.7 1 10007 (still compatible)
* ... * ...
* 1.0.19 10 10019 10.so.0.19[.0] * 1.0.69 10 10069 10.so.0.69[.0]
* ... * ...
* 1.2.53 13 10253 12.so.0.53[.0] * 1.2.59 13 10259 12.so.0.59[.0]
* ... * ...
* 1.5.23 15 10523 15.so.15.23[.0] * 1.4.20 14 10420 14.so.0.20[.0]
* ... * ...
* 1.6.19 16 10619 16.so.16.19[.0] * 1.5.30 15 10530 15.so.15.30[.0]
* ...
* 1.6.37 16 10637 16.so.16.37[.0]
* *
* Henceforth the source version will match the shared-library major * Henceforth the source version will match the shared-library major and
* and minor numbers; the shared-library major version number will be * minor numbers; the shared-library major version number will be used for
* used for changes in backward compatibility, as it is intended. The * changes in backward compatibility, as it is intended.
* PNG_LIBPNG_VER macro, which is not used within libpng but is available * The PNG_LIBPNG_VER macro, which is not used within libpng but is
* for applications, is an unsigned integer of the form xyyzz corresponding * available for applications, is an unsigned integer of the form XYYZZ
* to the source version x.y.z (leading zeros in y and z). Beta versions * corresponding to the source version X.Y.Z (leading zeros in Y and Z).
* were given the previous public release number plus a letter, until * Beta versions were given the previous public release number plus a
* version 1.0.6j; from then on they were given the upcoming public * letter, until version 1.0.6j; from then on they were given the upcoming
* release number plus "betaNN" or "rcNN". * public release number plus "betaNN" or "rcNN".
* *
* Binary incompatibility exists only when applications make direct access * Binary incompatibility exists only when applications make direct access
* to the info_ptr or png_ptr members through png.h, and the compiled * to the info_ptr or png_ptr members through png.h, and the compiled
@ -205,65 +259,8 @@
* in binary compatibility (e.g., when a new feature is added). * in binary compatibility (e.g., when a new feature is added).
* *
* See libpng.txt or libpng.3 for more information. The PNG specification * See libpng.txt or libpng.3 for more information. The PNG specification
* is available as a W3C Recommendation and as an ISO Specification, * is available as a W3C Recommendation and as an ISO/IEC Standard; see
* <http://www.w3.org/TR/2003/REC-PNG-20031110/ * <https://www.w3.org/TR/2003/REC-PNG-20031110/>
*/
/*
* Y2K compliance in libpng:
* =========================
*
* November 12, 2015
*
* Since the PNG Development group is an ad-hoc body, we can't make
* an official declaration.
*
* This is your unofficial assurance that libpng from version 0.71 and
* upward through 1.6.19 are Y2K compliant. It is my belief that
* earlier versions were also Y2K compliant.
*
* Libpng only has two year fields. One is a 2-byte unsigned integer
* that will hold years up to 65535. The other, which is deprecated,
* holds the date in text format, and will hold years up to 9999.
*
* The integer is
* "png_uint_16 year" in png_time_struct.
*
* The string is
* "char time_buffer[29]" in png_struct. This is no longer used
* in libpng-1.6.x and will be removed from libpng-1.7.0.
*
* There are seven time-related functions:
* png.c: png_convert_to_rfc_1123_buffer() in png.c
* (formerly png_convert_to_rfc_1123() prior to libpng-1.5.x and
* png_convert_to_rfc_1152() in error prior to libpng-0.98)
* png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
* png_convert_from_time_t() in pngwrite.c
* png_get_tIME() in pngget.c
* png_handle_tIME() in pngrutil.c, called in pngread.c
* png_set_tIME() in pngset.c
* png_write_tIME() in pngwutil.c, called in pngwrite.c
*
* All handle dates properly in a Y2K environment. The
* png_convert_from_time_t() function calls gmtime() to convert from system
* clock time, which returns (year - 1900), which we properly convert to
* the full 4-digit year. There is a possibility that libpng applications
* are not passing 4-digit years into the png_convert_to_rfc_1123_buffer()
* function, or that they are incorrectly passing only a 2-digit year
* instead of "year - 1900" into the png_convert_from_struct_tm() function,
* but this is not under our control. The libpng documentation has always
* stated that it works with 4-digit years, and the APIs have been
* documented as such.
*
* The tIME chunk itself is also Y2K compliant. It uses a 2-byte unsigned
* integer to hold the year, and can hold years as large as 65535.
*
* zlib, upon which libpng depends, is also Y2K compliant. It contains
* no date-related code.
*
* Glenn Randers-Pehrson
* libpng maintainer
* PNG Development Group
*/ */
#ifndef PNG_H #ifndef PNG_H
@ -281,9 +278,8 @@
*/ */
/* Version information for png.h - this should match the version in png.c */ /* Version information for png.h - this should match the version in png.c */
#define PNG_LIBPNG_VER_STRING "1.6.19" #define PNG_LIBPNG_VER_STRING "1.6.37"
#define PNG_HEADER_VERSION_STRING \ #define PNG_HEADER_VERSION_STRING " libpng version 1.6.37 - April 14, 2019\n"
" libpng version 1.6.19 - November 12, 2015\n"
#define PNG_LIBPNG_VER_SONUM 16 #define PNG_LIBPNG_VER_SONUM 16
#define PNG_LIBPNG_VER_DLLNUM 16 #define PNG_LIBPNG_VER_DLLNUM 16
@ -291,12 +287,11 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6 #define PNG_LIBPNG_VER_MINOR 6
#define PNG_LIBPNG_VER_RELEASE 19 #define PNG_LIBPNG_VER_RELEASE 37
/* This should match the numeric part of the final component of /* This should be zero for a public release, or non-zero for a
* PNG_LIBPNG_VER_STRING, omitting any leading zero: * development version. [Deprecated]
*/ */
#define PNG_LIBPNG_VER_BUILD 0 #define PNG_LIBPNG_VER_BUILD 0
/* Release Status */ /* Release Status */
@ -316,26 +311,27 @@
#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE #define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE
/* Careful here. At one time, Guy wanted to use 082, but that would be octal. /* Careful here. At one time, Guy wanted to use 082, but that
* We must not include leading zeros. * would be octal. We must not include leading zeros.
* Versions 0.7 through 1.0.0 were in the range 0 to 100 here (only * Versions 0.7 through 1.0.0 were in the range 0 to 100 here
* version 1.0.0 was mis-numbered 100 instead of 10000). From * (only version 1.0.0 was mis-numbered 100 instead of 10000).
* version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release * From version 1.0.1 it is:
* XXYYZZ, where XX=major, YY=minor, ZZ=release
*/ */
#define PNG_LIBPNG_VER 10619 /* 1.6.19 */ #define PNG_LIBPNG_VER 10637 /* 1.6.37 */
/* Library configuration: these options cannot be changed after /* Library configuration: these options cannot be changed after
* the library has been built. * the library has been built.
*/ */
#ifndef PNGLCONF_H #ifndef PNGLCONF_H
/* If pnglibconf.h is missing, you can /* If pnglibconf.h is missing, you can
* copy scripts/pnglibconf.h.prebuilt to pnglibconf.h * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h
*/ */
# include "pnglibconf.h" # include "pnglibconf.h"
#endif #endif
#ifndef PNG_VERSION_INFO_ONLY #ifndef PNG_VERSION_INFO_ONLY
/* Machine specific configuration. */ /* Machine specific configuration. */
# include "pngconf.h" # include "pngconf.h"
#endif #endif
@ -432,7 +428,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h /* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number. * do not agree upon the version number.
*/ */
typedef char* png_libpng_version_1_6_19; typedef char* png_libpng_version_1_6_37;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
* *
@ -573,8 +569,8 @@ typedef struct png_text_struct
png_charp key; /* keyword, 1-79 character description of "text" */ png_charp key; /* keyword, 1-79 character description of "text" */
png_charp text; /* comment, may be an empty string (ie "") png_charp text; /* comment, may be an empty string (ie "")
or a NULL pointer */ or a NULL pointer */
png_size_t text_length; /* length of the text string */ size_t text_length; /* length of the text string */
png_size_t itxt_length; /* length of the itxt string */ size_t itxt_length; /* length of the itxt string */
png_charp lang; /* language code, 0-79 characters png_charp lang; /* language code, 0-79 characters
or a NULL pointer */ or a NULL pointer */
png_charp lang_key; /* keyword translated UTF-8 string, 0 or more png_charp lang_key; /* keyword translated UTF-8 string, 0 or more
@ -627,7 +623,7 @@ typedef struct png_unknown_chunk_t
{ {
png_byte name[5]; /* Textual chunk name with '\0' terminator */ 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! */
png_size_t size; size_t size;
/* 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
@ -652,7 +648,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
/* 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)
#define PNG_UINT_32_MAX ((png_uint_32)(-1)) #define PNG_UINT_32_MAX ((png_uint_32)(-1))
#define PNG_SIZE_MAX ((png_size_t)(-1)) #define PNG_SIZE_MAX ((size_t)(-1))
/* These are constants for fixed point values encoded in the /* These are constants for fixed point values encoded in the
* PNG specification manner (x100000) * PNG specification manner (x100000)
@ -733,24 +729,23 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
* data in the info_struct to be written into the output file. The values * data in the info_struct to be written into the output file. The values
* of the PNG_INFO_<chunk> defines should NOT be changed. * of the PNG_INFO_<chunk> defines should NOT be changed.
*/ */
#define PNG_INFO_gAMA 0x0001 #define PNG_INFO_gAMA 0x0001U
#define PNG_INFO_sBIT 0x0002 #define PNG_INFO_sBIT 0x0002U
#define PNG_INFO_cHRM 0x0004 #define PNG_INFO_cHRM 0x0004U
#define PNG_INFO_PLTE 0x0008 #define PNG_INFO_PLTE 0x0008U
#define PNG_INFO_tRNS 0x0010 #define PNG_INFO_tRNS 0x0010U
#define PNG_INFO_bKGD 0x0020 #define PNG_INFO_bKGD 0x0020U
#define PNG_INFO_hIST 0x0040 #define PNG_INFO_hIST 0x0040U
#define PNG_INFO_pHYs 0x0080 #define PNG_INFO_pHYs 0x0080U
#define PNG_INFO_oFFs 0x0100 #define PNG_INFO_oFFs 0x0100U
#define PNG_INFO_tIME 0x0200 #define PNG_INFO_tIME 0x0200U
#define PNG_INFO_pCAL 0x0400 #define PNG_INFO_pCAL 0x0400U
#define PNG_INFO_sRGB 0x0800 /* GR-P, 0.96a */ #define PNG_INFO_sRGB 0x0800U /* GR-P, 0.96a */
#define PNG_INFO_iCCP 0x1000 /* ESR, 1.0.6 */ #define PNG_INFO_iCCP 0x1000U /* ESR, 1.0.6 */
#define PNG_INFO_sPLT 0x2000 /* ESR, 1.0.6 */ #define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */
#define PNG_INFO_sCAL 0x4000 /* ESR, 1.0.6 */ #define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */
#if INT_MAX >= 0x8000 /* else this might break */ #define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */
#define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */ #define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */
#endif
/* This is used for the transformation routines, as some of them /* This is used for the transformation routines, as some of them
* change these values for the row. It also should enable using * change these values for the row. It also should enable using
@ -759,7 +754,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
typedef struct png_row_info_struct typedef struct png_row_info_struct
{ {
png_uint_32 width; /* width of row */ png_uint_32 width; /* width of row */
png_size_t rowbytes; /* number of bytes in row */ size_t rowbytes; /* number of bytes in row */
png_byte color_type; /* color type of row */ png_byte color_type; /* color type of row */
png_byte bit_depth; /* bit depth of row */ png_byte bit_depth; /* bit depth of row */
png_byte channels; /* number of channels (1, 2, 3, or 4) */ png_byte channels; /* number of channels (1, 2, 3, or 4) */
@ -778,7 +773,7 @@ typedef png_row_info * * png_row_infopp;
* expected to return the read data in the buffer. * expected to return the read data in the buffer.
*/ */
typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp)); typedef PNG_CALLBACK(void, *png_error_ptr, (png_structp, png_const_charp));
typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, png_size_t)); typedef PNG_CALLBACK(void, *png_rw_ptr, (png_structp, png_bytep, size_t));
typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp));
typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32,
int)); int));
@ -915,8 +910,8 @@ PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes));
* signature, and non-zero otherwise. Having num_to_check == 0 or * signature, and non-zero otherwise. Having num_to_check == 0 or
* start > 7 will always fail (ie return non-zero). * start > 7 will always fail (ie return non-zero).
*/ */
PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start,
png_size_t num_to_check)); size_t num_to_check));
/* Simple signature checking function. This is the same as calling /* Simple signature checking function. This is the same as calling
* png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
@ -935,11 +930,11 @@ PNG_EXPORTA(5, png_structp, png_create_write_struct,
png_error_ptr warn_fn), png_error_ptr warn_fn),
PNG_ALLOCATED); PNG_ALLOCATED);
PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, PNG_EXPORT(6, size_t, png_get_compression_buffer_size,
(png_const_structrp png_ptr)); (png_const_structrp png_ptr));
PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr,
png_size_t size)); size_t size));
/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp /* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp
* match up. * match up.
@ -992,7 +987,7 @@ PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr));
/* Write a PNG chunk - size, type, (optional) data, CRC. */ /* Write a PNG chunk - size, type, (optional) data, CRC. */
PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep
chunk_name, png_const_bytep data, png_size_t length)); chunk_name, png_const_bytep data, size_t length));
/* Write the start of a PNG chunk - length and chunk name. */ /* Write the start of a PNG chunk - length and chunk name. */
PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr,
@ -1000,7 +995,7 @@ PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr,
/* Write the data of a PNG chunk started with png_write_chunk_start(). */ /* Write the data of a PNG chunk started with png_write_chunk_start(). */
PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr, PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr,
png_const_bytep data, png_size_t length)); png_const_bytep data, size_t length));
/* Finish a chunk started with png_write_chunk_start() (includes CRC). */ /* Finish a chunk started with png_write_chunk_start() (includes CRC). */
PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr));
@ -1014,7 +1009,7 @@ PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr),
* the API will be removed in the future. * the API will be removed in the future.
*/ */
PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr,
png_size_t png_info_struct_size), PNG_DEPRECATED); size_t png_info_struct_size), PNG_DEPRECATED);
/* Writes all the PNG information before the image. */ /* Writes all the PNG information before the image. */
PNG_EXPORT(20, void, png_write_info_before_PLTE, PNG_EXPORT(20, void, png_write_info_before_PLTE,
@ -1111,7 +1106,7 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
* corresponding composited pixel, and the color channels are unassociated * corresponding composited pixel, and the color channels are unassociated
* (not premultiplied). The gamma encoded color channels must be scaled * (not premultiplied). The gamma encoded color channels must be scaled
* according to the contribution and to do this it is necessary to undo * according to the contribution and to do this it is necessary to undo
* the encoding, scale the color values, perform the composition and reencode * the encoding, scale the color values, perform the composition and re-encode
* the values. This is the 'PNG' mode. * the values. This is the 'PNG' mode.
* *
* The alternative is to 'associate' the alpha with the color information by * The alternative is to 'associate' the alpha with the color information by
@ -1167,7 +1162,7 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr,
* *
* png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC); * png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC);
* In this case the output is assumed to be something like an sRGB conformant * In this case the output is assumed to be something like an sRGB conformant
* display preceeded by a power-law lookup table of power 1.45. This is how * display preceded by a power-law lookup table of power 1.45. This is how
* early Mac systems behaved. * early Mac systems behaved.
* *
* png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR);
@ -1214,7 +1209,7 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr,
* *
* When the default gamma of PNG files doesn't match the output gamma. * When the default gamma of PNG files doesn't match the output gamma.
* If you have PNG files with no gamma information png_set_alpha_mode allows * If you have PNG files with no gamma information png_set_alpha_mode allows
* you to provide a default gamma, but it also sets the ouput gamma to the * you to provide a default gamma, but it also sets the output gamma to the
* matching value. If you know your PNG files have a gamma that doesn't * matching value. If you know your PNG files have a gamma that doesn't
* match the output you can take advantage of the fact that * match the output you can take advantage of the fact that
* png_set_alpha_mode always sets the output gamma but only sets the PNG * png_set_alpha_mode always sets the output gamma but only sets the PNG
@ -1321,7 +1316,7 @@ PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr));
#endif #endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */ #define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */
/* Strip the second byte of information from a 16-bit depth file. */ /* Strip the second byte of information from a 16-bit depth file. */
PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr));
#endif #endif
@ -1472,8 +1467,8 @@ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
#define PNG_FILTER_UP 0x20 #define PNG_FILTER_UP 0x20
#define PNG_FILTER_AVG 0x40 #define PNG_FILTER_AVG 0x40
#define PNG_FILTER_PAETH 0x80 #define PNG_FILTER_PAETH 0x80
#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \ #define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP)
PNG_FILTER_AVG | PNG_FILTER_PAETH) #define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH)
/* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now. /* Filter values (not flags) - used in pngwrite.c, pngwutil.c for now.
* These defines should NOT be changed. * These defines should NOT be changed.
@ -1665,7 +1660,7 @@ PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp));
* chunk will cause an error at this point unless it is to be saved. * chunk will cause an error at this point unless it is to be saved.
* positive: The chunk was handled, libpng will ignore/discard it. * positive: The chunk was handled, libpng will ignore/discard it.
* *
* See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about * See "INTERACTION WITH USER CHUNK CALLBACKS" below for important notes about
* how this behavior will change in libpng 1.7 * how this behavior will change in libpng 1.7
*/ */
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,
@ -1690,7 +1685,7 @@ PNG_EXPORT(91, png_voidp, png_get_progressive_ptr,
/* Function to be called when data becomes available */ /* Function to be called when data becomes available */
PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr,
png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size)); png_inforp info_ptr, png_bytep buffer, size_t buffer_size));
/* A function which may be called *only* within png_process_data to stop the /* A function which may be called *only* within png_process_data to stop the
* processing of any more data. The function returns the number of bytes * processing of any more data. The function returns the number of bytes
@ -1699,7 +1694,7 @@ PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr,
* 'save' is set to true the routine will first save all the pending data and * 'save' is set to true the routine will first save all the pending data and
* will always return 0. * will always return 0.
*/ */
PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save)); PNG_EXPORT(219, size_t, png_process_data_pause, (png_structrp, int save));
/* A function which may be called *only* outside (after) a call to /* A function which may be called *only* outside (after) a call to
* png_process_data. It returns the number of bytes of data to skip in the * png_process_data. It returns the number of bytes of data to skip in the
@ -1750,21 +1745,22 @@ PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
#define PNG_SET_WILL_FREE_DATA 1 #define PNG_SET_WILL_FREE_DATA 1
#define PNG_USER_WILL_FREE_DATA 2 #define PNG_USER_WILL_FREE_DATA 2
/* Flags for png_ptr->free_me and info_ptr->free_me */ /* Flags for png_ptr->free_me and info_ptr->free_me */
#define PNG_FREE_HIST 0x0008 #define PNG_FREE_HIST 0x0008U
#define PNG_FREE_ICCP 0x0010 #define PNG_FREE_ICCP 0x0010U
#define PNG_FREE_SPLT 0x0020 #define PNG_FREE_SPLT 0x0020U
#define PNG_FREE_ROWS 0x0040 #define PNG_FREE_ROWS 0x0040U
#define PNG_FREE_PCAL 0x0080 #define PNG_FREE_PCAL 0x0080U
#define PNG_FREE_SCAL 0x0100 #define PNG_FREE_SCAL 0x0100U
#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
# define PNG_FREE_UNKN 0x0200 # define PNG_FREE_UNKN 0x0200U
#endif #endif
/* PNG_FREE_LIST 0x0400 removed in 1.6.0 because it is ignored */ /* PNG_FREE_LIST 0x0400U removed in 1.6.0 because it is ignored */
#define PNG_FREE_PLTE 0x1000 #define PNG_FREE_PLTE 0x1000U
#define PNG_FREE_TRNS 0x2000 #define PNG_FREE_TRNS 0x2000U
#define PNG_FREE_TEXT 0x4000 #define PNG_FREE_TEXT 0x4000U
#define PNG_FREE_ALL 0x7fff #define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */
#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ #define PNG_FREE_ALL 0xffffU
#define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
#ifdef PNG_USER_MEM_SUPPORTED #ifdef PNG_USER_MEM_SUPPORTED
PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr,
@ -1843,7 +1839,7 @@ 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, png_size_t, png_get_rowbytes, (png_const_structrp png_ptr, PNG_EXPORT(111, 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_INFO_IMAGE_SUPPORTED
@ -1982,6 +1978,18 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
png_fixed_point int_blue_Z)) png_fixed_point int_blue_Z))
#endif #endif
#ifdef PNG_eXIf_SUPPORTED
PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr,
png_inforp info_ptr, png_bytep *exif));
PNG_EXPORT(247, void, png_set_eXIf, (png_const_structrp png_ptr,
png_inforp info_ptr, png_bytep exif));
PNG_EXPORT(248, png_uint_32, png_get_eXIf_1, (png_const_structrp png_ptr,
png_const_inforp info_ptr, png_uint_32 *num_exif, png_bytep *exif));
PNG_EXPORT(249, void, png_set_eXIf_1, (png_const_structrp png_ptr,
png_inforp info_ptr, png_uint_32 num_exif, png_bytep exif));
#endif
#ifdef PNG_gAMA_SUPPORTED #ifdef PNG_gAMA_SUPPORTED
PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr,
png_const_inforp info_ptr, double *file_gamma)) png_const_inforp info_ptr, double *file_gamma))
@ -2000,9 +2008,6 @@ PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr,
#ifdef PNG_hIST_SUPPORTED #ifdef PNG_hIST_SUPPORTED
PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr,
png_inforp info_ptr, png_uint_16p *hist)); png_inforp info_ptr, png_uint_16p *hist));
#endif
#ifdef PNG_hIST_SUPPORTED
PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr,
png_inforp info_ptr, png_const_uint_16p hist)); png_inforp info_ptr, png_const_uint_16p hist));
#endif #endif
@ -2203,7 +2208,7 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr,
* to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks
* it simply resets the behavior to the libpng default. * it simply resets the behavior to the libpng default.
* *
* INTERACTION WTIH USER CHUNK CALLBACKS: * INTERACTION WITH USER CHUNK CALLBACKS:
* The per-chunk handling is always used when there is a png_user_chunk_ptr * The per-chunk handling is always used when there is a png_user_chunk_ptr
* callback and the callback returns 0; the chunk is then always stored *unless* * callback and the callback returns 0; the chunk is then always stored *unless*
* it is critical and the per-chunk setting is other than ALWAYS. Notice that * it is critical and the per-chunk setting is other than ALWAYS. Notice that
@ -2270,8 +2275,10 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr,
* except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to
* be processed by libpng. * be processed by libpng.
*/ */
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr,
int keep, png_const_bytep chunk_list, int num_chunks)); int keep, png_const_bytep chunk_list, int num_chunks));
#endif /* HANDLE_AS_UNKNOWN */
/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; /* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned;
* the result is therefore true (non-zero) if special handling is required, * the result is therefore true (non-zero) if special handling is required,
@ -2279,7 +2286,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_const_structrp png_ptr, PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr,
@ -2501,18 +2508,22 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
/* fg and bg should be in `gamma 1.0' space; alpha is the opacity */ /* fg and bg should be in `gamma 1.0' space; alpha is the opacity */
# define png_composite(composite, fg, alpha, bg) \ # define png_composite(composite, fg, alpha, bg) \
{ png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \ { \
png_uint_16 temp = (png_uint_16)((png_uint_16)(fg) \
* (png_uint_16)(alpha) \ * (png_uint_16)(alpha) \
+ (png_uint_16)(bg)*(png_uint_16)(255 \ + (png_uint_16)(bg)*(png_uint_16)(255 \
- (png_uint_16)(alpha)) + 128); \ - (png_uint_16)(alpha)) + 128); \
(composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); } (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); \
}
# define png_composite_16(composite, fg, alpha, bg) \ # define png_composite_16(composite, fg, alpha, bg) \
{ png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \ { \
png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \
* (png_uint_32)(alpha) \ * (png_uint_32)(alpha) \
+ (png_uint_32)(bg)*(65535 \ + (png_uint_32)(bg)*(65535 \
- (png_uint_32)(alpha)) + 32768); \ - (png_uint_32)(alpha)) + 32768); \
(composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); } (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); \
}
#else /* Standard method using integer division */ #else /* Standard method using integer division */
@ -2580,7 +2591,7 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \
: (png_int_32)png_get_uint_32(buf))) : (png_int_32)png_get_uint_32(buf)))
/* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, /* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h,
* but defining a macro name prefixed with PNG_PREFIX. * but defining a macro name prefixed with PNG_PREFIX.
*/ */
# ifndef PNG_PREFIX # ifndef PNG_PREFIX
@ -2616,7 +2627,7 @@ PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr,
* The simplified API hides the details of both libpng and the PNG file format * The simplified API hides the details of both libpng and the PNG file format
* itself. It allows PNG files to be read into a very limited number of * itself. It allows PNG files to be read into a very limited number of
* in-memory bitmap formats or to be written from the same formats. If these * in-memory bitmap formats or to be written from the same formats. If these
* formats do not accomodate your needs then you can, and should, use the more * formats do not accommodate your needs then you can, and should, use the more
* sophisticated APIs above - these support a wide variety of in-memory formats * sophisticated APIs above - these support a wide variety of in-memory formats
* and a wide variety of sophisticated transformations to those formats as well * and a wide variety of sophisticated transformations to those formats as well
* as a wide variety of APIs to manipulate ancillary information. * as a wide variety of APIs to manipulate ancillary information.
@ -2722,7 +2733,7 @@ typedef struct
* *
* When the simplified API needs to convert between sRGB and linear colorspaces, * When the simplified API needs to convert between sRGB and linear colorspaces,
* the actual sRGB transfer curve defined in the sRGB specification (see the * the actual sRGB transfer curve defined in the sRGB specification (see the
* article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 * article at <https://en.wikipedia.org/wiki/SRGB>) is used, not the gamma=1/2.2
* approximation used elsewhere in libpng. * approximation used elsewhere in libpng.
* *
* When an alpha channel is present it is expected to denote pixel coverage * When an alpha channel is present it is expected to denote pixel coverage
@ -2777,6 +2788,8 @@ typedef struct
# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ # define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */
#endif #endif
#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */
/* Commonly used formats have predefined macros. /* Commonly used formats have predefined macros.
* *
* First the single byte (sRGB) formats: * First the single byte (sRGB) formats:
@ -2888,12 +2901,19 @@ typedef struct
* is the minimum 'row stride', the minimum count of components between each * is the minimum 'row stride', the minimum count of components between each
* row. For a color-mapped image this is the minimum number of bytes in a * row. For a color-mapped image this is the minimum number of bytes in a
* row. * row.
*
* WARNING: this macro overflows for some images with more than one component
* and very large image widths. libpng will refuse to process an image where
* this macro would overflow.
*/ */
#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\ #define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
(PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride)) (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
/* Return the size, in bytes, of an image buffer given a png_image and a row /* Return the size, in bytes, of an image buffer given a png_image and a row
* stride - the number of components to leave space for in each row. * stride - the number of components to leave space for in each row.
*
* WARNING: this macro overflows a 32-bit integer for some large PNG images,
* libpng will refuse to process an image where such an overflow would occur.
*/ */
#define PNG_IMAGE_SIZE(image)\ #define PNG_IMAGE_SIZE(image)\
@ -2916,7 +2936,7 @@ typedef struct
* 'flags' field of png_image. * 'flags' field of png_image.
*/ */
#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01 #define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01
/* This indicates the the RGB values of the in-memory bitmap do not /* This indicates that the RGB values of the in-memory bitmap do not
* correspond to the red, green and blue end-points defined by sRGB. * correspond to the red, green and blue end-points defined by sRGB.
*/ */
@ -2969,7 +2989,7 @@ PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image,
#endif /* STDIO */ #endif /* STDIO */
PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image,
png_const_voidp memory, png_size_t size)); png_const_voidp memory, size_t size));
/* The PNG header is read from the given memory buffer. */ /* The PNG header is read from the given memory buffer. */
PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
@ -3014,7 +3034,6 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image));
#endif /* SIMPLIFIED_READ */ #endif /* SIMPLIFIED_READ */
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
#ifdef PNG_STDIO_SUPPORTED
/* WRITE APIS /* WRITE APIS
* ---------- * ----------
* For write you must initialize a png_image structure to describe the image to * For write you must initialize a png_image structure to describe the image to
@ -3031,6 +3050,7 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image));
* values do not correspond to the colors in sRGB. * values do not correspond to the colors in sRGB.
* colormap_entries: set to the number of entries in the color-map (0 to 256) * colormap_entries: set to the number of entries in the color-map (0 to 256)
*/ */
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
const char *file, int convert_to_8bit, const void *buffer, const char *file, int convert_to_8bit, const void *buffer,
png_int_32 row_stride, const void *colormap)); png_int_32 row_stride, const void *colormap));
@ -3040,8 +3060,9 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
int convert_to_8_bit, const void *buffer, png_int_32 row_stride, int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
const void *colormap)); const void *colormap));
/* Write the image to the given (FILE*). */ /* Write the image to the given (FILE*). */
#endif /* SIMPLIFIED_WRITE_STDIO */
/* With both write APIs if image is in one of the linear formats with 16-bit /* With all write APIs if image is in one of the linear formats with 16-bit
* data then setting convert_to_8_bit will cause the output to be an 8-bit PNG * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
* gamma encoded according to the sRGB specification, otherwise a 16-bit linear * gamma encoded according to the sRGB specification, otherwise a 16-bit linear
* encoded PNG file is written. * encoded PNG file is written.
@ -3053,13 +3074,103 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
* *
* With all APIs row_stride is handled as in the read APIs - it is the spacing * With all APIs row_stride is handled as in the read APIs - it is the spacing
* from one row to the next in component sized units (1 or 2 bytes) and if * from one row to the next in component sized units (1 or 2 bytes) and if
* negative indicates a bottom-up row layout in the buffer. If row_stride is zero, * negative indicates a bottom-up row layout in the buffer. If row_stride is
* libpng will calculate it for you from the image width and number of channels. * zero, libpng will calculate it for you from the image width and number of
* channels.
* *
* Note that the write API does not support interlacing, sub-8-bit pixels, indexed * Note that the write API does not support interlacing, sub-8-bit pixels or
* PNG (color_type 3) or most ancillary chunks. * most ancillary chunks. If you need to write text chunks (e.g. for copyright
* notices) you need to use one of the other APIs.
*/
PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8_bit,
const void *buffer, png_int_32 row_stride, const void *colormap));
/* Write the image to the given memory buffer. The function both writes the
* whole PNG data stream to *memory and updates *memory_bytes with the count
* of bytes written.
*
* 'memory' may be NULL. In this case *memory_bytes is not read however on
* success the number of bytes which would have been written will still be
* stored in *memory_bytes. On failure *memory_bytes will contain 0.
*
* If 'memory' is not NULL it must point to memory[*memory_bytes] of
* writeable memory.
*
* If the function returns success memory[*memory_bytes] (if 'memory' is not
* NULL) contains the written PNG data. *memory_bytes will always be less
* than or equal to the original value.
*
* If the function returns false and *memory_bytes was not changed an error
* occurred during write. If *memory_bytes was changed, or is not 0 if
* 'memory' was NULL, the write would have succeeded but for the memory
* buffer being too small. *memory_bytes contains the required number of
* bytes and will be bigger that the original value.
*/
#define png_image_write_get_memory_size(image, size, convert_to_8_bit, buffer,\
row_stride, colormap)\
png_image_write_to_memory(&(image), 0, &(size), convert_to_8_bit, buffer,\
row_stride, colormap)
/* Return the amount of memory in 'size' required to compress this image.
* The png_image structure 'image' must be filled in as in the above
* function and must not be changed before the actual write call, the buffer
* and all other parameters must also be identical to that in the final
* write call. The 'size' variable need not be initialized.
*
* NOTE: the macro returns true/false, if false is returned 'size' will be
* set to zero and the write failed and probably will fail if tried again.
*/
/* You can pre-allocate the buffer by making sure it is of sufficient size
* regardless of the amount of compression achieved. The buffer size will
* always be bigger than the original image and it will never be filled. The
* following macros are provided to assist in allocating the buffer.
*/
#define PNG_IMAGE_DATA_SIZE(image) (PNG_IMAGE_SIZE(image)+(image).height)
/* The number of uncompressed bytes in the PNG byte encoding of the image;
* uncompressing the PNG IDAT data will give this number of bytes.
*
* NOTE: while PNG_IMAGE_SIZE cannot overflow for an image in memory this
* macro can because of the extra bytes used in the PNG byte encoding. You
* need to avoid this macro if your image size approaches 2^30 in width or
* height. The same goes for the remainder of these macros; they all produce
* bigger numbers than the actual in-memory image size.
*/
#ifndef PNG_ZLIB_MAX_SIZE
# define PNG_ZLIB_MAX_SIZE(b) ((b)+(((b)+7U)>>3)+(((b)+63U)>>6)+11U)
/* An upper bound on the number of compressed bytes given 'b' uncompressed
* bytes. This is based on deflateBounds() in zlib; different
* implementations of zlib compression may conceivably produce more data so
* if your zlib implementation is not zlib itself redefine this macro
* appropriately.
*/
#endif
#define PNG_IMAGE_COMPRESSED_SIZE_MAX(image)\
PNG_ZLIB_MAX_SIZE((png_alloc_size_t)PNG_IMAGE_DATA_SIZE(image))
/* An upper bound on the size of the data in the PNG IDAT chunks. */
#define PNG_IMAGE_PNG_SIZE_MAX_(image, image_size)\
((8U/*sig*/+25U/*IHDR*/+16U/*gAMA*/+44U/*cHRM*/+12U/*IEND*/+\
(((image).format&PNG_FORMAT_FLAG_COLORMAP)?/*colormap: PLTE, tRNS*/\
12U+3U*(image).colormap_entries/*PLTE data*/+\
(((image).format&PNG_FORMAT_FLAG_ALPHA)?\
12U/*tRNS*/+(image).colormap_entries:0U):0U)+\
12U)+(12U*((image_size)/PNG_ZBUF_SIZE))/*IDAT*/+(image_size))
/* A helper for the following macro; if your compiler cannot handle the
* following macro use this one with the result of
* PNG_IMAGE_COMPRESSED_SIZE_MAX(image) as the second argument (most
* compilers should handle this just fine.)
*/
#define PNG_IMAGE_PNG_SIZE_MAX(image)\
PNG_IMAGE_PNG_SIZE_MAX_(image, PNG_IMAGE_COMPRESSED_SIZE_MAX(image))
/* An upper bound on the total length of the PNG data stream for 'image'.
* The result is of type png_alloc_size_t, on 32-bit systems this may
* overflow even though PNG_IMAGE_DATA_SIZE does not overflow; the write will
* run out of buffer space but return a corrected size which should work.
*/ */
#endif /* STDIO */
#endif /* SIMPLIFIED_WRITE */ #endif /* SIMPLIFIED_WRITE */
/******************************************************************************* /*******************************************************************************
* END OF SIMPLIFIED API * END OF SIMPLIFIED API
@ -3075,7 +3186,7 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
* option and 'onoff' is 0 (off) or non-0 (on). The value returned is given * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given
* by the PNG_OPTION_ defines below. * by the PNG_OPTION_ defines below.
* *
* HARDWARE: normally hardware capabilites, such as the Intel SSE instructions, * HARDWARE: normally hardware capabilities, such as the Intel SSE instructions,
* are detected at run time, however sometimes it may be impossible * are detected at run time, however sometimes it may be impossible
* 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
@ -3093,7 +3204,14 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
#endif #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 */ #ifdef PNG_MIPS_MSA_API_SUPPORTED
# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */
#endif
#define PNG_IGNORE_ADLER32 8
#ifdef PNG_POWERPC_VSX_API_SUPPORTED
# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions supported */
#endif
#define PNG_OPTION_NEXT 12 /* Next option - numbers must be even */
/* Return values: NOTE: there are four values and 'off' is *not* zero */ /* Return values: NOTE: there are four values and 'off' is *not* zero */
#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */ #define PNG_OPTION_UNSET 0 /* Unset - defaults to off */
@ -3117,7 +3235,7 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
* one to use is one more than this.) * one to use is one more than this.)
*/ */
#ifdef PNG_EXPORT_LAST_ORDINAL #ifdef PNG_EXPORT_LAST_ORDINAL
PNG_EXPORT_LAST_ORDINAL(244); PNG_EXPORT_LAST_ORDINAL(249);
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -1,11 +1,12 @@
/* pngconf.h - machine configurable file for libpng /* pngconf.h - machine-configurable file for libpng
* *
* libpng version 1.6.19, July 23, 2015 * libpng version 1.6.37
* *
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 2018-2019 Cosmin Truta
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -47,12 +48,8 @@
#ifdef PNG_SETJMP_SUPPORTED #ifdef PNG_SETJMP_SUPPORTED
/* Required for the definition of jmp_buf and the declaration of longjmp: */ /* Required for the definition of jmp_buf and the declaration of longjmp: */
#ifdef __cplusplus
# include <csetjmp>
#else
# include <setjmp.h> # include <setjmp.h>
#endif #endif
#endif
#ifdef PNG_CONVERT_tIME_SUPPORTED #ifdef PNG_CONVERT_tIME_SUPPORTED
/* Required for struct tm: */ /* Required for struct tm: */
@ -61,14 +58,13 @@
#endif /* PNG_BUILDING_SYMBOL_TABLE */ #endif /* PNG_BUILDING_SYMBOL_TABLE */
/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using /* Prior to 1.6.0, it was possible to turn off 'const' in declarations,
* PNG_NO_CONST; this is no longer supported except for data declarations which * using PNG_NO_CONST. This is no longer supported.
* apparently still cause problems in 2011 on some compilers.
*/ */
#define PNG_CONST const /* backward compatibility only */ #define PNG_CONST const /* backward compatibility only */
/* This controls optimization of the reading of 16-bit and 32-bit values /* This controls optimization of the reading of 16-bit and 32-bit
* from PNG files. It can be set on a per-app-file basis - it * values from PNG files. It can be set on a per-app-file basis: it
* just changes whether a macro is used when the function is called. * just changes whether a macro is used when the function is called.
* The library builder sets the default; if read functions are not * The library builder sets the default; if read functions are not
* built into the library the macro implementation is forced on. * built into the library the macro implementation is forced on.
@ -131,7 +127,7 @@
* *
* These cases only differ if the operating system does not use the C * These cases only differ if the operating system does not use the C
* calling convention, at present this just means the above cases * calling convention, at present this just means the above cases
* (x86 DOS/Windows sytems) and, even then, this does not apply to * (x86 DOS/Windows systems) and, even then, this does not apply to
* Cygwin running on those systems. * Cygwin running on those systems.
* *
* Note that the value must be defined in pnglibconf.h so that what * Note that the value must be defined in pnglibconf.h so that what
@ -511,16 +507,18 @@
# error "libpng requires a signed 32-bit (or more) type" # error "libpng requires a signed 32-bit (or more) type"
#endif #endif
#if UINT_MAX > 4294967294 #if UINT_MAX > 4294967294U
typedef unsigned int png_uint_32; typedef unsigned int png_uint_32;
#elif ULONG_MAX > 4294967294 #elif ULONG_MAX > 4294967294U
typedef unsigned long int png_uint_32; typedef unsigned long int png_uint_32;
#else #else
# error "libpng requires an unsigned 32-bit (or more) type" # error "libpng requires an unsigned 32-bit (or more) type"
#endif #endif
/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, /* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t.
* requires an ISOC90 compiler and relies on consistent behavior of sizeof. * From 1.6.0 onwards, an ISO C90 compiler, as well as a standard-compliant
* behavior of sizeof and ptrdiff_t are required.
* The legacy typedefs are provided here for backwards compatibility.
*/ */
typedef size_t png_size_t; typedef size_t png_size_t;
typedef ptrdiff_t png_ptrdiff_t; typedef ptrdiff_t png_ptrdiff_t;
@ -541,13 +539,12 @@ typedef ptrdiff_t png_ptrdiff_t;
# endif # endif
#endif #endif
/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no /* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller
* smaller than png_uint_32. Casts from png_size_t or png_uint_32 to * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are
* png_alloc_size_t are not necessary; in fact, it is recommended not to use * not necessary; in fact, it is recommended not to use them at all, so that
* them at all so that the compiler can complain when something turns out to be * the compiler can complain when something turns out to be problematic.
* problematic.
* *
* Casts in the other direction (from png_alloc_size_t to png_size_t or * Casts in the other direction (from png_alloc_size_t to size_t or
* png_uint_32) should be explicitly applied; however, we do not expect to * png_uint_32) should be explicitly applied; however, we do not expect to
* encounter practical situations that require such conversions. * encounter practical situations that require such conversions.
* *
@ -557,7 +554,7 @@ typedef ptrdiff_t png_ptrdiff_t;
#ifdef PNG_SMALL_SIZE_T #ifdef PNG_SMALL_SIZE_T
typedef png_uint_32 png_alloc_size_t; typedef png_uint_32 png_alloc_size_t;
#else #else
typedef png_size_t png_alloc_size_t; typedef size_t png_alloc_size_t;
#endif #endif
/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler /* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler
@ -593,8 +590,8 @@ typedef char * png_charp;
typedef const char * png_const_charp; typedef const char * png_const_charp;
typedef png_fixed_point * png_fixed_point_p; typedef png_fixed_point * png_fixed_point_p;
typedef const png_fixed_point * png_const_fixed_point_p; typedef const png_fixed_point * png_const_fixed_point_p;
typedef png_size_t * png_size_tp; typedef size_t * png_size_tp;
typedef const png_size_t * png_const_size_tp; typedef const size_t * png_const_size_tp;
#ifdef PNG_STDIO_SUPPORTED #ifdef PNG_STDIO_SUPPORTED
typedef FILE * png_FILE_p; typedef FILE * png_FILE_p;

View File

@ -1,10 +1,10 @@
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c /* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
* *
* Last changed in libpng 1.6.8 [December 19, 2013] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2013 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer

View File

@ -1,10 +1,10 @@
/* pngerror.c - stub functions for i/o and memory allocation /* pngerror.c - stub functions for i/o and memory allocation
* *
* Last changed in libpng 1.6.15 [November 20, 2014] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2014 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -44,7 +44,7 @@ png_error,(png_const_structrp png_ptr, png_const_charp error_message),
if (png_ptr != NULL) if (png_ptr != NULL)
{ {
if ((png_ptr->flags & if ((png_ptr->flags &
(PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0 (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
{ {
if (*error_message == PNG_LITERAL_SHARP) if (*error_message == PNG_LITERAL_SHARP)
{ {
@ -163,7 +163,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_02u: case PNG_NUMBER_FORMAT_02u:
/* Expects at least 2 digits. */ /* Expects at least 2 digits. */
mincount = 2; mincount = 2;
FALLTHROUGH; /* FALLTHROUGH */
case PNG_NUMBER_FORMAT_u: case PNG_NUMBER_FORMAT_u:
*--end = digits[number % 10]; *--end = digits[number % 10];
@ -173,7 +173,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_02x: case PNG_NUMBER_FORMAT_02x:
/* This format expects at least two digits */ /* This format expects at least two digits */
mincount = 2; mincount = 2;
FALLTHROUGH; /* FALLTHROUGH */
case PNG_NUMBER_FORMAT_x: case PNG_NUMBER_FORMAT_x:
*--end = digits[number & 0xf]; *--end = digits[number & 0xf];
@ -425,7 +425,7 @@ png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
* if the character is invalid. * if the character is invalid.
*/ */
#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 const char png_digit[16] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F' 'A', 'B', 'C', 'D', 'E', 'F'
}; };
@ -573,7 +573,7 @@ png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN)
{ {
# define fixed_message "fixed point overflow in " # define fixed_message "fixed point overflow in "
# define fixed_message_ln ((sizeof fixed_message)-1) # define fixed_message_ln ((sizeof fixed_message)-1)
int iin; unsigned int iin;
char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT]; char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
memcpy(msg, fixed_message, fixed_message_ln); memcpy(msg, fixed_message, fixed_message_ln);
iin = 0; iin = 0;
@ -885,7 +885,7 @@ PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
PNG_NORETURN) PNG_NORETURN)
{ {
const png_const_structrp png_ptr = png_nonconst_ptr; png_const_structrp png_ptr = png_nonconst_ptr;
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
/* An error is always logged here, overwriting anything (typically a warning) /* An error is always logged here, overwriting anything (typically a warning)
@ -920,7 +920,7 @@ png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
void /* PRIVATE */ PNGCBAPI void /* PRIVATE */ PNGCBAPI
png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message) png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
{ {
const png_const_structrp png_ptr = png_nonconst_ptr; png_const_structrp png_ptr = png_nonconst_ptr;
png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
/* A warning is only logged if there is no prior warning or error. */ /* A warning is only logged if there is no prior warning or error. */

View File

@ -1,10 +1,10 @@
/* pngget.c - retrieval of values from info struct /* pngget.c - retrieval of values from info struct
* *
* Last changed in libpng 1.6.17 [March 26, 2015] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -26,7 +26,7 @@ png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr,
return(0); return(0);
} }
png_size_t PNGAPI 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)
@ -338,7 +338,7 @@ ppi_from_ppm(png_uint_32 ppm)
png_fixed_point result; png_fixed_point result;
if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127, if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127,
5000) != 0) 5000) != 0)
return result; return (png_uint_32)result;
/* Overflow. */ /* Overflow. */
return 0; return 0;
@ -367,7 +367,7 @@ png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
static png_fixed_point static png_fixed_point
png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns) png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns)
{ {
/* Convert from metres * 1,000,000 to inches * 100,000, meters to /* Convert from meters * 1,000,000 to inches * 100,000, meters to
* inches is simply *(100/2.54), so we want *(10/2.54) == 500/127. * inches is simply *(100/2.54), so we want *(10/2.54) == 500/127.
* Notice that this can overflow - a warning is output and 0 is * Notice that this can overflow - a warning is output and 0 is
* returned. * returned.
@ -741,8 +741,7 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
if (png_ptr != NULL && info_ptr != NULL && if (png_ptr != NULL && info_ptr != NULL &&
(info_ptr->valid & PNG_INFO_iCCP) != 0 && (info_ptr->valid & PNG_INFO_iCCP) != 0 &&
name != NULL && compression_type != NULL && profile != NULL && name != NULL && profile != NULL && proflen != NULL)
proflen != NULL)
{ {
*name = info_ptr->iccp_name; *name = info_ptr->iccp_name;
*profile = info_ptr->iccp_profile; *profile = info_ptr->iccp_profile;
@ -750,11 +749,13 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
/* This is somewhat irrelevant since the profile data returned has /* This is somewhat irrelevant since the profile data returned has
* actually been uncompressed. * actually been uncompressed.
*/ */
if (compression_type != NULL)
*compression_type = PNG_COMPRESSION_TYPE_BASE; *compression_type = PNG_COMPRESSION_TYPE_BASE;
return (PNG_INFO_iCCP); return (PNG_INFO_iCCP);
} }
return (0); return (0);
} }
#endif #endif
@ -773,6 +774,35 @@ png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
} }
#endif #endif
#ifdef PNG_eXIf_SUPPORTED
png_uint_32 PNGAPI
png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
png_bytep *exif)
{
png_warning(png_ptr, "png_get_eXIf does not work; use png_get_eXIf_1");
PNG_UNUSED(info_ptr)
PNG_UNUSED(exif)
return 0;
}
png_uint_32 PNGAPI
png_get_eXIf_1(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_uint_32 *num_exif, png_bytep *exif)
{
png_debug1(1, "in %s retrieval function", "eXIf");
if (png_ptr != NULL && info_ptr != NULL &&
(info_ptr->valid & PNG_INFO_eXIf) != 0 && exif != NULL)
{
*num_exif = info_ptr->num_exif;
*exif = info_ptr->exif;
return (PNG_INFO_eXIf);
}
return (0);
}
#endif
#ifdef PNG_hIST_SUPPORTED #ifdef PNG_hIST_SUPPORTED
png_uint_32 PNGAPI png_uint_32 PNGAPI
png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr, png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
@ -1135,7 +1165,7 @@ png_get_user_chunk_ptr(png_const_structrp png_ptr)
} }
#endif #endif
png_size_t PNGAPI size_t PNGAPI
png_get_compression_buffer_size(png_const_structrp png_ptr) png_get_compression_buffer_size(png_const_structrp png_ptr)
{ {
if (png_ptr == NULL) if (png_ptr == NULL)

View File

@ -1,10 +1,10 @@
/* pnginfo.h - header file for PNG reference library /* pnginfo.h - header file for PNG reference library
* *
* Last changed in libpng 1.6.1 [March 28, 2013] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2013 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -58,7 +58,7 @@ struct png_info_def
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) */ png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */
png_size_t rowbytes; /* bytes needed to hold an untransformed row */ 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) */ png_uint_16 num_palette; /* number of color entries in "palette" (PLTE) */
png_uint_16 num_trans; /* number of transparent palette color (tRNS) */ png_uint_16 num_trans; /* number of transparent palette color (tRNS) */
@ -185,6 +185,14 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */
#endif #endif
#ifdef PNG_eXIf_SUPPORTED
int num_exif; /* Added at libpng-1.6.31 */
png_bytep exif;
# ifdef PNG_READ_eXIf_SUPPORTED
png_bytep eXIf_buf; /* Added at libpng-1.6.32 */
# endif
#endif
#ifdef PNG_hIST_SUPPORTED #ifdef PNG_hIST_SUPPORTED
/* The hIST chunk contains the relative frequency or importance of the /* The hIST chunk contains the relative frequency or importance of the
* various palette entries, so that a viewer can intelligently select a * various palette entries, so that a viewer can intelligently select a
@ -239,7 +247,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
/* The sCAL chunk describes the actual physical dimensions of the /* The sCAL chunk describes the actual physical dimensions of the
* subject matter of the graphic. The chunk contains a unit specification * subject matter of the graphic. The chunk contains a unit specification
* a byte value, and two ASCII strings representing floating-point * a byte value, and two ASCII strings representing floating-point
* values. The values are width and height corresponsing to one pixel * values. The values are width and height corresponding to one pixel
* in the image. Data values are valid if (valid & PNG_INFO_sCAL) is * in the image. Data values are valid if (valid & PNG_INFO_sCAL) is
* non-zero. * non-zero.
*/ */

View File

@ -1,10 +1,9 @@
/* libpng 1.6.19 STANDARD API DEFINITION */
/* pnglibconf.h - library build configuration */ /* pnglibconf.h - library build configuration */
/* Libpng version 1.6.19 - November 12, 2015 */ /* libpng version 1.6.37 */
/* Copyright (c) 1998-2015 Glenn Randers-Pehrson */ /* Copyright (c) 2018-2019 Cosmin Truta */
/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */ /* This code is released under the libpng license. */
/* For conditions of distribution and use, see the disclaimer */ /* For conditions of distribution and use, see the disclaimer */
@ -44,6 +43,8 @@
#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_POINTER_INDEXING_SUPPORTED
/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
/*#undef PNG_POWERPC_VSX_CHECK_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
@ -82,6 +83,7 @@
#define PNG_READ_USER_TRANSFORM_SUPPORTED #define PNG_READ_USER_TRANSFORM_SUPPORTED
#define PNG_READ_bKGD_SUPPORTED #define PNG_READ_bKGD_SUPPORTED
#define PNG_READ_cHRM_SUPPORTED #define PNG_READ_cHRM_SUPPORTED
#define PNG_READ_eXIf_SUPPORTED
#define PNG_READ_gAMA_SUPPORTED #define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_hIST_SUPPORTED #define PNG_READ_hIST_SUPPORTED
#define PNG_READ_iCCP_SUPPORTED #define PNG_READ_iCCP_SUPPORTED
@ -109,6 +111,7 @@
#define PNG_SIMPLIFIED_READ_SUPPORTED #define PNG_SIMPLIFIED_READ_SUPPORTED
#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED #define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED #define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
#define PNG_SIMPLIFIED_WRITE_SUPPORTED #define PNG_SIMPLIFIED_WRITE_SUPPORTED
#define PNG_STDIO_SUPPORTED #define PNG_STDIO_SUPPORTED
#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED #define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
@ -150,6 +153,7 @@
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED #define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
#define PNG_WRITE_bKGD_SUPPORTED #define PNG_WRITE_bKGD_SUPPORTED
#define PNG_WRITE_cHRM_SUPPORTED #define PNG_WRITE_cHRM_SUPPORTED
#define PNG_WRITE_eXIf_SUPPORTED
#define PNG_WRITE_gAMA_SUPPORTED #define PNG_WRITE_gAMA_SUPPORTED
#define PNG_WRITE_hIST_SUPPORTED #define PNG_WRITE_hIST_SUPPORTED
#define PNG_WRITE_iCCP_SUPPORTED #define PNG_WRITE_iCCP_SUPPORTED
@ -167,6 +171,7 @@
#define PNG_WRITE_zTXt_SUPPORTED #define PNG_WRITE_zTXt_SUPPORTED
#define PNG_bKGD_SUPPORTED #define PNG_bKGD_SUPPORTED
#define PNG_cHRM_SUPPORTED #define PNG_cHRM_SUPPORTED
#define PNG_eXIf_SUPPORTED
#define PNG_gAMA_SUPPORTED #define PNG_gAMA_SUPPORTED
#define PNG_hIST_SUPPORTED #define PNG_hIST_SUPPORTED
#define PNG_iCCP_SUPPORTED #define PNG_iCCP_SUPPORTED

View File

@ -1,10 +1,10 @@
/* pngmem.c - stub functions for memory allocation /* pngmem.c - stub functions for memory allocation
* *
* Last changed in libpng 1.6.15 [November 20, 2014] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2014 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -109,7 +109,7 @@ static png_voidp
png_malloc_array_checked(png_const_structrp png_ptr, int nelements, png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
size_t element_size) size_t element_size)
{ {
png_alloc_size_t req = nelements; /* known to be > 0 */ png_alloc_size_t req = (png_alloc_size_t)nelements; /* known to be > 0 */
if (req <= PNG_SIZE_MAX/element_size) if (req <= PNG_SIZE_MAX/element_size)
return png_malloc_base(png_ptr, req * element_size); return png_malloc_base(png_ptr, req * element_size);

View File

@ -1,10 +1,10 @@
/* pngpread.c - read a png file in push mode /* pngpread.c - read a png file in push mode
* *
* Last changed in libpng 1.6.18 [July 23, 2015] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -34,7 +34,7 @@ if (png_ptr->buffer_size < N) \
void PNGAPI void PNGAPI
png_process_data(png_structrp png_ptr, png_inforp info_ptr, png_process_data(png_structrp png_ptr, png_inforp info_ptr,
png_bytep buffer, png_size_t buffer_size) png_bytep buffer, size_t buffer_size)
{ {
if (png_ptr == NULL || info_ptr == NULL) if (png_ptr == NULL || info_ptr == NULL)
return; return;
@ -47,7 +47,7 @@ png_process_data(png_structrp png_ptr, png_inforp info_ptr,
} }
} }
png_size_t PNGAPI size_t PNGAPI
png_process_data_pause(png_structrp png_ptr, int save) png_process_data_pause(png_structrp png_ptr, int save)
{ {
if (png_ptr != NULL) if (png_ptr != NULL)
@ -60,7 +60,7 @@ png_process_data_pause(png_structrp png_ptr, int save)
else else
{ {
/* This includes any pending saved bytes: */ /* This includes any pending saved bytes: */
png_size_t remaining = png_ptr->buffer_size; size_t remaining = png_ptr->buffer_size;
png_ptr->buffer_size = 0; png_ptr->buffer_size = 0;
/* So subtract the saved buffer size, unless all the data /* So subtract the saved buffer size, unless all the data
@ -77,7 +77,7 @@ png_process_data_pause(png_structrp png_ptr, int save)
png_uint_32 PNGAPI png_uint_32 PNGAPI
png_process_data_skip(png_structrp png_ptr) png_process_data_skip(png_structrp png_ptr)
{ {
/* TODO: Deprecate and remove this API. /* TODO: Deprecate and remove this API.
* Somewhere the implementation of this seems to have been lost, * Somewhere the implementation of this seems to have been lost,
* or abandoned. It was only to support some internal back-door access * or abandoned. It was only to support some internal back-door access
* to png_struct) in libpng-1.4.x. * to png_struct) in libpng-1.4.x.
@ -133,8 +133,8 @@ png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
void /* PRIVATE */ void /* PRIVATE */
png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
{ {
png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */
num_to_check = 8 - num_checked; size_t num_to_check = 8 - num_checked;
if (png_ptr->buffer_size < num_to_check) if (png_ptr->buffer_size < num_to_check)
{ {
@ -189,6 +189,7 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
png_crc_read(png_ptr, chunk_tag, 4); png_crc_read(png_ptr, chunk_tag, 4);
png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
png_check_chunk_name(png_ptr, png_ptr->chunk_name); png_check_chunk_name(png_ptr, png_ptr->chunk_name);
png_check_chunk_length(png_ptr, png_ptr->push_length);
png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
} }
@ -210,13 +211,15 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
(png_ptr->mode & PNG_HAVE_PLTE) == 0) (png_ptr->mode & PNG_HAVE_PLTE) == 0)
png_error(png_ptr, "Missing PLTE before IDAT"); png_error(png_ptr, "Missing PLTE before IDAT");
png_ptr->mode |= PNG_HAVE_IDAT;
png_ptr->process_mode = PNG_READ_IDAT_MODE; png_ptr->process_mode = PNG_READ_IDAT_MODE;
if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0) if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
if (png_ptr->push_length == 0) if (png_ptr->push_length == 0)
return; return;
png_ptr->mode |= PNG_HAVE_IDAT;
if ((png_ptr->mode & PNG_AFTER_IDAT) != 0) if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
png_benign_error(png_ptr, "Too many IDATs found"); png_benign_error(png_ptr, "Too many IDATs found");
} }
@ -415,7 +418,7 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
} }
void PNGCBAPI void PNGCBAPI
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, size_t length)
{ {
png_bytep ptr; png_bytep ptr;
@ -425,7 +428,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
ptr = buffer; ptr = buffer;
if (png_ptr->save_buffer_size != 0) if (png_ptr->save_buffer_size != 0)
{ {
png_size_t save_size; size_t save_size;
if (length < png_ptr->save_buffer_size) if (length < png_ptr->save_buffer_size)
save_size = length; save_size = length;
@ -442,7 +445,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
} }
if (length != 0 && png_ptr->current_buffer_size != 0) if (length != 0 && png_ptr->current_buffer_size != 0)
{ {
png_size_t save_size; size_t save_size;
if (length < png_ptr->current_buffer_size) if (length < png_ptr->current_buffer_size)
save_size = length; save_size = length;
@ -464,7 +467,7 @@ png_push_save_buffer(png_structrp png_ptr)
{ {
if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
{ {
png_size_t i, istop; size_t i, istop;
png_bytep sp; png_bytep sp;
png_bytep dp; png_bytep dp;
@ -479,7 +482,7 @@ png_push_save_buffer(png_structrp png_ptr)
if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
png_ptr->save_buffer_max) png_ptr->save_buffer_max)
{ {
png_size_t new_max; size_t new_max;
png_bytep old_buffer; png_bytep old_buffer;
if (png_ptr->save_buffer_size > PNG_SIZE_MAX - if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
@ -491,7 +494,7 @@ png_push_save_buffer(png_structrp png_ptr)
new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
old_buffer = png_ptr->save_buffer; old_buffer = png_ptr->save_buffer;
png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
(png_size_t)new_max); (size_t)new_max);
if (png_ptr->save_buffer == NULL) if (png_ptr->save_buffer == NULL)
{ {
@ -499,7 +502,10 @@ png_push_save_buffer(png_structrp png_ptr)
png_error(png_ptr, "Insufficient memory for save_buffer"); png_error(png_ptr, "Insufficient memory for save_buffer");
} }
if (old_buffer)
memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
else if (png_ptr->save_buffer_size)
png_error(png_ptr, "save_buffer error");
png_free(png_ptr, old_buffer); png_free(png_ptr, old_buffer);
png_ptr->save_buffer_max = new_max; png_ptr->save_buffer_max = new_max;
} }
@ -516,7 +522,7 @@ png_push_save_buffer(png_structrp png_ptr)
void /* PRIVATE */ void /* PRIVATE */
png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
png_size_t buffer_length) size_t buffer_length)
{ {
png_ptr->current_buffer = buffer; png_ptr->current_buffer = buffer;
png_ptr->current_buffer_size = buffer_length; png_ptr->current_buffer_size = buffer_length;
@ -556,7 +562,7 @@ png_push_read_IDAT(png_structrp png_ptr)
if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0) if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
{ {
png_size_t save_size = png_ptr->save_buffer_size; size_t save_size = png_ptr->save_buffer_size;
png_uint_32 idat_size = png_ptr->idat_size; png_uint_32 idat_size = png_ptr->idat_size;
/* We want the smaller of 'idat_size' and 'current_buffer_size', but they /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
@ -566,7 +572,7 @@ png_push_read_IDAT(png_structrp png_ptr)
* will break on either 16-bit or 64-bit platforms. * will break on either 16-bit or 64-bit platforms.
*/ */
if (idat_size < save_size) if (idat_size < save_size)
save_size = (png_size_t)idat_size; save_size = (size_t)idat_size;
else else
idat_size = (png_uint_32)save_size; idat_size = (png_uint_32)save_size;
@ -583,7 +589,7 @@ png_push_read_IDAT(png_structrp png_ptr)
if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0) if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
{ {
png_size_t save_size = png_ptr->current_buffer_size; size_t save_size = png_ptr->current_buffer_size;
png_uint_32 idat_size = png_ptr->idat_size; png_uint_32 idat_size = png_ptr->idat_size;
/* We want the smaller of 'idat_size' and 'current_buffer_size', but they /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
@ -592,7 +598,7 @@ png_push_read_IDAT(png_structrp png_ptr)
* larger - this cannot overflow. * larger - this cannot overflow.
*/ */
if (idat_size < save_size) if (idat_size < save_size)
save_size = (png_size_t)idat_size; save_size = (size_t)idat_size;
else else
idat_size = (png_uint_32)save_size; idat_size = (png_uint_32)save_size;
@ -619,7 +625,7 @@ png_push_read_IDAT(png_structrp png_ptr)
void /* PRIVATE */ void /* PRIVATE */
png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
png_size_t buffer_length) size_t buffer_length)
{ {
/* The caller checks for a non-zero buffer length. */ /* The caller checks for a non-zero buffer length. */
if (!(buffer_length > 0) || buffer == NULL) if (!(buffer_length > 0) || buffer == NULL)
@ -662,7 +668,7 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
* change the current behavior (see comments in inflate.c * change the current behavior (see comments in inflate.c
* for why this doesn't happen at present with zlib 1.2.5). * for why this doesn't happen at present with zlib 1.2.5).
*/ */
ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH); ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH);
/* Check for any failure before proceeding. */ /* Check for any failure before proceeding. */
if (ret != Z_OK && ret != Z_STREAM_END) if (ret != Z_OK && ret != Z_STREAM_END)
@ -678,8 +684,13 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
png_ptr->pass > 6) png_ptr->pass > 6)
png_warning(png_ptr, "Truncated compressed data in IDAT"); png_warning(png_ptr, "Truncated compressed data in IDAT");
else
{
if (ret == Z_DATA_ERROR)
png_benign_error(png_ptr, "IDAT: ADLER32 checksum mismatch");
else else
png_error(png_ptr, "Decompression error in IDAT"); png_error(png_ptr, "Decompression error in IDAT");
}
/* Skip the check on unprocessed input */ /* Skip the check on unprocessed input */
return; return;
@ -961,20 +972,20 @@ png_read_push_finish_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */ /* Start of interlace block */
static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */ /* Offset to next interlace block */
static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */ /* Start of interlace block in the y direction */
static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */ /* Offset to next interlace block in the y direction */
static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
/* Height of interlace block. This is not currently used - if you need /* Height of interlace block. This is not currently used - if you need
* it, uncomment it here and in png.h * it, uncomment it here and in png.h
static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
*/ */
#endif #endif

View File

@ -1,10 +1,10 @@
/* pngpriv.h - private declarations for use inside libpng /* pngpriv.h - private declarations for use inside libpng
* *
* Last changed in libpng 1.6.18 [July 23, 2015] * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -35,7 +35,9 @@
* Windows/Visual Studio) there is no effect; the OS specific tests below are * Windows/Visual Studio) there is no effect; the OS specific tests below are
* still required (as of 2011-05-02.) * still required (as of 2011-05-02.)
*/ */
#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */ #ifndef _POSIX_SOURCE
# define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
#endif
#ifndef PNG_VERSION_INFO_ONLY #ifndef PNG_VERSION_INFO_ONLY
/* Standard library headers not required by png.h: */ /* Standard library headers not required by png.h: */
@ -172,7 +174,10 @@
# else /* !defined __ARM_NEON__ */ # else /* !defined __ARM_NEON__ */
/* The 'intrinsics' code simply won't compile without this -mfpu=neon: /* The 'intrinsics' code simply won't compile without this -mfpu=neon:
*/ */
# if !defined(__aarch64__)
/* The assembler code currently does not work on ARM64 */
# define PNG_ARM_NEON_IMPLEMENTATION 2 # define PNG_ARM_NEON_IMPLEMENTATION 2
# endif /* __aarch64__ */
# endif /* __ARM_NEON__ */ # endif /* __ARM_NEON__ */
# endif /* !PNG_ARM_NEON_IMPLEMENTATION */ # endif /* !PNG_ARM_NEON_IMPLEMENTATION */
@ -182,6 +187,90 @@
# endif # endif
#endif /* PNG_ARM_NEON_OPT > 0 */ #endif /* PNG_ARM_NEON_OPT > 0 */
#ifndef PNG_MIPS_MSA_OPT
# if defined(__mips_msa) && (__mips_isa_rev >= 5) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
# define PNG_MIPS_MSA_OPT 2
# else
# define PNG_MIPS_MSA_OPT 0
# endif
#endif
#ifndef PNG_POWERPC_VSX_OPT
# if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__)
# define PNG_POWERPC_VSX_OPT 2
# else
# define PNG_POWERPC_VSX_OPT 0
# endif
#endif
#ifndef PNG_INTEL_SSE_OPT
# ifdef PNG_INTEL_SSE
/* Only check for SSE if the build configuration has been modified to
* enable SSE optimizations. This means that these optimizations will
* be off by default. See contrib/intel for more details.
*/
# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
(defined(_M_IX86_FP) && _M_IX86_FP >= 2)
# define PNG_INTEL_SSE_OPT 1
# else
# define PNG_INTEL_SSE_OPT 0
# endif
# else
# define PNG_INTEL_SSE_OPT 0
# endif
#endif
#if PNG_INTEL_SSE_OPT > 0
# ifndef PNG_INTEL_SSE_IMPLEMENTATION
# if defined(__SSE4_1__) || defined(__AVX__)
/* We are not actually using AVX, but checking for AVX is the best
way we can detect SSE4.1 and SSSE3 on MSVC.
*/
# define PNG_INTEL_SSE_IMPLEMENTATION 3
# elif defined(__SSSE3__)
# define PNG_INTEL_SSE_IMPLEMENTATION 2
# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
(defined(_M_IX86_FP) && _M_IX86_FP >= 2)
# define PNG_INTEL_SSE_IMPLEMENTATION 1
# else
# define PNG_INTEL_SSE_IMPLEMENTATION 0
# endif
# endif
# if PNG_INTEL_SSE_IMPLEMENTATION > 0
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2
# endif
#else
# define PNG_INTEL_SSE_IMPLEMENTATION 0
#endif
#if PNG_MIPS_MSA_OPT > 0
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa
# ifndef PNG_MIPS_MSA_IMPLEMENTATION
# if defined(__mips_msa)
# if defined(__clang__)
# elif defined(__GNUC__)
# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7)
# define PNG_MIPS_MSA_IMPLEMENTATION 2
# endif /* no GNUC support */
# endif /* __GNUC__ */
# else /* !defined __mips_msa */
# define PNG_MIPS_MSA_IMPLEMENTATION 2
# endif /* __mips_msa */
# endif /* !PNG_MIPS_MSA_IMPLEMENTATION */
# ifndef PNG_MIPS_MSA_IMPLEMENTATION
# define PNG_MIPS_MSA_IMPLEMENTATION 1
# endif
#endif /* PNG_MIPS_MSA_OPT > 0 */
#if PNG_POWERPC_VSX_OPT > 0
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx
# define PNG_POWERPC_VSX_IMPLEMENTATION 1
#endif
/* Is this a build of a DLL where compilation of the object modules requires /* Is this a build of a DLL where compilation of the object modules requires
* different preprocessor settings to those required for a simple library? If * different preprocessor settings to those required for a simple library? If
* so PNG_BUILD_DLL must be set. * so PNG_BUILD_DLL must be set.
@ -374,25 +463,6 @@
# define png_fixed_error(s1,s2) png_err(s1) # define png_fixed_error(s1,s2) png_err(s1)
#endif #endif
/* C allows up-casts from (void*) to any pointer and (const void*) to any
* pointer to a const object. C++ regards this as a type error and requires an
* explicit, static, cast and provides the static_cast<> rune to ensure that
* const is not cast away.
*/
#ifdef __cplusplus
# define png_voidcast(type, value) static_cast<type>(value)
# define png_constcast(type, value) const_cast<type>(value)
# define png_aligncast(type, value) \
static_cast<type>(static_cast<void*>(value))
# define png_aligncastconst(type, value) \
static_cast<type>(static_cast<const void*>(value))
#else
# define png_voidcast(type, value) (value)
# define png_constcast(type, value) ((type)(value))
# define png_aligncast(type, value) ((void*)(value))
# define png_aligncastconst(type, value) ((const void*)(value))
#endif /* __cplusplus */
/* Some fixed point APIs are still required even if not exported because /* Some fixed point APIs are still required even if not exported because
* they get used by the corresponding floating point APIs. This magic * they get used by the corresponding floating point APIs. This magic
* deals with this: * deals with this:
@ -407,6 +477,35 @@
/* Other defines specific to compilers can go here. Try to keep /* Other defines specific to compilers can go here. Try to keep
* them inside an appropriate ifdef/endif pair for portability. * them inside an appropriate ifdef/endif pair for portability.
*/ */
/* C allows up-casts from (void*) to any pointer and (const void*) to any
* pointer to a const object. C++ regards this as a type error and requires an
* explicit, static, cast and provides the static_cast<> rune to ensure that
* const is not cast away.
*/
#ifdef __cplusplus
# define png_voidcast(type, value) static_cast<type>(value)
# define png_constcast(type, value) const_cast<type>(value)
# define png_aligncast(type, value) \
static_cast<type>(static_cast<void*>(value))
# define png_aligncastconst(type, value) \
static_cast<type>(static_cast<const void*>(value))
#else
# define png_voidcast(type, value) (value)
# ifdef _WIN64
# ifdef __GNUC__
typedef unsigned long long png_ptruint;
# else
typedef unsigned __int64 png_ptruint;
# endif
# else
typedef unsigned long png_ptruint;
# endif
# define png_constcast(type, value) ((type)(png_ptruint)(const void*)(value))
# define png_aligncast(type, value) ((void*)(value))
# define png_aligncastconst(type, value) ((const void*)(value))
#endif /* __cplusplus */
#if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ #if defined(PNG_FLOATING_POINT_SUPPORTED) ||\
defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)
/* png.c requires the following ANSI-C constants if the conversion of /* png.c requires the following ANSI-C constants if the conversion of
@ -458,7 +557,7 @@
/* Memory model/platform independent fns */ /* Memory model/platform independent fns */
#ifndef PNG_ABORT #ifndef PNG_ABORT
# ifdef _WINDOWS_ # ifdef _WINDOWS_
# define PNG_ABORT() abort() # define PNG_ABORT() ExitProcess(0)
# else # else
# define PNG_ABORT() abort() # define PNG_ABORT() abort()
# endif # endif
@ -504,7 +603,8 @@
/* This implicitly assumes alignment is always to a power of 2. */ /* This implicitly assumes alignment is always to a power of 2. */
#ifdef png_alignof #ifdef png_alignof
# define png_isaligned(ptr, type)\ # define png_isaligned(ptr, type)\
((((const char*)ptr-(const char*)0) & (png_alignof(type)-1)) == 0) (((type)((const char*)ptr-(const char*)0) & \
(type)(png_alignof(type)-1)) == 0)
#else #else
# define png_isaligned(ptr, type) 0 # define png_isaligned(ptr, type) 0
#endif #endif
@ -521,92 +621,92 @@
* are defined in png.h because they need to be visible to applications * are defined in png.h because they need to be visible to applications
* that call png_set_unknown_chunk(). * that call png_set_unknown_chunk().
*/ */
/* #define PNG_HAVE_IHDR 0x01 (defined in png.h) */ /* #define PNG_HAVE_IHDR 0x01U (defined in png.h) */
/* #define PNG_HAVE_PLTE 0x02 (defined in png.h) */ /* #define PNG_HAVE_PLTE 0x02U (defined in png.h) */
#define PNG_HAVE_IDAT 0x04 #define PNG_HAVE_IDAT 0x04U
/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */ /* #define PNG_AFTER_IDAT 0x08U (defined in png.h) */
#define PNG_HAVE_IEND 0x10 #define PNG_HAVE_IEND 0x10U
/* 0x20 (unused) */ /* 0x20U (unused) */
/* 0x40 (unused) */ /* 0x40U (unused) */
/* 0x80 (unused) */ /* 0x80U (unused) */
#define PNG_HAVE_CHUNK_HEADER 0x100 #define PNG_HAVE_CHUNK_HEADER 0x100U
#define PNG_WROTE_tIME 0x200 #define PNG_WROTE_tIME 0x200U
#define PNG_WROTE_INFO_BEFORE_PLTE 0x400 #define PNG_WROTE_INFO_BEFORE_PLTE 0x400U
#define PNG_BACKGROUND_IS_GRAY 0x800 #define PNG_BACKGROUND_IS_GRAY 0x800U
#define PNG_HAVE_PNG_SIGNATURE 0x1000 #define PNG_HAVE_PNG_SIGNATURE 0x1000U
#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */ #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */
/* 0x4000 (unused) */ /* 0x4000U (unused) */
#define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */ #define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */
/* Flags for the transformations the PNG library does on the image data */ /* Flags for the transformations the PNG library does on the image data */
#define PNG_BGR 0x0001 #define PNG_BGR 0x0001U
#define PNG_INTERLACE 0x0002 #define PNG_INTERLACE 0x0002U
#define PNG_PACK 0x0004 #define PNG_PACK 0x0004U
#define PNG_SHIFT 0x0008 #define PNG_SHIFT 0x0008U
#define PNG_SWAP_BYTES 0x0010 #define PNG_SWAP_BYTES 0x0010U
#define PNG_INVERT_MONO 0x0020 #define PNG_INVERT_MONO 0x0020U
#define PNG_QUANTIZE 0x0040 #define PNG_QUANTIZE 0x0040U
#define PNG_COMPOSE 0x0080 /* Was PNG_BACKGROUND */ #define PNG_COMPOSE 0x0080U /* Was PNG_BACKGROUND */
#define PNG_BACKGROUND_EXPAND 0x0100 #define PNG_BACKGROUND_EXPAND 0x0100U
#define PNG_EXPAND_16 0x0200 /* Added to libpng 1.5.2 */ #define PNG_EXPAND_16 0x0200U /* Added to libpng 1.5.2 */
#define PNG_16_TO_8 0x0400 /* Becomes 'chop' in 1.5.4 */ #define PNG_16_TO_8 0x0400U /* Becomes 'chop' in 1.5.4 */
#define PNG_RGBA 0x0800 #define PNG_RGBA 0x0800U
#define PNG_EXPAND 0x1000 #define PNG_EXPAND 0x1000U
#define PNG_GAMMA 0x2000 #define PNG_GAMMA 0x2000U
#define PNG_GRAY_TO_RGB 0x4000 #define PNG_GRAY_TO_RGB 0x4000U
#define PNG_FILLER 0x8000 #define PNG_FILLER 0x8000U
#define PNG_PACKSWAP 0x10000 #define PNG_PACKSWAP 0x10000U
#define PNG_SWAP_ALPHA 0x20000 #define PNG_SWAP_ALPHA 0x20000U
#define PNG_STRIP_ALPHA 0x40000 #define PNG_STRIP_ALPHA 0x40000U
#define PNG_INVERT_ALPHA 0x80000 #define PNG_INVERT_ALPHA 0x80000U
#define PNG_USER_TRANSFORM 0x100000 #define PNG_USER_TRANSFORM 0x100000U
#define PNG_RGB_TO_GRAY_ERR 0x200000 #define PNG_RGB_TO_GRAY_ERR 0x200000U
#define PNG_RGB_TO_GRAY_WARN 0x400000 #define PNG_RGB_TO_GRAY_WARN 0x400000U
#define PNG_RGB_TO_GRAY 0x600000 /* two bits, RGB_TO_GRAY_ERR|WARN */ #define PNG_RGB_TO_GRAY 0x600000U /* two bits, RGB_TO_GRAY_ERR|WARN */
#define PNG_ENCODE_ALPHA 0x800000 /* Added to libpng-1.5.4 */ #define PNG_ENCODE_ALPHA 0x800000U /* Added to libpng-1.5.4 */
#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */ #define PNG_ADD_ALPHA 0x1000000U /* Added to libpng-1.2.7 */
#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */ #define PNG_EXPAND_tRNS 0x2000000U /* Added to libpng-1.2.9 */
#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */ #define PNG_SCALE_16_TO_8 0x4000000U /* Added to libpng-1.5.4 */
/* 0x8000000 unused */ /* 0x8000000U unused */
/* 0x10000000 unused */ /* 0x10000000U unused */
/* 0x20000000 unused */ /* 0x20000000U unused */
/* 0x40000000 unused */ /* 0x40000000U unused */
/* Flags for png_create_struct */ /* Flags for png_create_struct */
#define PNG_STRUCT_PNG 0x0001 #define PNG_STRUCT_PNG 0x0001U
#define PNG_STRUCT_INFO 0x0002 #define PNG_STRUCT_INFO 0x0002U
/* Flags for the png_ptr->flags rather than declaring a byte for each one */ /* Flags for the png_ptr->flags rather than declaring a byte for each one */
#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 #define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001U
#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */ #define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002U /* Added to libpng-1.6.0 */
/* 0x0004 unused */ /* 0x0004U unused */
#define PNG_FLAG_ZSTREAM_ENDED 0x0008 /* Added to libpng-1.6.0 */ #define PNG_FLAG_ZSTREAM_ENDED 0x0008U /* Added to libpng-1.6.0 */
/* 0x0010 unused */ /* 0x0010U unused */
/* 0x0020 unused */ /* 0x0020U unused */
#define PNG_FLAG_ROW_INIT 0x0040 #define PNG_FLAG_ROW_INIT 0x0040U
#define PNG_FLAG_FILLER_AFTER 0x0080 #define PNG_FLAG_FILLER_AFTER 0x0080U
#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100 #define PNG_FLAG_CRC_ANCILLARY_USE 0x0100U
#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200 #define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200U
#define PNG_FLAG_CRC_CRITICAL_USE 0x0400 #define PNG_FLAG_CRC_CRITICAL_USE 0x0400U
#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800 #define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800U
#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */ #define PNG_FLAG_ASSUME_sRGB 0x1000U /* Added to libpng-1.5.4 */
#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */ #define PNG_FLAG_OPTIMIZE_ALPHA 0x2000U /* Added to libpng-1.5.4 */
#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */ #define PNG_FLAG_DETECT_UNINITIALIZED 0x4000U /* Added to libpng-1.5.4 */
/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 */ /* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000U */
/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 */ /* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000U */
#define PNG_FLAG_LIBRARY_MISMATCH 0x20000 #define PNG_FLAG_LIBRARY_MISMATCH 0x20000U
#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000 #define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000U
#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000 #define PNG_FLAG_STRIP_ERROR_TEXT 0x80000U
#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000 /* Added to libpng-1.4.0 */ #define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000U /* Added to libpng-1.4.0 */
#define PNG_FLAG_APP_WARNINGS_WARN 0x200000 /* Added to libpng-1.6.0 */ #define PNG_FLAG_APP_WARNINGS_WARN 0x200000U /* Added to libpng-1.6.0 */
#define PNG_FLAG_APP_ERRORS_WARN 0x400000 /* Added to libpng-1.6.0 */ #define PNG_FLAG_APP_ERRORS_WARN 0x400000U /* Added to libpng-1.6.0 */
/* 0x800000 unused */ /* 0x800000U unused */
/* 0x1000000 unused */ /* 0x1000000U unused */
/* 0x2000000 unused */ /* 0x2000000U unused */
/* 0x4000000 unused */ /* 0x4000000U unused */
/* 0x8000000 unused */ /* 0x8000000U unused */
/* 0x10000000 unused */ /* 0x10000000U unused */
/* 0x20000000 unused */ /* 0x20000000U unused */
/* 0x40000000 unused */ /* 0x40000000U unused */
#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ #define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \
PNG_FLAG_CRC_ANCILLARY_NOWARN) PNG_FLAG_CRC_ANCILLARY_NOWARN)
@ -637,8 +737,26 @@
/* Added to libpng-1.2.6 JB */ /* Added to libpng-1.2.6 JB */
#define PNG_ROWBYTES(pixel_bits, width) \ #define PNG_ROWBYTES(pixel_bits, width) \
((pixel_bits) >= 8 ? \ ((pixel_bits) >= 8 ? \
((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ ((size_t)(width) * (((size_t)(pixel_bits)) >> 3)) : \
(( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) (( ((size_t)(width) * ((size_t)(pixel_bits))) + 7) >> 3) )
/* This returns the number of trailing bits in the last byte of a row, 0 if the
* last byte is completely full of pixels. It is, in principle, (pixel_bits x
* width) % 8, but that would overflow for large 'width'. The second macro is
* the same except that it returns the number of unused bits in the last byte;
* (8-TRAILBITS), but 0 when TRAILBITS is 0.
*
* NOTE: these macros are intended to be self-evidently correct and never
* overflow on the assumption that pixel_bits is in the range 0..255. The
* arguments are evaluated only once and they can be signed (e.g. as a result of
* the integral promotions). The result of the expression always has type
* (png_uint_32), however the compiler always knows it is in the range 0..7.
*/
#define PNG_TRAILBITS(pixel_bits, width) \
(((pixel_bits) * ((width) % (png_uint_32)8)) % 8)
#define PNG_PADBITS(pixel_bits, width) \
((8 - PNG_TRAILBITS(pixel_bits, width)) % 8)
/* PNG_OUT_OF_RANGE returns true if value is outside the range /* PNG_OUT_OF_RANGE returns true if value is outside the range
* ideal-delta..ideal+delta. Each argument is evaluated twice. * ideal-delta..ideal+delta. Each argument is evaluated twice.
@ -733,6 +851,7 @@
#define png_PLTE PNG_U32( 80, 76, 84, 69) #define png_PLTE PNG_U32( 80, 76, 84, 69)
#define png_bKGD PNG_U32( 98, 75, 71, 68) #define png_bKGD PNG_U32( 98, 75, 71, 68)
#define png_cHRM PNG_U32( 99, 72, 82, 77) #define png_cHRM PNG_U32( 99, 72, 82, 77)
#define png_eXIf PNG_U32(101, 88, 73, 102) /* registered July 2017 */
#define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */ #define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */
#define png_gAMA PNG_U32(103, 65, 77, 65) #define png_gAMA PNG_U32(103, 65, 77, 65)
#define png_gIFg PNG_U32(103, 73, 70, 103) #define png_gIFg PNG_U32(103, 73, 70, 103)
@ -807,7 +926,7 @@
* PNG files the -I directives must match. * PNG files the -I directives must match.
* *
* The most likely explanation is that you passed a -I in CFLAGS. This will * The most likely explanation is that you passed a -I in CFLAGS. This will
* not work; all the preprocessor directories and in particular all the -I * not work; all the preprocessor directives and in particular all the -I
* directives must be in CPPFLAGS. * directives must be in CPPFLAGS.
*/ */
#endif #endif
@ -936,15 +1055,15 @@ PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY);
*/ */
PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr, PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr,
png_bytep data, png_size_t length),PNG_EMPTY); png_bytep data, size_t length),PNG_EMPTY);
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr, PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr,
png_bytep buffer, png_size_t length),PNG_EMPTY); png_bytep buffer, size_t length),PNG_EMPTY);
#endif #endif
PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr, PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr,
png_bytep data, png_size_t length),PNG_EMPTY); png_bytep data, size_t length),PNG_EMPTY);
#ifdef PNG_WRITE_FLUSH_SUPPORTED #ifdef PNG_WRITE_FLUSH_SUPPORTED
# ifdef PNG_STDIO_SUPPORTED # ifdef PNG_STDIO_SUPPORTED
@ -958,7 +1077,7 @@ PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY);
/* Write the "data" buffer to whatever output you are using */ /* Write the "data" buffer to whatever output you are using */
PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr,
png_const_bytep data, png_size_t length),PNG_EMPTY); png_const_bytep data, size_t length),PNG_EMPTY);
/* Read and check the PNG file signature */ /* Read and check the PNG file signature */
PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr,
@ -970,7 +1089,7 @@ PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr),
/* Read data from whatever input you are using into the "data" buffer */ /* Read data from whatever input you are using into the "data" buffer */
PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data, PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data,
png_size_t length),PNG_EMPTY); size_t length),PNG_EMPTY);
/* Read bytes into buf, and update png_ptr->crc */ /* Read bytes into buf, and update png_ptr->crc */
PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf, PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf,
@ -988,7 +1107,7 @@ PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY);
* since this is the maximum buffer size we can specify. * since this is the maximum buffer size we can specify.
*/ */
PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr,
png_const_bytep ptr, png_size_t length),PNG_EMPTY); png_const_bytep ptr, size_t length),PNG_EMPTY);
#ifdef PNG_WRITE_FLUSH_SUPPORTED #ifdef PNG_WRITE_FLUSH_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY);
@ -1033,6 +1152,11 @@ PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr,
int intent),PNG_EMPTY); int intent),PNG_EMPTY);
#endif #endif
#ifdef PNG_WRITE_eXIf_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_write_eXIf,(png_structrp png_ptr,
png_bytep exif, int num_exif),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_iCCP_SUPPORTED #ifdef PNG_WRITE_iCCP_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr,
png_const_charp name, png_const_bytep profile), PNG_EMPTY); png_const_charp name, png_const_bytep profile), PNG_EMPTY);
@ -1066,7 +1190,7 @@ PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr,
/* Chunks that have keywords */ /* Chunks that have keywords */
#ifdef PNG_WRITE_tEXt_SUPPORTED #ifdef PNG_WRITE_tEXt_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr,
png_const_charp key, png_const_charp text, png_size_t text_len),PNG_EMPTY); png_const_charp key, png_const_charp text, size_t text_len),PNG_EMPTY);
#endif #endif
#ifdef PNG_WRITE_zTXt_SUPPORTED #ifdef PNG_WRITE_zTXt_SUPPORTED
@ -1174,6 +1298,7 @@ PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info,
PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop
row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY); row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY);
#if PNG_ARM_NEON_OPT > 0
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info, PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info,
png_bytep row, png_const_bytep prev_row),PNG_EMPTY); png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop
@ -1188,6 +1313,56 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
#endif
#if PNG_MIPS_MSA_OPT > 0
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_msa,(png_row_infop row_info,
png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_msa,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_msa,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_msa,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_msa,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_msa,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_msa,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
#endif
#if PNG_POWERPC_VSX_OPT > 0
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info,
png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_vsx,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_vsx,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_vsx,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_vsx,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_vsx,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_vsx,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
#endif
#if PNG_INTEL_SSE_IMPLEMENTATION > 0
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_sse2,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_sse2,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_sse2,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_sse2,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_sse2,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
#endif
/* Choose the best filter to use and filter the row data */ /* Choose the best filter to use and filter the row data */
PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
@ -1215,6 +1390,14 @@ PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr),
/* Initialize the row buffers, etc. */ /* Initialize the row buffers, etc. */
PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY);
#if ZLIB_VERNUM >= 0x1240
PNG_INTERNAL_FUNCTION(int,png_zlib_inflate,(png_structrp png_ptr, int flush),
PNG_EMPTY);
# define PNG_INFLATE(pp, flush) png_zlib_inflate(pp, flush)
#else /* Zlib < 1.2.4 */
# define PNG_INFLATE(pp, flush) inflate(&(pp)->zstream, flush)
#endif /* Zlib < 1.2.4 */
#ifdef PNG_READ_TRANSFORMS_SUPPORTED #ifdef PNG_READ_TRANSFORMS_SUPPORTED
/* Optional call to update the users info structure */ /* Optional call to update the users info structure */
PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr,
@ -1273,6 +1456,11 @@ PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif #endif
#ifdef PNG_READ_eXIf_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_handle_eXIf,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_gAMA_SUPPORTED #ifdef PNG_READ_gAMA_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
@ -1348,9 +1536,12 @@ PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif #endif
PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_const_structrp png_ptr,
png_uint_32 chunk_name),PNG_EMPTY); png_uint_32 chunk_name),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr,
png_uint_32 chunk_length),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY); png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
/* This is the function that gets called for unknown chunks. The 'keep' /* This is the function that gets called for unknown chunks. The 'keep'
@ -1392,10 +1583,10 @@ PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr), PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr),
PNG_EMPTY); PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr,
png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); png_bytep buffer, size_t buffer_length),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr,
png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); png_bytep buffer, size_t buffer_length),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr), PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr),
PNG_EMPTY); PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr,
@ -1484,9 +1675,11 @@ PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr,
/* The 'name' is used for information only */ /* The 'name' is used for information only */
/* Routines for checking parts of an ICC profile. */ /* Routines for checking parts of an ICC profile. */
#ifdef PNG_READ_iCCP_SUPPORTED
PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr, PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr,
png_colorspacerp colorspace, png_const_charp name, png_colorspacerp colorspace, png_const_charp name,
png_uint_32 profile_length), PNG_EMPTY); png_uint_32 profile_length), PNG_EMPTY);
#endif /* READ_iCCP */
PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr,
png_colorspacerp colorspace, png_const_charp name, png_colorspacerp colorspace, png_const_charp name,
png_uint_32 profile_length, png_uint_32 profile_length,
@ -1663,13 +1856,13 @@ PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr,
#ifdef PNG_FLOATING_POINT_SUPPORTED #ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr,
png_charp ascii, png_size_t size, double fp, unsigned int precision), png_charp ascii, size_t size, double fp, unsigned int precision),
PNG_EMPTY); PNG_EMPTY);
#endif /* FLOATING_POINT */ #endif /* FLOATING_POINT */
#ifdef PNG_FIXED_POINT_SUPPORTED #ifdef PNG_FIXED_POINT_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr,
png_charp ascii, png_size_t size, png_fixed_point fp),PNG_EMPTY); png_charp ascii, size_t size, png_fixed_point fp),PNG_EMPTY);
#endif /* FIXED_POINT */ #endif /* FIXED_POINT */
#endif /* sCAL */ #endif /* sCAL */
@ -1762,7 +1955,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr,
* the problem character.) This has not been tested within libpng. * the problem character.) This has not been tested within libpng.
*/ */
PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string,
png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); size_t size, int *statep, png_size_tp whereami),PNG_EMPTY);
/* This is the same but it checks a complete string and returns true /* This is the same but it checks a complete string and returns true
* only if it just contains a floating point number. As of 1.5.4 this * only if it just contains a floating point number. As of 1.5.4 this
@ -1771,7 +1964,7 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string,
* for negative or zero values using the sticky flag. * for negative or zero values using the sticky flag.
*/ */
PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string, PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
png_size_t size),PNG_EMPTY); size_t size),PNG_EMPTY);
#endif /* pCAL || sCAL */ #endif /* pCAL || sCAL */
#if defined(PNG_GAMMA_SUPPORTED) ||\ #if defined(PNG_GAMMA_SUPPORTED) ||\
@ -1846,7 +2039,7 @@ typedef struct png_control
png_voidp error_buf; /* Always a jmp_buf at present. */ png_voidp error_buf; /* Always a jmp_buf at present. */
png_const_bytep memory; /* Memory buffer. */ png_const_bytep memory; /* Memory buffer. */
png_size_t size; /* Size of the memory buffer. */ size_t size; /* Size of the memory buffer. */
unsigned int for_write :1; /* Otherwise it is a read structure */ unsigned int for_write :1; /* Otherwise it is a read structure */
unsigned int owned_file :1; /* We own the file in io_ptr */ unsigned int owned_file :1; /* We own the file in io_ptr */
@ -1905,14 +2098,46 @@ PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr,
* the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in
* CFLAGS in place of CPPFLAGS *and* uses symbol prefixing. * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing.
*/ */
# if PNG_ARM_NEON_OPT > 0
PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon, PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
(png_structp png_ptr, unsigned int bpp), PNG_EMPTY); (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
#endif #endif
#if __has_attribute(fallthrough) #if PNG_MIPS_MSA_OPT > 0
#define FALLTHROUGH __attribute__((fallthrough)) PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa,
#else (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
#define FALLTHROUGH #endif
# if PNG_INTEL_SSE_IMPLEMENTATION > 0
PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
(png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
# endif
#endif
PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
png_const_charp key, png_bytep new_key), PNG_EMPTY);
#if PNG_ARM_NEON_IMPLEMENTATION == 1
PNG_INTERNAL_FUNCTION(void,
png_riffle_palette_neon,
(png_structrp),
PNG_EMPTY);
PNG_INTERNAL_FUNCTION(int,
png_do_expand_palette_rgba8_neon,
(png_structrp,
png_row_infop,
png_const_bytep,
const png_bytepp,
const png_bytepp),
PNG_EMPTY);
PNG_INTERNAL_FUNCTION(int,
png_do_expand_palette_rgb8_neon,
(png_structrp,
png_row_infop,
png_const_bytep,
const png_bytepp,
const png_bytepp),
PNG_EMPTY);
#endif #endif
/* Maintainer: Put new private prototypes here ^ */ /* Maintainer: Put new private prototypes here ^ */

View File

@ -1,10 +1,10 @@
/* pngread.c - read a PNG file /* pngread.c - read a PNG file
* *
* Last changed in libpng 1.6.17 [March 26, 2015] * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -127,7 +127,10 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
} }
else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
png_ptr->mode |= PNG_AFTER_IDAT; png_ptr->mode |= PNG_AFTER_IDAT;
}
/* This should be a binary subdivision search or a hash for /* This should be a binary subdivision search or a hash for
* matching the chunk name rather than a linear search. * matching the chunk name rather than a linear search.
@ -172,6 +175,11 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
png_handle_cHRM(png_ptr, info_ptr, length); png_handle_cHRM(png_ptr, info_ptr, length);
#endif #endif
#ifdef PNG_READ_eXIf_SUPPORTED
else if (chunk_name == png_eXIf)
png_handle_eXIf(png_ptr, info_ptr, length);
#endif
#ifdef PNG_READ_gAMA_SUPPORTED #ifdef PNG_READ_gAMA_SUPPORTED
else if (chunk_name == png_gAMA) else if (chunk_name == png_gAMA)
png_handle_gAMA(png_ptr, info_ptr, length); png_handle_gAMA(png_ptr, info_ptr, length);
@ -356,9 +364,9 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
{ {
png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1);
png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3);
png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5);
png_uint_32 red = (s0 + s1 + 65536) & 0xffff; png_uint_32 red = (s0 + s1 + 65536) & 0xffff;
png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
*(rp ) = (png_byte)((red >> 8) & 0xff); *(rp ) = (png_byte)((red >> 8) & 0xff);
@ -531,6 +539,7 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
png_error(png_ptr, "Invalid attempt to read row data"); png_error(png_ptr, "Invalid attempt to read row data");
/* Fill the row with IDAT data: */ /* Fill the row with IDAT data: */
png_ptr->row_buf[0]=255; /* to force error if no data was found */
png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1); png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1);
if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
@ -785,6 +794,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
png_uint_32 length = png_read_chunk_header(png_ptr); png_uint_32 length = png_read_chunk_header(png_ptr);
png_uint_32 chunk_name = png_ptr->chunk_name; png_uint_32 chunk_name = png_ptr->chunk_name;
if (chunk_name != png_IDAT)
png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
if (chunk_name == png_IEND) if (chunk_name == png_IEND)
png_handle_IEND(png_ptr, info_ptr, length); png_handle_IEND(png_ptr, info_ptr, length);
@ -799,9 +811,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
{ {
if (chunk_name == png_IDAT) if (chunk_name == png_IDAT)
{ {
if ((length > 0) || if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
png_benign_error(png_ptr, "Too many IDATs found"); png_benign_error(png_ptr, ".Too many IDATs found");
} }
png_handle_unknown(png_ptr, info_ptr, length, keep); png_handle_unknown(png_ptr, info_ptr, length, keep);
if (chunk_name == png_PLTE) if (chunk_name == png_PLTE)
@ -812,10 +824,14 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
else if (chunk_name == png_IDAT) else if (chunk_name == png_IDAT)
{ {
/* Zero length IDATs are legal after the last IDAT has been /* Zero length IDATs are legal after the last IDAT has been
* read, but not after other chunks have been read. * read, but not after other chunks have been read. 1.6 does not
* always read all the deflate data; specifically it cannot be relied
* upon to read the Adler32 at the end. If it doesn't ignore IDAT
* chunks which are longer than zero as well:
*/ */
if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) if ((length > 0 && !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
png_benign_error(png_ptr, "Too many IDATs found"); || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
png_benign_error(png_ptr, "..Too many IDATs found");
png_crc_finish(png_ptr, length); png_crc_finish(png_ptr, length);
} }
@ -832,6 +848,11 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
png_handle_cHRM(png_ptr, info_ptr, length); png_handle_cHRM(png_ptr, info_ptr, length);
#endif #endif
#ifdef PNG_READ_eXIf_SUPPORTED
else if (chunk_name == png_eXIf)
png_handle_eXIf(png_ptr, info_ptr, length);
#endif
#ifdef PNG_READ_gAMA_SUPPORTED #ifdef PNG_READ_gAMA_SUPPORTED
else if (chunk_name == png_gAMA) else if (chunk_name == png_gAMA)
png_handle_gAMA(png_ptr, info_ptr, length); png_handle_gAMA(png_ptr, info_ptr, length);
@ -973,6 +994,12 @@ png_read_destroy(png_structrp png_ptr)
png_ptr->chunk_list = NULL; png_ptr->chunk_list = NULL;
#endif #endif
#if defined(PNG_READ_EXPAND_SUPPORTED) && \
defined(PNG_ARM_NEON_IMPLEMENTATION)
png_free(png_ptr, png_ptr->riffled_palette);
png_ptr->riffled_palette = NULL;
#endif
/* NOTE: the 'setjmp' buffer may still be allocated and the memory and error /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
* callbacks are still set at this point. They are required to complete the * callbacks are still set at this point. They are required to complete the
* destruction of the png_struct itself. * destruction of the png_struct itself.
@ -1020,8 +1047,7 @@ png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)
#ifdef PNG_INFO_IMAGE_SUPPORTED #ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI void PNGAPI
png_read_png(png_structrp png_ptr, png_inforp info_ptr, png_read_png(png_structrp png_ptr, png_inforp info_ptr,
int transforms, int transforms, voidp params)
voidp params)
{ {
if (png_ptr == NULL || info_ptr == NULL) if (png_ptr == NULL || info_ptr == NULL)
return; return;
@ -1384,7 +1410,9 @@ png_image_read_header(png_voidp argument)
png_structrp png_ptr = image->opaque->png_ptr; png_structrp png_ptr = image->opaque->png_ptr;
png_inforp info_ptr = image->opaque->info_ptr; png_inforp info_ptr = image->opaque->info_ptr;
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
png_set_benign_errors(png_ptr, 1/*warn*/); png_set_benign_errors(png_ptr, 1/*warn*/);
#endif
png_read_info(png_ptr, info_ptr); png_read_info(png_ptr, info_ptr);
/* Do this the fast way; just read directly out of png_struct. */ /* Do this the fast way; just read directly out of png_struct. */
@ -1422,7 +1450,7 @@ png_image_read_header(png_voidp argument)
break; break;
case PNG_COLOR_TYPE_PALETTE: case PNG_COLOR_TYPE_PALETTE:
cmap_entries = png_ptr->num_palette; cmap_entries = (png_uint_32)png_ptr->num_palette;
break; break;
default: default:
@ -1510,7 +1538,7 @@ png_image_begin_read_from_file(png_imagep image, const char *file_name)
#endif /* STDIO */ #endif /* STDIO */
static void PNGCBAPI static void PNGCBAPI
png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) png_image_memory_read(png_structp png_ptr, png_bytep out, size_t need)
{ {
if (png_ptr != NULL) if (png_ptr != NULL)
{ {
@ -1521,7 +1549,7 @@ png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
if (cp != NULL) if (cp != NULL)
{ {
png_const_bytep memory = cp->memory; png_const_bytep memory = cp->memory;
png_size_t size = cp->size; size_t size = cp->size;
if (memory != NULL && size >= need) if (memory != NULL && size >= need)
{ {
@ -1540,7 +1568,7 @@ png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
} }
int PNGAPI png_image_begin_read_from_memory(png_imagep image, int PNGAPI png_image_begin_read_from_memory(png_imagep image,
png_const_voidp memory, png_size_t size) png_const_voidp memory, size_t size)
{ {
if (image != NULL && image->version == PNG_IMAGE_VERSION) if (image != NULL && image->version == PNG_IMAGE_VERSION)
{ {
@ -1599,7 +1627,7 @@ png_image_skip_unused_chunks(png_structrp png_ptr)
* errors (which are unfortunately quite common.) * errors (which are unfortunately quite common.)
*/ */
{ {
static PNG_CONST png_byte chunks_to_process[] = { static const png_byte chunks_to_process[] = {
98, 75, 71, 68, '\0', /* bKGD */ 98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */ 99, 72, 82, 77, '\0', /* cHRM */
103, 65, 77, 65, '\0', /* gAMA */ 103, 65, 77, 65, '\0', /* gAMA */
@ -1736,9 +1764,9 @@ png_create_colormap_entry(png_image_read_control *display,
png_uint_32 alpha, int encoding) png_uint_32 alpha, int encoding)
{ {
png_imagep image = display->image; png_imagep image = display->image;
const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ? int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
P_LINEAR : P_sRGB; P_LINEAR : P_sRGB;
const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
(red != green || green != blue); (red != green || green != blue);
if (ip > 255) if (ip > 255)
@ -1847,13 +1875,13 @@ png_create_colormap_entry(png_image_read_control *display,
/* Store the value. */ /* Store the value. */
{ {
# ifdef PNG_FORMAT_AFIRST_SUPPORTED # ifdef PNG_FORMAT_AFIRST_SUPPORTED
const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(image->format & PNG_FORMAT_FLAG_ALPHA) != 0; (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else # else
# define afirst 0 # define afirst 0
# endif # endif
# ifdef PNG_FORMAT_BGR_SUPPORTED # ifdef PNG_FORMAT_BGR_SUPPORTED
const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
# else # else
# define bgr 0 # define bgr 0
# endif # endif
@ -1872,7 +1900,7 @@ png_create_colormap_entry(png_image_read_control *display,
{ {
case 4: case 4:
entry[afirst ? 0 : 3] = (png_uint_16)alpha; entry[afirst ? 0 : 3] = (png_uint_16)alpha;
FALLTHROUGH; /* FALLTHROUGH */
case 3: case 3:
if (alpha < 65535) if (alpha < 65535)
@ -1894,7 +1922,7 @@ png_create_colormap_entry(png_image_read_control *display,
case 2: case 2:
entry[1 ^ afirst] = (png_uint_16)alpha; entry[1 ^ afirst] = (png_uint_16)alpha;
FALLTHROUGH; /* FALLTHROUGH */
case 1: case 1:
if (alpha < 65535) if (alpha < 65535)
@ -1923,7 +1951,7 @@ png_create_colormap_entry(png_image_read_control *display,
{ {
case 4: case 4:
entry[afirst ? 0 : 3] = (png_byte)alpha; entry[afirst ? 0 : 3] = (png_byte)alpha;
FALLTHROUGH; /* FALLTHROUGH */
case 3: case 3:
entry[afirst + (2 ^ bgr)] = (png_byte)blue; entry[afirst + (2 ^ bgr)] = (png_byte)blue;
entry[afirst + 1] = (png_byte)green; entry[afirst + 1] = (png_byte)green;
@ -1932,7 +1960,7 @@ png_create_colormap_entry(png_image_read_control *display,
case 2: case 2:
entry[1 ^ afirst] = (png_byte)alpha; entry[1 ^ afirst] = (png_byte)alpha;
FALLTHROUGH; /* FALLTHROUGH */
case 1: case 1:
entry[afirst] = (png_byte)green; entry[afirst] = (png_byte)green;
break; break;
@ -1959,7 +1987,7 @@ make_gray_file_colormap(png_image_read_control *display)
for (i=0; i<256; ++i) for (i=0; i<256; ++i)
png_create_colormap_entry(display, i, i, i, i, 255, P_FILE); png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);
return i; return (int)i;
} }
static int static int
@ -1970,7 +1998,7 @@ make_gray_colormap(png_image_read_control *display)
for (i=0; i<256; ++i) for (i=0; i<256; ++i)
png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB); png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);
return i; return (int)i;
} }
#define PNG_GRAY_COLORMAP_ENTRIES 256 #define PNG_GRAY_COLORMAP_ENTRIES 256
@ -2024,7 +2052,7 @@ make_ga_colormap(png_image_read_control *display)
P_sRGB); P_sRGB);
} }
return i; return (int)i;
} }
#define PNG_GA_COLORMAP_ENTRIES 256 #define PNG_GA_COLORMAP_ENTRIES 256
@ -2049,7 +2077,7 @@ make_rgb_colormap(png_image_read_control *display)
} }
} }
return i; return (int)i;
} }
#define PNG_RGB_COLORMAP_ENTRIES 216 #define PNG_RGB_COLORMAP_ENTRIES 216
@ -2063,11 +2091,11 @@ png_image_read_colormap(png_voidp argument)
{ {
png_image_read_control *display = png_image_read_control *display =
png_voidcast(png_image_read_control*, argument); png_voidcast(png_image_read_control*, argument);
const png_imagep image = display->image; png_imagep image = display->image;
const png_structrp png_ptr = image->opaque->png_ptr; png_structrp png_ptr = image->opaque->png_ptr;
const png_uint_32 output_format = image->format; png_uint_32 output_format = image->format;
const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ? int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
P_LINEAR : P_sRGB; P_LINEAR : P_sRGB;
unsigned int cmap_entries; unsigned int cmap_entries;
@ -2097,7 +2125,7 @@ png_image_read_colormap(png_voidp argument)
else if (display->background == NULL /* no way to remove it */) else if (display->background == NULL /* no way to remove it */)
png_error(png_ptr, png_error(png_ptr,
"a background color must be supplied to remove alpha/transparency"); "background color must be supplied to remove alpha/transparency");
/* Get a copy of the background color (this avoids repeating the checks /* Get a copy of the background color (this avoids repeating the checks
* below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the
@ -2242,7 +2270,7 @@ png_image_read_colormap(png_voidp argument)
if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "gray[16] color-map: too few entries"); png_error(png_ptr, "gray[16] color-map: too few entries");
cmap_entries = make_gray_colormap(display); cmap_entries = (unsigned int)make_gray_colormap(display);
if (png_ptr->num_trans > 0) if (png_ptr->num_trans > 0)
{ {
@ -2340,7 +2368,7 @@ png_image_read_colormap(png_voidp argument)
if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "gray+alpha color-map: too few entries"); png_error(png_ptr, "gray+alpha color-map: too few entries");
cmap_entries = make_ga_colormap(display); cmap_entries = (unsigned int)make_ga_colormap(display);
background_index = PNG_CMAP_GA_BACKGROUND; background_index = PNG_CMAP_GA_BACKGROUND;
output_processing = PNG_CMAP_GA; output_processing = PNG_CMAP_GA;
@ -2374,7 +2402,7 @@ png_image_read_colormap(png_voidp argument)
if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "gray-alpha color-map: too few entries"); png_error(png_ptr, "gray-alpha color-map: too few entries");
cmap_entries = make_gray_colormap(display); cmap_entries = (unsigned int)make_gray_colormap(display);
if (output_encoding == P_LINEAR) if (output_encoding == P_LINEAR)
{ {
@ -2422,8 +2450,8 @@ png_image_read_colormap(png_voidp argument)
background_index = i; background_index = i;
png_create_colormap_entry(display, i++, back_r, back_g, back_b, png_create_colormap_entry(display, i++, back_r, back_g, back_b,
#ifdef __COVERITY__ #ifdef __COVERITY__
/* Coverity claims that output_encoding cannot be 2 (P_LINEAR) /* Coverity claims that output_encoding
* here. * cannot be 2 (P_LINEAR) here.
*/ 255U, */ 255U,
#else #else
output_encoding == P_LINEAR ? 65535U : 255U, output_encoding == P_LINEAR ? 65535U : 255U,
@ -2513,7 +2541,7 @@ png_image_read_colormap(png_voidp argument)
if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "rgb[ga] color-map: too few entries"); png_error(png_ptr, "rgb[ga] color-map: too few entries");
cmap_entries = make_ga_colormap(display); cmap_entries = (unsigned int)make_ga_colormap(display);
background_index = PNG_CMAP_GA_BACKGROUND; background_index = PNG_CMAP_GA_BACKGROUND;
output_processing = PNG_CMAP_GA; output_processing = PNG_CMAP_GA;
} }
@ -2539,12 +2567,12 @@ png_image_read_colormap(png_voidp argument)
png_ptr->num_trans > 0) && png_ptr->num_trans > 0) &&
png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0) png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0)
{ {
cmap_entries = make_gray_file_colormap(display); cmap_entries = (unsigned int)make_gray_file_colormap(display);
data_encoding = P_FILE; data_encoding = P_FILE;
} }
else else
cmap_entries = make_gray_colormap(display); cmap_entries = (unsigned int)make_gray_colormap(display);
/* But if the input has alpha or transparency it must be removed /* But if the input has alpha or transparency it must be removed
*/ */
@ -2632,7 +2660,7 @@ png_image_read_colormap(png_voidp argument)
if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
png_error(png_ptr, "rgb+alpha color-map: too few entries"); png_error(png_ptr, "rgb+alpha color-map: too few entries");
cmap_entries = make_rgb_colormap(display); cmap_entries = (unsigned int)make_rgb_colormap(display);
/* Add a transparent entry. */ /* Add a transparent entry. */
png_create_colormap_entry(display, cmap_entries, 255, 255, png_create_colormap_entry(display, cmap_entries, 255, 255,
@ -2681,7 +2709,7 @@ png_image_read_colormap(png_voidp argument)
if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
png_error(png_ptr, "rgb-alpha color-map: too few entries"); png_error(png_ptr, "rgb-alpha color-map: too few entries");
cmap_entries = make_rgb_colormap(display); cmap_entries = (unsigned int)make_rgb_colormap(display);
png_create_colormap_entry(display, cmap_entries, back_r, png_create_colormap_entry(display, cmap_entries, back_r,
back_g, back_b, 0/*unused*/, output_encoding); back_g, back_b, 0/*unused*/, output_encoding);
@ -2766,7 +2794,7 @@ png_image_read_colormap(png_voidp argument)
if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries) if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries)
png_error(png_ptr, "rgb color-map: too few entries"); png_error(png_ptr, "rgb color-map: too few entries");
cmap_entries = make_rgb_colormap(display); cmap_entries = (unsigned int)make_rgb_colormap(display);
output_processing = PNG_CMAP_RGB; output_processing = PNG_CMAP_RGB;
} }
} }
@ -2780,7 +2808,7 @@ png_image_read_colormap(png_voidp argument)
unsigned int num_trans = png_ptr->num_trans; unsigned int num_trans = png_ptr->num_trans;
png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
png_const_colorp colormap = png_ptr->palette; png_const_colorp colormap = png_ptr->palette;
const int do_background = trans != NULL && int do_background = trans != NULL &&
(output_format & PNG_FORMAT_FLAG_ALPHA) == 0; (output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
unsigned int i; unsigned int i;
@ -2790,11 +2818,11 @@ png_image_read_colormap(png_voidp argument)
output_processing = PNG_CMAP_NONE; output_processing = PNG_CMAP_NONE;
data_encoding = P_FILE; /* Don't change from color-map indices */ data_encoding = P_FILE; /* Don't change from color-map indices */
cmap_entries = png_ptr->num_palette; cmap_entries = (unsigned int)png_ptr->num_palette;
if (cmap_entries > 256) if (cmap_entries > 256)
cmap_entries = 256; cmap_entries = 256;
if (cmap_entries > image->colormap_entries) if (cmap_entries > (unsigned int)image->colormap_entries)
png_error(png_ptr, "palette color-map: too few entries"); png_error(png_ptr, "palette color-map: too few entries");
for (i=0; i < cmap_entries; ++i) for (i=0; i < cmap_entries; ++i)
@ -2811,12 +2839,12 @@ png_image_read_colormap(png_voidp argument)
* on the sRGB color in 'back'. * on the sRGB color in 'back'.
*/ */
png_create_colormap_entry(display, i, png_create_colormap_entry(display, i,
png_colormap_compose(display, colormap[i].red, P_FILE, png_colormap_compose(display, colormap[i].red,
trans[i], back_r, output_encoding), P_FILE, trans[i], back_r, output_encoding),
png_colormap_compose(display, colormap[i].green, P_FILE, png_colormap_compose(display, colormap[i].green,
trans[i], back_g, output_encoding), P_FILE, trans[i], back_g, output_encoding),
png_colormap_compose(display, colormap[i].blue, P_FILE, png_colormap_compose(display, colormap[i].blue,
trans[i], back_b, output_encoding), P_FILE, trans[i], back_b, output_encoding),
output_encoding == P_LINEAR ? trans[i] * 257U : output_encoding == P_LINEAR ? trans[i] * 257U :
trans[i], trans[i],
output_encoding); output_encoding);
@ -2840,7 +2868,6 @@ png_image_read_colormap(png_voidp argument)
default: default:
png_error(png_ptr, "invalid PNG color type"); png_error(png_ptr, "invalid PNG color type");
/*NOT REACHED*/ /*NOT REACHED*/
break;
} }
/* Now deal with the output processing */ /* Now deal with the output processing */
@ -2853,7 +2880,7 @@ png_image_read_colormap(png_voidp argument)
case P_sRGB: case P_sRGB:
/* Change to 8-bit sRGB */ /* Change to 8-bit sRGB */
png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
FALLTHROUGH; /* FALLTHROUGH */
case P_FILE: case P_FILE:
if (png_ptr->bit_depth > 8) if (png_ptr->bit_depth > 8)
@ -2907,7 +2934,7 @@ png_image_read_colormap(png_voidp argument)
png_error(png_ptr, "bad background index (internal error)"); png_error(png_ptr, "bad background index (internal error)");
} }
display->colormap_processing = output_processing; display->colormap_processing = (int)output_processing;
return 1/*ok*/; return 1/*ok*/;
} }
@ -3171,8 +3198,7 @@ png_image_read_colormapped(png_voidp argument)
image->colormap_entries == 244 /* 216 + 1 + 27 */) image->colormap_entries == 244 /* 216 + 1 + 27 */)
break; break;
/* goto bad_output; */ goto bad_output;
FALLTHROUGH;
default: default:
bad_output: bad_output:
@ -3216,14 +3242,14 @@ png_image_read_colormapped(png_voidp argument)
else else
{ {
png_alloc_size_t row_bytes = display->row_bytes; png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
while (--passes >= 0) while (--passes >= 0)
{ {
png_uint_32 y = image->height; png_uint_32 y = image->height;
png_bytep row = png_voidcast(png_bytep, display->first_row); png_bytep row = png_voidcast(png_bytep, display->first_row);
while (y-- > 0) for (; y > 0; --y)
{ {
png_read_row(png_ptr, row, NULL); png_read_row(png_ptr, row, NULL);
row += row_bytes; row += row_bytes;
@ -3426,8 +3452,7 @@ png_image_read_background(png_voidp argument)
for (pass = 0; pass < passes; ++pass) for (pass = 0; pass < passes; ++pass)
{ {
png_bytep row = png_voidcast(png_bytep, png_bytep row = png_voidcast(png_bytep, display->first_row);
display->first_row);
unsigned int startx, stepx, stepy; unsigned int startx, stepx, stepy;
png_uint_32 y; png_uint_32 y;
@ -3552,8 +3577,9 @@ png_image_read_background(png_voidp argument)
* stride which was multiplied by 2 (below) to get row_bytes. * stride which was multiplied by 2 (below) to get row_bytes.
*/ */
ptrdiff_t step_row = display->row_bytes / 2; ptrdiff_t step_row = display->row_bytes / 2;
int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; unsigned int preserve_alpha = (image->format &
unsigned int outchannels = 1+preserve_alpha; PNG_FORMAT_FLAG_ALPHA) != 0;
unsigned int outchannels = 1U+preserve_alpha;
int swap_alpha = 0; int swap_alpha = 0;
# ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED # ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
@ -3740,6 +3766,12 @@ png_image_read_direct(png_voidp argument)
output_gamma = PNG_DEFAULT_sRGB; output_gamma = PNG_DEFAULT_sRGB;
} }
if ((change & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0)
{
mode = PNG_ALPHA_OPTIMIZED;
change &= ~PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
}
/* If 'do_local_background' is set check for the presence of gamma /* If 'do_local_background' is set check for the presence of gamma
* correction; this is part of the work-round for the libpng bug * correction; this is part of the work-round for the libpng bug
* described above. * described above.
@ -3851,7 +3883,7 @@ png_image_read_direct(png_voidp argument)
else else
filler = 255; filler = 255;
# ifdef PNG_FORMAT_AFIRST_SUPPORTED #ifdef PNG_FORMAT_AFIRST_SUPPORTED
if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
{ {
where = PNG_FILLER_BEFORE; where = PNG_FILLER_BEFORE;
@ -3859,7 +3891,7 @@ png_image_read_direct(png_voidp argument)
} }
else else
# endif #endif
where = PNG_FILLER_AFTER; where = PNG_FILLER_AFTER;
png_set_add_alpha(png_ptr, filler, where); png_set_add_alpha(png_ptr, filler, where);
@ -3920,7 +3952,7 @@ png_image_read_direct(png_voidp argument)
*/ */
if (linear != 0) if (linear != 0)
{ {
PNG_CONST png_uint_16 le = 0x0001; png_uint_16 le = 0x0001;
if ((*(png_const_bytep) & le) != 0) if ((*(png_const_bytep) & le) != 0)
png_set_swap(png_ptr); png_set_swap(png_ptr);
@ -3965,15 +3997,19 @@ png_image_read_direct(png_voidp argument)
else if (do_local_compose != 0) /* internal error */ else if (do_local_compose != 0) /* internal error */
png_error(png_ptr, "png_image_read: alpha channel lost"); png_error(png_ptr, "png_image_read: alpha channel lost");
if ((format & PNG_FORMAT_FLAG_ASSOCIATED_ALPHA) != 0) {
info_format |= PNG_FORMAT_FLAG_ASSOCIATED_ALPHA;
}
if (info_ptr->bit_depth == 16) if (info_ptr->bit_depth == 16)
info_format |= PNG_FORMAT_FLAG_LINEAR; info_format |= PNG_FORMAT_FLAG_LINEAR;
# ifdef PNG_FORMAT_BGR_SUPPORTED #ifdef PNG_FORMAT_BGR_SUPPORTED
if ((png_ptr->transformations & PNG_BGR) != 0) if ((png_ptr->transformations & PNG_BGR) != 0)
info_format |= PNG_FORMAT_FLAG_BGR; info_format |= PNG_FORMAT_FLAG_BGR;
# endif #endif
# ifdef PNG_FORMAT_AFIRST_SUPPORTED #ifdef PNG_FORMAT_AFIRST_SUPPORTED
if (do_local_background == 2) if (do_local_background == 2)
{ {
if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
@ -4050,14 +4086,14 @@ png_image_read_direct(png_voidp argument)
else else
{ {
png_alloc_size_t row_bytes = display->row_bytes; png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes;
while (--passes >= 0) while (--passes >= 0)
{ {
png_uint_32 y = image->height; png_uint_32 y = image->height;
png_bytep row = png_voidcast(png_bytep, display->first_row); png_bytep row = png_voidcast(png_bytep, display->first_row);
while (y-- > 0) for (; y > 0; --y)
{ {
png_read_row(png_ptr, row, NULL); png_read_row(png_ptr, row, NULL);
row += row_bytes; row += row_bytes;
@ -4073,20 +4109,57 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
void *buffer, png_int_32 row_stride, void *colormap) void *buffer, png_int_32 row_stride, void *colormap)
{ {
if (image != NULL && image->version == PNG_IMAGE_VERSION) if (image != NULL && image->version == PNG_IMAGE_VERSION)
{
/* Check for row_stride overflow. This check is not performed on the
* original PNG format because it may not occur in the output PNG format
* and libpng deals with the issues of reading the original.
*/
unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
/* The following checks just the 'row_stride' calculation to ensure it
* fits in a signed 32-bit value. Because channels/components can be
* either 1 or 2 bytes in size the length of a row can still overflow 32
* bits; this is just to verify that the 'row_stride' argument can be
* represented.
*/
if (image->width <= 0x7fffffffU/channels) /* no overflow */
{ {
png_uint_32 check; png_uint_32 check;
png_uint_32 png_row_stride = image->width * channels;
if (row_stride == 0) if (row_stride == 0)
row_stride = PNG_IMAGE_ROW_STRIDE(*image); row_stride = (png_int_32)/*SAFE*/png_row_stride;
if (row_stride < 0) if (row_stride < 0)
check = -row_stride; check = (png_uint_32)(-row_stride);
else else
check = row_stride; check = (png_uint_32)row_stride;
if (image->opaque != NULL && buffer != NULL && /* This verifies 'check', the absolute value of the actual stride
check >= PNG_IMAGE_ROW_STRIDE(*image)) * passed in and detects overflow in the application calculation (i.e.
* if the app did actually pass in a non-zero 'row_stride'.
*/
if (image->opaque != NULL && buffer != NULL && check >= png_row_stride)
{
/* Now check for overflow of the image buffer calculation; this
* limits the whole image size to 32 bits for API compatibility with
* the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
*
* The PNG_IMAGE_BUFFER_SIZE macro is:
*
* (PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)*height*(row_stride))
*
* And the component size is always 1 or 2, so make sure that the
* number of *bytes* that the application is saying are available
* does actually fit into a 32-bit number.
*
* NOTE: this will be changed in 1.7 because PNG_IMAGE_BUFFER_SIZE
* will be changed to use png_alloc_size_t; bigger images can be
* accommodated on 64-bit systems.
*/
if (image->height <=
0xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check)
{ {
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
(image->colormap_entries > 0 && colormap != NULL)) (image->colormap_entries > 0 && colormap != NULL))
@ -4102,17 +4175,20 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
display.background = background; display.background = background;
display.local_row = NULL; display.local_row = NULL;
/* Choose the correct 'end' routine; for the color-map case all the /* Choose the correct 'end' routine; for the color-map case
* setup has already been done. * all the setup has already been done.
*/ */
if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0) if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
result = result =
png_safe_execute(image, png_image_read_colormap, &display) && png_safe_execute(image,
png_safe_execute(image, png_image_read_colormapped, &display); png_image_read_colormap, &display) &&
png_safe_execute(image,
png_image_read_colormapped, &display);
else else
result = result =
png_safe_execute(image, png_image_read_direct, &display); png_safe_execute(image,
png_image_read_direct, &display);
png_image_free(image); png_image_free(image);
return result; return result;
@ -4123,11 +4199,21 @@ png_image_finish_read(png_imagep image, png_const_colorp background,
"png_image_finish_read[color-map]: no color-map"); "png_image_finish_read[color-map]: no color-map");
} }
else
return png_image_error(image,
"png_image_finish_read: image too large");
}
else else
return png_image_error(image, return png_image_error(image,
"png_image_finish_read: invalid argument"); "png_image_finish_read: invalid argument");
} }
else
return png_image_error(image,
"png_image_finish_read: row_stride too large");
}
else if (image != NULL) else if (image != NULL)
return png_image_error(image, return png_image_error(image,
"png_image_finish_read: damaged PNG_IMAGE_VERSION"); "png_image_finish_read: damaged PNG_IMAGE_VERSION");

View File

@ -1,10 +1,10 @@
/* pngrio.c - functions for data input /* pngrio.c - functions for data input
* *
* Last changed in libpng 1.6.17 [March 26, 2015] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -29,7 +29,7 @@
* to read more than 64K on a 16-bit machine. * to read more than 64K on a 16-bit machine.
*/ */
void /* PRIVATE */ void /* PRIVATE */
png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) png_read_data(png_structrp png_ptr, png_bytep data, size_t length)
{ {
png_debug1(4, "reading %d bytes", (int)length); png_debug1(4, "reading %d bytes", (int)length);
@ -47,14 +47,14 @@ png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length)
* than changing the library. * than changing the library.
*/ */
void PNGCBAPI void PNGCBAPI
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) png_default_read_data(png_structp png_ptr, png_bytep data, size_t length)
{ {
png_size_t check; size_t check;
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
/* fread() returns 0 on error, so it is OK to store this in a png_size_t /* fread() returns 0 on error, so it is OK to store this in a size_t
* instead of an int, which is what fread() actually returns. * instead of an int, which is what fread() actually returns.
*/ */
check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));

View File

@ -1,10 +1,10 @@
/* pngrtran.c - transforms the data in a row for PNG readers /* pngrtran.c - transforms the data in a row for PNG readers
* *
* Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -18,6 +18,17 @@
#include "pngpriv.h" #include "pngpriv.h"
#ifdef PNG_ARM_NEON_IMPLEMENTATION
# if PNG_ARM_NEON_IMPLEMENTATION == 1
# define PNG_ARM_NEON_INTRINSICS_AVAILABLE
# if defined(_MSC_VER) && defined(_M_ARM64)
# include <arm64_neon.h>
# else
# include <arm_neon.h>
# endif
# endif
#endif
#ifdef PNG_READ_SUPPORTED #ifdef PNG_READ_SUPPORTED
/* Set the action on getting a CRC error for an ancillary or critical chunk. */ /* Set the action on getting a CRC error for an ancillary or critical chunk. */
@ -49,8 +60,9 @@ png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */ case PNG_CRC_WARN_DISCARD: /* Not a valid action for critical data */
png_warning(png_ptr, png_warning(png_ptr,
"Can't discard critical data on CRC error"); "Can't discard critical data on CRC error");
FALLTHROUGH; /* FALLTHROUGH */
case PNG_CRC_ERROR_QUIT: /* Error/quit */ case PNG_CRC_ERROR_QUIT: /* Error/quit */
case PNG_CRC_DEFAULT: case PNG_CRC_DEFAULT:
default: default:
png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK; png_ptr->flags &= ~PNG_FLAG_CRC_CRITICAL_MASK;
@ -289,9 +301,12 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
* is expected to be 1 or greater, but this range test allows for some * is expected to be 1 or greater, but this range test allows for some
* viewing correction values. The intent is to weed out users of this API * viewing correction values. The intent is to weed out users of this API
* who use the inverse of the gamma value accidentally! Since some of these * who use the inverse of the gamma value accidentally! Since some of these
* values are reasonable this may have to be changed. * values are reasonable this may have to be changed:
*
* 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit
* gamma of 36, and its reciprocal.)
*/ */
if (output_gamma < 70000 || output_gamma > 300000) if (output_gamma < 1000 || output_gamma > 10000000)
png_error(png_ptr, "output gamma out of expected range"); png_error(png_ptr, "output gamma out of expected range");
/* The default file gamma is the inverse of the output gamma; the output /* The default file gamma is the inverse of the output gamma; the output
@ -426,7 +441,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
int i; int i;
png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
(png_uint_32)(num_palette * (sizeof (png_byte)))); (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
for (i = 0; i < num_palette; i++) for (i = 0; i < num_palette; i++)
png_ptr->quantize_index[i] = (png_byte)i; png_ptr->quantize_index[i] = (png_byte)i;
} }
@ -443,7 +458,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
/* Initialize an array to sort colors */ /* Initialize an array to sort colors */
png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
(png_uint_32)(num_palette * (sizeof (png_byte)))); (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
/* Initialize the quantize_sort array */ /* Initialize the quantize_sort array */
for (i = 0; i < num_palette; i++) for (i = 0; i < num_palette; i++)
@ -577,9 +592,11 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
/* Initialize palette index arrays */ /* Initialize palette index arrays */
png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
(png_uint_32)(num_palette * (sizeof (png_byte)))); (png_alloc_size_t)((png_uint_32)num_palette *
(sizeof (png_byte))));
png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
(png_uint_32)(num_palette * (sizeof (png_byte)))); (png_alloc_size_t)((png_uint_32)num_palette *
(sizeof (png_byte))));
/* Initialize the sort array */ /* Initialize the sort array */
for (i = 0; i < num_palette; i++) for (i = 0; i < num_palette; i++)
@ -588,7 +605,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
png_ptr->palette_to_index[i] = (png_byte)i; png_ptr->palette_to_index[i] = (png_byte)i;
} }
hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * hash = (png_dsortpp)png_calloc(png_ptr, (png_alloc_size_t)(769 *
(sizeof (png_dsortp)))); (sizeof (png_dsortp))));
num_new_palette = num_palette; num_new_palette = num_palette;
@ -619,7 +636,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
{ {
t = (png_dsortp)png_malloc_warn(png_ptr, t = (png_dsortp)png_malloc_warn(png_ptr,
(png_uint_32)(sizeof (png_dsort))); (png_alloc_size_t)(sizeof (png_dsort)));
if (t == NULL) if (t == NULL)
break; break;
@ -741,12 +758,12 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
int num_red = (1 << PNG_QUANTIZE_RED_BITS); int num_red = (1 << PNG_QUANTIZE_RED_BITS);
int num_green = (1 << PNG_QUANTIZE_GREEN_BITS); int num_green = (1 << PNG_QUANTIZE_GREEN_BITS);
int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS); int num_blue = (1 << PNG_QUANTIZE_BLUE_BITS);
png_size_t num_entries = ((png_size_t)1 << total_bits); size_t num_entries = ((size_t)1 << total_bits);
png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr, png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
(png_uint_32)(num_entries * (sizeof (png_byte)))); (png_alloc_size_t)(num_entries * (sizeof (png_byte))));
distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries *
(sizeof (png_byte)))); (sizeof (png_byte))));
memset(distance, 0xff, num_entries * (sizeof (png_byte))); memset(distance, 0xff, num_entries * (sizeof (png_byte)));
@ -1174,9 +1191,9 @@ png_init_palette_transformations(png_structrp png_ptr)
*/ */
int i, istop = png_ptr->num_trans; int i, istop = png_ptr->num_trans;
for (i=0; i<istop; i++) for (i = 0; i < istop; i++)
png_ptr->trans_alpha[i] = (png_byte)(255 - png_ptr->trans_alpha[i] =
png_ptr->trans_alpha[i]); (png_byte)(255 - png_ptr->trans_alpha[i]);
} }
} }
#endif /* READ_INVERT_ALPHA */ #endif /* READ_INVERT_ALPHA */
@ -1250,7 +1267,7 @@ png_init_rgb_transformations(png_structrp png_ptr)
default: default:
case 8: case 8:
/* FALL THROUGH (Already 8 bits) */ /* FALLTHROUGH */ /* (Already 8 bits) */
case 16: case 16:
/* Already a full 16 bits */ /* Already a full 16 bits */
@ -1311,7 +1328,7 @@ png_init_read_transformations(png_structrp png_ptr)
else if (png_ptr->screen_gamma != 0) else if (png_ptr->screen_gamma != 0)
/* The converse - assume the file matches the screen, note that this /* The converse - assume the file matches the screen, note that this
* perhaps undesireable default can (from 1.5.4) be changed by calling * perhaps undesirable default can (from 1.5.4) be changed by calling
* png_set_alpha_mode (even if the alpha handling mode isn't required * png_set_alpha_mode (even if the alpha handling mode isn't required
* or isn't changed from the default.) * or isn't changed from the default.)
*/ */
@ -1879,7 +1896,7 @@ png_init_read_transformations(png_structrp png_ptr)
png_ptr->transformations &= ~PNG_SHIFT; png_ptr->transformations &= ~PNG_SHIFT;
/* significant bits can be in the range 1 to 7 for a meaninful result, if /* significant bits can be in the range 1 to 7 for a meaningful result, if
* the number of significant bits is 0 then no shift is done (this is an * the number of significant bits is 0 then no shift is done (this is an
* error condition which is silently ignored.) * error condition which is silently ignored.)
*/ */
@ -2145,9 +2162,9 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
{ {
case 1: case 1:
{ {
png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); png_bytep sp = row + (size_t)((row_width - 1) >> 3);
png_bytep dp = row + (png_size_t)row_width - 1; png_bytep dp = row + (size_t)row_width - 1;
png_uint_32 shift = 7 - (int)((row_width + 7) & 0x07); png_uint_32 shift = 7U - ((row_width + 7U) & 0x07);
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*dp = (png_byte)((*sp >> shift) & 0x01); *dp = (png_byte)((*sp >> shift) & 0x01);
@ -2169,9 +2186,9 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
case 2: case 2:
{ {
png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); png_bytep sp = row + (size_t)((row_width - 1) >> 2);
png_bytep dp = row + (png_size_t)row_width - 1; png_bytep dp = row + (size_t)row_width - 1;
png_uint_32 shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1);
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*dp = (png_byte)((*sp >> shift) & 0x03); *dp = (png_byte)((*sp >> shift) & 0x03);
@ -2192,9 +2209,9 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
case 4: case 4:
{ {
png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); png_bytep sp = row + (size_t)((row_width - 1) >> 1);
png_bytep dp = row + (png_size_t)row_width - 1; png_bytep dp = row + (size_t)row_width - 1;
png_uint_32 shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2);
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*dp = (png_byte)((*sp >> shift) & 0x0f); *dp = (png_byte)((*sp >> shift) & 0x0f);
@ -2457,10 +2474,10 @@ png_do_chop(png_row_infop row_info, png_bytep row)
static void static void
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{ {
png_uint_32 row_width = row_info->width;
png_debug(1, "in png_do_read_swap_alpha"); png_debug(1, "in png_do_read_swap_alpha");
{
png_uint_32 row_width = row_info->width;
if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
{ {
/* This converts from RGBA to ARGB */ /* This converts from RGBA to ARGB */
@ -2546,7 +2563,6 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
} }
#endif #endif
} }
}
} }
#endif #endif
@ -2675,8 +2691,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
if ((flags & PNG_FLAG_FILLER_AFTER) != 0) if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{ {
/* This changes the data from G to GX */ /* This changes the data from G to GX */
png_bytep sp = row + (png_size_t)row_width; png_bytep sp = row + (size_t)row_width;
png_bytep dp = sp + (png_size_t)row_width; png_bytep dp = sp + (size_t)row_width;
for (i = 1; i < row_width; i++) for (i = 1; i < row_width; i++)
{ {
*(--dp) = lo_filler; *(--dp) = lo_filler;
@ -2691,8 +2707,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
else else
{ {
/* This changes the data from G to XG */ /* This changes the data from G to XG */
png_bytep sp = row + (png_size_t)row_width; png_bytep sp = row + (size_t)row_width;
png_bytep dp = sp + (png_size_t)row_width; png_bytep dp = sp + (size_t)row_width;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*(--dp) = *(--sp); *(--dp) = *(--sp);
@ -2710,8 +2726,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
if ((flags & PNG_FLAG_FILLER_AFTER) != 0) if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{ {
/* This changes the data from GG to GGXX */ /* This changes the data from GG to GGXX */
png_bytep sp = row + (png_size_t)row_width * 2; png_bytep sp = row + (size_t)row_width * 2;
png_bytep dp = sp + (png_size_t)row_width * 2; png_bytep dp = sp + (size_t)row_width * 2;
for (i = 1; i < row_width; i++) for (i = 1; i < row_width; i++)
{ {
*(--dp) = lo_filler; *(--dp) = lo_filler;
@ -2729,8 +2745,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
else else
{ {
/* This changes the data from GG to XXGG */ /* This changes the data from GG to XXGG */
png_bytep sp = row + (png_size_t)row_width * 2; png_bytep sp = row + (size_t)row_width * 2;
png_bytep dp = sp + (png_size_t)row_width * 2; png_bytep dp = sp + (size_t)row_width * 2;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*(--dp) = *(--sp); *(--dp) = *(--sp);
@ -2752,8 +2768,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
if ((flags & PNG_FLAG_FILLER_AFTER) != 0) if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{ {
/* This changes the data from RGB to RGBX */ /* This changes the data from RGB to RGBX */
png_bytep sp = row + (png_size_t)row_width * 3; png_bytep sp = row + (size_t)row_width * 3;
png_bytep dp = sp + (png_size_t)row_width; png_bytep dp = sp + (size_t)row_width;
for (i = 1; i < row_width; i++) for (i = 1; i < row_width; i++)
{ {
*(--dp) = lo_filler; *(--dp) = lo_filler;
@ -2770,8 +2786,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
else else
{ {
/* This changes the data from RGB to XRGB */ /* This changes the data from RGB to XRGB */
png_bytep sp = row + (png_size_t)row_width * 3; png_bytep sp = row + (size_t)row_width * 3;
png_bytep dp = sp + (png_size_t)row_width; png_bytep dp = sp + (size_t)row_width;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*(--dp) = *(--sp); *(--dp) = *(--sp);
@ -2791,8 +2807,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
if ((flags & PNG_FLAG_FILLER_AFTER) != 0) if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{ {
/* This changes the data from RRGGBB to RRGGBBXX */ /* This changes the data from RRGGBB to RRGGBBXX */
png_bytep sp = row + (png_size_t)row_width * 6; png_bytep sp = row + (size_t)row_width * 6;
png_bytep dp = sp + (png_size_t)row_width * 2; png_bytep dp = sp + (size_t)row_width * 2;
for (i = 1; i < row_width; i++) for (i = 1; i < row_width; i++)
{ {
*(--dp) = lo_filler; *(--dp) = lo_filler;
@ -2814,8 +2830,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
else else
{ {
/* This changes the data from RRGGBB to XXRRGGBB */ /* This changes the data from RRGGBB to XXRRGGBB */
png_bytep sp = row + (png_size_t)row_width * 6; png_bytep sp = row + (size_t)row_width * 6;
png_bytep dp = sp + (png_size_t)row_width * 2; png_bytep dp = sp + (size_t)row_width * 2;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*(--dp) = *(--sp); *(--dp) = *(--sp);
@ -2856,8 +2872,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
if (row_info->bit_depth == 8) if (row_info->bit_depth == 8)
{ {
/* This changes G to RGB */ /* This changes G to RGB */
png_bytep sp = row + (png_size_t)row_width - 1; png_bytep sp = row + (size_t)row_width - 1;
png_bytep dp = sp + (png_size_t)row_width * 2; png_bytep dp = sp + (size_t)row_width * 2;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*(dp--) = *sp; *(dp--) = *sp;
@ -2869,8 +2885,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
else else
{ {
/* This changes GG to RRGGBB */ /* This changes GG to RRGGBB */
png_bytep sp = row + (png_size_t)row_width * 2 - 1; png_bytep sp = row + (size_t)row_width * 2 - 1;
png_bytep dp = sp + (png_size_t)row_width * 4; png_bytep dp = sp + (size_t)row_width * 4;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*(dp--) = *sp; *(dp--) = *sp;
@ -2888,8 +2904,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
if (row_info->bit_depth == 8) if (row_info->bit_depth == 8)
{ {
/* This changes GA to RGBA */ /* This changes GA to RGBA */
png_bytep sp = row + (png_size_t)row_width * 2 - 1; png_bytep sp = row + (size_t)row_width * 2 - 1;
png_bytep dp = sp + (png_size_t)row_width * 2; png_bytep dp = sp + (size_t)row_width * 2;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*(dp--) = *(sp--); *(dp--) = *(sp--);
@ -2902,8 +2918,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
else else
{ {
/* This changes GGAA to RRGGBBAA */ /* This changes GGAA to RRGGBBAA */
png_bytep sp = row + (png_size_t)row_width * 4 - 1; png_bytep sp = row + (size_t)row_width * 4 - 1;
png_bytep dp = sp + (png_size_t)row_width * 4; png_bytep dp = sp + (size_t)row_width * 4;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
*(dp--) = *(sp--); *(dp--) = *(sp--);
@ -2931,7 +2947,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
* using the equation given in Poynton's ColorFAQ of 1998-01-04 at * using the equation given in Poynton's ColorFAQ of 1998-01-04 at
* <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008 but * <http://www.inforamp.net/~poynton/> (THIS LINK IS DEAD June 2008 but
* versions dated 1998 through November 2002 have been archived at * versions dated 1998 through November 2002 have been archived at
* http://web.archive.org/web/20000816232553/http://www.inforamp.net/ * https://web.archive.org/web/20000816232553/www.inforamp.net/
* ~poynton/notes/colour_and_gamma/ColorFAQ.txt ) * ~poynton/notes/colour_and_gamma/ColorFAQ.txt )
* Charles Poynton poynton at poynton.com * Charles Poynton poynton at poynton.com
* *
@ -2974,14 +2990,13 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
* values this results in an implicit assumption that the original PNG RGB * values this results in an implicit assumption that the original PNG RGB
* values were linear. * values were linear.
* *
* Other integer coefficents can be used via png_set_rgb_to_gray(). Because * Other integer coefficients can be used via png_set_rgb_to_gray(). Because
* the API takes just red and green coefficients the blue coefficient is * the API takes just red and green coefficients the blue coefficient is
* calculated to make the sum 32768. This will result in different rounding * calculated to make the sum 32768. This will result in different rounding
* to that used above. * to that used above.
*/ */
static int static int
png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
{ {
int rgb_error = 0; int rgb_error = 0;
@ -2990,12 +3005,11 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 && if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
(row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{ {
PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
PNG_CONST png_uint_32 bc = 32768 - rc - gc; png_uint_32 bc = 32768 - rc - gc;
PNG_CONST png_uint_32 row_width = row_info->width; png_uint_32 row_width = row_info->width;
PNG_CONST int have_alpha = int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
(row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0;
if (row_info->bit_depth == 8) if (row_info->bit_depth == 8)
{ {
@ -3203,7 +3217,6 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
png_debug(1, "in png_do_compose"); png_debug(1, "in png_do_compose");
{
switch (row_info->color_type) switch (row_info->color_type)
{ {
case PNG_COLOR_TYPE_GRAY: case PNG_COLOR_TYPE_GRAY:
@ -3220,7 +3233,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
== png_ptr->trans_color.gray) == png_ptr->trans_color.gray)
{ {
unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
tmp |= png_ptr->background.gray << shift; tmp |=
(unsigned int)(png_ptr->background.gray << shift);
*sp = (png_byte)(tmp & 0xff); *sp = (png_byte)(tmp & 0xff);
} }
@ -3249,7 +3263,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
== png_ptr->trans_color.gray) == png_ptr->trans_color.gray)
{ {
unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
tmp |= png_ptr->background.gray << shift; tmp |=
(unsigned int)png_ptr->background.gray << shift;
*sp = (png_byte)(tmp & 0xff); *sp = (png_byte)(tmp & 0xff);
} }
@ -3259,7 +3274,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
unsigned int g = (gamma_table [p | (p << 2) | unsigned int g = (gamma_table [p | (p << 2) |
(p << 4) | (p << 6)] >> 6) & 0x03; (p << 4) | (p << 6)] >> 6) & 0x03;
unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
tmp |= g << shift; tmp |= (unsigned int)(g << shift);
*sp = (png_byte)(tmp & 0xff); *sp = (png_byte)(tmp & 0xff);
} }
@ -3285,7 +3300,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
== png_ptr->trans_color.gray) == png_ptr->trans_color.gray)
{ {
unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
tmp |= png_ptr->background.gray << shift; tmp |=
(unsigned int)png_ptr->background.gray << shift;
*sp = (png_byte)(tmp & 0xff); *sp = (png_byte)(tmp & 0xff);
} }
@ -3315,7 +3331,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
== png_ptr->trans_color.gray) == png_ptr->trans_color.gray)
{ {
unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
tmp |= png_ptr->background.gray << shift; tmp |=
(unsigned int)(png_ptr->background.gray << shift);
*sp = (png_byte)(tmp & 0xff); *sp = (png_byte)(tmp & 0xff);
} }
@ -3325,7 +3342,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
unsigned int g = (gamma_table[p | (p << 4)] >> 4) & unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
0x0f; 0x0f;
unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
tmp |= g << shift; tmp |= (unsigned int)(g << shift);
*sp = (png_byte)(tmp & 0xff); *sp = (png_byte)(tmp & 0xff);
} }
@ -3351,7 +3368,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
== png_ptr->trans_color.gray) == png_ptr->trans_color.gray)
{ {
unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); unsigned int tmp = *sp & (0x0f0f >> (4 - shift));
tmp |= png_ptr->background.gray << shift; tmp |=
(unsigned int)(png_ptr->background.gray << shift);
*sp = (png_byte)(tmp & 0xff); *sp = (png_byte)(tmp & 0xff);
} }
@ -3912,7 +3930,6 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
default: default:
break; break;
} }
}
} }
#endif /* READ_BACKGROUND || READ_ALPHA_MODE */ #endif /* READ_BACKGROUND || READ_ALPHA_MODE */
@ -4135,12 +4152,11 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{ {
if (row_info->bit_depth == 8) if (row_info->bit_depth == 8)
{ {
PNG_CONST png_bytep table = png_ptr->gamma_from_1; png_bytep table = png_ptr->gamma_from_1;
if (table != NULL) if (table != NULL)
{ {
PNG_CONST int step = int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
(row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2;
/* The alpha channel is the last component: */ /* The alpha channel is the last component: */
row += step - 1; row += step - 1;
@ -4154,13 +4170,12 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
else if (row_info->bit_depth == 16) else if (row_info->bit_depth == 16)
{ {
PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; png_uint_16pp table = png_ptr->gamma_16_from_1;
PNG_CONST int gamma_shift = png_ptr->gamma_shift; int gamma_shift = png_ptr->gamma_shift;
if (table != NULL) if (table != NULL)
{ {
PNG_CONST int step = int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
(row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4;
/* The alpha channel is the last component: */ /* The alpha channel is the last component: */
row += step - 2; row += step - 2;
@ -4191,8 +4206,9 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
* upon whether you supply trans and num_trans. * upon whether you supply trans and num_trans.
*/ */
static void static void
png_do_expand_palette(png_row_infop row_info, png_bytep row, png_do_expand_palette(png_structrp png_ptr, png_row_infop row_info,
png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) png_bytep row, png_const_colorp palette, png_const_bytep trans_alpha,
int num_trans)
{ {
int shift, value; int shift, value;
png_bytep sp, dp; png_bytep sp, dp;
@ -4209,8 +4225,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
{ {
case 1: case 1:
{ {
sp = row + (png_size_t)((row_width - 1) >> 3); sp = row + (size_t)((row_width - 1) >> 3);
dp = row + (png_size_t)row_width - 1; dp = row + (size_t)row_width - 1;
shift = 7 - (int)((row_width + 7) & 0x07); shift = 7 - (int)((row_width + 7) & 0x07);
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
@ -4236,8 +4252,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
case 2: case 2:
{ {
sp = row + (png_size_t)((row_width - 1) >> 2); sp = row + (size_t)((row_width - 1) >> 2);
dp = row + (png_size_t)row_width - 1; dp = row + (size_t)row_width - 1;
shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
@ -4259,8 +4275,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
case 4: case 4:
{ {
sp = row + (png_size_t)((row_width - 1) >> 1); sp = row + (size_t)((row_width - 1) >> 1);
dp = row + (png_size_t)row_width - 1; dp = row + (size_t)row_width - 1;
shift = (int)((row_width & 0x01) << 2); shift = (int)((row_width & 0x01) << 2);
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
@ -4293,17 +4309,30 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
{ {
if (num_trans > 0) if (num_trans > 0)
{ {
sp = row + (png_size_t)row_width - 1; sp = row + (size_t)row_width - 1;
dp = row + (png_size_t)(row_width << 2) - 1; dp = row + ((size_t)row_width << 2) - 1;
for (i = 0; i < row_width; i++) i = 0;
#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
if (png_ptr->riffled_palette != NULL)
{
/* The RGBA optimization works with png_ptr->bit_depth == 8
* but sometimes row_info->bit_depth has been changed to 8.
* In these cases, the palette hasn't been riffled.
*/
i = png_do_expand_palette_rgba8_neon(png_ptr, row_info, row,
&sp, &dp);
}
#else
PNG_UNUSED(png_ptr)
#endif
for (; i < row_width; i++)
{ {
if ((int)(*sp) >= num_trans) if ((int)(*sp) >= num_trans)
*dp-- = 0xff; *dp-- = 0xff;
else else
*dp-- = trans_alpha[*sp]; *dp-- = trans_alpha[*sp];
*dp-- = palette[*sp].blue; *dp-- = palette[*sp].blue;
*dp-- = palette[*sp].green; *dp-- = palette[*sp].green;
*dp-- = palette[*sp].red; *dp-- = palette[*sp].red;
@ -4318,10 +4347,17 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
else else
{ {
sp = row + (png_size_t)row_width - 1; sp = row + (size_t)row_width - 1;
dp = row + (png_size_t)(row_width * 3) - 1; dp = row + (size_t)(row_width * 3) - 1;
i = 0;
#ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
i = png_do_expand_palette_rgb8_neon(png_ptr, row_info, row,
&sp, &dp);
#else
PNG_UNUSED(png_ptr)
#endif
for (i = 0; i < row_width; i++) for (; i < row_width; i++)
{ {
*dp-- = palette[*sp].blue; *dp-- = palette[*sp].blue;
*dp-- = palette[*sp].green; *dp-- = palette[*sp].green;
@ -4354,7 +4390,6 @@ png_do_expand(png_row_infop row_info, png_bytep row,
png_debug(1, "in png_do_expand"); png_debug(1, "in png_do_expand");
{
if (row_info->color_type == PNG_COLOR_TYPE_GRAY) if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
{ {
unsigned int gray = trans_color != NULL ? trans_color->gray : 0; unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
@ -4366,8 +4401,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
case 1: case 1:
{ {
gray = (gray & 0x01) * 0xff; gray = (gray & 0x01) * 0xff;
sp = row + (png_size_t)((row_width - 1) >> 3); sp = row + (size_t)((row_width - 1) >> 3);
dp = row + (png_size_t)row_width - 1; dp = row + (size_t)row_width - 1;
shift = 7 - (int)((row_width + 7) & 0x07); shift = 7 - (int)((row_width + 7) & 0x07);
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
@ -4394,8 +4429,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
case 2: case 2:
{ {
gray = (gray & 0x03) * 0x55; gray = (gray & 0x03) * 0x55;
sp = row + (png_size_t)((row_width - 1) >> 2); sp = row + (size_t)((row_width - 1) >> 2);
dp = row + (png_size_t)row_width - 1; dp = row + (size_t)row_width - 1;
shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
@ -4419,8 +4454,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
case 4: case 4:
{ {
gray = (gray & 0x0f) * 0x11; gray = (gray & 0x0f) * 0x11;
sp = row + (png_size_t)((row_width - 1) >> 1); sp = row + (size_t)((row_width - 1) >> 1);
dp = row + (png_size_t)row_width - 1; dp = row + (size_t)row_width - 1;
shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
@ -4454,8 +4489,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
if (row_info->bit_depth == 8) if (row_info->bit_depth == 8)
{ {
gray = gray & 0xff; gray = gray & 0xff;
sp = row + (png_size_t)row_width - 1; sp = row + (size_t)row_width - 1;
dp = row + (png_size_t)(row_width << 1) - 1; dp = row + ((size_t)row_width << 1) - 1;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
@ -4510,8 +4545,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
png_byte red = (png_byte)(trans_color->red & 0xff); png_byte red = (png_byte)(trans_color->red & 0xff);
png_byte green = (png_byte)(trans_color->green & 0xff); png_byte green = (png_byte)(trans_color->green & 0xff);
png_byte blue = (png_byte)(trans_color->blue & 0xff); png_byte blue = (png_byte)(trans_color->blue & 0xff);
sp = row + (png_size_t)row_info->rowbytes - 1; sp = row + (size_t)row_info->rowbytes - 1;
dp = row + (png_size_t)(row_width << 2) - 1; dp = row + ((size_t)row_width << 2) - 1;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue)
@ -4534,7 +4569,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
png_byte green_low = (png_byte)(trans_color->green & 0xff); png_byte green_low = (png_byte)(trans_color->green & 0xff);
png_byte blue_low = (png_byte)(trans_color->blue & 0xff); png_byte blue_low = (png_byte)(trans_color->blue & 0xff);
sp = row + row_info->rowbytes - 1; sp = row + row_info->rowbytes - 1;
dp = row + (png_size_t)(row_width << 3) - 1; dp = row + ((size_t)row_width << 3) - 1;
for (i = 0; i < row_width; i++) for (i = 0; i < row_width; i++)
{ {
if (*(sp - 5) == red_high && if (*(sp - 5) == red_high &&
@ -4567,7 +4602,6 @@ png_do_expand(png_row_infop row_info, png_bytep row,
row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2);
row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width);
} }
}
} }
#endif #endif
@ -4593,7 +4627,9 @@ png_do_expand_16(png_row_infop row_info, png_bytep row)
png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */ png_byte *sp = row + row_info->rowbytes; /* source, last byte + 1 */
png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */ png_byte *dp = sp + row_info->rowbytes; /* destination, end + 1 */
while (dp > sp) while (dp > sp)
dp[-2] = dp[-1] = *--sp, dp -= 2; {
dp[-2] = dp[-1] = *--sp; dp -= 2;
}
row_info->rowbytes *= 2; row_info->rowbytes *= 2;
row_info->bit_depth = 16; row_info->bit_depth = 16;
@ -4735,7 +4771,19 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
{ {
if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
{ {
png_do_expand_palette(row_info, png_ptr->row_buf + 1, #ifdef PNG_ARM_NEON_INTRINSICS_AVAILABLE
if ((png_ptr->num_trans > 0) && (png_ptr->bit_depth == 8))
{
if (png_ptr->riffled_palette == NULL)
{
/* Initialize the accelerated palette expansion. */
png_ptr->riffled_palette =
(png_bytep)png_malloc(png_ptr, 256 * 4);
png_riffle_palette_neon(png_ptr);
}
}
#endif
png_do_expand_palette(png_ptr, row_info, png_ptr->row_buf + 1,
png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
} }
@ -4747,8 +4795,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
&(png_ptr->trans_color)); &(png_ptr->trans_color));
else else
png_do_expand(row_info, png_ptr->row_buf + 1, png_do_expand(row_info, png_ptr->row_buf + 1, NULL);
NULL);
} }
} }
#endif #endif
@ -4972,7 +5019,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
(png_ptr, /* png_ptr */ (png_ptr, /* png_ptr */
row_info, /* row_info: */ row_info, /* row_info: */
/* png_uint_32 width; width of row */ /* png_uint_32 width; width of row */
/* png_size_t rowbytes; number of bytes in row */ /* size_t rowbytes; number of bytes in row */
/* png_byte color_type; color type of pixels */ /* png_byte color_type; color type of pixels */
/* png_byte bit_depth; bit depth of samples */ /* png_byte bit_depth; bit depth of samples */
/* png_byte channels; number of channels (1-4) */ /* png_byte channels; number of channels (1-4) */

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
/* pngset.c - storage of image information into info struct /* pngset.c - storage of image information into info struct
* *
* Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -134,6 +134,53 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
#endif /* cHRM */ #endif /* cHRM */
#ifdef PNG_eXIf_SUPPORTED
void PNGAPI
png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
png_bytep eXIf_buf)
{
png_warning(png_ptr, "png_set_eXIf does not work; use png_set_eXIf_1");
PNG_UNUSED(info_ptr)
PNG_UNUSED(eXIf_buf)
}
void PNGAPI
png_set_eXIf_1(png_const_structrp png_ptr, png_inforp info_ptr,
png_uint_32 num_exif, png_bytep eXIf_buf)
{
int i;
png_debug1(1, "in %s storage function", "eXIf");
if (png_ptr == NULL || info_ptr == NULL)
return;
if (info_ptr->exif)
{
png_free(png_ptr, info_ptr->exif);
info_ptr->exif = NULL;
}
info_ptr->num_exif = num_exif;
info_ptr->exif = png_voidcast(png_bytep, png_malloc_warn(png_ptr,
info_ptr->num_exif));
if (info_ptr->exif == NULL)
{
png_warning(png_ptr, "Insufficient memory for eXIf chunk data");
return;
}
info_ptr->free_me |= PNG_FREE_EXIF;
for (i = 0; i < (int) info_ptr->num_exif; i++)
info_ptr->exif[i] = eXIf_buf[i];
info_ptr->valid |= PNG_INFO_eXIf;
}
#endif /* eXIf */
#ifdef PNG_gAMA_SUPPORTED #ifdef PNG_gAMA_SUPPORTED
void PNGFAPI void PNGFAPI
png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr, png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
@ -266,7 +313,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type, png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
int nparams, png_const_charp units, png_charpp params) int nparams, png_const_charp units, png_charpp params)
{ {
png_size_t length; size_t length;
int i; int i;
png_debug1(1, "in %s storage function", "pCAL"); png_debug1(1, "in %s storage function", "pCAL");
@ -283,17 +330,29 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
/* Check that the type matches the specification. */ /* Check that the type matches the specification. */
if (type < 0 || type > 3) if (type < 0 || type > 3)
png_error(png_ptr, "Invalid pCAL equation type"); {
png_chunk_report(png_ptr, "Invalid pCAL equation type",
PNG_CHUNK_WRITE_ERROR);
return;
}
if (nparams < 0 || nparams > 255) if (nparams < 0 || nparams > 255)
png_error(png_ptr, "Invalid pCAL parameter count"); {
png_chunk_report(png_ptr, "Invalid pCAL parameter count",
PNG_CHUNK_WRITE_ERROR);
return;
}
/* Validate params[nparams] */ /* Validate params[nparams] */
for (i=0; i<nparams; ++i) for (i=0; i<nparams; ++i)
{ {
if (params[i] == NULL || if (params[i] == NULL ||
!png_check_fp_string(params[i], strlen(params[i]))) !png_check_fp_string(params[i], strlen(params[i])))
png_error(png_ptr, "Invalid format for pCAL parameter"); {
png_chunk_report(png_ptr, "Invalid format for pCAL parameter",
PNG_CHUNK_WRITE_ERROR);
return;
}
} }
info_ptr->pcal_purpose = png_voidcast(png_charp, info_ptr->pcal_purpose = png_voidcast(png_charp,
@ -301,8 +360,8 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
if (info_ptr->pcal_purpose == NULL) if (info_ptr->pcal_purpose == NULL)
{ {
png_warning(png_ptr, "Insufficient memory for pCAL purpose"); png_chunk_report(png_ptr, "Insufficient memory for pCAL purpose",
PNG_CHUNK_WRITE_ERROR);
return; return;
} }
@ -331,7 +390,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
memcpy(info_ptr->pcal_units, units, length); memcpy(info_ptr->pcal_units, units, length);
info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
(png_size_t)((nparams + 1) * (sizeof (png_charp))))); (size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp)))));
if (info_ptr->pcal_params == NULL) if (info_ptr->pcal_params == NULL)
{ {
@ -340,7 +399,8 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
return; return;
} }
memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp))); memset(info_ptr->pcal_params, 0, ((unsigned int)nparams + 1) *
(sizeof (png_charp)));
for (i = 0; i < nparams; i++) for (i = 0; i < nparams; i++)
{ {
@ -370,7 +430,7 @@ void PNGAPI
png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
int unit, png_const_charp swidth, png_const_charp sheight) int unit, png_const_charp swidth, png_const_charp sheight)
{ {
png_size_t lengthw = 0, lengthh = 0; size_t lengthw = 0, lengthh = 0;
png_debug1(1, "in %s storage function", "sCAL"); png_debug1(1, "in %s storage function", "sCAL");
@ -520,8 +580,8 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
if (png_ptr == NULL || info_ptr == NULL) if (png_ptr == NULL || info_ptr == NULL)
return; return;
max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? max_palette_length = (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ?
(1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; (1 << info_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH;
if (num_palette < 0 || num_palette > (int) max_palette_length) if (num_palette < 0 || num_palette > (int) max_palette_length)
{ {
@ -563,7 +623,8 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
if (num_palette > 0) if (num_palette > 0)
memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color))); memcpy(png_ptr->palette, palette, (unsigned int)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 = (png_uint_16)num_palette; info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
@ -630,7 +691,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
{ {
png_charp new_iccp_name; png_charp new_iccp_name;
png_bytep new_iccp_profile; png_bytep new_iccp_profile;
png_size_t length; size_t length;
png_debug1(1, "in %s storage function", "iCCP"); png_debug1(1, "in %s storage function", "iCCP");
@ -952,12 +1013,14 @@ 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);
/* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep,
png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); {
/* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
info_ptr->trans_alpha = png_voidcast(png_bytep,
png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans);
}
png_ptr->trans_alpha = info_ptr->trans_alpha;
} }
if (trans_color != NULL) if (trans_color != NULL)
@ -1035,7 +1098,7 @@ png_set_sPLT(png_const_structrp png_ptr,
do do
{ {
png_size_t length; size_t length;
/* Skip invalid input entries */ /* Skip invalid input entries */
if (entries->name == NULL || entries->entries == NULL) if (entries->name == NULL || entries->entries == NULL)
@ -1078,7 +1141,7 @@ png_set_sPLT(png_const_structrp png_ptr,
* checked it when doing the allocation. * checked it when doing the allocation.
*/ */
memcpy(np->entries, entries->entries, memcpy(np->entries, entries->entries,
entries->nentries * sizeof (png_sPLT_entry)); (unsigned int)entries->nentries * sizeof (png_sPLT_entry));
/* Note that 'continue' skips the advance of the out pointer and out /* Note that 'continue' skips the advance of the out pointer and out
* count, so an invalid entry is not added. * count, so an invalid entry is not added.
@ -1086,8 +1149,9 @@ png_set_sPLT(png_const_structrp png_ptr,
info_ptr->valid |= PNG_INFO_sPLT; info_ptr->valid |= PNG_INFO_sPLT;
++(info_ptr->splt_palettes_num); ++(info_ptr->splt_palettes_num);
++np; ++np;
++entries;
} }
while (++entries, --nentries); while (--nentries);
if (nentries > 0) if (nentries > 0)
png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR); png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
@ -1247,7 +1311,7 @@ png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
{ {
png_app_error(png_ptr, "invalid unknown chunk location"); png_app_error(png_ptr, "invalid unknown chunk location");
/* Fake out the pre 1.6.0 behavior: */ /* Fake out the pre 1.6.0 behavior: */
if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */ if (((unsigned int)location & PNG_HAVE_IDAT) != 0) /* undocumented! */
location = PNG_AFTER_IDAT; location = PNG_AFTER_IDAT;
else else
@ -1335,9 +1399,10 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
/* Ignore all unknown chunks and all chunks recognized by /* Ignore all unknown chunks and all chunks recognized by
* libpng except for IHDR, PLTE, tRNS, IDAT, and IEND * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
*/ */
static PNG_CONST png_byte chunks_to_ignore[] = { static const png_byte chunks_to_ignore[] = {
98, 75, 71, 68, '\0', /* bKGD */ 98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */ 99, 72, 82, 77, '\0', /* cHRM */
101, 88, 73, 102, '\0', /* eXIf */
103, 65, 77, 65, '\0', /* gAMA */ 103, 65, 77, 65, '\0', /* gAMA */
104, 73, 83, 84, '\0', /* hIST */ 104, 73, 83, 84, '\0', /* hIST */
105, 67, 67, 80, '\0', /* iCCP */ 105, 67, 67, 80, '\0', /* iCCP */
@ -1371,7 +1436,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
return; return;
} }
num_chunks = num_chunks_in; num_chunks = (unsigned int)num_chunks_in;
} }
old_num_chunks = png_ptr->num_chunk_list; old_num_chunks = png_ptr->num_chunk_list;
@ -1498,7 +1563,7 @@ png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
#endif #endif
void PNGAPI void PNGAPI
png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size) png_set_compression_buffer_size(png_structrp png_ptr, size_t size)
{ {
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
@ -1561,7 +1626,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 &= (unsigned int)(~mask);
} }
@ -1573,7 +1638,7 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
{ {
/* Images with dimensions larger than these limits will be /* Images with dimensions larger than these limits will be
* rejected by png_set_IHDR(). To accept any PNG datastream * rejected by png_set_IHDR(). To accept any PNG datastream
* regardless of dimensions, set both limits to 0x7ffffff. * regardless of dimensions, set both limits to 0x7fffffff.
*/ */
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
@ -1644,4 +1709,94 @@ png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
png_ptr->num_palette_max = -1; png_ptr->num_palette_max = -1;
} }
#endif #endif
#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) || \
defined(PNG_iCCP_SUPPORTED) || defined(PNG_sPLT_SUPPORTED)
/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
* and if invalid, correct the keyword rather than discarding the entire
* chunk. The PNG 1.0 specification requires keywords 1-79 characters in
* length, forbids leading or trailing whitespace, multiple internal spaces,
* and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
*
* The 'new_key' buffer must be 80 characters in size (for the keyword plus a
* trailing '\0'). If this routine returns 0 then there was no keyword, or a
* valid one could not be generated, and the caller must png_error.
*/
png_uint_32 /* PRIVATE */
png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
{
#ifdef PNG_WARNINGS_SUPPORTED
png_const_charp orig_key = key;
#endif
png_uint_32 key_len = 0;
int bad_character = 0;
int space = 1;
png_debug(1, "in png_check_keyword");
if (key == NULL)
{
*new_key = 0;
return 0;
}
while (*key && key_len < 79)
{
png_byte ch = (png_byte)*key++;
if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
{
*new_key++ = ch; ++key_len; space = 0;
}
else if (space == 0)
{
/* A space or an invalid character when one wasn't seen immediately
* before; output just a space.
*/
*new_key++ = 32; ++key_len; space = 1;
/* If the character was not a space then it is invalid. */
if (ch != 32)
bad_character = ch;
}
else if (bad_character == 0)
bad_character = ch; /* just skip it, record the first error */
}
if (key_len > 0 && space != 0) /* trailing space */
{
--key_len; --new_key;
if (bad_character == 0)
bad_character = 32;
}
/* Terminate the keyword */
*new_key = 0;
if (key_len == 0)
return 0;
#ifdef PNG_WARNINGS_SUPPORTED
/* Try to only output one warning per keyword: */
if (*key != 0) /* keyword too long */
png_warning(png_ptr, "keyword truncated");
else if (bad_character != 0)
{
PNG_WARNING_PARAMETERS(p)
png_warning_parameter(p, 1, orig_key);
png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
}
#else /* !WARNINGS */
PNG_UNUSED(png_ptr)
#endif /* !WARNINGS */
return key_len;
}
#endif /* TEXT || pCAL || iCCP || sPLT */
#endif /* READ || WRITE */ #endif /* READ || WRITE */

View File

@ -1,10 +1,10 @@
/* pngstruct.h - header file for PNG reference library /* pngstruct.h - header file for PNG reference library
* *
* Last changed in libpng 1.6.18 [July 23, 2015] * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -47,7 +47,7 @@
/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib /* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib
* can handle at once. This type need be no larger than 16 bits (so maximum of * can handle at once. This type need be no larger than 16 bits (so maximum of
* 65535), this define allows us to discover how big it is, but limited by the * 65535), this define allows us to discover how big it is, but limited by the
* maximuum for png_size_t. The value can be overriden in a library build * maximum for size_t. The value can be overridden in a library build
* (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably
* lower value (e.g. 255 works). A lower value may help memory usage (slightly) * lower value (e.g. 255 works). A lower value may help memory usage (slightly)
* and may even improve performance on some systems (and degrade it on others.) * and may even improve performance on some systems (and degrade it on others.)
@ -214,7 +214,7 @@ struct png_struct_def
png_uint_32 height; /* height of image in pixels */ png_uint_32 height; /* height of image in pixels */
png_uint_32 num_rows; /* number of rows in current pass */ png_uint_32 num_rows; /* number of rows in current pass */
png_uint_32 usr_width; /* width of row at start of write */ png_uint_32 usr_width; /* width of row at start of write */
png_size_t rowbytes; /* size of row in bytes */ size_t rowbytes; /* size of row in bytes */
png_uint_32 iwidth; /* width of current interlaced row in pixels */ png_uint_32 iwidth; /* width of current interlaced row in pixels */
png_uint_32 row_number; /* current row in interlace pass */ png_uint_32 row_number; /* current row in interlace pass */
png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */
@ -232,7 +232,7 @@ struct png_struct_def
png_bytep try_row; /* buffer to save trial row when filtering */ png_bytep try_row; /* buffer to save trial row when filtering */
png_bytep tst_row; /* buffer to save best trial row when filtering */ png_bytep tst_row; /* buffer to save best trial row when filtering */
#endif #endif
png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */
png_uint_32 idat_size; /* current IDAT size for read */ png_uint_32 idat_size; /* current IDAT size for read */
png_uint_32 crc; /* current chunk CRC value */ png_uint_32 crc; /* current chunk CRC value */
@ -249,7 +249,7 @@ struct png_struct_def
png_byte filter; /* file filter type (always 0) */ png_byte filter; /* file filter type (always 0) */
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 pass; /* current interlace pass (0 - 6) */
png_byte do_filter; /* row filter flags (see PNG_FILTER_ below ) */ png_byte do_filter; /* row filter flags (see PNG_FILTER_ in png.h ) */
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 usr_bit_depth; /* bit depth of users row: write only */ png_byte usr_bit_depth; /* bit depth of users row: write only */
@ -263,6 +263,9 @@ struct png_struct_def
/* pixel depth used for the row buffers */ /* pixel depth used for the row buffers */
png_byte transformed_pixel_depth; png_byte transformed_pixel_depth;
/* pixel depth after read/write transforms */ /* pixel depth after read/write transforms */
#if ZLIB_VERNUM >= 0x1240
png_byte zstream_start; /* at start of an input zlib stream */
#endif /* Zlib >= 1.2.4 */
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
png_uint_16 filler; /* filler bytes for pixel expansion */ png_uint_16 filler; /* filler bytes for pixel expansion */
#endif #endif
@ -304,7 +307,7 @@ struct png_struct_def
#endif #endif
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
png_color_8 shift; /* shift for significant bit tranformation */ png_color_8 shift; /* shift for significant bit transformation */
#endif #endif
#if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \
@ -325,10 +328,10 @@ struct png_struct_def
png_bytep current_buffer; /* buffer for recently used data */ png_bytep current_buffer; /* buffer for recently used data */
png_uint_32 push_length; /* size of current input chunk */ png_uint_32 push_length; /* size of current input chunk */
png_uint_32 skip_length; /* bytes to skip in input data */ png_uint_32 skip_length; /* bytes to skip in input data */
png_size_t save_buffer_size; /* amount of data now in save_buffer */ size_t save_buffer_size; /* amount of data now in save_buffer */
png_size_t save_buffer_max; /* total size of save_buffer */ size_t save_buffer_max; /* total size of save_buffer */
png_size_t buffer_size; /* total amount of available input data */ size_t buffer_size; /* total amount of available input data */
png_size_t current_buffer_size; /* amount of data now in current_buffer */ size_t current_buffer_size; /* amount of data now in current_buffer */
int process_mode; /* what push library is currently doing */ int process_mode; /* what push library is currently doing */
int cur_palette; /* current push library palette index */ int cur_palette; /* current push library palette index */
@ -350,7 +353,7 @@ struct png_struct_def
/* Options */ /* Options */
#ifdef PNG_SET_OPTION_SUPPORTED #ifdef PNG_SET_OPTION_SUPPORTED
png_byte options; /* On/off state (up to 4 options) */ png_uint_32 options; /* On/off state (up to 16 options) */
#endif #endif
#if PNG_LIBPNG_VER < 10700 #if PNG_LIBPNG_VER < 10700
@ -389,6 +392,12 @@ struct png_struct_def
/* deleted in 1.5.5: rgb_to_gray_blue_coeff; */ /* deleted in 1.5.5: rgb_to_gray_blue_coeff; */
#endif #endif
/* New member added in libpng-1.6.36 */
#if defined(PNG_READ_EXPAND_SUPPORTED) && \
defined(PNG_ARM_NEON_IMPLEMENTATION)
png_bytep riffled_palette; /* buffer for accelerated palette expansion */
#endif
/* New member added in libpng-1.0.4 (renamed in 1.0.9) */ /* New member added in libpng-1.0.4 (renamed in 1.0.9) */
#if defined(PNG_MNG_FEATURES_SUPPORTED) #if defined(PNG_MNG_FEATURES_SUPPORTED)
/* Changed from png_byte to png_uint_32 at version 1.2.0 */ /* Changed from png_byte to png_uint_32 at version 1.2.0 */
@ -448,7 +457,7 @@ struct png_struct_def
#endif #endif
/* New member added in libpng-1.2.26 */ /* New member added in libpng-1.2.26 */
png_size_t old_big_row_buf_size; size_t old_big_row_buf_size;
#ifdef PNG_READ_SUPPORTED #ifdef PNG_READ_SUPPORTED
/* New member added in libpng-1.2.30 */ /* New member added in libpng-1.2.30 */

View File

@ -1,10 +1,10 @@
/* pngtest.c - a simple test program to test libpng /* pngtest.c - a simple test program to test libpng
* *
* Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -60,12 +60,12 @@
defined PNG_READ_pHYs_SUPPORTED &&\ defined PNG_READ_pHYs_SUPPORTED &&\
defined PNG_READ_sBIT_SUPPORTED &&\ defined PNG_READ_sBIT_SUPPORTED &&\
defined PNG_READ_sCAL_SUPPORTED &&\ defined PNG_READ_sCAL_SUPPORTED &&\
defined PNG_READ_sPLT_SUPPORTED &&\
defined PNG_READ_sRGB_SUPPORTED &&\ defined PNG_READ_sRGB_SUPPORTED &&\
defined PNG_READ_sPLT_SUPPORTED &&\
defined PNG_READ_tEXt_SUPPORTED &&\ defined PNG_READ_tEXt_SUPPORTED &&\
defined PNG_READ_tIME_SUPPORTED &&\ defined PNG_READ_tIME_SUPPORTED &&\
defined PNG_READ_zTXt_SUPPORTED &&\ defined PNG_READ_zTXt_SUPPORTED &&\
defined PNG_WRITE_INTERLACING_SUPPORTED (defined PNG_WRITE_INTERLACING_SUPPORTED || PNG_LIBPNG_VER >= 10700)
#ifdef PNG_ZLIB_HEADER #ifdef PNG_ZLIB_HEADER
# include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */ # include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */
@ -102,6 +102,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
*/ */
@ -119,11 +123,28 @@ static float t_start, t_stop, t_decode, t_encode, t_misc;
#define PNG_tIME_STRING_LENGTH 29 #define PNG_tIME_STRING_LENGTH 29
static int tIME_chunk_present = 0; static int tIME_chunk_present = 0;
static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present"; static char tIME_string[PNG_tIME_STRING_LENGTH] = "tIME chunk is not present";
#if PNG_LIBPNG_VER < 10619
#define png_convert_to_rfc1123_buffer(ts, t) tIME_to_str(read_ptr, ts, t)
static int
tIME_to_str(png_structp png_ptr, png_charp ts, png_const_timep t)
{
png_const_charp str = png_convert_to_rfc1123(png_ptr, t);
if (str == NULL)
return 0;
strcpy(ts, str);
return 1;
}
#endif /* older libpng */
#endif #endif
static int verbose = 0; static int verbose = 0;
static int strict = 0; static int strict = 0;
static int relaxed = 0; static int relaxed = 0;
static int xfail = 0;
static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */ static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */
static int error_count = 0; /* count calls to png_error */ static int error_count = 0; /* count calls to png_error */
static int warning_count = 0; /* count calls to png_warning */ static int warning_count = 0; /* count calls to png_warning */
@ -186,16 +207,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
@ -326,10 +345,10 @@ count_zero_samples(png_structp png_ptr, png_row_infop row_info, png_bytep data)
#ifdef PNG_IO_STATE_SUPPORTED #ifdef PNG_IO_STATE_SUPPORTED
void void
pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, pngtest_check_io_state(png_structp png_ptr, size_t data_length,
png_uint_32 io_op); png_uint_32 io_op);
void void
pngtest_check_io_state(png_structp png_ptr, png_size_t data_length, pngtest_check_io_state(png_structp png_ptr, size_t data_length,
png_uint_32 io_op) png_uint_32 io_op)
{ {
png_uint_32 io_state = png_get_io_state(png_ptr); png_uint_32 io_state = png_get_io_state(png_ptr);
@ -367,12 +386,12 @@ pngtest_check_io_state(png_structp png_ptr, png_size_t data_length,
#endif #endif
static void PNGCBAPI static void PNGCBAPI
pngtest_read_data(png_structp png_ptr, png_bytep data, png_size_t length) pngtest_read_data(png_structp png_ptr, png_bytep data, size_t length)
{ {
png_size_t check = 0; size_t check = 0;
png_voidp io_ptr; png_voidp io_ptr;
/* fread() returns 0 on error, so it is OK to store this in a png_size_t /* fread() returns 0 on error, so it is OK to store this in a size_t
* instead of an int, which is what fread() actually returns. * instead of an int, which is what fread() actually returns.
*/ */
io_ptr = png_get_io_ptr(png_ptr); io_ptr = png_get_io_ptr(png_ptr);
@ -406,9 +425,9 @@ pngtest_flush(png_structp png_ptr)
* than changing the library. * than changing the library.
*/ */
static void PNGCBAPI static void PNGCBAPI
pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length) pngtest_write_data(png_structp png_ptr, png_bytep data, size_t length)
{ {
png_size_t check; size_t check;
check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr)); check = fwrite(data, 1, length, (png_FILE_p)png_get_io_ptr(png_ptr));
@ -430,13 +449,13 @@ pngtest_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
*/ */
typedef struct typedef struct
{ {
PNG_CONST char *file_name; const char *file_name;
} pngtest_error_parameters; } pngtest_error_parameters;
static void PNGCBAPI static void PNGCBAPI
pngtest_warning(png_structp png_ptr, png_const_charp message) pngtest_warning(png_structp png_ptr, png_const_charp message)
{ {
PNG_CONST char *name = "UNKNOWN (ERROR!)"; const char *name = "UNKNOWN (ERROR!)";
pngtest_error_parameters *test = pngtest_error_parameters *test =
(pngtest_error_parameters*)png_get_error_ptr(png_ptr); (pngtest_error_parameters*)png_get_error_ptr(png_ptr);
@ -445,7 +464,7 @@ pngtest_warning(png_structp png_ptr, png_const_charp message)
if (test != NULL && test->file_name != NULL) if (test != NULL && test->file_name != NULL)
name = test->file_name; name = test->file_name;
fprintf(STDERR, "%s: libpng warning: %s\n", name, message); fprintf(STDERR, "\n%s: libpng warning: %s\n", name, message);
} }
/* This is the default error handling function. Note that replacements for /* This is the default error handling function. Note that replacements for
@ -686,7 +705,7 @@ read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunkp chunk)
* The unknown chunk structure contains the chunk data: * The unknown chunk structure contains the chunk data:
* png_byte name[5]; * png_byte name[5];
* png_byte *data; * png_byte *data;
* png_size_t size; * size_t size;
* *
* Note that libpng has already taken care of the CRC handling. * Note that libpng has already taken care of the CRC handling.
*/ */
@ -793,7 +812,7 @@ write_chunks(png_structp write_ptr, int location)
*/ */
#ifdef PNG_TEXT_SUPPORTED #ifdef PNG_TEXT_SUPPORTED
static void static void
pngtest_check_text_support(png_const_structp png_ptr, png_textp text_ptr, pngtest_check_text_support(png_structp png_ptr, png_textp text_ptr,
int num_text) int num_text)
{ {
while (num_text > 0) while (num_text > 0)
@ -806,6 +825,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;
@ -813,6 +834,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;
@ -828,7 +850,7 @@ pngtest_check_text_support(png_const_structp png_ptr, png_textp text_ptr,
/* Test one file */ /* Test one file */
static int static int
test_one_file(PNG_CONST char *inname, PNG_CONST char *outname) test_one_file(const char *inname, const char *outname)
{ {
static png_FILE_p fpin; static png_FILE_p fpin;
static png_FILE_p fpout; /* "static" prevents setjmp corruption */ static png_FILE_p fpout; /* "static" prevents setjmp corruption */
@ -839,16 +861,19 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_structp write_ptr; png_structp write_ptr;
png_infop write_info_ptr; png_infop write_info_ptr;
png_infop write_end_info_ptr; png_infop write_end_info_ptr;
#ifdef PNG_WRITE_FILTER_SUPPORTED
int interlace_preserved = 1; int interlace_preserved = 1;
#else #endif /* WRITE_FILTER */
#else /* !WRITE */
png_structp write_ptr = NULL; png_structp write_ptr = NULL;
png_infop write_info_ptr = NULL; png_infop write_info_ptr = NULL;
png_infop write_end_info_ptr = NULL; png_infop write_end_info_ptr = NULL;
#endif #endif /* !WRITE */
png_bytep row_buf; png_bytep row_buf;
png_uint_32 y; png_uint_32 y;
png_uint_32 width, height; png_uint_32 width, height;
int num_pass = 1, pass; volatile int num_passes;
int pass;
int bit_depth, color_type; int bit_depth, color_type;
row_buf = NULL; row_buf = NULL;
@ -912,8 +937,12 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname);
png_free(read_ptr, row_buf); png_free(read_ptr, row_buf);
row_buf = NULL; row_buf = NULL;
if (verbose != 0)
fprintf(STDERR, " destroy read structs\n");
png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
#ifdef PNG_WRITE_SUPPORTED #ifdef PNG_WRITE_SUPPORTED
if (verbose != 0)
fprintf(STDERR, " destroy write structs\n");
png_destroy_info_struct(write_ptr, &write_end_info_ptr); png_destroy_info_struct(write_ptr, &write_end_info_ptr);
png_destroy_write_struct(&write_ptr, &write_info_ptr); png_destroy_write_struct(&write_ptr, &write_info_ptr);
#endif #endif
@ -928,11 +957,15 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
if (setjmp(png_jmpbuf(write_ptr))) if (setjmp(png_jmpbuf(write_ptr)))
{ {
fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname); fprintf(STDERR, "%s -> %s: libpng write error\n", inname, outname);
png_free(read_ptr, row_buf);
row_buf = NULL;
if (verbose != 0)
fprintf(STDERR, " destroying read structs\n");
png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr);
if (verbose != 0)
fprintf(STDERR, " destroying write structs\n");
png_destroy_info_struct(write_ptr, &write_end_info_ptr); png_destroy_info_struct(write_ptr, &write_end_info_ptr);
#ifdef PNG_WRITE_SUPPORTED
png_destroy_write_struct(&write_ptr, &write_info_ptr); png_destroy_write_struct(&write_ptr, &write_info_ptr);
#endif
FCLOSE(fpin); FCLOSE(fpin);
FCLOSE(fpout); FCLOSE(fpout);
return (1); return (1);
@ -940,15 +973,16 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
#endif #endif
#endif #endif
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
if (strict != 0) if (strict != 0)
{ {
/* Treat png_benign_error() as errors on read */ /* Treat png_benign_error() as errors on read */
png_set_benign_errors(read_ptr, 0); png_set_benign_errors(read_ptr, 0);
#ifdef PNG_WRITE_SUPPORTED # ifdef PNG_WRITE_SUPPORTED
/* Treat them as errors on write */ /* Treat them as errors on write */
png_set_benign_errors(write_ptr, 0); png_set_benign_errors(write_ptr, 0);
#endif # endif
/* if strict is not set, then app warnings and errors are treated as /* if strict is not set, then app warnings and errors are treated as
* warnings in release builds, but not in unstable builds; this can be * warnings in release builds, but not in unstable builds; this can be
@ -961,10 +995,20 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
/* Allow application (pngtest) errors and warnings to pass */ /* Allow application (pngtest) errors and warnings to pass */
png_set_benign_errors(read_ptr, 1); png_set_benign_errors(read_ptr, 1);
#ifdef PNG_WRITE_SUPPORTED /* Turn off CRC checking while reading */
png_set_benign_errors(write_ptr, 1); png_set_crc_action(read_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
#ifdef PNG_IGNORE_ADLER32
/* Turn off ADLER32 checking while reading */
png_set_option(read_ptr, PNG_IGNORE_ADLER32, PNG_OPTION_ON);
#endif #endif
# ifdef PNG_WRITE_SUPPORTED
png_set_benign_errors(write_ptr, 1);
# endif
} }
#endif /* BENIGN_ERRORS */
pngtest_debug("Initializing input and output streams"); pngtest_debug("Initializing input and output streams");
#ifdef PNG_STDIO_SUPPORTED #ifdef PNG_STDIO_SUPPORTED
@ -1001,14 +1045,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;
@ -1055,29 +1092,28 @@ 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_passes may not be available below if interlace support is not
/* num_pass will not be set below, set it here if the image is * provided by libpng for both read and write.
* interlaced: what happens is that write interlacing is *not* turned
* on and the partial interlaced rows are written directly.
*/ */
switch (interlace_type) switch (interlace_type)
{ {
case PNG_INTERLACE_NONE: case PNG_INTERLACE_NONE:
num_pass = 1; num_passes = 1;
break; break;
case PNG_INTERLACE_ADAM7: case PNG_INTERLACE_ADAM7:
num_pass = 7; num_passes = 7;
break; break;
default: default:
png_error(read_ptr, "invalid interlace type"); png_error(read_ptr, "invalid interlace type");
/*NOT REACHED*/ /*NOT REACHED*/
} }
#endif
}
} }
else
png_error(read_ptr, "png_get_IHDR failed");
}
#ifdef PNG_FIXED_POINT_SUPPORTED #ifdef PNG_FIXED_POINT_SUPPORTED
#ifdef PNG_cHRM_SUPPORTED #ifdef PNG_cHRM_SUPPORTED
{ {
@ -1092,7 +1128,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
} }
} }
#endif #endif
#ifdef PNG_gAMA_SUPPORTED #ifdef PNG_gAMA_SUPPORTED
{ {
png_fixed_point gamma; png_fixed_point gamma;
@ -1126,7 +1161,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
#endif #endif
#endif /* Floating point */ #endif /* Floating point */
#endif /* Fixed point */ #endif /* Fixed point */
#ifdef PNG_iCCP_SUPPORTED #ifdef PNG_iCCP_SUPPORTED
{ {
png_charp name; png_charp name;
@ -1142,7 +1176,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
} }
} }
#endif #endif
#ifdef PNG_sRGB_SUPPORTED #ifdef PNG_sRGB_SUPPORTED
{ {
int intent; int intent;
@ -1151,7 +1184,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_set_sRGB(write_ptr, write_info_ptr, intent); png_set_sRGB(write_ptr, write_info_ptr, intent);
} }
#endif #endif
{ {
png_colorp palette; png_colorp palette;
int num_palette; int num_palette;
@ -1159,7 +1191,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette) != 0) if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette) != 0)
png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette);
} }
#ifdef PNG_bKGD_SUPPORTED #ifdef PNG_bKGD_SUPPORTED
{ {
png_color_16p background; png_color_16p background;
@ -1170,7 +1201,22 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
} }
} }
#endif #endif
#ifdef PNG_READ_eXIf_SUPPORTED
{
png_bytep exif=NULL;
png_uint_32 exif_length;
if (png_get_eXIf_1(read_ptr, read_info_ptr, &exif_length, &exif) != 0)
{
if (exif_length > 1)
fprintf(STDERR," eXIf type %c%c, %lu bytes\n",exif[0],exif[1],
(unsigned long)exif_length);
# ifdef PNG_WRITE_eXIf_SUPPORTED
png_set_eXIf_1(write_ptr, write_info_ptr, exif_length, exif);
# endif
}
}
#endif
#ifdef PNG_hIST_SUPPORTED #ifdef PNG_hIST_SUPPORTED
{ {
png_uint_16p hist; png_uint_16p hist;
@ -1179,7 +1225,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_set_hIST(write_ptr, write_info_ptr, hist); png_set_hIST(write_ptr, write_info_ptr, hist);
} }
#endif #endif
#ifdef PNG_oFFs_SUPPORTED #ifdef PNG_oFFs_SUPPORTED
{ {
png_int_32 offset_x, offset_y; png_int_32 offset_x, offset_y;
@ -1192,7 +1237,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
} }
} }
#endif #endif
#ifdef PNG_pCAL_SUPPORTED #ifdef PNG_pCAL_SUPPORTED
{ {
png_charp purpose, units; png_charp purpose, units;
@ -1208,7 +1252,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
} }
} }
#endif #endif
#ifdef PNG_pHYs_SUPPORTED #ifdef PNG_pHYs_SUPPORTED
{ {
png_uint_32 res_x, res_y; png_uint_32 res_x, res_y;
@ -1219,7 +1262,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type);
} }
#endif #endif
#ifdef PNG_sBIT_SUPPORTED #ifdef PNG_sBIT_SUPPORTED
{ {
png_color_8p sig_bit; png_color_8p sig_bit;
@ -1228,7 +1270,6 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_set_sBIT(write_ptr, write_info_ptr, sig_bit); png_set_sBIT(write_ptr, write_info_ptr, sig_bit);
} }
#endif #endif
#ifdef PNG_sCAL_SUPPORTED #ifdef PNG_sCAL_SUPPORTED
#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ #if defined(PNG_FLOATING_POINT_SUPPORTED) && \
defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)
@ -1255,9 +1296,9 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
scal_height); scal_height);
} }
} }
#endif /* FIXED_POINT */ #endif
#endif /* FLOATING_POINT */ #endif
#endif /* sCAL */ #endif
#ifdef PNG_sPLT_SUPPORTED #ifdef PNG_sPLT_SUPPORTED
{ {
@ -1269,7 +1310,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries); png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries);
} }
} }
#endif /* sPLT */ #endif
#ifdef PNG_TEXT_SUPPORTED #ifdef PNG_TEXT_SUPPORTED
{ {
@ -1286,10 +1327,10 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
{ {
int i; int i;
printf("\n"); fprintf(STDERR,"\n");
for (i=0; i<num_text; i++) for (i=0; i<num_text; i++)
{ {
printf(" Text compression[%d]=%d\n", fprintf(STDERR," Text compression[%d]=%d\n",
i, text_ptr[i].compression); i, text_ptr[i].compression);
} }
} }
@ -1297,8 +1338,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); png_set_text(write_ptr, write_info_ptr, text_ptr, num_text);
} }
} }
#endif /* TEXT */ #endif
#ifdef PNG_tIME_SUPPORTED #ifdef PNG_tIME_SUPPORTED
{ {
png_timep mod_time; png_timep mod_time;
@ -1320,8 +1360,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
#endif /* TIME_RFC1123 */ #endif /* TIME_RFC1123 */
} }
} }
#endif /* tIME */ #endif
#ifdef PNG_tRNS_SUPPORTED #ifdef PNG_tRNS_SUPPORTED
{ {
png_bytep trans_alpha; png_bytep trans_alpha;
@ -1343,8 +1382,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
trans_color); trans_color);
} }
} }
#endif /* tRNS */ #endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
{ {
png_unknown_chunkp unknowns; png_unknown_chunkp unknowns;
@ -1384,6 +1422,15 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
png_write_info(write_ptr, write_info_ptr); png_write_info(write_ptr, write_info_ptr);
write_chunks(write_ptr, before_IDAT); /* after PLTE */ write_chunks(write_ptr, before_IDAT); /* after PLTE */
png_write_info(write_ptr, write_end_info_ptr);
write_chunks(write_ptr, after_IDAT); /* after IDAT */
#ifdef PNG_COMPRESSION_COMPAT
/* Test the 'compatibility' setting here, if it is available. */
png_set_compression(write_ptr, PNG_COMPRESSION_COMPAT);
#endif
#endif #endif
#ifdef SINGLE_ROWBUF_ALLOC #ifdef SINGLE_ROWBUF_ALLOC
@ -1391,25 +1438,53 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
row_buf = (png_bytep)png_malloc(read_ptr, row_buf = (png_bytep)png_malloc(read_ptr,
png_get_rowbytes(read_ptr, read_info_ptr)); png_get_rowbytes(read_ptr, read_info_ptr));
pngtest_debug1("\t0x%08lx", (unsigned long)row_buf); pngtest_debug1("\t%p", row_buf);
#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_INTERLACING_SUPPORTED) &&\
num_pass = png_set_interlace_handling(read_ptr); defined(PNG_WRITE_INTERLACING_SUPPORTED)
if (png_set_interlace_handling(write_ptr) != num_pass) /* Both must be defined for libpng to be able to handle the interlace,
png_error(write_ptr, "png_set_interlace_handling: inconsistent num_pass"); * otherwise it gets handled below by simply reading and writing the passes
#endif * directly.
*/
if (png_set_interlace_handling(read_ptr) != num_passes)
png_error(write_ptr,
"png_set_interlace_handling(read): wrong pass count ");
if (png_set_interlace_handling(write_ptr) != num_passes)
png_error(write_ptr,
"png_set_interlace_handling(write): wrong pass count ");
#else /* png_set_interlace_handling not called on either read or write */
# define calc_pass_height
#endif /* not using libpng interlace handling */
#ifdef PNGTEST_TIMING #ifdef PNGTEST_TIMING
t_stop = (float)clock(); t_stop = (float)clock();
t_misc += (t_stop - t_start); t_misc += (t_stop - t_start);
t_start = t_stop; t_start = t_stop;
#endif #endif
for (pass = 0; pass < num_pass; pass++) for (pass = 0; pass < num_passes; pass++)
{ {
# ifdef calc_pass_height
png_uint_32 pass_height;
if (num_passes == 7) /* interlaced */
{
if (PNG_PASS_COLS(width, pass) > 0)
pass_height = PNG_PASS_ROWS(height, pass);
else
pass_height = 0;
}
else /* not interlaced */
pass_height = height;
# else
# define pass_height height
# endif
pngtest_debug1("Writing row data for pass %d", pass); pngtest_debug1("Writing row data for pass %d", pass);
for (y = 0; y < height; y++) for (y = 0; y < pass_height; y++)
{ {
#ifndef SINGLE_ROWBUF_ALLOC #ifndef SINGLE_ROWBUF_ALLOC
pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y);
@ -1417,7 +1492,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
row_buf = (png_bytep)png_malloc(read_ptr, row_buf = (png_bytep)png_malloc(read_ptr,
png_get_rowbytes(read_ptr, read_info_ptr)); png_get_rowbytes(read_ptr, read_info_ptr));
pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf, pngtest_debug2("\t%p (%lu bytes)", row_buf,
(unsigned long)png_get_rowbytes(read_ptr, read_info_ptr)); (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr));
#endif /* !SINGLE_ROWBUF_ALLOC */ #endif /* !SINGLE_ROWBUF_ALLOC */
@ -1472,10 +1547,10 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
{ {
int i; int i;
printf("\n"); fprintf(STDERR,"\n");
for (i=0; i<num_text; i++) for (i=0; i<num_text; i++)
{ {
printf(" Text compression[%d]=%d\n", fprintf(STDERR," Text compression[%d]=%d\n",
i, text_ptr[i].compression); i, text_ptr[i].compression);
} }
} }
@ -1484,6 +1559,22 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
} }
} }
#endif #endif
#ifdef PNG_READ_eXIf_SUPPORTED
{
png_bytep exif=NULL;
png_uint_32 exif_length;
if (png_get_eXIf_1(read_ptr, end_info_ptr, &exif_length, &exif) != 0)
{
if (exif_length > 1)
fprintf(STDERR," eXIf type %c%c, %lu bytes\n",exif[0],exif[1],
(unsigned long)exif_length);
# ifdef PNG_WRITE_eXIf_SUPPORTED
png_set_eXIf_1(write_ptr, write_end_info_ptr, exif_length, exif);
# endif
}
}
#endif
#ifdef PNG_tIME_SUPPORTED #ifdef PNG_tIME_SUPPORTED
{ {
png_timep mod_time; png_timep mod_time;
@ -1599,7 +1690,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",
@ -1630,13 +1721,14 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
return (1); return (1);
} }
#ifdef PNG_WRITE_SUPPORTED /* else nothing was written */ #if defined (PNG_WRITE_SUPPORTED) /* else nothing was written */ &&\
defined (PNG_WRITE_FILTER_SUPPORTED)
if (interlace_preserved != 0) /* else the files will be changed */ if (interlace_preserved != 0) /* else the files will be changed */
{ {
for (;;) for (;;)
{ {
static int wrote_question = 0; static int wrote_question = 0;
png_size_t num_in, num_out; size_t num_in, num_out;
char inbuf[256], outbuf[256]; char inbuf[256], outbuf[256];
num_in = fread(inbuf, 1, sizeof inbuf, fpin); num_in = fread(inbuf, 1, sizeof inbuf, fpin);
@ -1650,7 +1742,8 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
if (wrote_question == 0 && unsupported_chunks == 0) if (wrote_question == 0 && unsupported_chunks == 0)
{ {
fprintf(STDERR, fprintf(STDERR,
" Was %s written with the same maximum IDAT chunk size (%d bytes),", " Was %s written with the same maximum IDAT"
" chunk size (%d bytes),",
inname, PNG_ZBUF_SIZE); inname, PNG_ZBUF_SIZE);
fprintf(STDERR, fprintf(STDERR,
"\n filtering heuristic (libpng default), compression"); "\n filtering heuristic (libpng default), compression");
@ -1681,7 +1774,8 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
if (wrote_question == 0 && unsupported_chunks == 0) if (wrote_question == 0 && unsupported_chunks == 0)
{ {
fprintf(STDERR, fprintf(STDERR,
" Was %s written with the same maximum IDAT chunk size (%d bytes),", " Was %s written with the same maximum"
" IDAT chunk size (%d bytes),",
inname, PNG_ZBUF_SIZE); inname, PNG_ZBUF_SIZE);
fprintf(STDERR, fprintf(STDERR,
"\n filtering heuristic (libpng default), compression"); "\n filtering heuristic (libpng default), compression");
@ -1707,7 +1801,7 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
} }
} }
} }
#endif /* WRITE */ #endif /* WRITE && WRITE_FILTER */
FCLOSE(fpin); FCLOSE(fpin);
FCLOSE(fpout); FCLOSE(fpout);
@ -1717,11 +1811,11 @@ test_one_file(PNG_CONST char *inname, PNG_CONST char *outname)
/* Input and output filenames */ /* Input and output filenames */
#ifdef RISCOS #ifdef RISCOS
static PNG_CONST char *inname = "pngtest/png"; static const char *inname = "pngtest/png";
static PNG_CONST char *outname = "pngout/png"; static const char *outname = "pngout/png";
#else #else
static PNG_CONST char *inname = "pngtest.png"; static const char *inname = "pngtest.png";
static PNG_CONST char *outname = "pngout.png"; static const char *outname = "pngout.png";
#endif #endif
int int
@ -1796,6 +1890,7 @@ main(int argc, char *argv[])
inname = argv[2]; inname = argv[2];
strict++; strict++;
relaxed = 0; relaxed = 0;
multiple=1;
} }
else if (strcmp(argv[1], "--relaxed") == 0) else if (strcmp(argv[1], "--relaxed") == 0)
@ -1805,6 +1900,17 @@ main(int argc, char *argv[])
inname = argv[2]; inname = argv[2];
strict = 0; strict = 0;
relaxed++; relaxed++;
multiple=1;
}
else if (strcmp(argv[1], "--xfail") == 0)
{
status_dots_requested = 0;
verbose = 1;
inname = argv[2];
strict = 0;
xfail++;
relaxed++;
multiple=1;
} }
else else
@ -1846,21 +1952,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);
@ -1869,11 +1966,16 @@ main(int argc, char *argv[])
#endif /* TIME_RFC1123 */ #endif /* TIME_RFC1123 */
} }
else
{
if (xfail)
fprintf(STDERR, " XFAIL\n");
else else
{ {
fprintf(STDERR, " FAIL\n"); fprintf(STDERR, " FAIL\n");
ierror += kerror; ierror += kerror;
} }
}
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
if (allocation_now != current_allocation) if (allocation_now != current_allocation)
fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
@ -1937,21 +2039,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);
@ -1969,9 +2062,14 @@ main(int argc, char *argv[])
#endif #endif
} }
if (xfail)
fprintf(STDERR, " XFAIL\n");
else
{
fprintf(STDERR, " FAIL\n"); fprintf(STDERR, " FAIL\n");
ierror += kerror; ierror += kerror;
} }
}
#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG #if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG
if (allocation_now != current_allocation) if (allocation_now != current_allocation)
fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n",
@ -2057,4 +2155,4 @@ main(void)
#endif #endif
/* Generate a compiler error if there is an old png.h in the search path. */ /* Generate a compiler error if there is an old png.h in the search path. */
typedef png_libpng_version_1_6_19 Your_png_h_is_not_version_1_6_19; typedef png_libpng_version_1_6_37 Your_png_h_is_not_version_1_6_37;

View File

@ -1,10 +1,10 @@
/* pngtrans.c - transforms the data in a row (used by both readers and writers) /* pngtrans.c - transforms the data in a row (used by both readers and writers)
* *
* Last changed in libpng 1.6.18 [July 23, 2015] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -172,7 +172,8 @@ png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
* size! * size!
*/ */
png_app_error(png_ptr, png_app_error(png_ptr,
"png_set_filler is invalid for low bit depth gray output"); "png_set_filler is invalid for"
" low bit depth gray output");
return; return;
} }
@ -268,8 +269,8 @@ png_do_invert(png_row_infop row_info, png_bytep row)
if (row_info->color_type == PNG_COLOR_TYPE_GRAY) if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
{ {
png_bytep rp = row; png_bytep rp = row;
png_size_t i; size_t i;
png_size_t istop = row_info->rowbytes; size_t istop = row_info->rowbytes;
for (i = 0; i < istop; i++) for (i = 0; i < istop; i++)
{ {
@ -282,8 +283,8 @@ png_do_invert(png_row_infop row_info, png_bytep row)
row_info->bit_depth == 8) row_info->bit_depth == 8)
{ {
png_bytep rp = row; png_bytep rp = row;
png_size_t i; size_t i;
png_size_t istop = row_info->rowbytes; size_t istop = row_info->rowbytes;
for (i = 0; i < istop; i += 2) for (i = 0; i < istop; i += 2)
{ {
@ -297,8 +298,8 @@ png_do_invert(png_row_infop row_info, png_bytep row)
row_info->bit_depth == 16) row_info->bit_depth == 16)
{ {
png_bytep rp = row; png_bytep rp = row;
png_size_t i; size_t i;
png_size_t istop = row_info->rowbytes; size_t istop = row_info->rowbytes;
for (i = 0; i < istop; i += 4) for (i = 0; i < istop; i += 4)
{ {
@ -344,7 +345,7 @@ png_do_swap(png_row_infop row_info, png_bytep row)
#endif #endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
static PNG_CONST png_byte onebppswaptable[256] = { static const png_byte onebppswaptable[256] = {
0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
@ -379,7 +380,7 @@ static PNG_CONST png_byte onebppswaptable[256] = {
0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
}; };
static PNG_CONST png_byte twobppswaptable[256] = { static const png_byte twobppswaptable[256] = {
0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0, 0x00, 0x40, 0x80, 0xC0, 0x10, 0x50, 0x90, 0xD0,
0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0,
0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4,
@ -414,7 +415,7 @@ static PNG_CONST png_byte twobppswaptable[256] = {
0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF 0x2F, 0x6F, 0xAF, 0xEF, 0x3F, 0x7F, 0xBF, 0xFF
}; };
static PNG_CONST png_byte fourbppswaptable[256] = { static const png_byte fourbppswaptable[256] = {
0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0,
0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71,
@ -513,11 +514,15 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
if (at_start != 0) /* Skip initial filler */ if (at_start != 0) /* Skip initial filler */
++sp; ++sp;
else /* Skip initial channel and, for sp, the filler */ else /* Skip initial channel and, for sp, the filler */
sp += 2, ++dp; {
sp += 2; ++dp;
}
/* For a 1 pixel wide image there is nothing to do */ /* For a 1 pixel wide image there is nothing to do */
while (sp < ep) while (sp < ep)
*dp++ = *sp, sp += 2; {
*dp++ = *sp; sp += 2;
}
row_info->pixel_depth = 8; row_info->pixel_depth = 8;
} }
@ -527,10 +532,14 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
if (at_start != 0) /* Skip initial filler */ if (at_start != 0) /* Skip initial filler */
sp += 2; sp += 2;
else /* Skip initial channel and, for sp, the filler */ else /* Skip initial channel and, for sp, the filler */
sp += 4, dp += 2; {
sp += 4; dp += 2;
}
while (sp < ep) while (sp < ep)
*dp++ = *sp++, *dp++ = *sp, sp += 3; {
*dp++ = *sp++; *dp++ = *sp; sp += 3;
}
row_info->pixel_depth = 16; row_info->pixel_depth = 16;
} }
@ -553,11 +562,15 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
if (at_start != 0) /* Skip initial filler */ if (at_start != 0) /* Skip initial filler */
++sp; ++sp;
else /* Skip initial channels and, for sp, the filler */ else /* Skip initial channels and, for sp, the filler */
sp += 4, dp += 3; {
sp += 4; dp += 3;
}
/* Note that the loop adds 3 to dp and 4 to sp each time. */ /* Note that the loop adds 3 to dp and 4 to sp each time. */
while (sp < ep) while (sp < ep)
*dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; {
*dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp; sp += 2;
}
row_info->pixel_depth = 24; row_info->pixel_depth = 24;
} }
@ -567,14 +580,16 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
if (at_start != 0) /* Skip initial filler */ if (at_start != 0) /* Skip initial filler */
sp += 2; sp += 2;
else /* Skip initial channels and, for sp, the filler */ else /* Skip initial channels and, for sp, the filler */
sp += 8, dp += 6; {
sp += 8; dp += 6;
}
while (sp < ep) while (sp < ep)
{ {
/* Copy 6 bytes, skip 2 */ /* Copy 6 bytes, skip 2 */
*dp++ = *sp++, *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
*dp++ = *sp++, *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp++;
*dp++ = *sp++, *dp++ = *sp, sp += 3; *dp++ = *sp++; *dp++ = *sp; sp += 3;
} }
row_info->pixel_depth = 48; row_info->pixel_depth = 48;
@ -594,7 +609,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
return; /* The filler channel has gone already */ return; /* The filler channel has gone already */
/* Fix the rowbytes value. */ /* Fix the rowbytes value. */
row_info->rowbytes = dp-row; row_info->rowbytes = (size_t)(dp-row);
} }
#endif #endif
@ -692,8 +707,8 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
* and this calculation is used because it avoids warnings that other * and this calculation is used because it avoids warnings that other
* forms produced on either GCC or MSVC. * forms produced on either GCC or MSVC.
*/ */
int padding = (-row_info->pixel_depth * row_info->width) & 7; int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
png_bytep rp = png_ptr->row_buf + row_info->rowbytes; png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1;
switch (row_info->bit_depth) switch (row_info->bit_depth)
{ {

View File

@ -1,10 +1,10 @@
/* pngwio.c - functions for data output /* pngwio.c - functions for data output
* *
* Last changed in libpng 1.6.15 [November 20, 2014] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2014 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2014,2016,2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -30,7 +30,7 @@
*/ */
void /* PRIVATE */ 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, 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->write_data_fn != NULL )
@ -48,9 +48,9 @@ png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length)
* than changing the library. * than changing the library.
*/ */
void PNGCBAPI void PNGCBAPI
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) png_default_write_data(png_structp png_ptr, png_bytep data, size_t length)
{ {
png_size_t check; size_t check;
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;

View File

@ -1,10 +1,10 @@
/* pngwrite.c - general routines to write a PNG file /* pngwrite.c - general routines to write a PNG file
* *
* Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 2018-2019 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -12,9 +12,9 @@
*/ */
#include "pngpriv.h" #include "pngpriv.h"
#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
# include <errno.h> # include <errno.h>
#endif #endif /* SIMPLIFIED_WRITE_STDIO */
#ifdef PNG_WRITE_SUPPORTED #ifdef PNG_WRITE_SUPPORTED
@ -237,6 +237,11 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
#endif #endif
#ifdef PNG_WRITE_eXIf_SUPPORTED
if ((info_ptr->valid & PNG_INFO_eXIf) != 0)
png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
#endif
#ifdef PNG_WRITE_hIST_SUPPORTED #ifdef PNG_WRITE_hIST_SUPPORTED
if ((info_ptr->valid & PNG_INFO_hIST) != 0) if ((info_ptr->valid & PNG_INFO_hIST) != 0)
png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
@ -432,6 +437,12 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
} }
} }
#endif #endif
#ifdef PNG_WRITE_eXIf_SUPPORTED
if ((info_ptr->valid & PNG_INFO_eXIf) != 0)
png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif);
#endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT); write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
#endif #endif
@ -458,7 +469,7 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
#ifdef PNG_CONVERT_tIME_SUPPORTED #ifdef PNG_CONVERT_tIME_SUPPORTED
void PNGAPI void PNGAPI
png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime) png_convert_from_struct_tm(png_timep ptime, const struct tm * ttime)
{ {
png_debug(1, "in png_convert_from_struct_tm"); png_debug(1, "in png_convert_from_struct_tm");
@ -666,9 +677,9 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
{ {
png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); png_uint_32 s0 = (png_uint_32)(*(rp ) << 8) | *(rp + 1);
png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); png_uint_32 s1 = (png_uint_32)(*(rp + 2) << 8) | *(rp + 3);
png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); png_uint_32 s2 = (png_uint_32)(*(rp + 4) << 8) | *(rp + 5);
png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
*(rp ) = (png_byte)(red >> 8); *(rp ) = (png_byte)(red >> 8);
@ -901,7 +912,7 @@ png_set_flush(png_structrp png_ptr, int nrows)
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); png_ptr->flush_dist = (nrows < 0 ? 0 : (png_uint_32)nrows);
} }
/* Flush the current output buffers now */ /* Flush the current output buffers now */
@ -1007,8 +1018,8 @@ png_set_filter(png_structrp png_ptr, int method, int filters)
case 5: case 5:
case 6: case 6:
case 7: png_app_error(png_ptr, "Unknown row filter for method 0"); case 7: png_app_error(png_ptr, "Unknown row filter for method 0");
FALLTHROUGH;
#endif /* WRITE_FILTER */ #endif /* WRITE_FILTER */
/* FALLTHROUGH */
case PNG_FILTER_VALUE_NONE: case PNG_FILTER_VALUE_NONE:
png_ptr->do_filter = PNG_FILTER_NONE; break; png_ptr->do_filter = PNG_FILTER_NONE; break;
@ -1452,7 +1463,6 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr,
#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
# ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
/* Initialize the write structure - general purpose utility. */ /* Initialize the write structure - general purpose utility. */
static int static int
png_image_write_init(png_imagep image) png_image_write_init(png_imagep image)
@ -1504,6 +1514,10 @@ typedef struct
png_const_voidp first_row; png_const_voidp first_row;
ptrdiff_t row_bytes; ptrdiff_t row_bytes;
png_voidp local_row; png_voidp local_row;
/* Byte count for memory writing */
png_bytep memory;
png_alloc_size_t memory_bytes; /* not used for STDIO */
png_alloc_size_t output_bytes; /* running total */
} png_image_write_control; } png_image_write_control;
/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to /* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
@ -1522,7 +1536,8 @@ png_write_image_16bit(png_voidp argument)
display->first_row); display->first_row);
png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
png_uint_16p row_end; png_uint_16p row_end;
const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
3 : 1;
int aindex = 0; int aindex = 0;
png_uint_32 y = image->height; png_uint_32 y = image->height;
@ -1536,9 +1551,9 @@ png_write_image_16bit(png_voidp argument)
++output_row; ++output_row;
} }
else else
aindex = channels; aindex = (int)channels;
# else # else
aindex = channels; aindex = (int)channels;
# endif # endif
} }
@ -1551,14 +1566,14 @@ png_write_image_16bit(png_voidp argument)
*/ */
row_end = output_row + image->width * (channels+1); row_end = output_row + image->width * (channels+1);
while (y-- > 0) for (; y > 0; --y)
{ {
png_const_uint_16p in_ptr = input_row; png_const_uint_16p in_ptr = input_row;
png_uint_16p out_ptr = output_row; png_uint_16p out_ptr = output_row;
while (out_ptr < row_end) while (out_ptr < row_end)
{ {
const png_uint_16 alpha = in_ptr[aindex]; png_uint_16 alpha = in_ptr[aindex];
png_uint_32 reciprocal = 0; png_uint_32 reciprocal = 0;
int c; int c;
@ -1572,7 +1587,7 @@ png_write_image_16bit(png_voidp argument)
if (alpha > 0 && alpha < 65535) if (alpha > 0 && alpha < 65535)
reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
c = channels; c = (int)channels;
do /* always at least one channel */ do /* always at least one channel */
{ {
png_uint_16 component = *in_ptr++; png_uint_16 component = *in_ptr++;
@ -1607,7 +1622,7 @@ png_write_image_16bit(png_voidp argument)
} }
png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
input_row += display->row_bytes/(sizeof (png_uint_16)); input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
} }
return 1; return 1;
@ -1621,7 +1636,7 @@ png_write_image_16bit(png_voidp argument)
* calculation can be done to 15 bits of accuracy; however, the output needs to * calculation can be done to 15 bits of accuracy; however, the output needs to
* be scaled in the range 0..255*65535, so include that scaling here. * be scaled in the range 0..255*65535, so include that scaling here.
*/ */
# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) # define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+((alpha)>>1))/(alpha))
static png_byte static png_byte
png_unpremultiply(png_uint_32 component, png_uint_32 alpha, png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
@ -1680,7 +1695,8 @@ png_write_image_8bit(png_voidp argument)
display->first_row); display->first_row);
png_bytep output_row = png_voidcast(png_bytep, display->local_row); png_bytep output_row = png_voidcast(png_bytep, display->local_row);
png_uint_32 y = image->height; png_uint_32 y = image->height;
const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ?
3 : 1;
if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0) if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
{ {
@ -1697,12 +1713,12 @@ png_write_image_8bit(png_voidp argument)
else else
# endif # endif
aindex = channels; aindex = (int)channels;
/* Use row_end in place of a loop counter: */ /* Use row_end in place of a loop counter: */
row_end = output_row + image->width * (channels+1); row_end = output_row + image->width * (channels+1);
while (y-- > 0) for (; y > 0; --y)
{ {
png_const_uint_16p in_ptr = input_row; png_const_uint_16p in_ptr = input_row;
png_bytep out_ptr = output_row; png_bytep out_ptr = output_row;
@ -1720,7 +1736,7 @@ png_write_image_8bit(png_voidp argument)
if (alphabyte > 0 && alphabyte < 255) if (alphabyte > 0 && alphabyte < 255)
reciprocal = UNP_RECIPROCAL(alpha); reciprocal = UNP_RECIPROCAL(alpha);
c = channels; c = (int)channels;
do /* always at least one channel */ do /* always at least one channel */
*out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
while (--c > 0); while (--c > 0);
@ -1732,7 +1748,7 @@ png_write_image_8bit(png_voidp argument)
png_write_row(png_ptr, png_voidcast(png_const_bytep, png_write_row(png_ptr, png_voidcast(png_const_bytep,
display->local_row)); display->local_row));
input_row += display->row_bytes/(sizeof (png_uint_16)); input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
} /* while y */ } /* while y */
} }
@ -1743,7 +1759,7 @@ png_write_image_8bit(png_voidp argument)
*/ */
png_bytep row_end = output_row + image->width * channels; png_bytep row_end = output_row + image->width * channels;
while (y-- > 0) for (; y > 0; --y)
{ {
png_const_uint_16p in_ptr = input_row; png_const_uint_16p in_ptr = input_row;
png_bytep out_ptr = output_row; png_bytep out_ptr = output_row;
@ -1757,7 +1773,7 @@ png_write_image_8bit(png_voidp argument)
} }
png_write_row(png_ptr, output_row); png_write_row(png_ptr, output_row);
input_row += display->row_bytes/(sizeof (png_uint_16)); input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16));
} }
} }
@ -1767,25 +1783,25 @@ png_write_image_8bit(png_voidp argument)
static void static void
png_image_set_PLTE(png_image_write_control *display) png_image_set_PLTE(png_image_write_control *display)
{ {
const png_imagep image = display->image; png_imagep image = display->image;
const void *cmap = display->colormap; const void *cmap = display->colormap;
const int entries = image->colormap_entries > 256 ? 256 : int entries = image->colormap_entries > 256 ? 256 :
(int)image->colormap_entries; (int)image->colormap_entries;
/* NOTE: the caller must check for cmap != NULL and entries != 0 */ /* NOTE: the caller must check for cmap != NULL and entries != 0 */
const png_uint_32 format = image->format; png_uint_32 format = image->format;
const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\ # if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED) defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
(format & PNG_FORMAT_FLAG_ALPHA) != 0; (format & PNG_FORMAT_FLAG_ALPHA) != 0;
# else # else
# define afirst 0 # define afirst 0
# endif # endif
# ifdef PNG_FORMAT_BGR_SUPPORTED # ifdef PNG_FORMAT_BGR_SUPPORTED
const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
# else # else
# define bgr 0 # define bgr 0
# endif # endif
@ -1806,7 +1822,7 @@ png_image_set_PLTE(png_image_write_control *display)
{ {
png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap); png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
entry += i * channels; entry += (unsigned int)i * channels;
if ((channels & 1) != 0) /* no alpha */ if ((channels & 1) != 0) /* no alpha */
{ {
@ -1862,7 +1878,7 @@ png_image_set_PLTE(png_image_write_control *display)
{ {
png_const_bytep entry = png_voidcast(png_const_bytep, cmap); png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
entry += i * channels; entry += (unsigned int)i * channels;
switch (channels) switch (channels)
{ {
@ -1870,7 +1886,7 @@ png_image_set_PLTE(png_image_write_control *display)
tRNS[i] = entry[afirst ? 0 : 3]; tRNS[i] = entry[afirst ? 0 : 3];
if (tRNS[i] < 255) if (tRNS[i] < 255)
num_trans = i+1; num_trans = i+1;
FALLTHROUGH; /* FALLTHROUGH */
case 3: case 3:
palette[i].blue = entry[afirst + (2 ^ bgr)]; palette[i].blue = entry[afirst + (2 ^ bgr)];
palette[i].green = entry[afirst + 1]; palette[i].green = entry[afirst + 1];
@ -1881,7 +1897,7 @@ png_image_set_PLTE(png_image_write_control *display)
tRNS[i] = entry[1 ^ afirst]; tRNS[i] = entry[1 ^ afirst];
if (tRNS[i] < 255) if (tRNS[i] < 255)
num_trans = i+1; num_trans = i+1;
FALLTHROUGH; /* FALLTHROUGH */
case 1: case 1:
palette[i].blue = palette[i].red = palette[i].green = palette[i].blue = palette[i].red = palette[i].green =
entry[afirst]; entry[afirst];
@ -1907,7 +1923,7 @@ png_image_set_PLTE(png_image_write_control *display)
png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS, png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
num_trans, NULL); num_trans, NULL);
image->colormap_entries = entries; image->colormap_entries = (png_uint_32)entries;
} }
static int static int
@ -1924,16 +1940,50 @@ png_image_write_main(png_voidp argument)
int colormap = (format & PNG_FORMAT_FLAG_COLORMAP); int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */ int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA); int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
int write_16bit = linear && !colormap && (display->convert_to_8bit == 0); int write_16bit = linear && (display->convert_to_8bit == 0);
# ifdef PNG_BENIGN_ERRORS_SUPPORTED # ifdef PNG_BENIGN_ERRORS_SUPPORTED
/* Make sure we error out on any bad situation */ /* Make sure we error out on any bad situation */
png_set_benign_errors(png_ptr, 0/*error*/); png_set_benign_errors(png_ptr, 0/*error*/);
# endif # endif
/* Default the 'row_stride' parameter if required. */ /* Default the 'row_stride' parameter if required, also check the row stride
* and total image size to ensure that they are within the system limits.
*/
{
unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format);
if (image->width <= 0x7fffffffU/channels) /* no overflow */
{
png_uint_32 check;
png_uint_32 png_row_stride = image->width * channels;
if (display->row_stride == 0) if (display->row_stride == 0)
display->row_stride = PNG_IMAGE_ROW_STRIDE(*image); display->row_stride = (png_int_32)/*SAFE*/png_row_stride;
if (display->row_stride < 0)
check = (png_uint_32)(-display->row_stride);
else
check = (png_uint_32)display->row_stride;
if (check >= png_row_stride)
{
/* Now check for overflow of the image buffer calculation; this
* limits the whole image size to 32 bits for API compatibility with
* the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro.
*/
if (image->height > 0xffffffffU/png_row_stride)
png_error(image->opaque->png_ptr, "memory image too large");
}
else
png_error(image->opaque->png_ptr, "supplied row stride too small");
}
else
png_error(image->opaque->png_ptr, "image row stride too large");
}
/* Set the required transforms then write the rows in the correct order. */ /* Set the required transforms then write the rows in the correct order. */
if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0) if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
@ -2002,7 +2052,7 @@ png_image_write_main(png_voidp argument)
*/ */
if (write_16bit != 0) if (write_16bit != 0)
{ {
PNG_CONST png_uint_16 le = 0x0001; png_uint_16 le = 0x0001;
if ((*(png_const_bytep) & le) != 0) if ((*(png_const_bytep) & le) != 0)
png_set_swap(png_ptr); png_set_swap(png_ptr);
@ -2099,7 +2149,7 @@ png_image_write_main(png_voidp argument)
ptrdiff_t row_bytes = display->row_bytes; ptrdiff_t row_bytes = display->row_bytes;
png_uint_32 y = image->height; png_uint_32 y = image->height;
while (y-- > 0) for (; y > 0; --y)
{ {
png_write_row(png_ptr, row); png_write_row(png_ptr, row);
row += row_bytes; row += row_bytes;
@ -2110,6 +2160,121 @@ png_image_write_main(png_voidp argument)
return 1; return 1;
} }
static void (PNGCBAPI
image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, size_t size)
{
png_image_write_control *display = png_voidcast(png_image_write_control*,
png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/);
png_alloc_size_t ob = display->output_bytes;
/* Check for overflow; this should never happen: */
if (size <= ((png_alloc_size_t)-1) - ob)
{
/* I don't think libpng ever does this, but just in case: */
if (size > 0)
{
if (display->memory_bytes >= ob+size) /* writing */
memcpy(display->memory+ob, data, size);
/* Always update the size: */
display->output_bytes = ob+size;
}
}
else
png_error(png_ptr, "png_image_write_to_memory: PNG too big");
}
static void (PNGCBAPI
image_memory_flush)(png_structp png_ptr)
{
PNG_UNUSED(png_ptr)
}
static int
png_image_write_memory(png_voidp argument)
{
png_image_write_control *display = png_voidcast(png_image_write_control*,
argument);
/* The rest of the memory-specific init and write_main in an error protected
* environment. This case needs to use callbacks for the write operations
* since libpng has no built in support for writing to memory.
*/
png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/,
image_memory_write, image_memory_flush);
return png_image_write_main(display);
}
int PNGAPI
png_image_write_to_memory(png_imagep image, void *memory,
png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit,
const void *buffer, png_int_32 row_stride, const void *colormap)
{
/* Write the image to the given buffer, or count the bytes if it is NULL */
if (image != NULL && image->version == PNG_IMAGE_VERSION)
{
if (memory_bytes != NULL && buffer != NULL)
{
/* This is to give the caller an easier error detection in the NULL
* case and guard against uninitialized variable problems:
*/
if (memory == NULL)
*memory_bytes = 0;
if (png_image_write_init(image) != 0)
{
png_image_write_control display;
int result;
memset(&display, 0, (sizeof display));
display.image = image;
display.buffer = buffer;
display.row_stride = row_stride;
display.colormap = colormap;
display.convert_to_8bit = convert_to_8bit;
display.memory = png_voidcast(png_bytep, memory);
display.memory_bytes = *memory_bytes;
display.output_bytes = 0;
result = png_safe_execute(image, png_image_write_memory, &display);
png_image_free(image);
/* write_memory returns true even if we ran out of buffer. */
if (result)
{
/* On out-of-buffer this function returns '0' but still updates
* memory_bytes:
*/
if (memory != NULL && display.output_bytes > *memory_bytes)
result = 0;
*memory_bytes = display.output_bytes;
}
return result;
}
else
return 0;
}
else
return png_image_error(image,
"png_image_write_to_memory: invalid argument");
}
else if (image != NULL)
return png_image_error(image,
"png_image_write_to_memory: incorrect PNG_IMAGE_VERSION");
else
return 0;
}
#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED
int PNGAPI int PNGAPI
png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
const void *buffer, png_int_32 row_stride, const void *colormap) const void *buffer, png_int_32 row_stride, const void *colormap)
@ -2117,7 +2282,7 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
/* Write the image to the given (FILE*). */ /* Write the image to the given (FILE*). */
if (image != NULL && image->version == PNG_IMAGE_VERSION) if (image != NULL && image->version == PNG_IMAGE_VERSION)
{ {
if (file != NULL) if (file != NULL && buffer != NULL)
{ {
if (png_image_write_init(image) != 0) if (png_image_write_init(image) != 0)
{ {
@ -2167,7 +2332,7 @@ png_image_write_to_file(png_imagep image, const char *file_name,
/* Write the image to the named file. */ /* Write the image to the named file. */
if (image != NULL && image->version == PNG_IMAGE_VERSION) if (image != NULL && image->version == PNG_IMAGE_VERSION)
{ {
if (file_name != NULL) if (file_name != NULL && buffer != NULL)
{ {
FILE *fp = fopen(file_name, "wb"); FILE *fp = fopen(file_name, "wb");
@ -2225,6 +2390,6 @@ png_image_write_to_file(png_imagep image, const char *file_name,
else else
return 0; return 0;
} }
# endif /* STDIO */ #endif /* SIMPLIFIED_WRITE_STDIO */
#endif /* SIMPLIFIED_WRITE */ #endif /* SIMPLIFIED_WRITE */
#endif /* WRITE */ #endif /* WRITE */

View File

@ -1,10 +1,10 @@
/* pngwtran.c - transforms the data in a row for PNG writers /* pngwtran.c - transforms the data in a row for PNG writers
* *
* Last changed in libpng 1.6.18 [July 23, 2015] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -177,7 +177,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
if (row_info->color_type != PNG_COLOR_TYPE_PALETTE) if (row_info->color_type != PNG_COLOR_TYPE_PALETTE)
{ {
int shift_start[4], shift_dec[4]; int shift_start[4], shift_dec[4];
int channels = 0; unsigned int channels = 0;
if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{ {
@ -212,9 +212,9 @@ png_do_shift(png_row_infop row_info, png_bytep row,
if (row_info->bit_depth < 8) if (row_info->bit_depth < 8)
{ {
png_bytep bp = row; png_bytep bp = row;
png_size_t i; size_t i;
unsigned int mask; unsigned int mask;
png_size_t row_bytes = row_info->rowbytes; size_t row_bytes = row_info->rowbytes;
if (bit_depth->gray == 1 && row_info->bit_depth == 2) if (bit_depth->gray == 1 && row_info->bit_depth == 2)
mask = 0x55; mask = 0x55;
@ -254,8 +254,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (i = 0; i < istop; i++, bp++) for (i = 0; i < istop; i++, bp++)
{ {
unsigned int c = i%channels;
const unsigned int c = i%channels;
int j; int j;
unsigned int v, out; unsigned int v, out;
@ -283,7 +282,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (bp = row, i = 0; i < istop; i++) for (bp = row, i = 0; i < istop; i++)
{ {
const unsigned int c = i%channels; unsigned int c = i%channels;
int j; int j;
unsigned int value, v; unsigned int value, v;
@ -514,7 +513,7 @@ png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
(png_ptr, /* png_ptr */ (png_ptr, /* png_ptr */
row_info, /* row_info: */ row_info, /* row_info: */
/* png_uint_32 width; width of row */ /* png_uint_32 width; width of row */
/* png_size_t rowbytes; number of bytes in row */ /* size_t rowbytes; number of bytes in row */
/* png_byte color_type; color type of pixels */ /* png_byte color_type; color type of pixels */
/* png_byte bit_depth; bit depth of samples */ /* png_byte bit_depth; bit depth of samples */
/* png_byte channels; number of channels (1-4) */ /* png_byte channels; number of channels (1-4) */

View File

@ -1,10 +1,10 @@
/* pngwutil.c - utilities to write a PNG file /* pngwutil.c - utilities to write a PNG file
* *
* Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 2018 Cosmin Truta
* Copyright (c) 1998-2015 Glenn Randers-Pehrson * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * Copyright (c) 1996-1997 Andreas Dilger
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
* *
* This code is released under the libpng license. * This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer * For conditions of distribution and use, see the disclaimer
@ -23,10 +23,10 @@
void PNGAPI void PNGAPI
png_save_uint_32(png_bytep buf, png_uint_32 i) png_save_uint_32(png_bytep buf, png_uint_32 i)
{ {
buf[0] = (png_byte)(i >> 24); buf[0] = (png_byte)((i >> 24) & 0xffU);
buf[1] = (png_byte)(i >> 16); buf[1] = (png_byte)((i >> 16) & 0xffU);
buf[2] = (png_byte)(i >> 8); buf[2] = (png_byte)((i >> 8) & 0xffU);
buf[3] = (png_byte)(i ); buf[3] = (png_byte)( i & 0xffU);
} }
/* Place a 16-bit number into a buffer in PNG byte order. /* Place a 16-bit number into a buffer in PNG byte order.
@ -36,8 +36,8 @@ png_save_uint_32(png_bytep buf, png_uint_32 i)
void PNGAPI void PNGAPI
png_save_uint_16(png_bytep buf, unsigned int i) png_save_uint_16(png_bytep buf, unsigned int i)
{ {
buf[0] = (png_byte)(i >> 8); buf[0] = (png_byte)((i >> 8) & 0xffU);
buf[1] = (png_byte)(i ); buf[1] = (png_byte)( i & 0xffU);
} }
#endif #endif
@ -59,7 +59,7 @@ png_write_sig(png_structrp png_ptr)
/* Write the rest of the 8 byte signature */ /* Write the rest of the 8 byte signature */
png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
(png_size_t)(8 - png_ptr->sig_bytes)); (size_t)(8 - png_ptr->sig_bytes));
if (png_ptr->sig_bytes < 3) if (png_ptr->sig_bytes < 3)
png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
@ -124,8 +124,7 @@ png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
* given to png_write_chunk_header(). * given to png_write_chunk_header().
*/ */
void PNGAPI void PNGAPI
png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, size_t length)
png_size_t length)
{ {
/* Write the data, and run the CRC over it */ /* Write the data, and run the CRC over it */
if (png_ptr == NULL) if (png_ptr == NULL)
@ -160,7 +159,7 @@ png_write_chunk_end(png_structrp png_ptr)
/* Write the crc in a single operation */ /* Write the crc in a single operation */
png_save_uint_32(buf, png_ptr->crc); png_save_uint_32(buf, png_ptr->crc);
png_write_data(png_ptr, buf, (png_size_t)4); png_write_data(png_ptr, buf, 4);
} }
/* Write a PNG chunk all at once. The type is an array of ASCII characters /* Write a PNG chunk all at once. The type is an array of ASCII characters
@ -174,7 +173,7 @@ png_write_chunk_end(png_structrp png_ptr)
*/ */
static void static void
png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
png_const_bytep data, png_size_t length) png_const_bytep data, size_t length)
{ {
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
@ -191,7 +190,7 @@ png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
/* This is the API that calls the internal function above. */ /* This is the API that calls the internal function above. */
void PNGAPI void PNGAPI
png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
png_const_bytep data, png_size_t length) png_const_bytep data, size_t length)
{ {
png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
length); length);
@ -408,7 +407,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
png_ptr->zstream.avail_out = 0; png_ptr->zstream.avail_out = 0;
/* Now initialize if required, setting the new parameters, otherwise just /* Now initialize if required, setting the new parameters, otherwise just
* to a simple reset to the previous parameters. * do a simple reset to the previous parameters.
*/ */
if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0) if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
ret = deflateReset(&png_ptr->zstream); ret = deflateReset(&png_ptr->zstream);
@ -665,90 +664,6 @@ png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
} }
#endif /* WRITE_COMPRESSED_TEXT */ #endif /* WRITE_COMPRESSED_TEXT */
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
* and if invalid, correct the keyword rather than discarding the entire
* chunk. The PNG 1.0 specification requires keywords 1-79 characters in
* length, forbids leading or trailing whitespace, multiple internal spaces,
* and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
*
* The 'new_key' buffer must be 80 characters in size (for the keyword plus a
* trailing '\0'). If this routine returns 0 then there was no keyword, or a
* valid one could not be generated, and the caller must png_error.
*/
static png_uint_32
png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
{
png_const_charp orig_key = key;
png_uint_32 key_len = 0;
int bad_character = 0;
int space = 1;
png_debug(1, "in png_check_keyword");
if (key == NULL)
{
*new_key = 0;
return 0;
}
while (*key && key_len < 79)
{
png_byte ch = (png_byte)*key++;
if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
*new_key++ = ch, ++key_len, space = 0;
else if (space == 0)
{
/* A space or an invalid character when one wasn't seen immediately
* before; output just a space.
*/
*new_key++ = 32, ++key_len, space = 1;
/* If the character was not a space then it is invalid. */
if (ch != 32)
bad_character = ch;
}
else if (bad_character == 0)
bad_character = ch; /* just skip it, record the first error */
}
if (key_len > 0 && space != 0) /* trailing space */
{
--key_len, --new_key;
if (bad_character == 0)
bad_character = 32;
}
/* Terminate the keyword */
*new_key = 0;
if (key_len == 0)
return 0;
#ifdef PNG_WARNINGS_SUPPORTED
/* Try to only output one warning per keyword: */
if (*key != 0) /* keyword too long */
png_warning(png_ptr, "keyword truncated");
else if (bad_character != 0)
{
PNG_WARNING_PARAMETERS(p)
png_warning_parameter(p, 1, orig_key);
png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
}
#endif /* WARNINGS */
return key_len;
}
#endif /* WRITE_TEXT || WRITE_pCAL || WRITE_iCCP || WRITE_sPLT */
/* Write the IHDR chunk, and update the png_struct with the necessary /* Write the IHDR chunk, and update the png_struct with the necessary
* information. Note that the rest of this code depends upon this * information. Note that the rest of this code depends upon this
* information being correct. * information being correct.
@ -759,6 +674,7 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
int interlace_type) int interlace_type)
{ {
png_byte buf[13]; /* Buffer to store the IHDR info */ png_byte buf[13]; /* Buffer to store the IHDR info */
int is_invalid_depth;
png_debug(1, "in png_write_IHDR"); png_debug(1, "in png_write_IHDR");
@ -784,11 +700,11 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
break; break;
case PNG_COLOR_TYPE_RGB: case PNG_COLOR_TYPE_RGB:
is_invalid_depth = (bit_depth != 8);
#ifdef PNG_WRITE_16BIT_SUPPORTED #ifdef PNG_WRITE_16BIT_SUPPORTED
if (bit_depth != 8 && bit_depth != 16) is_invalid_depth = (is_invalid_depth && bit_depth != 16);
#else
if (bit_depth != 8)
#endif #endif
if (is_invalid_depth)
png_error(png_ptr, "Invalid bit depth for RGB image"); png_error(png_ptr, "Invalid bit depth for RGB image");
png_ptr->channels = 3; png_ptr->channels = 3;
@ -810,18 +726,22 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
break; break;
case PNG_COLOR_TYPE_GRAY_ALPHA: case PNG_COLOR_TYPE_GRAY_ALPHA:
if (bit_depth != 8 && bit_depth != 16) is_invalid_depth = (bit_depth != 8);
#ifdef PNG_WRITE_16BIT_SUPPORTED
is_invalid_depth = (is_invalid_depth && bit_depth != 16);
#endif
if (is_invalid_depth)
png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
png_ptr->channels = 2; png_ptr->channels = 2;
break; break;
case PNG_COLOR_TYPE_RGB_ALPHA: case PNG_COLOR_TYPE_RGB_ALPHA:
is_invalid_depth = (bit_depth != 8);
#ifdef PNG_WRITE_16BIT_SUPPORTED #ifdef PNG_WRITE_16BIT_SUPPORTED
if (bit_depth != 8 && bit_depth != 16) is_invalid_depth = (is_invalid_depth && bit_depth != 16);
#else
if (bit_depth != 8)
#endif #endif
if (is_invalid_depth)
png_error(png_ptr, "Invalid bit depth for RGBA image"); png_error(png_ptr, "Invalid bit depth for RGBA image");
png_ptr->channels = 4; png_ptr->channels = 4;
@ -899,7 +819,7 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
buf[12] = (png_byte)interlace_type; buf[12] = (png_byte)interlace_type;
/* Write the chunk */ /* Write the chunk */
png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); png_write_complete_chunk(png_ptr, png_IHDR, buf, 13);
if ((png_ptr->do_filter) == PNG_NO_FILTERS) if ((png_ptr->do_filter) == PNG_NO_FILTERS)
{ {
@ -968,7 +888,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
buf[0] = pal_ptr->red; buf[0] = pal_ptr->red;
buf[1] = pal_ptr->green; buf[1] = pal_ptr->green;
buf[2] = pal_ptr->blue; buf[2] = pal_ptr->blue;
png_write_chunk_data(png_ptr, buf, (png_size_t)3); png_write_chunk_data(png_ptr, buf, 3);
} }
#else #else
@ -982,7 +902,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
buf[0] = pal_ptr[i].red; buf[0] = pal_ptr[i].red;
buf[1] = pal_ptr[i].green; buf[1] = pal_ptr[i].green;
buf[2] = pal_ptr[i].blue; buf[2] = pal_ptr[i].blue;
png_write_chunk_data(png_ptr, buf, (png_size_t)3); png_write_chunk_data(png_ptr, buf, 3);
} }
#endif #endif
@ -1082,6 +1002,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
optimize_cmf(data, png_image_size(png_ptr)); optimize_cmf(data, png_image_size(png_ptr));
#endif #endif
if (size > 0)
png_write_complete_chunk(png_ptr, png_IDAT, data, size); png_write_complete_chunk(png_ptr, png_IDAT, data, size);
png_ptr->mode |= PNG_HAVE_IDAT; png_ptr->mode |= PNG_HAVE_IDAT;
@ -1128,6 +1049,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
optimize_cmf(data, png_image_size(png_ptr)); optimize_cmf(data, png_image_size(png_ptr));
#endif #endif
if (size > 0)
png_write_complete_chunk(png_ptr, png_IDAT, data, size); png_write_complete_chunk(png_ptr, png_IDAT, data, size);
png_ptr->zstream.avail_out = 0; png_ptr->zstream.avail_out = 0;
png_ptr->zstream.next_out = NULL; png_ptr->zstream.next_out = NULL;
@ -1152,7 +1074,7 @@ png_write_IEND(png_structrp png_ptr)
{ {
png_debug(1, "in png_write_IEND"); png_debug(1, "in png_write_IEND");
png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); png_write_complete_chunk(png_ptr, png_IEND, NULL, 0);
png_ptr->mode |= PNG_HAVE_IEND; png_ptr->mode |= PNG_HAVE_IEND;
} }
@ -1167,7 +1089,7 @@ png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
/* file_gamma is saved in 1/100,000ths */ /* file_gamma is saved in 1/100,000ths */
png_save_uint_32(buf, (png_uint_32)file_gamma); png_save_uint_32(buf, (png_uint_32)file_gamma);
png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); png_write_complete_chunk(png_ptr, png_gAMA, buf, 4);
} }
#endif #endif
@ -1185,7 +1107,7 @@ png_write_sRGB(png_structrp png_ptr, int srgb_intent)
"Invalid sRGB rendering intent specified"); "Invalid sRGB rendering intent specified");
buf[0]=(png_byte)srgb_intent; buf[0]=(png_byte)srgb_intent;
png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); png_write_complete_chunk(png_ptr, png_sRGB, buf, 1);
} }
#endif #endif
@ -1259,8 +1181,8 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
png_uint_32 name_len; png_uint_32 name_len;
png_byte new_name[80]; png_byte new_name[80];
png_byte entrybuf[10]; png_byte entrybuf[10];
png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); size_t entry_size = (spalette->depth == 8 ? 6 : 10);
png_size_t palette_size = entry_size * spalette->nentries; size_t palette_size = entry_size * (size_t)spalette->nentries;
png_sPLT_entryp ep; png_sPLT_entryp ep;
#ifndef PNG_POINTER_INDEXING_SUPPORTED #ifndef PNG_POINTER_INDEXING_SUPPORTED
int i; int i;
@ -1277,10 +1199,9 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
png_write_chunk_header(png_ptr, png_sPLT, png_write_chunk_header(png_ptr, png_sPLT,
(png_uint_32)(name_len + 2 + palette_size)); (png_uint_32)(name_len + 2 + palette_size));
png_write_chunk_data(png_ptr, (png_bytep)new_name, png_write_chunk_data(png_ptr, (png_bytep)new_name, (size_t)(name_len + 1));
(png_size_t)(name_len + 1));
png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); png_write_chunk_data(png_ptr, &spalette->depth, 1);
/* Loop through each palette entry, writing appropriately */ /* Loop through each palette entry, writing appropriately */
#ifdef PNG_POINTER_INDEXING_SUPPORTED #ifdef PNG_POINTER_INDEXING_SUPPORTED
@ -1342,7 +1263,7 @@ void /* PRIVATE */
png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
{ {
png_byte buf[4]; png_byte buf[4];
png_size_t size; size_t size;
png_debug(1, "in png_write_sBIT"); png_debug(1, "in png_write_sBIT");
@ -1442,7 +1363,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
/* Write the chunk out as it is */ /* Write the chunk out as it is */
png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
(png_size_t)num_trans); (size_t)num_trans);
} }
else if (color_type == PNG_COLOR_TYPE_GRAY) else if (color_type == PNG_COLOR_TYPE_GRAY)
@ -1457,7 +1378,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
} }
png_save_uint_16(buf, tran->gray); png_save_uint_16(buf, tran->gray);
png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); png_write_complete_chunk(png_ptr, png_tRNS, buf, 2);
} }
else if (color_type == PNG_COLOR_TYPE_RGB) else if (color_type == PNG_COLOR_TYPE_RGB)
@ -1477,7 +1398,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
return; return;
} }
png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); png_write_complete_chunk(png_ptr, png_tRNS, buf, 6);
} }
else else
@ -1510,7 +1431,7 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
} }
buf[0] = back->index; buf[0] = back->index;
png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); png_write_complete_chunk(png_ptr, png_bKGD, buf, 1);
} }
else if ((color_type & PNG_COLOR_MASK_COLOR) != 0) else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
@ -1525,12 +1446,13 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
#endif #endif
{ {
png_warning(png_ptr, png_warning(png_ptr,
"Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); "Ignoring attempt to write 16-bit bKGD chunk "
"when bit_depth is 8");
return; return;
} }
png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); png_write_complete_chunk(png_ptr, png_bKGD, buf, 6);
} }
else else
@ -1544,11 +1466,33 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
} }
png_save_uint_16(buf, back->gray); png_save_uint_16(buf, back->gray);
png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); png_write_complete_chunk(png_ptr, png_bKGD, buf, 2);
} }
} }
#endif #endif
#ifdef PNG_WRITE_eXIf_SUPPORTED
/* Write the Exif data */
void /* PRIVATE */
png_write_eXIf(png_structrp png_ptr, png_bytep exif, int num_exif)
{
int i;
png_byte buf[1];
png_debug(1, "in png_write_eXIf");
png_write_chunk_header(png_ptr, png_eXIf, (png_uint_32)(num_exif));
for (i = 0; i < num_exif; i++)
{
buf[0] = exif[i];
png_write_chunk_data(png_ptr, buf, 1);
}
png_write_chunk_end(png_ptr);
}
#endif
#ifdef PNG_WRITE_hIST_SUPPORTED #ifdef PNG_WRITE_hIST_SUPPORTED
/* Write the histogram */ /* Write the histogram */
void /* PRIVATE */ void /* PRIVATE */
@ -1573,7 +1517,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
for (i = 0; i < num_hist; i++) for (i = 0; i < num_hist; i++)
{ {
png_save_uint_16(buf, hist[i]); png_save_uint_16(buf, hist[i]);
png_write_chunk_data(png_ptr, buf, (png_size_t)2); png_write_chunk_data(png_ptr, buf, 2);
} }
png_write_chunk_end(png_ptr); png_write_chunk_end(png_ptr);
@ -1584,7 +1528,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
/* Write a tEXt chunk */ /* Write a tEXt chunk */
void /* PRIVATE */ void /* PRIVATE */
png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
png_size_t text_len) size_t text_len)
{ {
png_uint_32 key_len; png_uint_32 key_len;
png_byte new_key[80]; png_byte new_key[80];
@ -1681,7 +1625,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
png_const_charp lang, png_const_charp lang_key, png_const_charp text) png_const_charp lang, png_const_charp lang_key, png_const_charp text)
{ {
png_uint_32 key_len, prefix_len; png_uint_32 key_len, prefix_len;
png_size_t lang_len, lang_key_len; size_t lang_len, lang_key_len;
png_byte new_key[82]; png_byte new_key[82];
compression_state comp; compression_state comp;
@ -1791,7 +1735,7 @@ png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
png_save_int_32(buf + 4, y_offset); png_save_int_32(buf + 4, y_offset);
buf[8] = (png_byte)unit_type; buf[8] = (png_byte)unit_type;
png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); png_write_complete_chunk(png_ptr, png_oFFs, buf, 9);
} }
#endif #endif
#ifdef PNG_WRITE_pCAL_SUPPORTED #ifdef PNG_WRITE_pCAL_SUPPORTED
@ -1802,7 +1746,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
png_charpp params) png_charpp params)
{ {
png_uint_32 purpose_len; png_uint_32 purpose_len;
png_size_t units_len, total_len; size_t units_len, total_len;
png_size_tp params_len; png_size_tp params_len;
png_byte buf[10]; png_byte buf[10];
png_byte new_purpose[80]; png_byte new_purpose[80];
@ -1826,7 +1770,7 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
total_len = purpose_len + units_len + 10; total_len = purpose_len + units_len + 10;
params_len = (png_size_tp)png_malloc(png_ptr, params_len = (png_size_tp)png_malloc(png_ptr,
(png_alloc_size_t)(nparams * (sizeof (png_size_t)))); (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (size_t))));
/* Find the length of each parameter, making sure we don't count the /* Find the length of each parameter, making sure we don't count the
* null terminator for the last parameter. * null terminator for the last parameter.
@ -1846,8 +1790,8 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
png_save_int_32(buf + 4, X1); png_save_int_32(buf + 4, X1);
buf[8] = (png_byte)type; buf[8] = (png_byte)type;
buf[9] = (png_byte)nparams; buf[9] = (png_byte)nparams;
png_write_chunk_data(png_ptr, buf, (png_size_t)10); png_write_chunk_data(png_ptr, buf, 10);
png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); png_write_chunk_data(png_ptr, (png_const_bytep)units, (size_t)units_len);
for (i = 0; i < nparams; i++) for (i = 0; i < nparams; i++)
{ {
@ -1866,7 +1810,7 @@ png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
png_const_charp height) png_const_charp height)
{ {
png_byte buf[64]; png_byte buf[64];
png_size_t wlen, hlen, total_len; size_t wlen, hlen, total_len;
png_debug(1, "in png_write_sCAL_s"); png_debug(1, "in png_write_sCAL_s");
@ -1907,7 +1851,7 @@ png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
png_save_uint_32(buf + 4, y_pixels_per_unit); png_save_uint_32(buf + 4, y_pixels_per_unit);
buf[8] = (png_byte)unit_type; buf[8] = (png_byte)unit_type;
png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); png_write_complete_chunk(png_ptr, png_pHYs, buf, 9);
} }
#endif #endif
@ -1937,7 +1881,7 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
buf[5] = mod_time->minute; buf[5] = mod_time->minute;
buf[6] = mod_time->second; buf[6] = mod_time->second;
png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); png_write_complete_chunk(png_ptr, png_tIME, buf, 7);
} }
#endif #endif
@ -1949,16 +1893,16 @@ png_write_start_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */ /* Start of interlace block */
static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */ /* Offset to next interlace block */
static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */ /* Start of interlace block in the y direction */
static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */ /* Offset to next interlace block in the y direction */
static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif #endif
png_alloc_size_t buf_size; png_alloc_size_t buf_size;
@ -2064,16 +2008,16 @@ png_write_finish_row(png_structrp png_ptr)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */ /* Start of interlace block */
static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */ /* Offset to next interlace block */
static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */ /* Start of interlace block in the y direction */
static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */ /* Offset to next interlace block in the y direction */
static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif #endif
png_debug(1, "in png_write_finish_row"); png_debug(1, "in png_write_finish_row");
@ -2127,8 +2071,8 @@ png_write_finish_row(png_structrp png_ptr)
{ {
if (png_ptr->prev_row != NULL) if (png_ptr->prev_row != NULL)
memset(png_ptr->prev_row, 0, memset(png_ptr->prev_row, 0,
(png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* PNG_ROWBYTES(png_ptr->usr_channels *
png_ptr->usr_bit_depth, png_ptr->width)) + 1); png_ptr->usr_bit_depth, png_ptr->width) + 1);
return; return;
} }
@ -2154,10 +2098,10 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */ /* Start of interlace block */
static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */ /* Offset to next interlace block */
static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
png_debug(1, "in png_do_write_interlace"); png_debug(1, "in png_do_write_interlace");
@ -2184,7 +2128,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
for (i = png_pass_start[pass]; i < row_width; for (i = png_pass_start[pass]; i < row_width;
i += png_pass_inc[pass]) i += png_pass_inc[pass])
{ {
sp = row + (png_size_t)(i >> 3); sp = row + (size_t)(i >> 3);
value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
d |= (value << shift); d |= (value << shift);
@ -2222,7 +2166,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
for (i = png_pass_start[pass]; i < row_width; for (i = png_pass_start[pass]; i < row_width;
i += png_pass_inc[pass]) i += png_pass_inc[pass])
{ {
sp = row + (png_size_t)(i >> 2); sp = row + (size_t)(i >> 2);
value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
d |= (value << shift); d |= (value << shift);
@ -2258,7 +2202,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
for (i = png_pass_start[pass]; i < row_width; for (i = png_pass_start[pass]; i < row_width;
i += png_pass_inc[pass]) i += png_pass_inc[pass])
{ {
sp = row + (png_size_t)(i >> 1); sp = row + (size_t)(i >> 1);
value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
d |= (value << shift); d |= (value << shift);
@ -2284,7 +2228,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
png_bytep dp; png_bytep dp;
png_uint_32 i; png_uint_32 i;
png_uint_32 row_width = row_info->width; png_uint_32 row_width = row_info->width;
png_size_t pixel_bytes; size_t pixel_bytes;
/* Start at the beginning */ /* Start at the beginning */
dp = row; dp = row;
@ -2297,7 +2241,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
i += png_pass_inc[pass]) i += png_pass_inc[pass])
{ {
/* Find out where the original pixel is */ /* Find out where the original pixel is */
sp = row + (png_size_t)i * pixel_bytes; sp = row + (size_t)i * pixel_bytes;
/* Move the pixel */ /* Move the pixel */
if (dp != sp) if (dp != sp)
@ -2328,17 +2272,17 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
*/ */
static void /* PRIVATE */ static void /* PRIVATE */
png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
png_size_t row_bytes); size_t row_bytes);
#ifdef PNG_WRITE_FILTER_SUPPORTED #ifdef PNG_WRITE_FILTER_SUPPORTED
static png_size_t /* PRIVATE */ static size_t /* PRIVATE */
png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, png_setup_sub_row(png_structrp png_ptr, png_uint_32 bpp,
const png_size_t row_bytes, const png_size_t lmins) size_t row_bytes, size_t lmins)
{ {
png_bytep rp, dp, lp; png_bytep rp, dp, lp;
png_size_t i; size_t i;
png_size_t sum = 0; size_t sum = 0;
int v; unsigned int v;
png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
@ -2346,14 +2290,22 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp,
i++, rp++, dp++) i++, rp++, dp++)
{ {
v = *dp = *rp; v = *dp = *rp;
#ifdef PNG_USE_ABS
sum += 128 - abs((int)v - 128);
#else
sum += (v < 128) ? v : 256 - v; sum += (v < 128) ? v : 256 - v;
#endif
} }
for (lp = png_ptr->row_buf + 1; i < row_bytes; for (lp = png_ptr->row_buf + 1; i < row_bytes;
i++, rp++, lp++, dp++) i++, rp++, lp++, dp++)
{ {
v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
#ifdef PNG_USE_ABS
sum += 128 - abs((int)v - 128);
#else
sum += (v < 128) ? v : 256 - v; sum += (v < 128) ? v : 256 - v;
#endif
if (sum > lmins) /* We are already worse, don't continue. */ if (sum > lmins) /* We are already worse, don't continue. */
break; break;
@ -2362,14 +2314,35 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp,
return (sum); return (sum);
} }
static png_size_t /* PRIVATE */ static void /* PRIVATE */
png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, png_setup_sub_row_only(png_structrp png_ptr, png_uint_32 bpp,
const png_size_t lmins) size_t row_bytes)
{
png_bytep rp, dp, lp;
size_t i;
png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB;
for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp;
i++, rp++, dp++)
{
*dp = *rp;
}
for (lp = png_ptr->row_buf + 1; i < row_bytes;
i++, rp++, lp++, dp++)
{
*dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
}
}
static size_t /* PRIVATE */
png_setup_up_row(png_structrp png_ptr, size_t row_bytes, size_t lmins)
{ {
png_bytep rp, dp, pp; png_bytep rp, dp, pp;
png_size_t i; size_t i;
png_size_t sum = 0; size_t sum = 0;
int v; unsigned int v;
png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
@ -2378,7 +2351,11 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes,
i++, rp++, pp++, dp++) i++, rp++, pp++, dp++)
{ {
v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
#ifdef PNG_USE_ABS
sum += 128 - abs((int)v - 128);
#else
sum += (v < 128) ? v : 256 - v; sum += (v < 128) ? v : 256 - v;
#endif
if (sum > lmins) /* We are already worse, don't continue. */ if (sum > lmins) /* We are already worse, don't continue. */
break; break;
@ -2386,15 +2363,30 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes,
return (sum); return (sum);
} }
static void /* PRIVATE */
png_setup_up_row_only(png_structrp png_ptr, size_t row_bytes)
{
png_bytep rp, dp, pp;
size_t i;
static png_size_t /* PRIVATE */ png_ptr->try_row[0] = PNG_FILTER_VALUE_UP;
png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
const png_size_t row_bytes, const png_size_t lmins) for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
pp = png_ptr->prev_row + 1; i < row_bytes;
i++, rp++, pp++, dp++)
{
*dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
}
}
static size_t /* PRIVATE */
png_setup_avg_row(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes, size_t lmins)
{ {
png_bytep rp, dp, pp, lp; png_bytep rp, dp, pp, lp;
png_uint_32 i; png_uint_32 i;
png_size_t sum = 0; size_t sum = 0;
int v; unsigned int v;
png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
@ -2403,7 +2395,11 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
{ {
v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
#ifdef PNG_USE_ABS
sum += 128 - abs((int)v - 128);
#else
sum += (v < 128) ? v : 256 - v; sum += (v < 128) ? v : 256 - v;
#endif
} }
for (lp = png_ptr->row_buf + 1; i < row_bytes; i++) for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
@ -2411,7 +2407,11 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
& 0xff); & 0xff);
#ifdef PNG_USE_ABS
sum += 128 - abs((int)v - 128);
#else
sum += (v < 128) ? v : 256 - v; sum += (v < 128) ? v : 256 - v;
#endif
if (sum > lmins) /* We are already worse, don't continue. */ if (sum > lmins) /* We are already worse, don't continue. */
break; break;
@ -2419,15 +2419,36 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp,
return (sum); return (sum);
} }
static void /* PRIVATE */
png_setup_avg_row_only(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes)
{
png_bytep rp, dp, pp, lp;
png_uint_32 i;
static png_size_t /* PRIVATE */ png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG;
png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
const png_size_t row_bytes, const png_size_t lmins) for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
pp = png_ptr->prev_row + 1; i < bpp; i++)
{
*dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
}
for (lp = png_ptr->row_buf + 1; i < row_bytes; i++)
{
*dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
& 0xff);
}
}
static size_t /* PRIVATE */
png_setup_paeth_row(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes, size_t lmins)
{ {
png_bytep rp, dp, pp, cp, lp; png_bytep rp, dp, pp, cp, lp;
png_size_t i; size_t i;
png_size_t sum = 0; size_t sum = 0;
int v; unsigned int v;
png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
@ -2436,7 +2457,11 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
{ {
v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
#ifdef PNG_USE_ABS
sum += 128 - abs((int)v - 128);
#else
sum += (v < 128) ? v : 256 - v; sum += (v < 128) ? v : 256 - v;
#endif
} }
for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
@ -2465,7 +2490,11 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
#ifdef PNG_USE_ABS
sum += 128 - abs((int)v - 128);
#else
sum += (v < 128) ? v : 256 - v; sum += (v < 128) ? v : 256 - v;
#endif
if (sum > lmins) /* We are already worse, don't continue. */ if (sum > lmins) /* We are already worse, don't continue. */
break; break;
@ -2473,6 +2502,48 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp,
return (sum); return (sum);
} }
static void /* PRIVATE */
png_setup_paeth_row_only(png_structrp png_ptr, png_uint_32 bpp,
size_t row_bytes)
{
png_bytep rp, dp, pp, cp, lp;
size_t i;
png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH;
for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1,
pp = png_ptr->prev_row + 1; i < bpp; i++)
{
*dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
}
for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes;
i++)
{
int a, b, c, pa, pb, pc, p;
b = *pp++;
c = *cp++;
a = *lp++;
p = b - c;
pc = a - c;
#ifdef PNG_USE_ABS
pa = abs(p);
pb = abs(pc);
pc = abs(p + pc);
#else
pa = p < 0 ? -p : p;
pb = pc < 0 ? -pc : pc;
pc = (p + pc) < 0 ? -(p + pc) : p + pc;
#endif
p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
*dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
}
}
#endif /* WRITE_FILTER */ #endif /* WRITE_FILTER */
void /* PRIVATE */ void /* PRIVATE */
@ -2481,12 +2552,12 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
#ifndef PNG_WRITE_FILTER_SUPPORTED #ifndef PNG_WRITE_FILTER_SUPPORTED
png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1);
#else #else
png_byte filter_to_do = png_ptr->do_filter; unsigned int filter_to_do = png_ptr->do_filter;
png_bytep row_buf; png_bytep row_buf;
png_bytep best_row; png_bytep best_row;
png_uint_32 bpp; png_uint_32 bpp;
png_size_t mins; size_t mins;
png_size_t row_bytes = row_info->rowbytes; size_t row_bytes = row_info->rowbytes;
png_debug(1, "in png_write_find_filter"); png_debug(1, "in png_write_find_filter");
@ -2527,32 +2598,33 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
*/ */
best_row = png_ptr->row_buf; best_row = png_ptr->row_buf;
if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE)
{
png_bytep rp;
png_size_t sum = 0;
png_size_t i;
int v;
if (PNG_SIZE_MAX/128 <= row_bytes) if (PNG_SIZE_MAX/128 <= row_bytes)
{ {
for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) /* Overflow can occur in the calculation, just select the lowest set
* filter.
*/
filter_to_do &= 0U-filter_to_do;
}
else if ((filter_to_do & PNG_FILTER_NONE) != 0 &&
filter_to_do != PNG_FILTER_NONE)
{ {
/* Check for overflow */ /* Overflow not possible and multiple filters in the list, including the
if (sum > PNG_SIZE_MAX/128 - 256) * 'none' filter.
break; */
png_bytep rp;
size_t sum = 0;
size_t i;
unsigned int v;
v = *rp;
sum += (v < 128) ? v : 256 - v;
}
}
else /* Overflow is not possible */
{ {
for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
{ {
v = *rp; v = *rp;
#ifdef PNG_USE_ABS
sum += 128 - abs((int)v - 128);
#else
sum += (v < 128) ? v : 256 - v; sum += (v < 128) ? v : 256 - v;
#endif
} }
} }
@ -2563,14 +2635,14 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
if (filter_to_do == PNG_FILTER_SUB) if (filter_to_do == PNG_FILTER_SUB)
/* It's the only filter so no testing is needed */ /* It's the only filter so no testing is needed */
{ {
(void) png_setup_sub_row(png_ptr, bpp, row_bytes, mins); png_setup_sub_row_only(png_ptr, bpp, row_bytes);
best_row = png_ptr->try_row; best_row = png_ptr->try_row;
} }
else if ((filter_to_do & PNG_FILTER_SUB) != 0) else if ((filter_to_do & PNG_FILTER_SUB) != 0)
{ {
png_size_t sum; size_t sum;
png_size_t lmins = mins; size_t lmins = mins;
sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins);
@ -2589,14 +2661,14 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
/* Up filter */ /* Up filter */
if (filter_to_do == PNG_FILTER_UP) if (filter_to_do == PNG_FILTER_UP)
{ {
(void) png_setup_up_row(png_ptr, row_bytes, mins); png_setup_up_row_only(png_ptr, row_bytes);
best_row = png_ptr->try_row; best_row = png_ptr->try_row;
} }
else if ((filter_to_do & PNG_FILTER_UP) != 0) else if ((filter_to_do & PNG_FILTER_UP) != 0)
{ {
png_size_t sum; size_t sum;
png_size_t lmins = mins; size_t lmins = mins;
sum = png_setup_up_row(png_ptr, row_bytes, lmins); sum = png_setup_up_row(png_ptr, row_bytes, lmins);
@ -2615,14 +2687,14 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
/* Avg filter */ /* Avg filter */
if (filter_to_do == PNG_FILTER_AVG) if (filter_to_do == PNG_FILTER_AVG)
{ {
(void) png_setup_avg_row(png_ptr, bpp, row_bytes, mins); png_setup_avg_row_only(png_ptr, bpp, row_bytes);
best_row = png_ptr->try_row; best_row = png_ptr->try_row;
} }
else if ((filter_to_do & PNG_FILTER_AVG) != 0) else if ((filter_to_do & PNG_FILTER_AVG) != 0)
{ {
png_size_t sum; size_t sum;
png_size_t lmins = mins; size_t lmins = mins;
sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins);
@ -2639,16 +2711,16 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
} }
/* Paeth filter */ /* Paeth filter */
if ((filter_to_do == PNG_FILTER_PAETH) != 0) if (filter_to_do == PNG_FILTER_PAETH)
{ {
(void) png_setup_paeth_row(png_ptr, bpp, row_bytes, mins); png_setup_paeth_row_only(png_ptr, bpp, row_bytes);
best_row = png_ptr->try_row; best_row = png_ptr->try_row;
} }
else if ((filter_to_do & PNG_FILTER_PAETH) != 0) else if ((filter_to_do & PNG_FILTER_PAETH) != 0)
{ {
png_size_t sum; size_t sum;
png_size_t lmins = mins; size_t lmins = mins;
sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins);
@ -2673,7 +2745,7 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
/* Do the actual writing of a previously filtered row. */ /* Do the actual writing of a previously filtered row. */
static void static void
png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
png_size_t full_row_length/*includes filter byte*/) size_t full_row_length/*includes filter byte*/)
{ {
png_debug(1, "in png_write_filtered_row"); png_debug(1, "in png_write_filtered_row");