diff --git a/image/decoders/nsPNGDecoder.cpp b/image/decoders/nsPNGDecoder.cpp index 78ed182d5b..00027cedc1 100644 --- a/image/decoders/nsPNGDecoder.cpp +++ b/image/decoders/nsPNGDecoder.cpp @@ -23,6 +23,24 @@ #include "SurfacePipeFactory.h" #include "mozilla/DebugOnly.h" +#ifdef PNG_APNG_SUPPORTED +# ifndef PNG_DISPOSE_OP_NONE +# define PNG_DISPOSE_OP_NONE 0 +# endif +# ifndef PNG_DISPOSE_OP_BACKGROUND +# define PNG_DISPOSE_OP_BACKGROUND 1 +# endif +# ifndef PNG_DISPOSE_OP_PREVIOUS +# define PNG_DISPOSE_OP_PREVIOUS 2 +# endif +# ifndef PNG_BLEND_OP_SOURCE +# define PNG_BLEND_OP_SOURCE 0 +# endif +# ifndef PNG_BLEND_OP_OVER +# define PNG_BLEND_OP_OVER 1 +# endif +#endif + using namespace mozilla::gfx; using std::min; diff --git a/image/encoders/png/nsPNGEncoder.cpp b/image/encoders/png/nsPNGEncoder.cpp index abe6f35b42..b1c77f3ced 100644 --- a/image/encoders/png/nsPNGEncoder.cpp +++ b/image/encoders/png/nsPNGEncoder.cpp @@ -11,6 +11,24 @@ #include "prprf.h" #include "mozilla/CheckedInt.h" +#ifdef PNG_APNG_SUPPORTED +# ifndef PNG_DISPOSE_OP_NONE +# define PNG_DISPOSE_OP_NONE 0 +# endif +# ifndef PNG_DISPOSE_OP_BACKGROUND +# define PNG_DISPOSE_OP_BACKGROUND 1 +# endif +# ifndef PNG_DISPOSE_OP_PREVIOUS +# define PNG_DISPOSE_OP_PREVIOUS 2 +# endif +# ifndef PNG_BLEND_OP_SOURCE +# define PNG_BLEND_OP_SOURCE 0 +# endif +# ifndef PNG_BLEND_OP_OVER +# define PNG_BLEND_OP_OVER 1 +# endif +#endif + using namespace mozilla; static LazyLogModule sPNGEncoderLog("PNGEncoder"); diff --git a/media/libpng/.appveyor.yml b/media/libpng/.appveyor.yml new file mode 100644 index 0000000000..b89ff62690 --- /dev/null +++ b/media/libpng/.appveyor.yml @@ -0,0 +1,83 @@ +version: 1.8.x-{build} + +branches: + except: + - /master/ + - /v[0-9]+[.][0-9]+[.][0-9]+/ + +image: + - Visual Studio 2022 + +shallow_clone: true + +environment: + matrix: + - TOOLCHAIN: vstudio + AUTOMATION: cmake + ARCH: x86 + - TOOLCHAIN: vstudio + AUTOMATION: cmake + ARCH: x64 + - TOOLCHAIN: vstudio + AUTOMATION: cmake + ARCH: arm64 + - TOOLCHAIN: llvm + AUTOMATION: cmake + ARCH: x64 + - TOOLCHAIN: msys2 + AUTOMATION: cmake + ARCH: i686 + - TOOLCHAIN: msys2 + AUTOMATION: cmake + ARCH: x86_64 + - TOOLCHAIN: msys2 + AUTOMATION: configure + ARCH: i686 + - TOOLCHAIN: msys2 + AUTOMATION: configure + ARCH: x86_64 + - TOOLCHAIN: msys2 + AUTOMATION: makefiles + ARCH: i686 + - TOOLCHAIN: msys2 + AUTOMATION: makefiles + ARCH: x86_64 + +install: + - 'if "%TOOLCHAIN%"=="vstudio" C:\tools\vcpkg\vcpkg.exe integrate install' + - 'if "%TOOLCHAIN%"=="vstudio" C:\tools\vcpkg\vcpkg.exe install zlib:%ARCH%-windows' + - 'if "%TOOLCHAIN%"=="llvm" C:\tools\vcpkg\vcpkg.exe integrate install' + - 'if "%TOOLCHAIN%"=="llvm" C:\tools\vcpkg\vcpkg.exe install zlib:%ARCH%-windows' + - 'if "%TOOLCHAIN%"=="msys2" C:\msys64\usr\bin\pacman.exe -S --noconfirm mingw-w64-%ARCH%-zlib' + - 'if "%TOOLCHAIN%"=="msys2" if "%AUTOMATION%"=="cmake" C:\msys64\usr\bin\pacman.exe -S --noconfirm mingw-w64-%ARCH%-cmake mingw-w64-%ARCH%-ninja' + - 'if "%TOOLCHAIN%"=="msys2" if "%AUTOMATION%"=="configure" C:\msys64\usr\bin\pacman.exe -S --noconfirm autoconf automake libtool' + +before_build: + - 'if "%TOOLCHAIN%"=="vstudio" set CI_CMAKE_GENERATOR=Visual Studio 17 2022' + - 'if "%TOOLCHAIN%"=="vstudio" set CI_CMAKE_TOOLCHAIN_FILE=C:\tools\vcpkg\scripts\buildsystems\vcpkg.cmake' + - 'if "%TOOLCHAIN%"=="vstudio" if "%ARCH%"=="x86" set CI_CMAKE_GENERATOR_PLATFORM=Win32' + - 'if "%TOOLCHAIN%"=="vstudio" if "%ARCH%"=="x64" set CI_CMAKE_GENERATOR_PLATFORM=x64' + - 'if "%TOOLCHAIN%"=="vstudio" if "%ARCH%"=="arm64" set CI_CMAKE_GENERATOR_PLATFORM=ARM64' + - 'if "%TOOLCHAIN%"=="vstudio" if "%ARCH%"=="arm64" set CI_CMAKE_VARS=-DPNG_TESTS=0' + - 'if "%TOOLCHAIN%"=="llvm" set CI_CMAKE_GENERATOR=Ninja' + - 'if "%TOOLCHAIN%"=="llvm" set CI_CMAKE_TOOLCHAIN_FILE=C:\tools\vcpkg\scripts\buildsystems\vcpkg.cmake' + - 'if "%TOOLCHAIN%"=="llvm" set CI_CC=clang' + - 'if "%TOOLCHAIN%"=="msys2" set CI_CMAKE_GENERATOR=Ninja' + - 'if "%TOOLCHAIN%"=="msys2" set CI_CC=gcc' + - 'if "%TOOLCHAIN%"=="msys2" if "%ARCH%"=="i686" set MSYSTEM=MINGW32' + - 'if "%TOOLCHAIN%"=="msys2" if "%ARCH%"=="x86_64" set MSYSTEM=MINGW64' + - 'set CI_CMAKE_BUILD_FLAGS=-j2' + - 'set CI_CTEST_FLAGS=-j2' + - 'set CI_MAKE_FLAGS=-j2' + - 'set CI_MAKEFILES=scripts/makefile.gcc scripts/makefile.std' + +build_script: + - 'if "%TOOLCHAIN%"=="vstudio" C:\msys64\usr\bin\bash.exe -l "%APPVEYOR_BUILD_FOLDER%\ci\ci_verify_cmake.sh"' + - 'if "%TOOLCHAIN%"=="llvm" C:\msys64\usr\bin\bash.exe -l "%APPVEYOR_BUILD_FOLDER%\ci\ci_verify_cmake.sh"' + - 'if "%TOOLCHAIN%"=="msys2" if "%AUTOMATION%"=="cmake" C:\msys64\usr\bin\bash.exe -l "%APPVEYOR_BUILD_FOLDER%\ci\ci_verify_cmake.sh"' + - 'if "%TOOLCHAIN%"=="msys2" if "%AUTOMATION%"=="configure" C:\msys64\usr\bin\bash.exe -l "%APPVEYOR_BUILD_FOLDER%\ci\ci_verify_configure.sh"' + - 'if "%TOOLCHAIN%"=="msys2" if "%AUTOMATION%"=="makefiles" C:\msys64\usr\bin\bash.exe -l "%APPVEYOR_BUILD_FOLDER%\ci\ci_verify_makefiles.sh"' + +cache: + - 'C:\tools\vcpkg\installed' + - 'C:\msys64\var\cache\pacman' diff --git a/media/libpng/.cmake-format.yaml b/media/libpng/.cmake-format.yaml new file mode 100644 index 0000000000..67c53d2db1 --- /dev/null +++ b/media/libpng/.cmake-format.yaml @@ -0,0 +1,94 @@ +# https://pypi.org/project/cmakelang +# https://github.com/cheshirekow/cmake_format + +# ---------------------- +# Options for formatting +# ---------------------- + +# How wide to allow formatted cmake files +# TODO: Reflow the CMake files to allow setting the maximum line width to 100. +line_width: 255 + +# How many spaces to tab for indent +tab_size: 2 + +# If true, lines are indented using tab characters (utf-8 0x09) instead of +# space characters (utf-8 0x20). In cases where the layout would +# require a fractional tab character, the behavior of the fractional +# indentation is governed by +use_tabchars: false + +# If is True, then the value of this variable indicates how +# fractional indentions are handled during whitespace replacement. If set to +# 'use-space', fractional indentation is left as spaces (utf-8 0x20). If set +# to `round-up` fractional indentation is replaced with a single tab character +# (utf-8 0x09) effectively shifting the column to the next tabstop +fractional_tab_policy: "use-space" + +# Enable comment markup parsing and reflow +enable_markup: false + +# ------------------- +# Options for linting +# ------------------- + +# Lint codes to disable +disabled_codes: [ + # TODO: + # Reconcile the CMake variable names with the patterns below, then + # re-enable the "invalid variable name XXX" messages. + "C0103", + + # TODO: + # Add brief COMMENT arguments to the `add_custom_target` commands. + "C0113", +] + +# Regular expression pattern describing valid function names +function_pattern: "[0-9a-z_]+" + +# Regular expression pattern describing valid macro names +macro_pattern: "[0-9A-Z_]+" + +# Regular expression pattern describing valid names for variables with global +# (cache) scope +global_var_pattern: "[A-Z][0-9A-Z_]+" + +# Regular expression pattern describing valid names for variables with global +# scope (but internal semantic) +internal_var_pattern: "_[A-Z][0-9A-Z_]+" + +# Regular expression pattern describing valid names for variables with local +# scope +local_var_pattern: "[a-z][a-z0-9_]+" + +# Regular expression pattern describing valid names for privatedirectory +# variables +private_var_pattern: "_[0-9a-z_]+" + +# Regular expression pattern describing valid names for public directory +# variables +public_var_pattern: "[A-Z][0-9A-Z_]+" + +# Regular expression pattern describing valid names for function/macro +# arguments and loop variables. +argument_var_pattern: "[a-z][a-z0-9_]+" + +# Regular expression pattern describing valid names for keywords used in +# functions or macros +keyword_pattern: "[A-Z][0-9A-Z_]+" + +# In the heuristic for C0201, how many conditionals to match within a loop in +# before considering the loop a parser +max_conditionals_custom_parser: 2 + +# Require at least this many newlines between statements; +# require no more than this many newlines between statements; +# etc. +min_statement_spacing: 1 +max_statement_spacing: 2 +max_returns: 6 +max_branches: 12 +max_arguments: 5 +max_localvars: 15 +max_statements: 50 diff --git a/media/libpng/.editorconfig b/media/libpng/.editorconfig new file mode 100644 index 0000000000..4181a3796b --- /dev/null +++ b/media/libpng/.editorconfig @@ -0,0 +1,55 @@ +# https://editorconfig.org + +root = true + +[*] +charset = utf-8 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.txt] +indent_size = unset +indent_style = space + +[*.[chS]] +indent_size = 3 +indent_style = space +max_doc_length = 80 +max_line_length = 80 + +[*.dfa] +indent_size = 3 +indent_style = space +max_doc_length = 80 +max_line_length = 80 + +[*.awk] +indent_size = 3 +indent_style = space +max_doc_length = 80 +max_line_length = 100 + +[*.cmake] +indent_size = 2 +indent_style = space +max_doc_length = 80 +max_line_length = 100 + +[*.sh] +indent_size = 4 +indent_style = space +max_doc_length = 100 +max_line_length = 100 + +[{Makefile.in,aclocal.m4,ltmain.sh}] +indent_size = unset +indent_style = unset +insert_final_newline = unset +max_doc_length = unset +max_line_length = unset +trim_trailing_whitespace = unset + +[COMMIT_EDITMSG] +indent_style = space +max_doc_length = unset +max_line_length = 72 diff --git a/media/libpng/.editorconfig-checker.json b/media/libpng/.editorconfig-checker.json new file mode 100644 index 0000000000..70eb654b5c --- /dev/null +++ b/media/libpng/.editorconfig-checker.json @@ -0,0 +1,10 @@ +{ + "Disable": { + "Charset": true, + "IndentSize": true + }, + "Exclude": [ + ".git/", + "out/" + ] +} diff --git a/media/libpng/.gitignore b/media/libpng/.gitignore new file mode 100644 index 0000000000..3d08cb3d7e --- /dev/null +++ b/media/libpng/.gitignore @@ -0,0 +1,171 @@ +# Prerequisites +*.d + +# Precompiled headers +*.gch +*.pch + +# Object files +*.slo +*.lo +*.o +*.obj + +# Linker output files +*.exp +*.ilk +*.map + +# Compiled dynamic libraries +*.dll +*.dylib +*.so +*.so.* + +# Compiled static libraries +*.a +*.la +*.lai +*.lib + +# Compiled executables +*.app/ +*.exe +a.out + +# Debug files +*.dSYM/ +*.dmp +*.idb +*.pdb +*.su +*.sym +*.tds +core +core.[0-9]* +!core/ + +# Tag files +TAGS +.TAGS +!TAGS/ +tags +.tags +!tags/ +gtags.files +GTAGS +GRTAGS +GPATH +GSYMS +cscope.files +cscope.out +cscope.*.out + +# Text editing and text processing artifacts +\#*\# +.\#* +[._]*.sw[a-p] +[._]sw[a-p] +*.bak +*.orig +*.rej +*.tmp +*~ + +# IDE files and directories +## Eclipse +.cproject/ +.project/ +.settings/ +## Embarcadero RAD Studio +*.cbproj.* +__recovery/ +## JetBrains +.idea/ +## NetBeans +nbbuild/ +nbdist/ +nbproject/ +## Visual Studio 2015 and newer +.vs/ +## Visual Studio Code +.vscode/* +!.vscode/extensions.json +!.vscode/launch.json +!.vscode/settings.json +!.vscode/tasks.json +## Xcode 9 and newer +xcuserdata/ +## (Various) +*.*cache +*.cache* +[._]*_history +.history/ +[Bb]ackup*/ +CMakeLists.txt.user* +CMakeUserPresets.json + +# Local files created or used by coding agents +*.local +*.local.* + +# Build, test and CI output directories +[._]build*/ +/[Bb]uild/ +/[Oo]ut/ +*[Dd]ebug/ +[Dd]ebug*/ +*[Rr]elease/ +[Rr]elease*/ + +# Libpng configuration and auxiliary build artifacts +*.out +*out.png +[._]deps/ +[._]libs/ +.dirstamp +/Makefile +/Makefile.in +/aclocal.m4 +/autom4te.cache/ +/compile +/config*~ +/config.guess +/config.h +/config.h.in +/config.log +/config.status +/config.sub +/configure +/depcomp +/install*~ +/install-sh +/libpng*-config +/libpng*.pc +/libpng.vers +/libtool +/ltmain.sh +/missing +/scripts/autoconf/libtool.m4 +/scripts/autoconf/lt*.m4 +/stamp-h1 +/test-driver +pnglibconf.[ch] +pnglibconf.dfn +pnglibconf.pre +pngprefix.h + +# Libpng test programs, scripts and artifacts +/test-suite.log +/tests/*.log +/tests/*.trs +/png-fix-itxt +/pngcp +/pngfix +/pnggetset +/pngimage +/pngstest +/pngtest +/pngunknown +/pngvalid +/timepng diff --git a/media/libpng/.markdownlint.yml b/media/libpng/.markdownlint.yml new file mode 100644 index 0000000000..5072a31792 --- /dev/null +++ b/media/libpng/.markdownlint.yml @@ -0,0 +1,25 @@ +# Markdownlint configuration +# See https://github.com/markdownlint/markdownlint/blob/main/docs/RULES.md + +# MD004 +ul-style: + style: sublist + +# MD007 +ul-indent: + start_indented: true + start_indent: 1 + indent: 3 + +# MD012 +no-multiple-blanks: + maximum: 2 + +# MD024 +no-duplicate-heading: false + +# MD025 +single-title: false + +# MD028 +no-blanks-blockquote: false diff --git a/media/libpng/.yamllint.yml b/media/libpng/.yamllint.yml new file mode 100644 index 0000000000..9b7af5f2c3 --- /dev/null +++ b/media/libpng/.yamllint.yml @@ -0,0 +1,7 @@ +extends: default +rules: + document-start: disable + document-end: disable + line-length: disable + truthy: + check-keys: false diff --git a/media/libpng/ANNOUNCE.md b/media/libpng/ANNOUNCE.md new file mode 100644 index 0000000000..94b9ed82e7 --- /dev/null +++ b/media/libpng/ANNOUNCE.md @@ -0,0 +1,13 @@ +libpng 1.8.0.git +================ + +This is a development version, not intended to be a public release. +It will be replaced by a public release, or by another development +version, at a later time. + +***** + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net. +Subscription is required; visit +https://lists.sourceforge.net/lists/listinfo/png-mng-implement +to subscribe. diff --git a/media/libpng/AUTHORS.md b/media/libpng/AUTHORS.md new file mode 100644 index 0000000000..291a0b73a0 --- /dev/null +++ b/media/libpng/AUTHORS.md @@ -0,0 +1,78 @@ +PNG REFERENCE LIBRARY AUTHORS +============================= + +This is the list of PNG Reference Library ("libpng") Contributing +Authors, for copyright and licensing purposes. + + * Adam Richter + * Alexander Smorkalov + * Andreas Dilger + * Chris Blume + * Cosmin Truta + * Daisuke Nishikawa + * Dave Martindale + * Eric S. Raymond + * Gilles Vollant + * Glenn Randers-Pehrson + * Greg Roelofs + * Guy Eric Schalnat + * Halil Oktay + * James Yu + * John Bowler + * Joshua Inscoe + * Kevin Bracey + * Lucas Chollet + * Maarten Bent + * Magnus Holmgren + * Mandar Sahastrabuddhe + * Manfred Schlaegl + * Mans Rullgard + * Matt Sarett + * Mike Klein + * Mohammad Seet + * Pascal Massimino + * Paul Schmidt + * Petr Simecek + * Philippe Antoine + * Qiang Zhou + * Sam Bushell + * Samuel Williams + * Simon-Pierre Cadieux + * Taegu Ha (하태구) + * Tim Wegner + * Tobias Stoeckmann + * Tom Lane + * Tom Tanner + * Vadim Barkov + * Willem van Schaik + * Yuelin Wang (王跃林) + * Zhijie Liang + * Apple Inc. + - Zixu Wang (王子旭) + * Arm Holdings + - Richard Townsend + * Google LLC + - Dan Field + - Dragoș Tiselice + - Leon Scroggins III + - Matt Sarett + - Mike Klein + - Sami Boukortt + - Wan-Teh Chang + * Loongson Technology Corporation Ltd. + - GuXiWei (顾希伟) + - JinBo (金波) + - ZhangLixia (张利霞) + * Samsung Group + - Filip Wasil + * SpacemiT Hangzhou Technology, Co. + - Liang Junzhao (梁俊钊) + +The build projects, the build scripts, the test scripts, and other +files in the "projects", "scripts" and "tests" directories, have +other copyright owners, but are released under the libpng license. + +Some files in the "ci" and "contrib" directories, as well as some +of the tools-generated files that are distributed with libpng, have +other copyright owners, and are released under other open source +licenses. diff --git a/media/libpng/CHANGES b/media/libpng/CHANGES index 9dd82b4345..60c262fc4e 100644 --- a/media/libpng/CHANGES +++ b/media/libpng/CHANGES @@ -1,4 +1,3 @@ -#if 0 CHANGES - changes for libpng version 0.1 [March 29, 1995] @@ -205,7 +204,7 @@ Version 0.97 [January, 1998] Added simple sRGB support (Glenn R-P) Easier conditional compiling, e.g., define PNG_READ/WRITE_NOT_FULLY_SUPPORTED; - all configurable options can be selected from command-line instead + all configurable options can be selected from command line instead of having to edit pngconf.h (Glenn R-P) Fixed memory leak in pngwrite.c (free info_ptr->text) (Glenn R-P) Added more conditions for png_do_background, to avoid changing @@ -833,7 +832,7 @@ Version 1.0.7beta11 [May 7, 2000] Removed the new PNG_CREATED_READ_STRUCT and PNG_CREATED_WRITE_STRUCT modes which are no longer used. Eliminated the three new members of png_text when PNG_LEGACY_SUPPORTED is - defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXT_SUPPORTED + defined or when neither PNG_READ_iTXt_SUPPORTED nor PNG_WRITE_iTXt_SUPPORTED is defined. Made PNG_NO_READ|WRITE_iTXt the default setting, to avoid memory overrun when old applications fill the info_ptr->text structure directly. @@ -943,7 +942,7 @@ Version 1.0.8 [July 24, 2000] Version 1.0.9beta1 [November 10, 2000] Fixed typo in scripts/makefile.hpux Updated makevms.com in scripts and contrib/* and contrib/* (Martin Zinser) - Fixed seqence-point bug in contrib/pngminus/png2pnm (Martin Zinser) + Fixed sequence-point bug in contrib/pngminus/png2pnm (Martin Zinser) Changed "cdrom.com" in documentation to "libpng.org" Revised pnggccrd.c to get it all working, and updated makefile.gcmmx (Greg). Changed type of "params" from voidp to png_voidp in png_read|write_png(). @@ -1454,7 +1453,7 @@ Version 1.2.6beta4 [July 28, 2004] sequential read support. Added some "#if PNG_WRITE_SUPPORTED" blocks. Added #ifdef to remove some redundancy in png_malloc_default(). - Use png_malloc instead of png_zalloc to allocate the pallete. + Use png_malloc instead of png_zalloc to allocate the palette. Version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] Fixed buffer overflow vulnerability (CVE-2004-0597) in png_handle_tRNS(). @@ -2296,7 +2295,7 @@ Version 1.4.0beta58 [May 14, 2009] Clarified usage of sig_bit versus sig_bit_p in example.c (Vincent Torri) Version 1.4.0beta59 [May 15, 2009] - Reformated sources in libpng style (3-space intentation, comment format) + Reformatted sources in libpng style (3-space indentation, comment format) Fixed typo in libpng docs (PNG_FILTER_AVE should be PNG_FILTER_AVG) Added sections about the git repository and our coding style to the documentation @@ -2662,7 +2661,7 @@ Version 1.4.1beta06 [January 28, 2010] Version 1.4.1beta07 [February 6, 2010] Folded some long lines in the source files. - Added defineable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, + Added definable PNG_USER_CHUNK_CACHE_MAX, PNG_USER_CHUNK_MALLOC_MAX, and a PNG_USER_LIMITS_SUPPORTED flag. Eliminated use of png_ptr->irowbytes and reused the slot in png_ptr as png_ptr->png_user_chunk_malloc_max. @@ -3259,7 +3258,7 @@ Version 1.5.2beta01 [February 13, 2011] Revised PNG_EXPORTA macro to not use an empty parameter, to accommodate the old VisualC++ preprocessor. Turned on interlace handling in png_read_png(). - Fixed gcc pendantic warnings. + Fixed gcc pedantic warnings. Handle longjmp in Cygwin. Fixed png_get_current_row_number() in the interlaced case. Cleaned up ALPHA flags and transformations. @@ -3359,7 +3358,7 @@ Version 1.5.3beta05 [May 6, 2011] Pass "" instead of '\0' to png_default_error() in png_err(). This mistake was introduced in libpng-1.2.20beta01. This fixes CVE-2011-2691. Added PNG_WRITE_OPTIMIZE_CMF_SUPPORTED macro to make the zlib "CMF" byte - optimization configureable. + optimization configurable. IDAT compression failed if preceded by a compressed text chunk (bug introduced in libpng-1.5.3beta01-02). This was because the attempt to reset the zlib stream in png_write_IDAT happened after the first IDAT @@ -3643,7 +3642,7 @@ Version 1.5.6beta05 [October 12, 2011] Fixed bug in png_write_chunk_header() debug print, introduced in 1.5.6beta01. Version 1.5.6beta06 [October 17, 2011] - Removed two redundant tests for unitialized row. + Removed two redundant tests for uninitialized row. Fixed a relatively harmless memory overwrite in compressed text writing with a 1 byte zlib buffer. Add ability to call png_read_update_info multiple times to pngvalid.c. @@ -3689,7 +3688,7 @@ Version 1.5.7beta01 [November 4, 2011] crash. The pngmem.c implementation of png_malloc() included a cast to png_size_t which would fail on large allocations on 16-bit systems. Fix for the preprocessor of the Intel C compiler. The preprocessor - splits adjacent @ signs with a space; this changes the concatentation + splits adjacent @ signs with a space; this changes the concatenation token from @-@-@ to PNG_JOIN; that should work with all compiler preprocessors. Paeth filter speed improvements from work by Siarhei Siamashka. This @@ -3735,7 +3734,7 @@ Version 1.5.7beta03 [November 17, 2011] gray (on palette) itself. Fixes for C++ compilation using g++ When libpng source is compiled using g++. The compiler imposes C++ rules on the C source; thus it - is desireable to make the source work with either C or C++ rules + is desirable to make the source work with either C or C++ rules without throwing away useful error information. This change adds png_voidcast to allow C semantic (void*) cases or the corresponding C++ static_cast operation, as appropriate. @@ -3887,7 +3886,7 @@ Version 1.6.0beta06 [January 24, 2012] Version 1.6.0beta07 [January 28, 2012] Eliminated Intel icc/icl compiler warnings. The Intel (GCC derived) compiler issues slightly different warnings from those issued by the - current vesions of GCC. This eliminates those warnings by + current versions of GCC. This eliminates those warnings by adding/removing casts and small code rewrites. Updated configure.ac from autoupdate: added --enable-werror option. Also some layout regularization and removal of introduced tab characters @@ -3920,7 +3919,7 @@ Version 1.6.0beta08 [February 1, 2012] version checking to configure.ac Improved pngstest speed by not doing redundant tests and add const to the background parameter of png_image_finish_read. The --background - option is now done automagically only when required, so that commandline + option is now done automagically only when required, so that command-line option no longer exists. Cleaned up pngpriv.h to consistently declare all functions and data. Also eliminated PNG_CONST_DATA, which is apparently not needed but we @@ -4053,7 +4052,7 @@ Version 1.6.0beta16 [March 6, 2012] (in fact this is harmless, but the PNG data produced may be sub-optimal). Version 1.6.0beta17 [March 10, 2012] - Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition. + Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition. Reject all iCCP chunks after the first, even if the first one is invalid. Deflate/inflate was reworked to move common zlib calls into single functions [rw]util.c. A new shared keyword check routine was also added @@ -4061,7 +4060,7 @@ Version 1.6.0beta17 [March 10, 2012] possible to call png_inflate() incrementally. A warning is no longer issued if the language tag or translated keyword in the iTXt chunk has zero length. - If benign errors are disabled use maximum window on ancilliary inflate. + If benign errors are disabled use maximum window on ancillary inflate. This works round a bug introduced in 1.5.4 where compressed ancillary chunks could end up with a too-small windowBits value in the deflate header. @@ -4176,7 +4175,7 @@ Version 1.6.0beta27 [August 11, 2012] declared even though the functions are never actually defined. This change provides a dummy definition so that the declarations work, yet any implementation will fail to compile because of an incomplete type. - Re-eliminated the use of strcpy() in pngtest.c. An unncessary use of + Re-eliminated the use of strcpy() in pngtest.c. An unnecessary use of strcpy() was accidentally re-introduced in libpng16; this change replaces it with strncpy(). Eliminated use of png_sizeof(); use sizeof() instead. @@ -4309,7 +4308,7 @@ Version 1.6.0beta31 [November 1, 2012] resulting in VS2010 having to update the files. Removed non-working ICC profile support code that was mostly added to libpng-1.6.0beta29 and beta30. There was too much code for too little - gain; implementing full ICC color correction may be desireable but is left + gain; implementing full ICC color correction may be desirable but is left up to applications. Version 1.6.0beta32 [November 25, 2012] @@ -4592,7 +4591,7 @@ Version 1.6.3beta07 [June 8, 2013] the optimizations ('check' vs 'api') are exposed in the public header files except that the new setting PNG_ARM_NEON_OPT documents how libpng makes the decision about whether or not to use the optimizations. - Protect symbol prefixing against CC/CPPFLAGS/CFLAGS useage. + Protect symbol prefixing against CC/CPPFLAGS/CFLAGS usage. Previous iOS/Xcode fixes for the ARM NEON optimizations moved the test on __ARM_NEON__ from configure time to compile time. This breaks symbol prefixing because the definition of the special png_init_filter_functions @@ -4963,7 +4962,7 @@ Version 1.6.13beta01 [July 4, 2014] Changed "if defined(__ARM_NEON__)" to "if (defined(__ARM_NEON__) || defined(__ARM_NEON))" (James Wu). Fixed clang no-warning builds: png_digit was defined but never used. - + Version 1.6.13beta02 [July 21, 2014] Fixed an incorrect separator ("/" should be "\") in scripts/makefile.vcwin32 (bug report from Wolfgang S. Kechel). Bug was introduced in libpng-1.6.11. @@ -5454,7 +5453,7 @@ Version 1.6.21beta01 [December 11, 2015] Version 1.6.21beta02 [December 14, 2015] Moved png_check_keyword() from pngwutil.c to pngset.c Removed LE/BE dependencies in pngvalid, to 'fix' the current problem - in the BigEndian tests by not testing it, making the BE code the same + in the BigEndian tests by not testing it, making the BE code the same as the LE version. Fixes to pngvalid for various reduced build configurations (eliminate unused statics) and a fix for the case in rgb_to_gray when the digitize option @@ -5518,7 +5517,7 @@ Version 1.6.22beta03 [March 9, 2016] Added a common-law trademark notice and export control information to the LICENSE file, png.h, and the man page. Restored "& 0xff" in png_save_uint_16() and png_save_uint_32() that - were accidentally removed from libpng-1.6.17. + were accidentally removed from libpng-1.6.17. Changed PNG_INFO_cHNK and PNG_FREE_cHNK from 0xnnnn to 0xnnnnU in png.h (Robert C. Seacord). Removed dubious "#if INT_MAX" test from png.h that was added to @@ -5635,7 +5634,7 @@ Version 1.6.24beta02 [June 23, 2016] to All and adds a list of the warnings that need to be turned off. This is semi-documentary; the intent is to tell libpng users which warnings have been examined and judged non-fixable at present. The warning about - structure padding is fixable, but it would be a signficant change (moving + structure padding is fixable, but it would be a significant change (moving structure members around). Version 1.6.24beta03 [July 4, 2016] @@ -5754,11 +5753,641 @@ Version 1.6.26 [October 20, 2016] Cosmetic change, "ptr != 0" to "ptr != NULL" in png.c and pngrutil.c Despammed email addresses (replaced "@" with " at "). -Send comments/corrections/commendations to png-mng-implement at lists.sf.net -(subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) -or to glennrp at users.sourceforge.net +Version 1.6.27beta01 [November 2, 2016] + Restrict the new ADLER32-skipping to IDAT chunks. It broke iCCP chunk + handling: an erroneous iCCP chunk would throw a png_error and reject the + entire PNG image instead of rejecting just the iCCP chunk with a warning, + if built with zlib-1.2.8.1. + +Version 1.6.27rc01 [December 27, 2016] + Control ADLER32 checking with new PNG_IGNORE_ADLER32 option. Fixes + an endless loop when handling erroneous ADLER32 checksums; bug + introduced in libpng-1.6.26. + Removed the use of a macro containing the pre-processor 'defined' + operator. It is unclear whether this is valid; a macro that + "generates" 'defined' is not permitted, but the use of the word + "generates" within the C90 standard seems to imply more than simple + substitution of an expression itself containing a well-formed defined + operation. + Added ARM support to CMakeLists.txt (Andreas Franek). + +Version 1.6.27 [December 29, 2016] + Fixed a potential null pointer dereference in png_set_text_2() (bug report + and patch by Patrick Keshishian, CVE-2016-10087). + +Version 1.6.28rc01 [January 3, 2017] + Fixed arm/aarch64 detection in CMakeLists.txt (Gianfranco Costamagna). + Added option to Cmake build allowing a custom location of zlib to be + specified in a scenario where libpng is being built as a subproject + alongside zlib by another project (Sam Serrels). + Changed png_ptr->options from a png_byte to png_uint_32, to accommodate + up to 16 options. + +Version 1.6.28rc02 [January 4, 2017] + Added "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna). + Moved SSE2 optimization code into the main libpng source directory. + Configure libpng with "configure --enable-intel-sse" or compile + libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it. + +Version 1.6.28rc03 [January 4, 2017] + Backed out the SSE optimization and last CMakeLists.txt to allow time for QA. + +Version 1.6.28 [January 5, 2017] + No changes. + +Version 1.6.29beta01 [January 12, 2017] + Readded "include(GNUInstallDirs)" to CMakeLists.txt (Gianfranco Costamagna). + Moved SSE2 optimization code into the main libpng source directory. + Configure libpng with "configure --enable-intel-sse" or compile + libpng with "-DPNG_INTEL_SSE" in CPPFLAGS to enable it. + Simplified conditional compilation in pngvalid.c, for AIX (Michael Felt). + +Version 1.6.29beta02 [February 22, 2017] + Avoid conditional directives that break statements in pngrutil.c (Romero + Malaquias) + The contrib/examples/pngtopng.c recovery code was in the wrong "if" + branches; the comments were correct. + Added code for PowerPC VSX optimisation (Vadim Barkov). + +Version 1.6.29beta03 [March 1, 2017] + Avoid potential overflow of shift operations in png_do_expand() (Aaron Boxer). + Change test ZLIB_VERNUM >= 0x1281 to ZLIB_VERNUM >= 0x1290 in pngrutil.c + because Solaris 11 distributes zlib-1.2.8.f that is older than 1.2.8.1, + as suggested in zlib FAQ, item 24. + Suppress clang warnings about implicit sign changes in png.c + +Version 1.6.29 [March 16, 2017] + No changes. + +Version 1.6.30beta01 [April 1, 2017] + Added missing "$(CPPFLAGS)" to the compile line for c.pic.o in + makefile.linux and makefile.solaris-x86 (Cosmin). + Revised documentation of png_get_error_ptr() in the libpng manual. + Silence clang -Wcomma and const drop warnings (Viktor Szakats). + Update Sourceforge URLs in documentation (https instead of http). + +Version 1.6.30beta02 [April 22, 2017] + Document need to check for integer overflow when allocating a pixel + buffer for multiple rows in contrib/gregbook, contrib/pngminus, + example.c, and in the manual (suggested by Jaeseung Choi). This + is similar to the bug reported against pngquant in CVE-2016-5735. + Removed reference to the obsolete PNG_SAFE_LIMITS macro in the documentation. + +Version 1.6.30beta03 [May 22, 2017] + Check for integer overflow in contrib/visupng and contrib/tools/genpng. + Do not double evaluate CMAKE_SYSTEM_PROCESSOR in CMakeLists.txt. + Test CMAKE_HOST_WIN32 instead of WIN32 in CMakeLists.txt. + Fix some URL in documentation. + +Version 1.6.30beta04 [June 7, 2017] + Avoid writing an empty IDAT when the last IDAT exactly fills the + compression buffer (bug report by Brian Baird). This bug was + introduced in libpng-1.6.0. + +Version 1.6.30rc01 [June 14, 2017] + No changes. + +Version 1.6.30rc02 [June 25, 2017] + Update copyright year in pnglibconf.h, make ltmain.sh executable. + Add a reference to the libpng.download site in README. + +Version 1.6.30 [June 28, 2017] + No changes. + +Version 1.6.31beta01 [July 5, 2017] + Guard the definition of _POSIX_SOURCE in pngpriv.h (AIX already defines it; + bug report by Michael Felt). + Revised pngpriv.h to work around failure to compile arm/filter_neon.S + ("typedef" directive is unrecognized by the assembler). The problem + was introduced in libpng-1.6.30beta01. + Added "Requires: zlib" to libpng.pc.in (Pieter Neerincx). + Added special case for FreeBSD in arm/filter_neon.S (Maya Rashish). + +Version 1.6.31beta02 [July 8, 2017] + Added instructions for disabling hardware optimizations in INSTALL. + Added "--enable-hardware-optimizations" configuration flag to enable + or disable all hardware optimizations with one flag. + +Version 1.6.31beta03 [July 9, 2017] + Updated CMakeLists.txt to add INTEL_SSE and MIPS_MSA platforms. + Changed "int" to "png_size_t" in intel/filter_sse2.c to prevent + possible integer overflow (Bug report by John Bowler). + Quieted "declaration after statement" warnings in intel/filter_sse2.c. + Added scripts/makefile-linux-opt, which has hardware optimizations enabled. + +Version 1.6.31beta04 [July 11, 2017] + Removed one of the GCC-7.1.0 'strict-overflow' warnings that result when + integers appear on both sides of a compare. Worked around the others by + forcing the strict-overflow setting in the relevant functions to a level + where they are not reported (John Bowler). + Changed "FALL THROUGH" comments to "FALLTHROUGH" because GCC doesn't like + the space. + Worked around some C-style casts from (void*) because g++ 5.4.0 objects + to them. + Increased the buffer size for 'sprint' to pass the gcc 7.1.0 'sprint + overflow' check that is on by default with -Wall -Wextra. + +Version 1.6.31beta05 [July 13, 2017] + Added eXIf chunk support. + +Version 1.6.31beta06 [July 17, 2017] + Added a minimal eXIf chunk (with Orientation and FocalLengthIn35mmFilm + tags) to pngtest.png. + +Version 1.6.31beta07 [July 18, 2017] + Revised the eXIf chunk in pngtest.png to fix "Bad IFD1 Directory" warning. + +Version 1.6.31rc01 [July 19, 2017] + No changes. + +Version 1.6.31rc02 [July 25, 2017] + Fixed typo in example.c (png_free_image should be png_image_free) (Bug + report by John Smith) + +Version 1.6.31 [July 27, 2017] + No changes. + +Version 1.6.32beta01 [July 31, 2017] + Avoid possible NULL dereference in png_handle_eXIf when benign_errors + are allowed. Avoid leaking the input buffer "eXIf_buf". + Eliminated png_ptr->num_exif member from pngstruct.h and added num_exif + to arguments for png_get_eXIf() and png_set_eXIf(). + Added calls to png_handle_eXIf(() in pngread.c and png_write_eXIf() in + pngwrite.c, and made various other fixes to png_write_eXIf(). + Changed name of png_get_eXIF and png_set_eXIf() to png_get_eXIf_1() and + png_set_eXIf_1(), respectively, to avoid breaking API compatibility + with libpng-1.6.31. + +Version 1.6.32beta02 [August 1, 2017] + Updated contrib/libtests/pngunknown.c with eXIf chunk. + +Version 1.6.32beta03 [August 2, 2017] + Initialized btoa[] in pngstest.c + Stop memory leak when returning from png_handle_eXIf() with an error + (Bug report from the OSS-fuzz project). + +Version 1.6.32beta04 [August 2, 2017] + Replaced local eXIf_buf with info_ptr->eXIf_buf in png_handle_eXIf(). + Update libpng.3 and libpng-manual.txt about eXIf functions. + +Version 1.6.32beta05 [August 2, 2017] + Restored png_get_eXIf() and png_set_eXIf() to maintain API compatibility. + +Version 1.6.32beta06 [August 2, 2017] + Removed png_get_eXIf_1() and png_set_eXIf_1(). + +Version 1.6.32beta07 [August 3, 2017] + Check length of all chunks except IDAT against user limit to fix an + OSS-fuzz issue (Fixes CVE-2017-12652). + +Version 1.6.32beta08 [August 3, 2017] + Check length of IDAT against maximum possible IDAT size, accounting + for height, rowbytes, interlacing and zlib/deflate overhead. + Restored png_get_eXIf_1() and png_set_eXIf_1(), because strlen(eXIf_buf) + does not work (the eXIf chunk data can contain zeroes). + +Version 1.6.32beta09 [August 3, 2017] + Require cmake-2.8.8 in CMakeLists.txt. Revised symlink creation, + no longer using deprecated cmake LOCATION feature (Clifford Yapp). + Fixed five-byte error in the calculation of IDAT maximum possible size. + +Version 1.6.32beta10 [August 5, 2017] + Moved chunk-length check into a png_check_chunk_length() private + function (Suggested by Max Stepin). + Moved bad pngs from tests to contrib/libtests/crashers + Moved testing of bad pngs into a separate tests/pngtest-badpngs script + Added the --xfail (expected FAIL) option to pngtest.c. It writes XFAIL + in the output but PASS for the libpng test. + Require cmake-3.0.2 in CMakeLists.txt (Clifford Yapp). + Fix "const" declaration info_ptr argument to png_get_eXIf_1() and the + num_exif argument to png_get_eXIf_1() (Github Issue 171). + +Version 1.6.32beta11 [August 7, 2017] + Added "eXIf" to "chunks_to_ignore[]" in png_set_keep_unknown_chunks(). + Added huge_IDAT.png and empty_ancillary_chunks.png to testpngs/crashers. + Make pngtest --strict, --relax, --xfail options imply -m (multiple). + Removed unused chunk_name parameter from png_check_chunk_length(). + Relocated setting free_me for eXIf data, to stop an OSS-fuzz leak. + Initialize profile_header[] in png_handle_iCCP() to fix OSS-fuzz issue. + Initialize png_ptr->row_buf[0] to 255 in png_read_row() to fix OSS-fuzz UMR. + Attempt to fix a UMR in png_set_text_2() to fix OSS-fuzz issue. + Increase minimum zlib stream from 9 to 14 in png_handle_iCCP(), to account + for the minimum 'deflate' stream, and relocate the test to a point + after the keyword has been read. + Check that the eXIf chunk has at least 2 bytes and begins with "II" or "MM". + +Version 1.6.32rc01 [August 18, 2017] + Added a set of "huge_xxxx_chunk.png" files to contrib/testpngs/crashers, + one for each known chunk type, with length = 2GB-1. + Check for 0 return from png_get_rowbytes() and added some (size_t) typecasts + in contrib/pngminus/*.c to stop some Coverity issues (162705, 162706, + and 162707). + Renamed chunks in contrib/testpngs/crashers to avoid having files whose + names differ only in case; this causes problems with some platforms + (github issue #172). + +Version 1.6.32rc02 [August 22, 2017] + Added contrib/oss-fuzz directory which contains files used by the oss-fuzz + project . + +Version 1.6.32 [August 24, 2017] + No changes. -Glenn R-P -#endif +Version 1.6.33beta01 [August 28, 2017] + Added PNGMINUS_UNUSED macro to contrib/pngminus/p*.c and added missing + parenthesis in contrib/pngminus/pnm2png.c (bug report by Christian Hesse). + Fixed off-by-one error in png_do_check_palette_indexes() (Bug report + by Mick P., Source Forge Issue #269). + +Version 1.6.33beta02 [September 3, 2017] + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + to fix shortlived oss-fuzz issue 3234. + Compute a larger limit on IDAT because some applications write a deflate + buffer for each row (Bug report by Andrew Church). + Use current date (DATE) instead of release-date (RDATE) in last + changed date of contrib/oss-fuzz files. + Enabled ARM support in CMakeLists.txt (Bernd Kuhls). + +Version 1.6.33beta03 [September 14, 2017] + Fixed incorrect typecast of some arguments to png_malloc() and + png_calloc() that were png_uint_32 instead of png_alloc_size_t + (Bug report by "irwir" in Github libpng issue #175). + Use pnglibconf.h.prebuilt when building for ANDROID with cmake (Github + issue 162, by rcdailey). + +Version 1.6.33rc01 [September 20, 2017] + Initialize memory allocated by png_inflate to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in png_set_text_2() + due to truncated iTXt or zTXt chunk. + Initialize memory allocated by png_read_buffer to zero, using memset, to + stop an oss-fuzz "use of uninitialized value" detection in + png_icc_check_tag_table() due to truncated iCCP chunk. + Removed a redundant test (suggested by "irwir" in Github issue #180). + +Version 1.6.33rc02 [September 23, 2017] + Added an interlaced version of each file in contrib/pngsuite. + Relocate new memset() call in pngrutil.c. + Removed more redundant tests (suggested by "irwir" in Github issue #180). + Add support for loading images with associated alpha in the Simplified + API (Samuel Williams). + +Version 1.6.33 [September 28, 2017] + Revert contrib/oss-fuzz/libpng_read_fuzzer.cc to libpng-1.6.32 state. + Initialize png_handler.row_ptr in contrib/oss-fuzz/libpng_read_fuzzer.cc + Add end_info structure and png_read_end() to the libpng fuzzer. + +Version 1.6.34 [September 29, 2017] + Removed contrib/pngsuite/i*.png; some of them caused test failures. + +Version 1.6.35beta01 [March 6, 2018] + Restored 21 of the contrib/pngsuite/i*.png, which do not cause test + failures. Placed the remainder in contrib/pngsuite/interlaced/i*.png. + Added calls to png_set_*() transforms commonly used by browsers to + the fuzzer. + Removed some unnecessary brackets in pngrtran.c + Fixed miscellaneous typos (Patch by github user "luzpaz"). + Change "ASM C" to "C ASM" in CMakeLists.txt + Fixed incorrect handling of bKGD chunk in sub-8-bit files (Cosmin) + Added hardware optimization directories to zip and 7z distributions. + Fixed incorrect bitmask for options. + Fixed many spelling typos. + +Version 1.6.35beta02 [March 28, 2018] + Make png_get_iCCP consistent with man page (allow compression-type argument + to be NULL, bug report by Lenard Szolnoki). + +Version 1.6.35 [July 15, 2018] + Replaced the remaining uses of png_size_t with size_t (Cosmin) + Fixed the calculation of row_factor in png_check_chunk_length + (reported by Thuan Pham in SourceForge issue #278) + Added missing parentheses to a macro definition + (suggested by "irwir" in GitHub issue #216) + +Version 1.6.36 [December 1, 2018] + Optimized png_do_expand_palette for ARM processors. + Improved performance by around 10-22% on a recent ARM Chromebook. + (Contributed by Richard Townsend, ARM Holdings) + Fixed manipulation of machine-specific optimization options. + (Contributed by Vicki Pfau) + Used memcpy instead of manual pointer arithmetic on Intel SSE2. + (Contributed by Samuel Williams) + Fixed build errors with MSVC on ARM64. + (Contributed by Zhijie Liang) + Fixed detection of libm in CMakeLists. + (Contributed by Cameron Cawley) + Fixed incorrect creation of pkg-config file in CMakeLists. + (Contributed by Kyle Bentley) + Fixed the CMake build on Windows MSYS by avoiding symlinks. + Fixed a build warning on OpenBSD. + (Contributed by Theo Buehler) + Fixed various typos in comments. + (Contributed by "luz.paz") + Raised the minimum required CMake version from 3.0.2 to 3.1. + Removed yet more of the vestigial support for pre-ANSI C compilers. + Removed ancient makefiles for ancient systems that have been broken + across all previous libpng-1.6.x versions. + Removed the Y2K compliance statement and the export control + information. + Applied various code style and documentation fixes. + +Version 1.6.37 [April 14, 2019] + Fixed a use-after-free vulnerability (CVE-2019-7317) in png_image_free. + Fixed a memory leak in the ARM NEON implementation of png_do_expand_palette. + Fixed a memory leak in pngtest.c. + Fixed two vulnerabilities (CVE-2018-14048, CVE-2018-14550) in + contrib/pngminus; refactor. + Changed the license of contrib/pngminus to MIT; refresh makefile and docs. + (Contributed by Willem van Schaik) + Fixed a typo in the libpng license v2. + (Contributed by Miguel Ojeda) + Added makefiles for AddressSanitizer-enabled builds. + Cleaned up various makefiles. + +Version 1.6.38 [September 14, 2022] + Added configurations and scripts for continuous integration. + Fixed various errors in the handling of tRNS, hIST and eXIf. + Implemented many stability improvements across all platforms. + Updated the internal documentation. + +Version 1.6.39 [November 20, 2022] + Changed the error handler of oversized chunks (i.e. larger than + PNG_USER_CHUNK_MALLOC_MAX) from png_chunk_error to png_benign_error. + Fixed a buffer overflow error in contrib/tools/pngfix. + Fixed a memory leak (CVE-2019-6129) in contrib/tools/pngcp. + Disabled the ARM Neon optimizations by default in the CMake file, + following the default behavior of the configure script. + Allowed configure.ac to work with the trunk version of autoconf. + Removed the support for "install" targets from the legacy makefiles; + removed the obsolete makefile.cegcc. + Cleaned up the code and updated the internal documentation. + +Version 1.6.40 [June 21, 2023] + Fixed the eXIf chunk multiplicity checks. + Fixed a memory leak in pCAL processing. + Corrected the validity report about tRNS inside png_get_valid(). + Fixed various build issues on *BSD, Mac and Windows. + Updated the configurations and the scripts for continuous integration. + Cleaned up the code, the build scripts, and the documentation. + +Version 1.6.41 [January 24, 2024] + Added SIMD-optimized code for the LoongArch LSX hardware. + (Contributed by GuXiWei, JinBo and ZhangLixia) + Fixed the run-time discovery of MIPS MSA hardware. + (Contributed by Sui Jingfeng) + Fixed an off-by-one error in the function png_do_check_palette_indexes(), + which failed to recognize errors that might have existed in the first + column of a broken palette-encoded image. This was a benign regression + accidentally introduced in libpng-1.6.33. No pixel was harmed. + (Contributed by Adam Richter; reviewed by John Bowler) + Fixed, improved and modernized the contrib/pngminus programs, i.e., + png2pnm.c and pnm2png.c + Removed old and peculiar portability hacks that were meant to silence + warnings issued by gcc version 7.1 alone. + (Contributed by John Bowler) + Fixed and modernized the CMake file, and raised the minimum required + CMake version from 3.1 to 3.6. + (Contributed by Clinton Ingram, Timothy Lyanguzov, Tyler Kropp, et al.) + Allowed the configure script to disable the building of auxiliary tools + and tests, thus catching up with the CMake file. + (Contributed by Carlo Bramini) + Fixed a build issue on Mac. + (Contributed by Zixu Wang) + Moved the Autoconf macro files to scripts/autoconf. + Moved the CMake files (except for the main CMakeLists.txt) to + scripts/cmake and moved the list of their contributing authors to + scripts/cmake/AUTHORS.md + Updated the CI configurations and scripts. + Relicensed the CI scripts to the MIT License. + Improved the test coverage. + (Contributed by John Bowler) + +Version 1.6.42 [January 29, 2024] + Fixed the implementation of the macro function png_check_sig(). + This was an API regression, introduced in libpng-1.6.41. + (Reported by Matthieu Darbois) + Fixed and updated the libpng manual. + +Version 1.6.43 [February 23, 2024] + Fixed the row width check in png_check_IHDR(). + This corrected a bug that was specific to the 16-bit platforms, + and removed a spurious compiler warning from the 64-bit builds. + (Reported by Jacek Caban; fixed by John Bowler) + Added eXIf chunk support to the push-mode reader in pngpread.c. + (Contributed by Chris Blume) + Added contrib/pngexif for the benefit of the users who would like + to inspect the content of eXIf chunks. + Added contrib/conftest/basic.dfa, a basic build-time configuration. + (Contributed by John Bowler) + Fixed a preprocessor condition in pngread.c that broke build-time + configurations like contrib/conftest/pngcp.dfa. + (Contributed by John Bowler) + Added CMake build support for LoongArch LSX. + (Contributed by GuXiWei) + Fixed a CMake build error that occurred under a peculiar state of the + dependency tree. This was a regression introduced in libpng-1.6.41. + (Contributed by Dan Rosser) + Marked the installed libpng headers as system headers in CMake. + (Contributed by Benjamin Buch) + Updated the build support for RISCOS. + (Contributed by Cameron Cawley) + Updated the makefiles to allow cross-platform builds to initialize + conventional make variables like AR and ARFLAGS. + Added various improvements to the CI scripts in areas like version + consistency verification and text linting. + Added version consistency verification to pngtest.c also. + +Version 1.6.44 [September 12, 2024] + Hardened calculations in chroma handling to prevent overflows, and + relaxed a constraint in cHRM validation to accomodate the standard + ACES AP1 set of color primaries. + (Contributed by John Bowler) + Removed the ASM implementation of ARM Neon optimizations and updated + the build accordingly. Only the remaining C implementation shall be + used from now on, thus ensuring the support of the PAC/BTI security + features on ARM64. + (Contributed by Ross Burton and John Bowler) + Fixed the pickup of the PNG_HARDWARE_OPTIMIZATIONS option in the + CMake build on FreeBSD/amd64. This is an important performance fix + on this platform. + Applied various fixes and improvements to the CMake build. + (Contributed by Eric Riff, Benjamin Buch and Erik Scholz) + Added fuzzing targets for the simplified read API. + (Contributed by Mikhail Khachayants) + Fixed a build error involving pngtest.c under a custom config. + This was a regression introduced in a code cleanup in libpng-1.6.43. + (Contributed by Ben Wagner) + Fixed and improved the config files for AppVeyor CI and Travis CI. + +Version 1.6.45 [January 7, 2025] + Added support for the cICP chunk. + (Contributed by Lucas Chollet and John Bowler) + Adjusted and improved various checks in colorspace calculations. + (Contributed by John Bowler) + Rearranged the write order of colorspace chunks for better conformance + with the PNG v3 draft specification. + (Contributed by John Bowler) + Raised the minimum required CMake version from 3.6 to 3.14. + Forked off a development branch for libpng version 1.8. + +Version 1.6.46 [January 23, 2025] + Added support for the mDCV and cLLI chunks. + (Contributed by John Bowler) + Fixed a build issue affecting C89 compilers. + This was a regression introduced in libpng-1.6.45. + (Contributed by John Bowler) + Added makefile.c89, specifically for testing C89 compilers. + Cleaned up contrib/pngminus: corrected an old typo, removed an old + workaround, and updated the CMake file. + +Version 1.6.47 [February 18, 2025] + Modified the behaviour of colorspace chunks in order to adhere + to the new precedence rules formulated in the latest draft of + the PNG Specification. + (Contributed by John Bowler) + Fixed a latent bug in `png_write_iCCP`. + This would have been a read-beyond-end-of-malloc vulnerability, + introduced early in the libpng-1.6.0 development, yet (fortunately!) + it was inaccessible before the above-mentioned modification of the + colorspace precedence rules, due to pre-existing colorspace checks. + (Reported by Bob Friesenhahn; fixed by John Bowler) + +Version 1.6.48 [April 30, 2025] + Fixed the floating-point version of the mDCv setter `png_set_mDCv`. + (Reported by Mohit Bakshi; fixed by John Bowler) + Added #error directives to discourage the inclusion of private + libpng implementation header files in PNG-supporting applications. + Added the CMake build option `PNG_LIBCONF_HEADER`, to be used as an + alternative to `DFA_XTRA`. + Removed the Travis CI configuration files, with heartfelt thanks for + their generous support of our project over the past five years! + +Version 1.6.49 [June 12, 2025] + Added SIMD-optimized code for the RISC-V Vector Extension (RVV). + (Contributed by Manfred Schlaegl, Dragos Tiselice and Filip Wasil) + Added various fixes and improvements to the build scripts and to + the sample code. + +Version 1.6.50 [July 1, 2025] + Improved the detection of the RVV Extension on the RISC-V platform. + (Contributed by Filip Wasil) + Replaced inline ASM with C intrinsics in the RVV code. + (Contributed by Filip Wasil) + Fixed a decoder defect in which unknown chunks trailing IDAT, set + to go through the unknown chunk handler, incorrectly triggered + out-of-place IEND errors. + (Contributed by John Bowler) + Fixed the CMake file for cross-platform builds that require `libm`. + +Version 1.6.51 [November 21, 2025] + Fixed CVE-2025-64505 (moderate severity): + Heap buffer overflow in `png_do_quantize` via malformed palette index. + (Reported by Samsung; analyzed by Fabio Gritti.) + Fixed CVE-2025-64506 (moderate severity): + Heap buffer over-read in `png_write_image_8bit` with 8-bit input and + `convert_to_8bit` enabled. + (Reported by Samsung and ; + analyzed by Fabio Gritti.) + Fixed CVE-2025-64720 (high severity): + Buffer overflow in `png_image_read_composite` via incorrect palette + premultiplication. + (Reported by Samsung; analyzed by John Bowler.) + Fixed CVE-2025-65018 (high severity): + Heap buffer overflow in `png_combine_row` triggered via + `png_image_finish_read`. + (Reported by .) + Fixed a memory leak in `png_set_quantize`. + (Reported by Samsung; analyzed by Fabio Gritti.) + Removed the experimental and incomplete ERROR_NUMBERS code. + (Contributed by Tobias Stoeckmann.) + Improved the RISC-V vector extension support; required RVV 1.0 or newer. + (Contributed by Filip Wasil.) + Added GitHub Actions workflows for automated testing. + Performed various refactorings and cleanups. + +Version 1.6.52 [December 3, 2025] + Fixed CVE-2025-66293 (high severity): + Out-of-bounds read in `png_image_read_composite`. + (Reported by flyfish101 .) + Fixed the Paeth filter handling in the RISC-V RVV implementation. + (Reported by Filip Wasil; fixed by Liang Junzhao.) + Improved the performance of the RISC-V RVV implementation. + (Contributed by Liang Junzhao.) + Added allocation failure fuzzing to oss-fuzz. + (Contributed by Philippe Antoine.) + +Version 1.6.53 [December 5, 2025] + Fixed a build failure on RISC-V RVV caused by a misspelled intrinsic. + (Contributed by Alexander Smorkalov.) + Fixed a build failure with CMake 4.1 or newer, on Windows, when using + Visual C++ without MASM installed. + +Version 1.6.54 [January 12, 2026] + Fixed CVE-2026-22695 (medium severity): + Heap buffer over-read in `png_image_read_direct_scaled`. + (Reported and fixed by Petr Simecek.) + Fixed CVE-2026-22801 (medium severity): + Integer truncation causing heap buffer over-read in `png_image_write_*`. + Implemented various improvements in oss-fuzz. + (Contributed by Philippe Antoine.) + +Version 1.6.55 [February 9, 2026] + Fixed CVE-2026-25646 (high severity): + Heap buffer overflow in `png_set_quantize`. + (Reported and fixed by Joshua Inscoe.) + Resolved an oss-fuzz build issue involving nalloc. + (Contributed by Philippe Antoine.) + +Version 1.6.56 [March 25, 2026] + Fixed CVE-2026-33416 (high severity): + Use-after-free via pointer aliasing in `png_set_tRNS` and `png_set_PLTE`. + (Reported by Halil Oktay and Ryo Shimada; + fixed by Halil Oktay and Cosmin Truta.) + Fixed CVE-2026-33636 (high severity): + Out-of-bounds read/write in the palette expansion on ARM Neon. + (Reported by Taegu Ha; fixed by Taegu Ha and Cosmin Truta.) + Fixed uninitialized reads beyond `num_trans` in `trans_alpha` buffers. + (Contributed by Halil Oktay.) + Fixed stale `info_ptr->palette` after in-place gamma and background + transforms. + Fixed wrong channel indices in `png_image_read_and_map` RGB_ALPHA path. + (Contributed by Yuelin Wang.) + Fixed wrong background color in colormap read. + (Contributed by Yuelin Wang.) + Fixed dead loop in sPLT write. + (Contributed by Yuelin Wang.) + Added missing null pointer checks in four public API functions. + (Contributed by Yuelin Wang.) + Validated shift bit depths in `png_set_shift` to prevent infinite loop. + (Contributed by Yuelin Wang.) + Avoided undefined behavior in library and tests. + Deprecated the hardly-ever-tested POINTER_INDEXING config option. + Added negative-stride test coverage for the simplified API. + Fixed memory leaks and API misuse in oss-fuzz. + (Contributed by Owen Sanzas.) + Implemented various fixes and improvements in oss-fuzz. + (Contributed by Bob Friesenhahn and Philippe Antoine.) + Performed various refactorings and cleanups. + +Version 1.6.57 [April 8, 2026] + Fixed CVE-2026-34757 (medium severity): + Use-after-free in `png_set_PLTE`, `png_set_tRNS` and `png_set_hIST` + leading to corrupted chunk data and potential heap information disclosure. + Also hardened the append-style setters (`png_set_text`, `png_set_sPLT`, + `png_set_unknown_chunks`) against a theoretical variant of the same + aliasing pattern. + (Reported by Iv4n .) + Fixed integer overflow in rowbytes computation in read transforms. + (Contributed by Mohammad Seet.) + +Version 1.6.58 [April 15, 2026] + Fixed a regression introduced in version 1.6.56 that caused `png_get_PLTE` + to return stale palette data after applying gamma and background transforms + in-place. + (Reported by ralfjunker .) + +Version 1.8.0 [TODO] + +Send comments/corrections/commendations to png-mng-implement at lists.sf.net. +Subscription is required; visit + +to subscribe. diff --git a/media/libpng/CMakeLists.txt b/media/libpng/CMakeLists.txt new file mode 100644 index 0000000000..090ef702e3 --- /dev/null +++ b/media/libpng/CMakeLists.txt @@ -0,0 +1,969 @@ +# CMakeLists.txt - CMake lists for libpng +# +# Copyright (c) 2018-2026 Cosmin Truta +# Copyright (c) 2007-2018 Glenn Randers-Pehrson +# Originally written by Christian Ehrlicher, 2007 +# +# Use, modification and distribution are subject to +# the same licensing terms and conditions as libpng. +# Please see the copyright notice in png.h or visit +# http://libpng.org/pub/png/src/libpng-LICENSE.txt +# +# For copyright and licensing purposes, please see +# the accompanying file scripts/cmake/AUTHORS.md +# +# SPDX-License-Identifier: libpng-2.0 + +cmake_minimum_required(VERSION 3.14...4.2) + +set(PNGLIB_MAJOR 1) +set(PNGLIB_MINOR 8) +set(PNGLIB_REVISION 0) +#set(PNGLIB_SUBREVISION 0) +set(PNGLIB_SUBREVISION "git") +set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_REVISION}) +set(PNGLIB_ABI_VERSION ${PNGLIB_MAJOR}${PNGLIB_MINOR}) +set(PNGLIB_SHARED_VERSION ${PNGLIB_ABI_VERSION}.${PNGLIB_REVISION}.${PNGLIB_SUBREVISION}) + +project(libpng + VERSION ${PNGLIB_VERSION} + LANGUAGES C) + +include(CheckCSourceCompiles) +include(CheckLibraryExists) +include(GNUInstallDirs) + +# Allow the users to specify an application-specific API prefix for libpng +# vendoring purposes. A standard libpng build should have no such prefix. +set(PNG_PREFIX + "" + CACHE STRING "Prefix to prepend to the API function names") + +# Allow the users to override the postfix appended to debug library file names. +# Previously, we used to set CMAKE_DEBUG_POSTFIX globally. That variable should +# not be cached, however, because doing so would affect all projects processed +# after libpng, in unexpected and undesirable ways. +set(PNG_DEBUG_POSTFIX + "d" + CACHE STRING "Postfix to append to library file names under the Debug configuration") + +# Allow the users to import their own extra configuration settings. +# Those settings can be either passed via DFA_XTRA if they are in DFA form +# (such as "pngusr.dfa"), or via PNG_LIBCONF_HEADER if they are in prebuilt +# header file form (such as "pnglibconf.h.prebuilt"), but not both. +# For platforms such as Android or iOS, or in certain cross-platform build +# scenarios, having a valid PNG_LIBCONF_HEADER is mandatory. +set(DFA_XTRA + "" + CACHE FILEPATH "DFA file containing customized build configuration settings for libpng") +set(PNG_LIBCONF_HEADER + "" + CACHE FILEPATH "C header file containing customized build configuration settings for libpng") +set(PNG_LIBCONF_HEADER_PREBUILT "${CMAKE_CURRENT_SOURCE_DIR}/pnglibconf.h.prebuilt") +if(ANDROID OR IOS) + set(PNG_LIBCONF_HEADER "${PNG_LIBCONF_HEADER_PREBUILT}") +endif() +if((NOT DFA_XTRA STREQUAL "") AND (NOT PNG_LIBCONF_HEADER STREQUAL "")) + message(SEND_ERROR "The options DFA_XTRA=\"${DFA_XTRA}\" " + "and PNG_LIBCONF_HEADER=\"${PNG_LIBCONF_HEADER}\" " + "are mutually exclusive") +endif() + +# Allow the users to switch on/off various library build types. +option(PNG_SHARED "Build libpng as a shared library" ON) +option(PNG_STATIC "Build libpng as a static library" ON) +if(APPLE) + option(PNG_FRAMEWORK "Build libpng as a framework bundle" ON) +else() + option(PNG_FRAMEWORK "Build libpng as a framework bundle (not available on this platform)" OFF) +endif() +if(NOT APPLE AND PNG_FRAMEWORK) + message(SEND_ERROR "The option PNG_FRAMEWORK should not be set on this platform") +endif() + +# Allow the users to switch on/off the auxiliary build and test artifacts. +# These artifacts are NOT part of libpng proper, and are subject to change +# at any time. +option(PNG_TESTS "Build the libpng tests" ON) + +# Same as above, but for the third-party tools. +# Although these tools are targeted at development environments only, +# the users are allowed to override the option to build by default. +if(ANDROID OR IOS) + option(PNG_TOOLS "Build the libpng tools" OFF) +else() + option(PNG_TOOLS "Build the libpng tools" ON) +endif() + +# Maintain backwards compatibility with the deprecated option PNG_EXECUTABLES. +option(PNG_EXECUTABLES "[Deprecated; please use PNG_TOOLS]" ON) +if(NOT PNG_EXECUTABLES) + message(DEPRECATION "The option PNG_EXECUTABLES has been deprecated in favour of PNG_TOOLS") + if(PNG_TOOLS) + message(AUTHOR_WARNING "Setting PNG_TOOLS to ${PNG_EXECUTABLES}, " + "to stay compatible with PNG_EXECUTABLES") + set(PNG_TOOLS "${PNG_EXECUTABLES}") + endif() +endif() + +# Allow the users to switch on/off the use of hardware (SIMD) optimized code. +option(PNG_HARDWARE_OPTIMIZATIONS "Enable hardware optimizations" ON) + +# Initialize and show the target architecture variable PNG_TARGET_ARCHITECTURE. +# +# NOTE: +# On macOS, CMake sets CMAKE_SYSTEM_PROCESSOR to either "x86_64" or "arm64", +# based upon the OS architecture, not the target architecture. As such, we need +# to check CMAKE_OSX_ARCHITECTURES to identify which hardware-specific flags to +# enable. Note that this will fail if you attempt to build a universal binary +# in a single CMake invocation. +if(APPLE AND CMAKE_OSX_ARCHITECTURES) + string(TOLOWER "${CMAKE_OSX_ARCHITECTURES}" PNG_TARGET_ARCHITECTURE) +else() + string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" PNG_TARGET_ARCHITECTURE) +endif() +message(STATUS "Building for target architecture: ${PNG_TARGET_ARCHITECTURE}") + +# Allow the users to specify a custom location of zlib. +# With CMake 3.12 and newer, this option is no longer necessary. +option(PNG_BUILD_ZLIB "[Deprecated; please use ZLIB_ROOT]" OFF) +if(PNG_BUILD_ZLIB) + if("x${ZLIB_ROOT}" STREQUAL "x") + message(SEND_ERROR "The option PNG_BUILD_ZLIB=${PNG_BUILD_ZLIB} is no longer supported; " + "please use ZLIB_ROOT instead") + else() + message(SEND_ERROR "The option PNG_BUILD_ZLIB=${PNG_BUILD_ZLIB} is no longer supported; " + "using ZLIB_ROOT=\"${ZLIB_ROOT}\"") + endif() +endif() + +# Find the zlib library. +find_package(ZLIB REQUIRED) +set(PNG_LINK_LIBRARIES ZLIB::ZLIB) + +# Find the math library (unless we already know it's not available or +# not needed). +if(UNIX AND NOT (APPLE OR BEOS OR HAIKU OR EMSCRIPTEN)) + check_library_exists(m pow "" PNG_HAVE_LIBM_POW) +endif() +if(PNG_HAVE_LIBM_POW) + list(APPEND PNG_LINK_LIBRARIES m) +endif() + +# Silence function deprecation warnings on the Windows compilers that might +# use the MSVC Runtime library headers. +if(WIN32 AND (CMAKE_C_COMPILER_ID MATCHES "MSVC|Intel|Clang")) + add_definitions(-D_CRT_NONSTDC_NO_DEPRECATE) + add_definitions(-D_CRT_SECURE_NO_DEPRECATE) +endif() + +option(ld-version-script "Enable linker version script" ON) +if(ld-version-script AND NOT (ANDROID OR APPLE)) + # Check if LD supports linker scripts. + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map" " +VERS_1 { global: sym1; local: *; }; +VERS_2 { global: sym2; main; } VERS_1; +") + set(_SAVED_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) + if(NOT CMAKE_HOST_SOLARIS) + # Avoid using CMAKE_SHARED_LIBRARY_C_FLAGS in version script checks on + # Solaris, because of an incompatibility with the Solaris link editor. + list(APPEND CMAKE_REQUIRED_FLAGS ${CMAKE_SHARED_LIBRARY_C_FLAGS}) + endif() + list(APPEND CMAKE_REQUIRED_FLAGS + "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/conftest.map'") + check_c_source_compiles(" +void sym1(void) {} +void sym2(void) {} +int main(void) { return 0; } +" HAVE_LD_VERSION_SCRIPT) + if(NOT HAVE_LD_VERSION_SCRIPT) + set(CMAKE_REQUIRED_FLAGS ${_SAVED_CMAKE_REQUIRED_FLAGS}) + if(NOT CMAKE_HOST_SOLARIS) + # Again, avoid using CMAKE_SHARED_LIBRARY_C_FLAGS in version script + # checks on Solaris. + list(APPEND CMAKE_REQUIRED_FLAGS ${CMAKE_SHARED_LIBRARY_C_FLAGS}) + endif() + list(APPEND CMAKE_REQUIRED_FLAGS "-Wl,-M -Wl,${CMAKE_CURRENT_BINARY_DIR}/conftest.map") + check_c_source_compiles(" +void sym1(void) {} +void sym2(void) {} +int main(void) { return 0; } +" HAVE_SOLARIS_LD_VERSION_SCRIPT) + endif() + set(CMAKE_REQUIRED_FLAGS ${_SAVED_CMAKE_REQUIRED_FLAGS}) + file(REMOVE "${CMAKE_CURRENT_BINARY_DIR}/conftest.map") +endif() + +if(PNG_LIBCONF_HEADER STREQUAL "") + # No custom configuration header file has been specified, so we build it + # from our DFA files and (optionally) out of the user-supplied DFA file. + # Find an AWK language processor. + # Start with specific AWK implementations like gawk and nawk, which are + # known to work with our scripts, then fall back to the system awk. + find_program(AWK NAMES gawk nawk awk) + if(AWK) + message(STATUS "Found AWK program: ${AWK}") + else() + message(STATUS "Could not find an AWK-compatible program") + endif() +endif() + +# Include the internal module PNGCheckLibconf.cmake +include("${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/PNGCheckLibconf.cmake") + +if(NOT PNG_LIBCONF_HEADER STREQUAL "") + # Configure libpng with the user-defined pnglibconf.h file. + png_check_libconf(HEADER "${PNG_LIBCONF_HEADER}") + configure_file("${PNG_LIBCONF_HEADER}" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" + @ONLY) + add_custom_target(png_genfiles) +elseif(NOT AWK) + # No AWK program available to generate pnglibconf.h. + # Configure libpng with pnglibconf.h.prebuilt. + png_check_libconf(HEADER "${PNG_LIBCONF_HEADER_PREBUILT}") + configure_file("${PNG_LIBCONF_HEADER_PREBUILT}" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" + @ONLY) + add_custom_target(png_genfiles) +else() + png_check_libconf(DFA_XTRA "${DFA_XTRA}") + + # Include the internal module PNGGenConfig.cmake + include("${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/PNGGenConfig.cmake") + + # Work around a limitation of various Windows AWK programs that are + # unable to process CRLF-terminated AWK scripts. + # Copy these AWK scripts to a temporary location, converting their + # line endings from Windows (CRLF) to Unix (LF) at the destination. + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf/checksym.awk" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/checksym.awk" + @ONLY + NEWLINE_STYLE LF) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf/options.awk" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/options.awk" + @ONLY + NEWLINE_STYLE LF) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf/dfn.awk" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/dfn.awk" + @ONLY + NEWLINE_STYLE LF) + + # Generate scripts/pnglibconf/pnglibconf.c + generate_source(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/pnglibconf.c" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/options.awk" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf/pnglibconf.dfa" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h") + + # Generate pnglibconf.c + generate_source(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/options.awk" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf/pnglibconf.dfa" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h") + + if(PNG_PREFIX) + set(PNGLIBCONF_H_EXTRA_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/prefix.out" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/macro.lst") + set(PNGPREFIX_H_EXTRA_DEPENDS + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/intprefix.out") + endif() + + generate_out(INPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out") + + # Generate pnglibconf.h + generate_source(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out" + ${PNGLIBCONF_H_EXTRA_DEPENDS}) + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf/intprefix.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/intprefix.out" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h") + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf/prefix.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/prefix.out" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out") + + # Generate pngprefix.h + generate_source(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h" + DEPENDS ${PNGPREFIX_H_EXTRA_DEPENDS}) + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf/sym.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/sym.out" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h") + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf/symbols.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/symbols.out" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pnglibconf.h.prebuilt") + + generate_out(INPUT "${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf/vers.c" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/vers.out" + DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/png.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pngconf.h" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h") + + generate_chk(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/symbols.out" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/symbols.chk" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/checksym.awk" + "${CMAKE_CURRENT_SOURCE_DIR}/scripts/symbols.def") + + generate_copy(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/sym.out" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym") + + generate_copy(INPUT "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/vers.out" + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers") + + add_custom_target(png_genprebuilt + COMMAND "${CMAKE_COMMAND}" + "-DOUTPUT=pnglibconf.h.prebuilt" + -P "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/gensrc.cmake" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + + # A single target handles generation of all generated files. + add_custom_target(png_genfiles + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/libpng.sym" + "${CMAKE_CURRENT_BINARY_DIR}/libpng.vers" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.c" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.out" + "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/intprefix.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/pnglibconf.c" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/prefix.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/sym.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/symbols.chk" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/symbols.out" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/pnglibconf/vers.out") +endif() + +# List the source code files. +set(libpng_public_hdrs + png.h + pngconf.h + "${CMAKE_CURRENT_BINARY_DIR}/pnglibconf.h" +) +set(libpng_private_hdrs + pngpriv.h + pngdebug.h + pnginfo.h + pngstruct.h +) +if(AWK) + list(APPEND libpng_private_hdrs "${CMAKE_CURRENT_BINARY_DIR}/pngprefix.h") +endif() +set(libpng_sources + ${libpng_public_hdrs} + ${libpng_private_hdrs} + png.c + pngerror.c + pngget.c + pngmem.c + pngpread.c + pngread.c + pngrio.c + pngrtran.c + pngrutil.c + pngset.c + pngtrans.c + pngwio.c + pngwrite.c + pngwtran.c + pngwutil.c + pngsimd.c +) + +set(pngtest_sources + pngtest.c +) +set(pngvalid_sources + contrib/libtests/pngvalid.c +) +set(pngstest_sources + contrib/libtests/pngstest.c +) +set(pnggetset_sources + contrib/libtests/pnggetset.c +) +set(pngunknown_sources + contrib/libtests/pngunknown.c +) +set(pngimage_sources + contrib/libtests/pngimage.c +) +set(pngfix_sources + contrib/tools/pngfix.c +) +set(png_fix_itxt_sources + contrib/tools/png-fix-itxt.c +) + +# Now build our targets. + +# Initialize the list of libpng library targets. +set(PNG_LIBRARY_TARGETS "") + +# Initialize the libpng library file names. +if(UNIX + OR (WIN32 AND NOT CMAKE_SHARED_LIBRARY_PREFIX STREQUAL "") + OR (WIN32 AND NOT CMAKE_STATIC_LIBRARY_PREFIX STREQUAL "")) + # We are on a Unix or Unix-like toolchain like the GNU toolchain on Windows. + # Library file names are expected to have an implicit prefix such as "lib". + # Let CMake prepend and append its usual prefixes and suffixes by default. + set(PNG_SHARED_OUTPUT_NAME "png${PNGLIB_ABI_VERSION}") + set(PNG_STATIC_OUTPUT_NAME "png${PNGLIB_ABI_VERSION}") +else() + # We are, most likely, on a Windows toolchain like MSVC, Clang on Windows, + # Borland/Embarcadero, etc. We need to specify the "libpng" name explicitly. + # We also need to use a custom suffix, in order to distinguish between the + # shared import library name and the static library name. + set(PNG_SHARED_OUTPUT_NAME "libpng${PNGLIB_ABI_VERSION}") + set(PNG_STATIC_OUTPUT_NAME "libpng${PNGLIB_ABI_VERSION}_static") +endif() + +if(PNG_SHARED) + add_library(png_shared SHARED ${libpng_sources}) + add_dependencies(png_shared png_genfiles) + list(APPEND PNG_LIBRARY_TARGETS png_shared) + set_target_properties(png_shared + PROPERTIES OUTPUT_NAME "${PNG_SHARED_OUTPUT_NAME}" + DEBUG_POSTFIX "${PNG_DEBUG_POSTFIX}" + VERSION "${PNGLIB_SHARED_VERSION}" + SOVERSION "${PNGLIB_ABI_VERSION}") + if(UNIX AND AWK) + if(HAVE_LD_VERSION_SCRIPT) + set_target_properties(png_shared + PROPERTIES LINK_FLAGS "-Wl,--version-script='${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'") + elseif(HAVE_SOLARIS_LD_VERSION_SCRIPT) + set_target_properties(png_shared + PROPERTIES LINK_FLAGS "-Wl,-M -Wl,'${CMAKE_CURRENT_BINARY_DIR}/libpng.vers'") + endif() + endif() + if(APPLE) + # Avoid CMake's implicit compile definition "png_shared_EXPORTS". + set_target_properties(png_shared + PROPERTIES DEFINE_SYMBOL "") + elseif(WIN32) + # Use the explicit compile definition "PNG_BUILD_DLL" for Windows DLLs. + set_target_properties(png_shared + PROPERTIES DEFINE_SYMBOL PNG_BUILD_DLL) + endif() + target_include_directories(png_shared + PUBLIC "$") + target_include_directories(png_shared + PUBLIC "$") + target_include_directories(png_shared + SYSTEM + INTERFACE "$") + target_link_libraries(png_shared + PUBLIC ${PNG_LINK_LIBRARIES}) +endif() + +if(PNG_STATIC) + add_library(png_static STATIC ${libpng_sources}) + add_dependencies(png_static png_genfiles) + list(APPEND PNG_LIBRARY_TARGETS png_static) + set_target_properties(png_static + PROPERTIES OUTPUT_NAME "${PNG_STATIC_OUTPUT_NAME}" + DEBUG_POSTFIX "${PNG_DEBUG_POSTFIX}") + target_include_directories(png_static + PUBLIC "$") + target_include_directories(png_static + PUBLIC "$") + target_include_directories(png_static + SYSTEM + INTERFACE "$") + target_link_libraries(png_static + PUBLIC ${PNG_LINK_LIBRARIES}) +endif() + +if(PNG_FRAMEWORK AND NOT APPLE) + message(AUTHOR_WARNING "Setting PNG_FRAMEWORK to OFF, as it only applies to Apple systems") + set(PNG_FRAMEWORK OFF) +endif() + +if(PNG_FRAMEWORK) + add_library(png_framework SHARED ${libpng_sources}) + add_dependencies(png_framework png_genfiles) + list(APPEND PNG_LIBRARY_TARGETS png_framework) + set_target_properties(png_framework + PROPERTIES FRAMEWORK TRUE + FRAMEWORK_VERSION "${PNGLIB_VERSION}" + MACOSX_FRAMEWORK_SHORT_VERSION_STRING "${PNGLIB_MAJOR}.${PNGLIB_MINOR}" + MACOSX_FRAMEWORK_BUNDLE_VERSION "${PNGLIB_VERSION}" + MACOSX_FRAMEWORK_IDENTIFIER "org.libpng.libpng" + XCODE_ATTRIBUTE_INSTALL_PATH "@rpath" + PUBLIC_HEADER "${libpng_public_hdrs}" + OUTPUT_NAME "png" + DEBUG_POSTFIX "${PNG_DEBUG_POSTFIX}") + # Avoid CMake's implicit compile definition "-Dpng_framework_EXPORTS". + set_target_properties(png_framework + PROPERTIES DEFINE_SYMBOL "") + target_include_directories(png_framework + PUBLIC "$") + target_include_directories(png_framework + PUBLIC "$") + target_include_directories(png_framework + SYSTEM + INTERFACE "$") + target_link_libraries(png_framework + PUBLIC ${PNG_LINK_LIBRARIES}) +endif() + +if(NOT PNG_LIBRARY_TARGETS) + message(SEND_ERROR "No library variant selected to build. " + "Please enable at least one of the following options: " + "PNG_SHARED, PNG_STATIC, PNG_FRAMEWORK") +endif() + +if(PNG_TESTS AND PNG_SHARED) + enable_testing() + + # Include the internal module PNGTest.cmake + include("${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/PNGTest.cmake") + + # Find test PNG files by globbing, but sort lists to ensure + # consistency between different filesystems. + file(GLOB PNGSUITE_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/pngsuite/*.png") + list(SORT PNGSUITE_PNGS) + file(GLOB TEST_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/*.png") + list(SORT TEST_PNGS) + file(GLOB TEST_PNG3_PNGS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/png-3/*.png") + list(SORT TEST_PNG3_PNGS) + + set(PNGTEST_PNG "${CMAKE_CURRENT_SOURCE_DIR}/pngtest.png") + + # pngtest tests: + # Basic read/write roundtrip using the sequential API. + add_executable(pngtest ${pngtest_sources}) + target_link_libraries(pngtest + PRIVATE png_shared) + + png_add_test(NAME pngtest + COMMAND pngtest + FILES "${PNGTEST_PNG}") + + png_add_test(NAME pngtest-png-3 + COMMAND pngtest + FILES "${TEST_PNG3_PNGS}") + + # pnggetset test: + # Getter-to-setter roundtrips for various chunk types. + add_executable(pnggetset ${pnggetset_sources}) + target_link_libraries(pnggetset + PRIVATE png_shared) + + png_add_test(NAME pnggetset + COMMAND pnggetset) + + # pngvalid tests: + # Internal validation of standard and progressive reading, + # transforms, and gamma handling. + add_executable(pngvalid ${pngvalid_sources}) + target_link_libraries(pngvalid + PRIVATE png_shared) + + png_add_test(NAME pngvalid-gamma-16-to-8 + COMMAND pngvalid + OPTIONS --gamma-16-to-8) + png_add_test(NAME pngvalid-gamma-alpha-mode + COMMAND pngvalid + OPTIONS --gamma-alpha-mode) + png_add_test(NAME pngvalid-gamma-background + COMMAND pngvalid + OPTIONS --gamma-background) + png_add_test(NAME pngvalid-gamma-expand16-alpha-mode + COMMAND pngvalid + OPTIONS --gamma-alpha-mode --expand16) + png_add_test(NAME pngvalid-gamma-expand16-background + COMMAND pngvalid + OPTIONS --gamma-background --expand16) + png_add_test(NAME pngvalid-gamma-expand16-transform + COMMAND pngvalid + OPTIONS --gamma-transform --expand16) + png_add_test(NAME pngvalid-gamma-sbit + COMMAND pngvalid + OPTIONS --gamma-sbit) + png_add_test(NAME pngvalid-gamma-threshold + COMMAND pngvalid + OPTIONS --gamma-threshold) + png_add_test(NAME pngvalid-gamma-transform + COMMAND pngvalid + OPTIONS --gamma-transform) + png_add_test(NAME pngvalid-progressive-interlace-standard + COMMAND pngvalid + OPTIONS --standard --progressive-read --interlace) + png_add_test(NAME pngvalid-progressive-size + COMMAND pngvalid + OPTIONS --size --progressive-read) + png_add_test(NAME pngvalid-progressive-standard + COMMAND pngvalid + OPTIONS --standard --progressive-read) + png_add_test(NAME pngvalid-standard + COMMAND pngvalid + OPTIONS --standard) + png_add_test(NAME pngvalid-transform + COMMAND pngvalid + OPTIONS --transform) + + # pngstest tests: + # Format conversions through the simplified API, + # by gamma type and alpha type. + add_executable(pngstest ${pngstest_sources}) + target_link_libraries(pngstest + PRIVATE png_shared) + + foreach(gamma_type 1.8 linear none sRGB) + foreach(alpha_type none alpha) + set(PNGSTEST_FILES) + foreach(test_png ${TEST_PNGS}) + string(REGEX MATCH "-linear[-.]" TEST_PNG_LINEAR "${test_png}") + string(REGEX MATCH "-sRGB[-.]" TEST_PNG_SRGB "${test_png}") + string(REGEX MATCH "-1.8[-.]" TEST_PNG_G18 "${test_png}") + string(REGEX MATCH "-alpha-" TEST_PNG_ALPHA "${test_png}") + + set(TEST_PNG_VALID TRUE) + + if(TEST_PNG_ALPHA) + if(NOT alpha_type STREQUAL "alpha") + set(TEST_PNG_VALID FALSE) + endif() + else() + if(alpha_type STREQUAL "alpha") + set(TEST_PNG_VALID FALSE) + endif() + endif() + + if(TEST_PNG_LINEAR) + if(NOT gamma_type STREQUAL "linear") + set(TEST_PNG_VALID FALSE) + endif() + elseif(TEST_PNG_SRGB) + if(NOT gamma_type STREQUAL "sRGB") + set(TEST_PNG_VALID FALSE) + endif() + elseif(TEST_PNG_G18) + if(NOT gamma_type STREQUAL "1.8") + set(TEST_PNG_VALID FALSE) + endif() + else() + if(NOT gamma_type STREQUAL "none") + set(TEST_PNG_VALID FALSE) + endif() + endif() + + if(TEST_PNG_VALID) + list(APPEND PNGSTEST_FILES "${test_png}") + endif() + endforeach() + # Should already be sorted, but sort anyway to be certain. + list(SORT PNGSTEST_FILES) + png_add_test(NAME pngstest-${gamma_type}-${alpha_type} + COMMAND pngstest + OPTIONS --tmpfile "${gamma_type}-${alpha_type}-" --log + FILES ${PNGSTEST_FILES}) + endforeach() + endforeach() + + # Large-stride test: + # Use stride_extra > 32767 to trigger row_bytes > 65535 for linear images. + png_add_test(NAME pngstest-large-stride + COMMAND pngstest + OPTIONS --stride-extra 33000 --tmpfile "large-stride-" --log + FILES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-alpha-16-linear.png") + + # Negative-stride test: + # Bottom-up layout through all read/write paths. + png_add_test(NAME pngstest-negative-stride + COMMAND pngstest + OPTIONS --negative-stride --tmpfile "negative-stride-" --log + FILES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/gray-1.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/gray-16-linear.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-8-linear.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-16-linear.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/palette-8-tRNS.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/gray-alpha-8-linear.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/gray-alpha-16-linear.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-alpha-8-1.8.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-alpha-8-sRGB.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-alpha-16-linear.png") + + # Negative-stride-extra test: + # Bottom-up layout with non-aligned padding. + png_add_test(NAME pngstest-negative-stride-extra + COMMAND pngstest + OPTIONS --negative-stride --stride-extra 7 + --tmpfile "negative-stride-extra-" --log + FILES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/gray-1.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/gray-16-linear.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-8-linear.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-16-linear.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/palette-8-tRNS.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/gray-alpha-8-linear.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/gray-alpha-16-linear.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-alpha-8-1.8.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-alpha-8-sRGB.png" + "${CMAKE_CURRENT_SOURCE_DIR}/contrib/testpngs/rgb-alpha-16-linear.png") + + # pngunknown tests: + # Unknown chunk handling under various read policies. + add_executable(pngunknown ${pngunknown_sources}) + target_link_libraries(pngunknown + PRIVATE png_shared) + + png_add_test(NAME pngunknown-discard + COMMAND pngunknown + OPTIONS --strict default=discard + FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-IDAT + COMMAND pngunknown + OPTIONS --strict default=discard IDAT=save + FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-if-safe + COMMAND pngunknown + OPTIONS --strict default=if-safe + FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-sAPI + COMMAND pngunknown + OPTIONS --strict + bKGD=save cHRM=save gAMA=save all=discard iCCP=save sBIT=save sRGB=save + FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-save + COMMAND pngunknown + OPTIONS --strict default=save + FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-sTER + COMMAND pngunknown + OPTIONS --strict sTER=if-safe + FILES "${PNGTEST_PNG}") + png_add_test(NAME pngunknown-vpAg + COMMAND pngunknown + OPTIONS --strict vpAg=if-safe + FILES "${PNGTEST_PNG}") + + # pngimage tests: + # Image read validation against the pngsuite corpus. + add_executable(pngimage ${pngimage_sources}) + target_link_libraries(pngimage + PRIVATE png_shared) + + png_add_test(NAME pngimage-quick + COMMAND pngimage + OPTIONS --list-combos --log + FILES ${PNGSUITE_PNGS}) + png_add_test(NAME pngimage-full + COMMAND pngimage + OPTIONS --exhaustive --list-combos --log + FILES ${PNGSUITE_PNGS}) +endif() + +if(PNG_SHARED AND PNG_TOOLS) + add_executable(pngfix ${pngfix_sources}) + target_link_libraries(pngfix + PRIVATE png_shared) + set(PNG_BIN_TARGETS pngfix) + + add_executable(png-fix-itxt ${png_fix_itxt_sources}) + target_link_libraries(png-fix-itxt + PRIVATE ${PNG_LINK_LIBRARIES}) + list(APPEND PNG_BIN_TARGETS png-fix-itxt) +endif() + +# Create a symlink that points to a target file (if symlinking is possible), +# or make a copy of the target file (if symlinking is not possible): +# create_symlink( [FILE | TARGET ]) +function(create_symlink DEST_FILE) + # TODO: + # Replace this implementation with CMake's built-in create_symlink function, + # which has been fully functional on all platforms, including Windows, since + # CMake version 3.13. + cmake_parse_arguments(_SYM "" "FILE;TARGET" "" ${ARGN}) + if(NOT _SYM_FILE AND NOT _SYM_TARGET) + message(FATAL_ERROR "create_symlink: Missing arguments: FILE or TARGET") + endif() + if(_SYM_FILE AND _SYM_TARGET) + message(FATAL_ERROR "create_symlink: Mutually-exclusive arguments:" + "FILE (${_SYM_FILE}) and TARGET (${_SYM_TARGET})") + endif() + + if(_SYM_FILE) + # If we don't need to symlink something that's coming from a build target, + # we can go ahead and symlink/copy at configure time. + if(CMAKE_HOST_WIN32 AND NOT CYGWIN) + execute_process(COMMAND "${CMAKE_COMMAND}" + -E copy_if_different + "${_SYM_FILE}" + "${DEST_FILE}" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + else() + execute_process(COMMAND "${CMAKE_COMMAND}" + -E create_symlink + "${_SYM_FILE}" + "${DEST_FILE}" + WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") + endif() + endif() + + if(_SYM_TARGET) + # We need to use generator expressions, which can be a bit tricky. + # For simplicity, make the symlink a POST_BUILD step, and use the TARGET + # signature of add_custom_command. + if(CMAKE_HOST_WIN32 AND NOT CYGWIN) + add_custom_command(TARGET ${_SYM_TARGET} + POST_BUILD + COMMAND "${CMAKE_COMMAND}" + -E copy_if_different + "$/$" + "$/${DEST_FILE}") + else() + add_custom_command(TARGET ${_SYM_TARGET} + POST_BUILD + COMMAND "${CMAKE_COMMAND}" + -E create_symlink + "$" + "$/${DEST_FILE}") + endif() + endif() +endfunction() + +# Create source generation scripts. +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/genchk.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/genchk.cmake" + @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/genout.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/genout.cmake" + @ONLY) +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/gensrc.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/scripts/cmake/gensrc.cmake" + @ONLY) + +# libpng is a library so default to 'lib' +if(NOT DEFINED CMAKE_INSTALL_LIBDIR) + set(CMAKE_INSTALL_LIBDIR lib) +endif() + +# Create pkgconfig files. +# We use the same files like ./configure, so we have to set its vars. +# Only do this on Windows for Cygwin - the files don't make much sense +# outside of a UNIX look-alike. +if(NOT WIN32 OR CYGWIN OR MINGW) + set(prefix "${CMAKE_INSTALL_PREFIX}") + set(exec_prefix "${CMAKE_INSTALL_PREFIX}") + set(libdir "${CMAKE_INSTALL_FULL_LIBDIR}") + set(includedir "${CMAKE_INSTALL_FULL_INCLUDEDIR}") + set(LIBS "-lz -lm") + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libpng.pc.in" + "${CMAKE_CURRENT_BINARY_DIR}/libpng${PNGLIB_ABI_VERSION}.pc" + @ONLY) + create_symlink(libpng.pc FILE libpng${PNGLIB_ABI_VERSION}.pc) + configure_file("${CMAKE_CURRENT_SOURCE_DIR}/libpng-config.in" + "${CMAKE_CURRENT_BINARY_DIR}/libpng${PNGLIB_ABI_VERSION}-config" + @ONLY) + create_symlink(libpng-config FILE libpng${PNGLIB_ABI_VERSION}-config) +endif() + +# Install. +if(NOT SKIP_INSTALL_LIBRARIES AND NOT SKIP_INSTALL_ALL) + install(TARGETS ${PNG_LIBRARY_TARGETS} + EXPORT libpng + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + FRAMEWORK DESTINATION "${CMAKE_INSTALL_LIBDIR}") + + if(PNG_SHARED) + # Create a symlink for libpng.dll.a => libpng18.dll.a on Cygwin + if(NOT WIN32 OR CYGWIN OR MINGW) + create_symlink(libpng${CMAKE_SHARED_LIBRARY_SUFFIX} TARGET png_shared) + install(FILES "$/libpng${CMAKE_SHARED_LIBRARY_SUFFIX}" + DESTINATION "${CMAKE_INSTALL_LIBDIR}") + endif() + endif() + + if(PNG_STATIC) + if(NOT WIN32 OR CYGWIN OR MINGW) + create_symlink(libpng${CMAKE_STATIC_LIBRARY_SUFFIX} TARGET png_static) + install(FILES "$/libpng${CMAKE_STATIC_LIBRARY_SUFFIX}" + DESTINATION "${CMAKE_INSTALL_LIBDIR}") + endif() + endif() +endif() + +if(NOT SKIP_INSTALL_HEADERS AND NOT SKIP_INSTALL_ALL) + install(FILES ${libpng_public_hdrs} + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}") + install(FILES ${libpng_public_hdrs} + DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/libpng${PNGLIB_ABI_VERSION}") +endif() +if(NOT SKIP_INSTALL_EXECUTABLES AND NOT SKIP_INSTALL_ALL) + if(NOT WIN32 OR CYGWIN OR MINGW) + install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/libpng-config" + DESTINATION "${CMAKE_INSTALL_BINDIR}") + install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/libpng${PNGLIB_ABI_VERSION}-config" + DESTINATION "${CMAKE_INSTALL_BINDIR}") + endif() +endif() + +if(NOT SKIP_INSTALL_PROGRAMS AND NOT SKIP_INSTALL_ALL) + install(TARGETS ${PNG_BIN_TARGETS} + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") +endif() + +if(NOT SKIP_INSTALL_FILES AND NOT SKIP_INSTALL_ALL) + # Install the man pages. + install(FILES manuals/libpng.3 + DESTINATION "${CMAKE_INSTALL_MANDIR}/man3") + install(FILES manuals/png.5 + DESTINATION "${CMAKE_INSTALL_MANDIR}/man5") + # Install the pkg-config files. + if(NOT CMAKE_HOST_WIN32 OR CYGWIN OR MINGW) + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libpng.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/libpng-config" + DESTINATION "${CMAKE_INSTALL_BINDIR}") + install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libpng${PNGLIB_ABI_VERSION}.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + install(PROGRAMS "${CMAKE_CURRENT_BINARY_DIR}/libpng${PNGLIB_ABI_VERSION}-config" + DESTINATION "${CMAKE_INSTALL_BINDIR}") + endif() +endif() + +# Create an export file that CMake users can include() to import our targets. +if(NOT SKIP_INSTALL_EXPORT AND NOT SKIP_INSTALL_ALL) + install(EXPORT libpng + DESTINATION "${CMAKE_INSTALL_LIBDIR}/libpng" + FILE libpng${PNGLIB_ABI_VERSION}.cmake) +endif() + +# Create a CMake Config File that can be used via find_package(PNG CONFIG) +if(NOT SKIP_INSTALL_CONFIG_FILE AND NOT SKIP_INSTALL_ALL) + install(TARGETS ${PNG_LIBRARY_TARGETS} + EXPORT PNGTargets + RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}" + LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" + ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" + FRAMEWORK DESTINATION "${CMAKE_INSTALL_LIBDIR}") + + include(CMakePackageConfigHelpers) + write_basic_package_version_file(PNGConfigVersion.cmake + VERSION ${PNGLIB_VERSION} + COMPATIBILITY SameMinorVersion) + + install(EXPORT PNGTargets + FILE PNGTargets.cmake + NAMESPACE PNG:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/PNG") + + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/PNGConfig.cmake" + "${CMAKE_CURRENT_BINARY_DIR}/PNGConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/PNG") +endif() + +# TODO: Create MSVC import lib for MinGW-compiled shared lib. +# pexports libpng.dll > libpng.def +# lib /def:libpng.def /machine:x86 diff --git a/media/libpng/LICENSE.md b/media/libpng/LICENSE.md new file mode 100644 index 0000000000..1b765ae9f9 --- /dev/null +++ b/media/libpng/LICENSE.md @@ -0,0 +1,134 @@ +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE +========================================= + +PNG Reference Library License version 2 +--------------------------------------- + + * Copyright (c) 1995-2026 The PNG Reference Library Authors. + * Copyright (c) 2018-2026 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. + +The software is supplied "as is", without warranty of any kind, +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 +disclaimer and license as libpng-1.0.6 with the following individuals +added to the list of Contributing Authors: + + Simon-Pierre Cadieux + Eric S. Raymond + Mans Rullgard + Cosmin Truta + Gilles Vollant + James Yu + Mandar Sahastrabuddhe + Google Inc. + Vadim Barkov + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of + the library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is + 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 +Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from +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 of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, +and are distributed according to the same disclaimer and license as +libpng-0.88, with the following individuals added to the list of +Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +Some files in the "scripts" directory have other copyright owners, +but are released under this license. + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing +Authors and Group 42, Inc. disclaim all warranties, expressed or +implied, including, without limitation, the warranties of +merchantability and of fitness for any purpose. The Contributing +Authors and Group 42, Inc. assume no liability for direct, indirect, +incidental, special, exemplary, or consequential damages, which may +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 +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + + 1. The origin of this source code must not be misrepresented. + + 2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, +without fee, and encourage the use of this source code as a component +to supporting the PNG file format in commercial products. If you use +this source code in a product, acknowledgment is not required but would +be appreciated. diff --git a/media/libpng/LICENSES/MIT-0.txt b/media/libpng/LICENSES/MIT-0.txt new file mode 100644 index 0000000000..30c629513b --- /dev/null +++ b/media/libpng/LICENSES/MIT-0.txt @@ -0,0 +1,16 @@ +MIT No Attribution + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/media/libpng/LICENSES/MIT.txt b/media/libpng/LICENSES/MIT.txt new file mode 100644 index 0000000000..9cf106272a --- /dev/null +++ b/media/libpng/LICENSES/MIT.txt @@ -0,0 +1,19 @@ +MIT License + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/media/libpng/Makefile.am b/media/libpng/Makefile.am new file mode 100644 index 0000000000..eb70781589 --- /dev/null +++ b/media/libpng/Makefile.am @@ -0,0 +1,420 @@ +# Makefile.am, the source file for Makefile.in (and hence Makefile), is +# +# Copyright (c) 2018-2026 Cosmin Truta +# Copyright (c) 2004-2016 Glenn Randers-Pehrson +# +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +PNGLIB_BASENAME= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ + +ACLOCAL_AMFLAGS = -I scripts/autoconf + +# test programs - run on make check, make distcheck +if ENABLE_TESTS +check_PROGRAMS= pngtest pnggetset pngunknown pngstest pngvalid pngimage pngcp +if HAVE_CLOCK_GETTIME +check_PROGRAMS += timepng +endif +else +check_PROGRAMS= +endif + +# Utilities - installed +if ENABLE_TOOLS +bin_PROGRAMS= pngfix png-fix-itxt +else +bin_PROGRAMS= +endif + +# This ensures that pnglibconf.h gets built at the start of 'make all' or +# 'make check', but it does not add dependencies to the individual programs, +# this is done below. +# +# IMPORTANT: always add the object modules of new programs to the list below +# because otherwise the sequence 'configure; make new-program' will *sometimes* +# result in the installed (system) pnglibconf.h being used and the result is +# always wrong and always very confusing. +BUILT_SOURCES = pnglibconf.h + +if ENABLE_TESTS +pngtest_SOURCES = pngtest.c +pngtest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pnggetset_SOURCES = contrib/libtests/pnggetset.c +pnggetset_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pngvalid_SOURCES = contrib/libtests/pngvalid.c +pngvalid_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pngstest_SOURCES = contrib/libtests/pngstest.c +pngstest_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pngunknown_SOURCES = contrib/libtests/pngunknown.c +pngunknown_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pngimage_SOURCES = contrib/libtests/pngimage.c +pngimage_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +timepng_SOURCES = contrib/libtests/timepng.c +timepng_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +pngcp_SOURCES = contrib/tools/pngcp.c +pngcp_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +endif + +if ENABLE_TOOLS +pngfix_SOURCES = contrib/tools/pngfix.c +pngfix_LDADD = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la + +png_fix_itxt_SOURCES = contrib/tools/png-fix-itxt.c +endif + +# Generally these are single line shell scripts to run a test with a particular +# set of parameters: +if ENABLE_TESTS +TESTS =\ + tests/pngtest-all\ + tests/pnggetset\ + tests/pngvalid-gamma-16-to-8\ + tests/pngvalid-gamma-alpha-mode\ + tests/pngvalid-gamma-background\ + tests/pngvalid-gamma-expand16-alpha-mode\ + tests/pngvalid-gamma-expand16-background\ + tests/pngvalid-gamma-expand16-transform\ + tests/pngvalid-gamma-sbit\ + tests/pngvalid-gamma-threshold\ + tests/pngvalid-gamma-transform\ + tests/pngvalid-progressive-size\ + tests/pngvalid-progressive-interlace-standard\ + tests/pngvalid-transform\ + tests/pngvalid-progressive-standard\ + tests/pngvalid-standard\ + tests/pngstest-1.8\ + tests/pngstest-1.8-alpha\ + tests/pngstest-linear\ + tests/pngstest-linear-alpha\ + tests/pngstest-none\ + tests/pngstest-none-alpha\ + tests/pngstest-sRGB\ + tests/pngstest-sRGB-alpha\ + tests/pngstest-large-stride\ + tests/pngstest-negative-stride\ + tests/pngstest-negative-stride-extra\ + tests/pngunknown-IDAT\ + tests/pngunknown-discard\ + tests/pngunknown-if-safe\ + tests/pngunknown-sAPI\ + tests/pngunknown-sTER\ + tests/pngunknown-save\ + tests/pngunknown-vpAg\ + tests/pngimage-quick\ + tests/pngimage-full +endif + +# man pages +dist_man_MANS= manuals/libpng.3 manuals/png.5 + +# generate the -config scripts if required +binconfigs= libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config +EXTRA_SCRIPTS= libpng-config libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config +bin_SCRIPTS= @binconfigs@ + +# rules to build libpng, only build the old library on request +lib_LTLIBRARIES=libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.la +# EXTRA_LTLIBRARIES= libpng.la +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\ + pngget.c pngmem.c pngpread.c pngread.c pngrio.c pngrtran.c pngrutil.c\ + pngset.c pngtrans.c pngwio.c pngwrite.c pngwtran.c pngwutil.c\ + pngsimd.c\ + png.h pngconf.h pngdebug.h pnginfo.h pngpriv.h pngstruct.h pngusr.dfa + +nodist_libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = pnglibconf.h + +libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS = -no-undefined -export-dynamic \ + -version-number @PNGLIB_MAJOR@@PNGLIB_MINOR@:@PNGLIB_RELEASE@:0 + +if HAVE_LD_VERSION_SCRIPT +# Versioned symbols and restricted exports +if HAVE_SOLARIS_LD + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -Wl,-M -Wl,libpng.vers +else + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -Wl,--version-script=libpng.vers +endif + + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.vers +else +# Only restricted exports when possible + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_LDFLAGS += -export-symbols libpng.sym + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_DEPENDENCIES = libpng.sym +endif + +#distribute headers in /usr/include/libpng/* +pkgincludedir= $(includedir)/$(PNGLIB_BASENAME) +pkginclude_HEADERS= png.h pngconf.h +nodist_pkginclude_HEADERS= pnglibconf.h + +# pkg-config stuff, note that libpng.pc is always required in order +# to get the correct library +pkgconfigdir = @pkgconfigdir@ +pkgconfig_DATA = libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc + +# Extra source distribution files, '${srcdir}' is used below to stop build files +# from those directories being included. This only works if the configure is +# not done in the source directory! +EXTRA_DIST= \ + ANNOUNCE AUTHORS CHANGES INSTALL LICENSE README TODO TRADEMARK \ + pngtest.png pngbar.png pngnow.png pngbar.jpg autogen.sh \ + ${srcdir}/ci ${srcdir}/contrib ${srcdir}/projects ${srcdir}/scripts \ + $(TESTS) $(XFAIL_TESTS) tests/pngstest \ + CMakeLists.txt example.c libpng-manual.txt + +SCRIPT_CLEANFILES=scripts/pnglibconf/*.out scripts/pnglibconf/*.chk + +CLEANFILES= *.tf? pngout.png libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@.pc \ + libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@-config libpng.vers libpng.sym \ + check.new pnglibconf.h pngprefix.h symbols.new pngtest-log.txt \ + pnglibconf.out pnglibconf.c pnglibconf.pre pnglibconf.dfn \ + $(SCRIPT_CLEANFILES) + +MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess config.h.in \ +config.sub configure depcomp install-sh ltmain.sh missing + +# PNG_COPTS give extra options for the C compiler to be used on all compilation +# steps (unless target_CFLAGS is specified; that will take precedence over +# AM_CFLAGS) +PNG_COPTS = @PNG_COPTS@ +AM_CFLAGS = ${PNG_COPTS} + +# DFNCPP is normally just CPP - the C preprocessor - but on Solaris and maybe +# other operating systems (NeXT?) the C preprocessor selected by configure +# checks input tokens for validity - effectively it performs part of the ANSI-C +# parsing - and therefore fails with the .df files. configure.ac has special +# checks for this and sets DFNCPP appropriately. +DFNCPP = @DFNCPP@ + +SUFFIXES = .chk .out + +$(PNGLIB_BASENAME).pc: libpng.pc + cp libpng.pc $@ + +$(PNGLIB_BASENAME)-config: libpng-config + cp libpng-config $@ + +scripts/pnglibconf/sym.out scripts/pnglibconf/vers.out: png.h pngconf.h pnglibconf.h +scripts/pnglibconf/prefix.out: png.h pngconf.h pnglibconf.out +scripts/pnglibconf/symbols.out: png.h pngconf.h $(srcdir)/pnglibconf.h.prebuilt +scripts/pnglibconf/intprefix.out: pnglibconf.h + +libpng.sym: scripts/pnglibconf/sym.out + rm -f $@ + cp $? $@ +libpng.vers: scripts/pnglibconf/vers.out + rm -f $@ + cp $? $@ + +if DO_PNG_PREFIX +# Rename functions in scripts/pnglibconf/prefix.out with a PNG_PREFIX prefix. +# Rename macros in scripts/macro.lst from PNG_PREFIXpng_ to PNG_ (the actual +# implementation of the macro). +pnglibconf.h: pnglibconf.out scripts/pnglibconf/prefix.out scripts/macro.lst + rm -f $@ + $(AWK) 's==0 && NR>1{print prev}\ + s==0{prev=$$0}\ + s==1{print "#define", $$1, "@PNG_PREFIX@" $$1}\ + s==2{print "#define @PNG_PREFIX@png_" $$1, "PNG_" $$1}\ + END{print prev}'\ + s=0 pnglibconf.out\ + s=1 scripts/pnglibconf/prefix.out\ + s=2 "${srcdir}/scripts/macro.lst" >pnglibconf.tf8 + mv pnglibconf.tf8 $@ + +pngprefix.h: scripts/pnglibconf/intprefix.out + rm -f pngprefix.tf1 + $(AWK) '{print "#define", $$1, "@PNG_PREFIX@" $$1}' $? >pngprefix.tf1 + mv pngprefix.tf1 $@ +else +pnglibconf.h: pnglibconf.out + rm -f $@ + cp $? $@ + +pngprefix.h: # is empty + :>$@ +endif + +$(srcdir)/pnglibconf.h.prebuilt: + @echo "Attempting to build $@" >&2 + @echo "This is a machine generated file, but if you want to make" >&2 + @echo "a new one simply make 'scripts/pnglibconf/pnglibconf.out'," >&2 + @echo "copy that AND set PNG_ZLIB_VERNUM to 0 (you MUST do this)" >&2 + @exit 1 + +# The following is necessary to ensure that the local pnglibconf.h is used, not +# an installed one (this can happen immediately after on a clean system if +# 'make test' is the first thing the user does.) Only files which include +# one of the png source files (typically png.h or pngpriv.h) need to be listed +# here: +pngtest.o: pnglibconf.h + +contrib/libtests/makepng.o: pnglibconf.h +contrib/libtests/pnggetset.o: pnglibconf.h +contrib/libtests/pngimage.o: pnglibconf.h +contrib/libtests/pngstest.o: pnglibconf.h +contrib/libtests/pngunknown.o: pnglibconf.h +contrib/libtests/pngvalid.o: pnglibconf.h +contrib/libtests/readpng.o: pnglibconf.h +contrib/libtests/tarith.o: pnglibconf.h +contrib/libtests/timepng.o: pnglibconf.h + +contrib/tools/makesRGB.o: pnglibconf.h +contrib/tools/pngfix.o: pnglibconf.h +contrib/tools/pngcp.o: pnglibconf.h + +# We must use -DPNG_NO_USE_READ_MACROS here even when the library may actually +# be built with PNG_USE_READ_MACROS; this prevents the read macros from +# interfering with the symbol file format. +SYMBOL_CFLAGS = -DPNGLIB_LIBNAME='PNG@PNGLIB_MAJOR@@PNGLIB_MINOR@_0'\ + -DPNGLIB_VERSION='@PNGLIB_VERSION@'\ + -DSYMBOL_PREFIX='$(SYMBOL_PREFIX)'\ + -DPNG_NO_USE_READ_MACROS -DPNG_BUILDING_SYMBOL_TABLE + +if DO_PNG_PREFIX +SYMBOL_CFLAGS += -DPNG_PREFIX='@PNG_PREFIX@' +endif + +.c.out: + rm -f $@ $*.tf[12] + test -d scripts || mkdir scripts || test -d scripts + test -d scripts/pnglibconf || mkdir scripts/pnglibconf || test -d scripts/pnglibconf + $(DFNCPP) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)\ + $(CPPFLAGS) $(SYMBOL_CFLAGS) $< > $*.tf1 + $(AWK) -f "${srcdir}/scripts/pnglibconf/dfn.awk"\ + out=$*.tf2 $*.tf1 1>&2 + rm -f $*.tf1 + mv $*.tf2 $@ + +# The .c file for pnglibconf.h is machine generated +pnglibconf.c: scripts/pnglibconf/pnglibconf.dfa scripts/pnglibconf/options.awk pngconf.h \ + pngusr.dfa $(DFA_XTRA) + rm -f $@ $*.tf[45] + $(AWK) -f "${srcdir}/scripts/pnglibconf/options.awk"\ + out=$*.tf4 version=search\ + "${srcdir}/pngconf.h" "${srcdir}/scripts/pnglibconf/pnglibconf.dfa"\ + "${srcdir}/pngusr.dfa" $(DFA_XTRA) 1>&2 + $(AWK) -f "${srcdir}/scripts/pnglibconf/options.awk"\ + out=$*.tf5 $*.tf4 1>&2 + rm $*.tf4 + mv $*.tf5 $@ + +# Symbol checks (.def and .out files should match) +scripts/pnglibconf/symbols.chk: scripts/pnglibconf/checksym.awk scripts/symbols.def \ + scripts/pnglibconf/symbols.out + +.out.chk: + rm -f $@ $*.new + $(AWK) -f "${srcdir}/scripts/pnglibconf/checksym.awk"\ + of=$*.new ${srcdir}/scripts/${*F}.def $*.out >&2 + mv $*.new $@ + +# used on demand to regenerate the standard header, CPPFLAGS should +# be empty - no non-standard defines +scripts/pnglibconf/pnglibconf.c: scripts/pnglibconf/pnglibconf.dfa scripts/pnglibconf/options.awk \ + pngconf.h + rm -f $@ pnglibconf.tf[67] + test -z "$(CPPFLAGS)" + echo "com @PNGLIB_VERSION@ STANDARD API DEFINITION" |\ + $(AWK) -f "${srcdir}/scripts/pnglibconf/options.awk"\ + out=pnglibconf.tf6 logunsupported=1 version=search\ + "${srcdir}/pngconf.h" -\ + "${srcdir}/scripts/pnglibconf/pnglibconf.dfa" 1>&2 + $(AWK) -f "${srcdir}/scripts/pnglibconf/options.awk"\ + out=pnglibconf.tf7 pnglibconf.tf6 1>&2 + rm pnglibconf.tf6 + mv pnglibconf.tf7 $@ + +$(libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_OBJECTS): png.h pngconf.h pnglibconf.h pngpriv.h \ + pngdebug.h pnginfo.h pngstruct.h pngprefix.h + +test: check-am + +# Extra checks +check: scripts/pnglibconf/symbols.chk + +# Don't distribute the generated script files +dist-hook: + cd '$(top_distdir)'; rm -f $(SCRIPT_CLEANFILES) + +# Make links between installed files with release-specific names and the generic +# file names. If this install rule is run the generic names will be deleted and +# recreated - this has obvious issues for systems with multiple installations. + +install-header-links: + @set -ex; cd '$(DESTDIR)$(includedir)'; for f in $(HEADERS); do \ + rm -f "$$f"; $(LN_S) "$(PNGLIB_BASENAME)/$$f" "$$f"; done + +uninstall-header-links: + cd '$(DESTDIR)$(includedir)'; rm -f $(HEADERS) + +install-libpng-pc: + @set -ex; cd '$(DESTDIR)$(pkgconfigdir)'; rm -f libpng.pc; \ + $(LN_S) '$(PNGLIB_BASENAME).pc' libpng.pc + +uninstall-libpng-pc: + rm -f '$(DESTDIR)$(pkgconfigdir)/libpng.pc' + +# EXT_LIST is a list of the possibly library directory extensions, this exists +# because we can't find a good way of discovering the file extensions that are +# actually installed on a given system, so instead we check for every extension +# we have seen. + +EXT_LIST = a dll.a so so.@PNGLIB_MAJOR@@PNGLIB_MINOR@.@PNGLIB_RELEASE@ la sl dylib + +install-library-links: + @set -x; cd '$(DESTDIR)$(libdir)';\ + for ext in $(EXT_LIST); do\ + rm -f "libpng.$$ext";\ + if test -f "$(PNGLIB_BASENAME).$$ext"; then\ + $(LN_S) "$(PNGLIB_BASENAME).$$ext" "libpng.$$ext" || exit 1;\ + fi;\ + done + +uninstall-library-links: + @set -x; cd '$(DESTDIR)$(libdir)'; for ext in $(EXT_LIST); do\ + rm -f "libpng.$$ext"; done + +install-libpng-config: + @set -ex; cd '$(DESTDIR)$(bindir)'; rm -f libpng-config; \ + $(LN_S) '$(PNGLIB_BASENAME)-config' libpng-config + +uninstall-libpng-config: + rm -f '$(DESTDIR)$(bindir)/libpng-config' + +if DO_INSTALL_LINKS +# If --enable-unversioned-links is specified the header and lib file links +# will be automatically made on a 'make install': + +install-data-hook: install-header-links +uninstall-hook: uninstall-header-links +install-exec-hook: install-library-links +uninstall-hook: uninstall-library-links +endif + +if DO_INSTALL_LIBPNG_PC +# Likewise, --install-pc causes libpng.pc to be constructed: + +install-data-hook: install-libpng-pc +uninstall-hook: uninstall-libpng-pc +endif + +if DO_INSTALL_LIBPNG_CONFIG +# And --install-config: + +install-exec-hook: install-libpng-config +uninstall-hook: uninstall-libpng-config +endif + +# The following addition ensures that 'make all' always builds the test programs +# too. It used to, but some change either in libpng or configure stopped this +# working. +all-am: $(check_PROGRAMS) diff --git a/media/libpng/README b/media/libpng/README deleted file mode 100644 index 709c269d0b..0000000000 --- a/media/libpng/README +++ /dev/null @@ -1,218 +0,0 @@ -README for libpng version 1.6.26 - October 20, 2016 (shared library 16.0) -See the note about version numbers near the top of png.h - -See INSTALL for instructions on how to install libpng. - -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, -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 -fact that it's the first release fool you. The libpng library has been in -extensive use and testing since mid-1995. By late 1997 it had -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 -libraries with versions < 1.0. Version 1.0.0 was released in -March 1998. - -**** -Note that some of the changes to the png_info structure render this -version of the library binary incompatible with libpng-0.89 or -earlier versions if you are using a shared library. The type of the -"filler" parameter for png_set_filler() has changed from png_byte to -png_uint_32, which will affect shared-library applications that use -this function. - -To avoid problems with changes to the internals of png info_struct, -new APIs have been made available in 0.95 to avoid direct application -access to info_ptr. These functions are the png_set_ and -png_get_ functions. These functions should be used when -accessing/storing the info_struct data, rather than manipulating it -directly, to avoid such problems in the future. - -It is important to note that the APIs did not make current programs -that access the info struct directly incompatible with the new -library, through libpng-1.2.x. In libpng-1.4.x, which was meant to -be a transitional release, members of the png_struct and the -info_struct can still be accessed, but the compiler will issue a -warning about deprecated usage. Since libpng-1.5.0, direct access -to these structs is not allowed, and the definitions of the structs -reside in private pngstruct.h and pnginfo.h header files that are not -accessible to applications. It is strongly suggested that new -programs use the new APIs (as shown in example.c and pngtest.c), and -older programs be converted to the new format, to facilitate upgrades -in the future. -**** - -Additions since 0.90 include the ability to compile libpng as a -Windows DLL, and new APIs for accessing data in the info struct. -Experimental functions include the ability to set weighting and cost -factors for row filter selection, direct reads of integers from buffers -on big-endian processors that support misaligned data access, faster -methods of doing alpha composition, and more accurate 16->8 bit color -conversion. - -The additions since 0.89 include the ability to read from a PNG stream -which has had some (or all) of the signature bytes read by the calling -application. This also allows the reading of embedded PNG streams that -do not have the PNG file signature. As well, it is now possible to set -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 -critical or an ancillary chunk. - -The changes made to the library, and bugs fixed are based on discussions -on the PNG-implement mailing list and not on material submitted -privately to Guy, Andreas, or Glenn. They will forward any good -suggestions to the list. - -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 -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 -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 -some images. You will definitely need zlib 1.0.4 or later if you are -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 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 -these at http://www.libpng.org/pub/png/documents/ - -This code is currently being archived at libpng.sf.net in the -[DOWNLOAD] area, and at ftp://ftp.simplesystems.org. If you can't find it -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 -Number (ECCN) for libpng is EAR99, which means not subject to export -controls or International Traffic in Arms Regulations (ITAR) because it -is open source, publicly available software, that does not contain any -encryption software. See the EAR, paragraphs 734.3(b)(3) and 734.7(b). - -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. - -Send comments/corrections/commendations to png-mng-implement at -lists.sourceforge.net (subscription required; visit -https://lists.sourceforge.net/lists/listinfo/png-mng-implement -to subscribe) or to glennrp at users.sourceforge.net - -You can't reach Guy, the original libpng author, at the addresses -given in previous versions of this document. He and Andreas will -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 -subscribe). If you have a question about something -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: - - ANNOUNCE => Announcement of this version, with recent changes - CHANGES => Description of changes between libpng versions - KNOWNBUG => List of known bugs and deficiencies - LICENSE => License to use and redistribute libpng - README => This file - TODO => Things not implemented in the current library - Y2KINFO => Statement of Y2K compliance - example.c => Example code for using libpng functions - libpng.3 => manual page for libpng (includes libpng-manual.txt) - libpng-manual.txt => Description of libpng and its functions - libpngpf.3 => manual page for libpng's private functions - png.5 => manual page for the PNG format - png.c => Basic interface functions common to library - png.h => Library function and interface declarations (public) - pngpriv.h => Library function and interface declarations (private) - pngconf.h => System specific library configuration (public) - pngstruct.h => png_struct declaration (private) - pnginfo.h => png_info struct declaration (private) - pngdebug.h => debugging macros (private) - pngerror.c => Error/warning message I/O functions - pngget.c => Functions for retrieving info from struct - pngmem.c => Memory handling functions - pngbar.png => PNG logo, 88x31 - pngnow.png => PNG logo, 98x31 - pngpread.c => Progressive reading functions - pngread.c => Read data/helper high-level functions - pngrio.c => Lowest-level data read I/O functions - pngrtran.c => Read data transformation functions - pngrutil.c => Read data utility functions - pngset.c => Functions for storing data into the info_struct - pngtest.c => Library test program - pngtest.png => Library test sample image - pngtrans.c => Common data transformation functions - pngwio.c => Lowest-level write I/O functions - pngwrite.c => High-level write functions - pngwtran.c => Write data transformations - pngwutil.c => Write utility functions - arm => Contains optimized code for the ARM platform - contrib => Contributions - arm-neon => Optimized code for ARM-NEON platform - examples => Example programs - gregbook => source code for PNG reading and writing, from - Greg Roelofs' "PNG: The Definitive Guide", - O'Reilly, 1999 - intel => Optimized code for INTEL-SSE2 platform - libtests => Test programs - pngminim => Minimal decoder, encoder, and progressive decoder - programs demonstrating use of pngusr.dfa - pngminus => Simple pnm2png and png2pnm programs - pngsuite => Test images - testpngs - tools => Various tools - visupng => Contains a MSVC workspace for VisualPng - projects => Contains project files and workspaces for - building a DLL - owatcom => Contains a WATCOM project for building libpng - visualc71 => Contains a Microsoft Visual C++ (MSVC) - workspace for building libpng and zlib - vstudio => Contains a Microsoft Visual C++ (MSVC) - workspace for building libpng and zlib - scripts => Directory containing scripts for building libpng: - (see scripts/README.txt for the list of scripts) - -Good luck, and happy coding. - --Glenn Randers-Pehrson (current maintainer, since 1998) - Internet: glennrp at users.sourceforge.net - --Andreas Eric Dilger (former maintainer, 1996-1997) - Internet: adilger at enel.ucalgary.ca - 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 diff --git a/media/libpng/README.md b/media/libpng/README.md new file mode 100644 index 0000000000..d2a9e7143f --- /dev/null +++ b/media/libpng/README.md @@ -0,0 +1,184 @@ +README for libpng version 1.8.0.git +=================================== + +See the note about version numbers near the top of `png.h`. +See `INSTALL` for instructions on how to install libpng. + +Libpng comes in several distribution formats. Get `libpng-*.tar.gz` +or `libpng-*.tar.xz` if you want UNIX-style line endings in the text +files, or `lpng*.7z` or `lpng*.zip` if you want DOS-style line endings. + +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`. + +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 which can cause the output of invalid compression streams for +some images. + +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 +. + +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 +these at . + +This code is currently being archived at +in the download area, and at . + +This release, based in a large way on Glenn's, Guy's and Andreas' +earlier work, was created and will be supported by myself and the PNG +development group. + +Send comments, corrections and commendations to `png-mng-implement` +at `lists.sourceforge.net`. (Subscription is required; visit + +to subscribe.) + +Send general questions about the PNG specification to `png-mng-misc` +at `lists.sourceforge.net`. (Subscription is required; visit + +to subscribe.) + +Historical notes +---------------- + +The libpng library has been in extensive use and testing since mid-1995. +Version 0.89, published a year later, was the first official release. +By late 1997, it had 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 libraries with versions below 1.0. Version 1.0.0 was +released in March 1998. + +Note that some of the changes to the `png_info` structure render this +version of the library binary incompatible with libpng-0.89 or +earlier versions if you are using a shared library. The type of the +`filler` parameter for `png_set_filler()` has changed from `png_byte` +to `png_uint_32`, which will affect shared-library applications that +use this function. + +To avoid problems with changes to the internals of the `info_struct`, +new APIs have been made available in 0.95 to avoid direct application +access to `info_ptr`. These functions are the `png_set_` and +`png_get_` functions. These functions should be used when +accessing/storing the `info_struct` data, rather than manipulating it +directly, to avoid such problems in the future. + +It is important to note that the APIs did not make current programs +that access the info struct directly incompatible with the new +library, through libpng-1.2.x. In libpng-1.4.x, which was meant to +be a transitional release, members of the `png_struct` and the +`info_struct` can still be accessed, but the compiler will issue a +warning about deprecated usage. Since libpng-1.5.0, direct access +to these structs is not allowed, and the definitions of the structs +reside in private `pngstruct.h` and `pnginfo.h` header files that are +not accessible to applications. It is strongly suggested that new +programs use the new APIs (as shown in `example.c` and `pngtest.c`), +and older programs be converted to the new format, to facilitate +upgrades in the future. + +The additions since 0.89 include the ability to read from a PNG stream +which has had some (or all) of the signature bytes read by the calling +application. This also allows the reading of embedded PNG streams that +do not have the PNG file signature. As well, it is now possible to set +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 +critical or an ancillary chunk. + +The additions since 0.90 include the ability to compile libpng as a +Windows DLL, and new APIs for accessing data in the `info_struct`. +Experimental functions included the ability to set weighting and cost +factors for row filter selection, direct reads of integers from buffers +on big-endian processors that support misaligned data access, faster +methods of doing alpha composition, and more accurate 16-to-8 bit color +conversion. Some of these experimental functions, such as the weighted +filter heuristics, have since been removed. + +Files included in this distribution +----------------------------------- + + ANNOUNCE.md => Announcement of this version, with recent changes + AUTHORS.md => List of contributing authors + CHANGES => Description of changes between libpng versions + LICENSE.md => License to use and redistribute libpng + README.md => This file + TODO.md => Things not implemented in the current library + TRADEMARK.md => Trademark information + example.c => Example code for using libpng functions + png.c => Basic interface functions common to library + png.h => Library function and interface declarations (public) + pngpriv.h => Library function and interface declarations (private) + pngconf.h => System specific library configuration (public) + pngstruct.h => png_struct declaration (private) + pnginfo.h => png_info struct declaration (private) + pngdebug.h => debugging macros (private) + pngerror.c => Error/warning message I/O functions + pngget.c => Functions for retrieving info from struct + pngmem.c => Memory handling functions + pngbar.png => PNG logo, 88x31 + pngnow.png => PNG logo, 98x31 + pngpread.c => Progressive reading functions + pngread.c => Read data/helper high-level functions + pngrio.c => Lowest-level data read I/O functions + pngrtran.c => Read data transformation functions + pngrutil.c => Read data utility functions + pngset.c => Functions for storing data into the info_struct + pngtest.c => Library test program + pngtest.png => Library test sample image + pngtrans.c => Common data transformation functions + pngwio.c => Lowest-level write I/O functions + pngwrite.c => High-level write functions + pngwtran.c => Write data transformations + pngwutil.c => Write utility functions + arm/ => Optimized code for ARM Neon + intel/ => Optimized code for INTEL SSE2 + loongarch/ => Optimized code for LoongArch LSX + mips/ => Optimized code for MIPS MSA and MIPS MMI + powerpc/ => Optimized code for PowerPC VSX + riscv/ => Optimized code for the RISC-V platform + ci/ => Scripts for continuous integration + contrib/ => External contributions + arm-neon/ => Optimized code for the ARM-NEON platform + mips-msa/ => Optimized code for the MIPS-MSA platform + powerpc-vsx/ => Optimized code for the POWERPC-VSX platform + examples/ => Examples of libpng usage + gregbook/ => Source code for PNG reading and writing, from + "PNG: The Definitive Guide" by Greg Roelofs, + O'Reilly, 1999 + libtests/ => Test programs + pngexif/ => Program to inspect the EXIF information in PNG files + pngminim/ => Minimal decoder, encoder, and progressive decoder + programs demonstrating the use of pngusr.dfa + pngminus/ => Simple pnm2png and png2pnm programs + pngsuite/ => Test images + riscv-rvv/ => Optimized code for the RISC-V Vector platform + testpngs/ => Test images + tools/ => Various tools + visupng/ => VisualPng, a Windows viewer for PNG images + manuals/ => Manuals + libpng-install.txt => Instructions to install libpng + libpng-manual.txt => Description of libpng and its functions + libpng.3 => Manual page for libpng (includes libpng-manual.txt) + png.5 => Manual page for the PNG format + projects/ => Project files and workspaces for various IDEs + owatcom/ => OpenWatcom project + visualc71/ => Microsoft Visual C++ 7.1 workspace + vstudio/ => Microsoft Visual Studio workspace + scripts/ => Scripts and makefiles for building libpng + (see scripts/README.txt for the complete list) + tests/ => Test scripts + +Good luck, and happy coding! + + * Cosmin Truta (current maintainer, since 2018) + * Glenn Randers-Pehrson (former maintainer, 1998-2018) + * Andreas Eric Dilger (former maintainer, 1996-1997) + * Guy Eric Schalnat (original author and former maintainer, 1995-1996) + (formerly of Group 42, Inc.) diff --git a/media/libpng/REUSE.toml b/media/libpng/REUSE.toml new file mode 100644 index 0000000000..4f385e592d --- /dev/null +++ b/media/libpng/REUSE.toml @@ -0,0 +1,9 @@ +version = 1 + +[[annotations]] +SPDX-License-Identifier = "MIT" +path = "ci/**" + +[[annotations]] +SPDX-License-Identifier = "MIT-0" +path = ".github/workflows/**" diff --git a/media/libpng/TODO.md b/media/libpng/TODO.md new file mode 100644 index 0000000000..83b123753b --- /dev/null +++ b/media/libpng/TODO.md @@ -0,0 +1,22 @@ +TODO list for libpng +==================== + + * Fix all defects (duh!) + * cHRM transformation. + * Palette creation. + * "grayscale->palette" transformation and "palette->grayscale" detection. + * Improved dithering. + * Multi-lingual error and warning message support. + * Complete sRGB transformation. (Currently it simply uses gamma=0.45455.) + * Man pages for function calls. + * Better documentation. + * Better filter selection + (e.g., counting huffman bits/precompression; filter inertia; filter costs). + * Histogram creation. + * Text conversion between different code pages (e.g., Latin-1 to Mac). + * Avoid building gamma tables whenever possible. + * Greater precision in changing to linear gamma for compositing against + background, and in doing rgb-to-gray transformations. + * Investigate pre-incremented loop counters and other loop constructions. + * Interpolated method of handling interlacing. + * More validations for libpng transformations. diff --git a/media/libpng/TRADEMARK.md b/media/libpng/TRADEMARK.md new file mode 100644 index 0000000000..ac667187d6 --- /dev/null +++ b/media/libpng/TRADEMARK.md @@ -0,0 +1,8 @@ +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. diff --git a/media/libpng/arm/arm_init.c b/media/libpng/arm/arm_init.c index f86fc8f662..664d05d857 100644 --- a/media/libpng/arm/arm_init.c +++ b/media/libpng/arm/arm_init.c @@ -1,117 +1,34 @@ - /* arm_init.c - NEON optimised filter functions * + * Copyright (c) 2018-2022 Cosmin Truta * Copyright (c) 2014,2016 Glenn Randers-Pehrson * Written by Mans Rullgard, 2011. - * Last changed in libpng 1.6.22 [May 26, 2016] * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ -/* Below, after checking __linux__, various non-C90 POSIX 1003.1 functions are - * called. - */ -#define _POSIX_SOURCE 1 - -#include "../pngpriv.h" - -#ifdef PNG_READ_SUPPORTED +#define png_target_impl "arm-neon" -#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 "linux.c" -# endif +#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_ARM64) +# include +#else +# include #endif -#ifdef PNG_ARM_NEON_FILE - -#include /* 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 */ +/* Obtain the definitions of the actual filter functions: */ +#include "filter_neon_intrinsics.c" -#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) +static void +png_init_filter_functions_neon(png_struct *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: + /* IMPORTANT: DO NOT DEFINE EXTERNAL FUNCTIONS HERE * - * ./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.) + * This is because external functions must be declared with + * PNG_INTERNAL_FUNCTION in pngpriv.h; without this the PNG_PREFIX option to + * the build will not work (it will not know about these symbols). */ pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon; @@ -131,5 +48,185 @@ png_init_filter_functions_neon(png_structp pp, unsigned int bpp) png_read_filter_row_paeth4_neon; } } -#endif /* PNG_ARM_NEON_OPT > 0 */ -#endif /* READ */ + +#define png_target_init_filter_functions_impl png_init_filter_functions_neon + +#ifdef PNG_TARGET_STORES_DATA +/* png_target_free_data_impl + * Must be defined if the implementation stores data in + * png_struct::target_data. Need not be defined otherwise. + */ +static void +png_target_free_data_arm(png_struct *pp) +{ + void *ptr = pp->target_data; + pp->target_data = NULL; + png_free(pp, ptr); +} +#define png_target_free_data_impl png_target_free_data_arm +#endif /* TARGET_STORES_DATA */ + +#ifdef PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE +/* png_target_do_expand_palette_impl [flag: png_target_expand_palette] + * static function + * OPTIONAL + * Handles the transform. Need not be defined, only called if the + * state contains png_target_, may set this flag to zero, may + * return false to indicate that the transform was not done (so the + * C implementation must then execute). + */ +#include "palette_neon_intrinsics.c" + +static int +png_target_do_expand_palette_neon(png_struct *png_ptr, png_row_info *row_info, + png_byte *row, const png_color *palette, const png_byte *trans_alpha, + int num_trans) +{ + /* NOTE: it is important that this is done. row_info->width is not a CSE + * because the pointer is not declared with the 'restrict' parameter, this + * makes it a CSE but then it is very important that no one changes it in + * this function, hence the const. + */ + const png_uint_32 row_width = row_info->width; + + /* NOTE: this is pretty much the original code: + * + * 1) The original code only works when the original PNG has 8-bits per + * palette. This test was in pngrtran.c and is now here. + * + * 2) The original code starts at the end and works backward but then stops + * when it is within 16 bytes of the start. It then left the remainder to + * the original code in pngrtran.c That code is now here. + * + * 3) The original code takes pointers to the end of the input and the end of + * the output; this is the way png_do_expand_palette works because it + * has to copy down from the end (otherwise it would overwrite the input + * data before it read it). Note that the row buffer is aliased by + * these two pointers. + * + * A consequence of passing pointers is that the row pointers (input and + * output) are forced into memory (they can't be in registers). This + * could be fixed and some compilers may be able to handle this but + * no changes have been made to the original ARM code at this point. + */ + if (row_info->color_type == PNG_COLOR_TYPE_PALETTE && + row_info->bit_depth == 8 /* <8 requires a bigger "riffled" palette */) + { + const png_byte *sp = row + (row_width - 1); /* 8 bit palette index */ + if (num_trans > 0) + { + /* This case needs a "riffled" palette. In this implementation the + * initialization is done here, on demand. + */ + if (png_ptr->target_data == NULL) + { + /* Initialize the accelerated palette expansion. + * + * The data is now allocated using png_malloc_warn so the code + * does not error out on OOM. + */ + png_ptr->target_data = png_malloc_warn(png_ptr, 256 * 4); + + /* On allocation error it is essential to clear the flag or a + * massive number of warnings will be output. + */ + if (png_ptr->target_data != NULL) + png_riffle_palette_neon(png_ptr->target_data, palette, + trans_alpha, num_trans); + else + goto clear_flag; + } + + /* This is the general convention in the core transform code; when + * expanding the number of bytes in the row copy down (necessary) and + * pass a pointer to the last byte, not the first. + * + * It does not have to be preserved here but maybe it is better this + * way despite the fact that the comments in the neon palette code + * obfuscate what is happening. + */ + png_byte *dp = row + (4/*RGBA*/*row_width - 1); + + /* Cosmin Truta: "Sometimes row_info->bit_depth has been changed to 8. + * In these cases, the palette hasn't been riffled." + * + * John Bowler: Explanation: The code in png_do_palette_expand + * *invariably* changes the bit depth to 8. So low palette bit depth + * gets expanded to 8 and png_row_info is adjusted to reflect this (see + * png_do_palette_expand), however the "riffle" initialization code + * checked the original png_ptr bit depth, so it didn't know this would + * happen... + * + * This could be changed; the original bit depth is irrelevant to the + * initialization code. + */ + png_uint_32 i = png_target_do_expand_palette_rgba8_neon( + png_ptr->target_data, row_info->width, &sp, &dp); + + if (i == 0) /* nothing was done */ + return 0; /* Return here: interlaced images start out narrow */ + + /* Now 'i' make not have reached row_width. + * NOTE: [i] is not the index into the row buffer, rather than is + * [row_width-i], this is the way it is done in the original + * png_do_expand_palette. + */ + for (; i < row_width; i++) + { + if ((int)(*sp) >= num_trans) + *dp-- = 0xff; + else + *dp-- = trans_alpha[*sp]; + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + + /* Finally update row_info to reflect the expanded output: */ + row_info->bit_depth = 8; + row_info->pixel_depth = 32; + row_info->rowbytes = (size_t)row_width * 4; + row_info->color_type = 6; + row_info->channels = 4; + return 1; + } + else + { + /* No tRNS chunk (num_trans == 0), expand to RGB not RGBA. */ + png_byte *dp = row + (3/*RGB*/ * (size_t)row_width - 1); + + png_uint_32 i = png_target_do_expand_palette_rgb8_neon(palette, + row_info->width, &sp, &dp); + + if (i == 0) + return 0; /* Return here: interlaced images start out narrow */ + + /* Finish the last bytes: */ + for (; i < row_width; i++) + { + *dp-- = palette[*sp].blue; + *dp-- = palette[*sp].green; + *dp-- = palette[*sp].red; + sp--; + } + + row_info->bit_depth = 8; + row_info->pixel_depth = 24; + row_info->rowbytes = (size_t)row_width * 3; + row_info->color_type = 2; + row_info->channels = 3; + return 1; + } + } + +clear_flag: + /* Here on malloc failure and on an inapplicable image. */ + png_ptr->target_state &= ~png_target_expand_palette; + return 0; +} + +#define png_target_do_expand_palette_impl png_target_do_expand_palette_neon +/* EXPAND_PALETTE */ + +#endif /*TODO*/ diff --git a/media/libpng/arm/check.h b/media/libpng/arm/check.h new file mode 100644 index 0000000000..8fb3521a82 --- /dev/null +++ b/media/libpng/arm/check.h @@ -0,0 +1,19 @@ +/* arm/check.h - NEON optimised filter functions + * + * Copyright (c) 2018-2022 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 + */ +#if defined(__ARM_NEON__) || defined(__ARM_NEON) +# define PNG_TARGET_CODE_IMPLEMENTATION "arm/arm_init.c" +# define PNG_TARGET_IMPLEMENTS_FILTERS +# ifdef PNG_READ_EXPAND_SUPPORTED +# define PNG_TARGET_STORES_DATA +# define PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE +# endif /* READ_EXPAND */ +# define PNG_TARGET_ROW_ALIGNMENT 16 +#endif /* ARM_NEON */ diff --git a/media/libpng/arm/filter_neon.S b/media/libpng/arm/filter_neon.S index 65692af3ed..0cbd372cb1 100644 --- a/media/libpng/arm/filter_neon.S +++ b/media/libpng/arm/filter_neon.S @@ -1,20 +1,30 @@ - -/* filter_neon.S - NEON optimised filter functions +/* filter_neon.S - placeholder file * - * Copyright (c) 2014 Glenn Randers-Pehrson - * Written by Mans Rullgard, 2011. - * Last changed in libpng 1.6.16 [December 22, 2014] + * Copyright (c) 2024 Cosmin Truta * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ -/* These are required because Mozilla's moz.build system doesn't pass - * -DDefined macros to the assembler. +/* IMPORTANT NOTE: + * + * Historically, the hand-coded assembler implementation of Neon optimizations + * in this module had not been in sync with the intrinsics-based implementation + * in filter_neon_intrinsics.c and palette_neon_intrinsics.c, at least since + * the introduction of riffled palette optimizations. Moreover, the assembler + * code used to work on 32-bit ARM only, and it caused problems, even if empty, + * on 64-bit ARM. + * + * All references to this module from our internal build scripts and projects + * have been removed. + * + * For the external projects that might still expect this module to be present, + * we leave this stub in place, for the remaining lifetime of libpng-1.6.x. + * Everything should continue to function normally, as long as there are no + * deliberate attempts to use the old hand-made assembler code. A build error + * will be raised otherwise. */ -#define PNG_READ_SUPPORTED -#define MOZ_PNG_HAVE_ARM_NEON /* 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. @@ -22,238 +32,29 @@ #define PNG_VERSION_INFO_ONLY #include "../pngpriv.h" -#if defined(__linux__) && defined(__ELF__) -.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */ -#endif - #ifdef PNG_READ_SUPPORTED - -/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for - * ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it - * only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h - * for the logic which sets PNG_USE_ARM_NEON_ASM: - */ #if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */ - #if PNG_ARM_NEON_OPT > 0 -#ifdef __ELF__ -# define ELF +#if defined(__clang__) +#define GNUC_VERSION 0 /* not gcc, although it might pretend to be */ +#elif defined(__GNUC__) +#define GNUC_MAJOR (__GNUC__ + 0) +#define GNUC_MINOR (__GNUC_MINOR__ + 0) +#define GNUC_PATCHLEVEL (__GNUC_PATCHLEVEL__ + 0) +#define GNUC_VERSION (GNUC_MAJOR * 10000 + GNUC_MINOR * 100 + GNUC_PATCHLEVEL) #else -# define ELF @ +#define GNUC_VERSION 0 /* not gcc */ #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 +#if (GNUC_VERSION > 0) && (GNUC_VERSION < 40300) +#error "PNG_ARM_NEON is not supported with gcc versions earlier than 4.3.0" +#elif GNUC_VERSION == 40504 +#error "PNG_ARM_NEON is not supported with gcc version 4.5.4" +#else +#error "Please use 'arm/*_neon_intrinsics.c' for PNG_ARM_NEON support" +#endif - pop {r4,pc} -endfunc #endif /* PNG_ARM_NEON_OPT > 0 */ -#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */ +#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 */ #endif /* READ */ diff --git a/media/libpng/arm/filter_neon_intrinsics.c b/media/libpng/arm/filter_neon_intrinsics.c index ea7e356bcc..a210bfde22 100644 --- a/media/libpng/arm/filter_neon_intrinsics.c +++ b/media/libpng/arm/filter_neon_intrinsics.c @@ -1,25 +1,16 @@ - /* filter_neon_intrinsics.c - NEON optimised filter functions * + * Copyright (c) 2018 Cosmin Truta * Copyright (c) 2014,2016 Glenn Randers-Pehrson * Written by James Yu , October 2013. * Based on filter_neon.S, written by Mans Rullgard, 2011. * - * Last changed in libpng 1.6.22 [May 26, 2016] - * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ -#include "../pngpriv.h" - -#ifdef PNG_READ_SUPPORTED - -/* This code requires -mfpu=neon on the command line: */ -#if PNG_ARM_NEON_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */ - -#include +/* [[libpng-1.8]] this is file is included by arm/arm_init.c */ /* libpng row pointers are not necessarily aligned to any particular boundary, * however this code will only work with appropriate alignment. arm/arm_init.c @@ -33,19 +24,22 @@ * '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) +static void +png_read_filter_row_up_neon(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_bytep rp = row; - png_bytep rp_stop = row + row_info->rowbytes; - png_const_bytep pp = prev_row; + png_byte *rp = row; + png_byte *rp_stop = row + row_info->rowbytes; + const png_byte *pp = prev_row; png_debug(1, "in png_read_filter_row_up_neon"); @@ -60,12 +54,12 @@ png_read_filter_row_up_neon(png_row_infop row_info, png_bytep row, } } -void -png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) +static void +png_read_filter_row_sub3_neon(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_bytep rp = row; - png_bytep rp_stop = row + row_info->rowbytes; + png_byte *rp = row; + png_byte *rp_stop = row + row_info->rowbytes; uint8x16_t vtmp = vld1q_u8(rp); uint8x8x2_t *vrpt = png_ptr(uint8x8x2_t, &vtmp); @@ -107,12 +101,12 @@ png_read_filter_row_sub3_neon(png_row_infop row_info, png_bytep row, PNG_UNUSED(prev_row) } -void -png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) +static void +png_read_filter_row_sub4_neon(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_bytep rp = row; - png_bytep rp_stop = row + row_info->rowbytes; + png_byte *rp = row; + png_byte *rp_stop = row + row_info->rowbytes; uint8x8x4_t vdest; vdest.val[3] = vdup_n_u8(0); @@ -125,24 +119,27 @@ png_read_filter_row_sub4_neon(png_row_infop row_info, png_bytep row, 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]); - vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + + 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) +static void +png_read_filter_row_avg3_neon(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_bytep rp = row; - png_const_bytep pp = prev_row; - png_bytep rp_stop = row + row_info->rowbytes; + png_byte *rp = row; + const png_byte *pp = prev_row; + png_byte *rp_stop = row + row_info->rowbytes; uint8x16_t vtmp; uint8x8x2_t *vrpt; @@ -204,13 +201,13 @@ png_read_filter_row_avg3_neon(png_row_infop row_info, png_bytep row, } } -void -png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) +static void +png_read_filter_row_avg4_neon(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_bytep rp = row; - png_bytep rp_stop = row + row_info->rowbytes; - png_const_bytep pp = prev_row; + png_byte *rp = row; + png_byte *rp_stop = row + row_info->rowbytes; + const png_byte *pp = prev_row; uint8x8x4_t vdest; vdest.val[3] = vdup_n_u8(0); @@ -223,6 +220,7 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, 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); @@ -240,7 +238,8 @@ png_read_filter_row_avg4_neon(png_row_infop row_info, png_bytep row, vdest.val[3] = vhadd_u8(vdest.val[2], vpp.val[3]); vdest.val[3] = vadd_u8(vdest.val[3], vrp.val[3]); - vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + vdest_val = png_ldr(uint32x2x4_t, &vdest); + vst4_lane_u32(png_ptr(uint32_t,rp), vdest_val, 0); } } @@ -271,13 +270,13 @@ paeth(uint8x8_t a, uint8x8_t b, uint8x8_t c) return e; } -void -png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) +static void +png_read_filter_row_paeth3_neon(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_bytep rp = row; - png_const_bytep pp = prev_row; - png_bytep rp_stop = row + row_info->rowbytes; + png_byte *rp = row; + const png_byte *pp = prev_row; + png_byte *rp_stop = row + row_info->rowbytes; uint8x16_t vtmp; uint8x8x2_t *vrpt; @@ -339,13 +338,13 @@ png_read_filter_row_paeth3_neon(png_row_infop row_info, png_bytep row, } } -void -png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) +static void +png_read_filter_row_paeth4_neon(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_bytep rp = row; - png_bytep rp_stop = row + row_info->rowbytes; - png_const_bytep pp = prev_row; + png_byte *rp = row; + png_byte *rp_stop = row + row_info->rowbytes; + const png_byte *pp = prev_row; uint8x8_t vlast = vdup_n_u8(0); uint8x8x4_t vdest; @@ -359,6 +358,7 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, 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); @@ -378,10 +378,7 @@ png_read_filter_row_paeth4_neon(png_row_infop row_info, png_bytep row, vlast = vpp.val[3]; - vst4_lane_u32(png_ptr(uint32_t,rp), png_ldr(uint32x2x4_t,&vdest), 0); + 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 */ diff --git a/media/libpng/arm/palette_neon_intrinsics.c b/media/libpng/arm/palette_neon_intrinsics.c new file mode 100644 index 0000000000..d5da6aec5c --- /dev/null +++ b/media/libpng/arm/palette_neon_intrinsics.c @@ -0,0 +1,130 @@ +/* palette_neon_intrinsics.c - NEON optimised palette expansion functions + * + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 2017-2018 Arm Holdings. All rights reserved. + * Written by Richard Townsend , February 2017. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Build an RGBA8 palette from the separate RGB and alpha palettes. */ +static void +png_riffle_palette_neon(png_byte *riffled_palette, const png_color *palette, + const png_byte *trans_alpha, int num_trans) +{ + int i; + + /* Initially black, opaque. */ + uint8x16x4_t w = {{ + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0x00), + vdupq_n_u8(0xff), + }}; + + png_debug(1, "in png_riffle_palette_neon"); + + /* 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((const png_byte *)(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 * 4, w); + } + + /* Fix up the missing transparency values. */ + for (i = 0; i < num_trans; i++) + riffled_palette[i * 4 + 3] = trans_alpha[i]; +} + +/* Expands a palettized row into RGBA8. */ +static png_uint_32 +png_target_do_expand_palette_rgba8_neon(const png_uint_32 *riffled_palette, + png_uint_32 row_width, const png_byte **ssp, png_byte **ddp) +{ + const png_uint_32 pixels_per_chunk = 4; + png_uint_32 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 * 4 - 1); + + for (i = 0; i + pixels_per_chunk <= row_width; i += pixels_per_chunk) + { + uint32x4_t cur; + const png_byte *sp = *ssp - i; + png_byte *dp = *ddp - i * 4; + 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); + } + + /* Undo the pre-adjustment of *ddp before the pointer handoff, + * so the scalar fallback in pngrtran.c receives a dp that points + * to the correct position. + */ + *ddp = *ddp + (pixels_per_chunk * 4 - 1); + *ssp = *ssp - i; + *ddp = *ddp - i * 4; + return i; +} + +/* Expands a palettized row into RGB8. */ +static png_uint_32 +png_target_do_expand_palette_rgb8_neon(const png_color *paletteIn, + png_uint_32 row_width, const png_byte **ssp, png_byte **ddp) +{ + /* TODO: This case is VERY dangerous: */ + const png_byte *palette = (const png_byte *)paletteIn; + + const png_uint_32 pixels_per_chunk = 8; + png_uint_32 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 * 3 - 1); + + for (i = 0; i + pixels_per_chunk <= row_width; i += pixels_per_chunk) + { + uint8x8x3_t cur; + const png_byte *sp = *ssp - i; + const png_byte *dp = *ddp - i * 3; + cur = vld3_dup_u8(palette + *(sp - 7) * 3); + cur = vld3_lane_u8(palette + *(sp - 6) * 3, cur, 1); + cur = vld3_lane_u8(palette + *(sp - 5) * 3, cur, 2); + cur = vld3_lane_u8(palette + *(sp - 4) * 3, cur, 3); + cur = vld3_lane_u8(palette + *(sp - 3) * 3, cur, 4); + cur = vld3_lane_u8(palette + *(sp - 2) * 3, cur, 5); + cur = vld3_lane_u8(palette + *(sp - 1) * 3, cur, 6); + cur = vld3_lane_u8(palette + *(sp - 0) * 3, cur, 7); + vst3_u8((void *)dp, cur); + } + + /* Undo the pre-adjustment of *ddp before the pointer handoff, + * so the scalar fallback in pngrtran.c receives a dp that points + * to the correct position. + */ + *ddp = *ddp + (pixels_per_chunk * 3 - 1); + *ssp = *ssp - i; + *ddp = *ddp - i * 3; + return i; +} diff --git a/media/libpng/autogen.sh b/media/libpng/autogen.sh new file mode 100644 index 0000000000..4ac8f4b9e5 --- /dev/null +++ b/media/libpng/autogen.sh @@ -0,0 +1,226 @@ +#! /bin/sh +# +# Run 'autoreconf' to build 'configure', 'Makefile.in' and other configure +# control files. +# +# The first time this is run on a GIT checkout the only files that exist are +# configure.ac and Makefile.am; all of the autotools support scripts are +# missing. They are instantiated with autoreconf --force --install. +# +# For regular ("tarball") distributions all the files should exist. We do not +# want them to be updated *under any circumstances*. It should never be +# necessary to run autogen.sh because ./configure --enable-maintainer-mode says +# what to do if Makefile.am or configure.ac are changed. +# +# It is *probably* OK to update the files on a GIT checkout, because they have +# come from the local tools, but leave that to the user who is assumed to know +# whether it is ok or required. +# +# This script is intended to work without arguments, there are, however, hidden +# arguments (a) for use while testing the script and (b) to fix up systems that +# have been broken. If (b) is required the script prompts for the correct +# options. For this reason the options are *NOT* documented in the help; this +# is deliberate; UTSL. +# +clean= +maintainer= +while test $# -gt 0 +do + case "$1" in + --maintainer) + maintainer=1;; + + --clean) + clean=1;; + + *) + exec >&2 + echo "$0: usage: ./autogen.sh" + if test -d .git + then + echo " ./autogen.sh generates the configure script and" + echo " Makefile.in, or refreshes them after changes to Makefile.am" + echo " or configure.ac. You may prefer to just run autoreconf." + elif test -z "$maintainer" + then + echo " DO NOT RUN THIS SCRIPT." + echo " If you need to change Makefile.am or configure.ac then you" + echo " also need to run ./configure --enable-maintainer-mode and" + echo " use the appropriate autotools, *NOT* this script, to update" + echo " everything, please check the documentation of autoreconf." + echo " WARNING: libpng is intentionally generated with a known," + echo " fixed, set of autotools. It is known *NOT* to work with" + echo " the collection of autotools distributed on highly reputable" + echo " operating systems." + echo " Remember: autotools is GNU software, you are expected to" + echo " pay for support." + else + echo " You have run autogen.sh with --maintainer enabled and you" + echo " are not using a GIT distribution, then you have given an" + echo " unrecognized argument. This is not good. --maintainer" + echo " switches off any assumptions that you might not know what" + echo " you are doing." + fi + exit 1;; + esac + + shift +done +# +# First check for a set of the autotools files; if absent then this is assumed +# to be a GIT version and the local autotools must be used. If present this +# is a tarball distribution and the script should not be used. If partially +# present bad things are happening. +# +# The autotools generated files: +libpng_autotools_files="Makefile.in aclocal.m4 config.guess config.h.in + config.sub configure depcomp install-sh ltmain.sh missing\ + test-driver" +# +# Files generated by versions of autoconf >2.68 or automake >1.13 (i.e. later +# versions than those required by configure.ac): +libpng_autotools_extra="compile config.h.in~" +# +# These are separate because 'maintainer-clean' does not remove them. +libpng_libtool_files="scripts/autoconf/libtool.m4 scripts/autoconf/ltoptions.m4\ + scripts/autoconf/ltsugar.m4 scripts/autoconf/ltversion.m4\ + scripts/autoconf/lt~obsolete.m4" + +libpng_autotools_dirs="autom4te.cache" # not required +# +# The configure generated files: +libpng_configure_files="Makefile config.h config.log config.status\ + libpng-config libpng.pc libtool stamp-h1" + +libpng_configure_dirs=".deps" +# +# We must remove the configure generated files as well as the autotools +# generated files if autotools are regenerated because otherwise if configure +# has been run without "--enable-maintainer-mode" make can do a partial update +# of Makefile. These functions do the two bits of cleaning. +clean_autotools(){ + rm -rf $libpng_autotools_files $libpng_libtool_files $libpng_autotools_dirs + rm -rf $libpng_autotools_extra +} + +clean_configure(){ + rm -rf $libpng_configure_files $libpng_configure_dirs +} +# +# Clean: remove everything (this is to help with testing) +if test -n "$clean" +then + clean_configure + if test -n "$maintainer" + then + clean_autotools + fi + + exit 0 +fi +# +# Validate the distribution. +libpng_autotools_file_found= +libpng_autotools_file_missing= +for file in $libpng_autotools_files +do + if test -f "$file" + then + libpng_autotools_file_found=1 + else + libpng_autotools_file_missing=1 + fi +done +# +# Presence of one of these does not *invalidate* missing, but absence +# invalidates found. +for file in $libpng_libtool_files +do + if test ! -f "$file" + then + libpng_autotools_file_missing=1 + fi +done +# +# The cache directory doesn't matter - it will be regenerated and does not exist +# anyway in a tarball. +# +# Either everything is missing or everything is there, the --maintainer option +# just changes this so that the mode is set to generate all the files. +mode= +if test -z "$libpng_autotools_file_found" -o -n "$maintainer" +then + mode="autoreconf" +else + if test -n "$libpng_autotools_file_missing" + then + mode="broken" + else + mode="configure" + fi +fi +# +# So: +case "$mode" in + autoreconf) + # Clean in case configure files exist + clean_configure + clean_autotools + # Everything must be initialized, so use --force + if autoreconf --warnings=all --force --install + then + missing= + for file in $libpng_autotools_files + do + test -f "$file" || missing=1 + done + # ignore the cache directory + test -z "$missing" || { + exec >&2 + echo "autoreconf was run, but did not produce all the expected" + echo "files. It is likely that your autotools installation is" + echo "not compatible with that expected by libpng." + exit 1 + } + else + exec >&2 + echo "autoreconf failed: your version of autotools is incompatible" + echo "with this libpng version. Please use a distributed archive" + echo "(which includes the autotools generated files) and run configure" + echo "instead." + exit 1 + fi;; + + configure) + if test -d .git + then + exec >&2 + echo "ERROR: running autoreconf on an initialized system" + echo " This is not necessary; it is only necessary to remake the" + echo " autotools generated files if Makefile.am or configure.ac" + echo " change and make does the right thing with:" + echo + echo " ./configure --enable-maintainer-mode." + echo + echo " You can run autoreconf yourself if you don't like maintainer" + echo " mode and you can also just run autoreconf -f -i to initialize" + echo " everything in the first place; this script is only for" + echo " compatibility with prior releases." + exit 1 + else + exec >&2 + echo "autogen.sh is intended only to generate 'configure' on systems" + echo "that do not have it. You have a complete 'configure', if you" + echo "need to change Makefile.am or configure.ac you also need to" + echo "run configure with the --enable-maintainer-mode option." + exit 1 + fi;; + + broken) + exec >&2 + echo "Your system has a partial set of autotools generated files." + echo "autogen.sh is unable to proceed. The full set of files is" + echo "contained in the libpng 'tar' distribution archive and you do" + echo "not need to run autogen.sh if you use it." + exit 1;; +esac diff --git a/media/libpng/configure.ac b/media/libpng/configure.ac new file mode 100644 index 0000000000..6b3fa95541 --- /dev/null +++ b/media/libpng/configure.ac @@ -0,0 +1,353 @@ +# configure.ac + +# Copyright (c) 2018-2024 Cosmin Truta +# Copyright (c) 2004-2016 Glenn Randers-Pehrson + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +dnl Process this file with autoconf to produce a configure script. +dnl +dnl Minor upgrades (compatible ABI): increment the package version +dnl (third field in two places below) and set the PNGLIB_RELEASE +dnl variable. +dnl +dnl Major upgrades (incompatible ABI): increment the package major +dnl version (second field, or first if desired), set the minor +dnl to 0, set PNGLIB_MAJOR below *and* follow the instructions in +dnl Makefile.am to upgrade the package name. + +dnl This is here to prevent earlier autoconf from being used, it +dnl should not be necessary to regenerate configure if the time +dnl stamps are correct +AC_PREREQ([2.68]) + +dnl Version number stuff here: + +AC_INIT([libpng],[1.8.0.git],[png-mng-implement@lists.sourceforge.net]) +AC_CONFIG_MACRO_DIR([scripts/autoconf]) + +# libpng does not follow GNU file name conventions (hence 'foreign') +# color-tests requires automake 1.11 or later +# silent-rules requires automake 1.11 or later +# dist-xz requires automake 1.11 or later +# 1.12.2 fixes a security issue in 1.11.2 and 1.12.1 +# 1.13 is required for parallel tests +AM_INIT_AUTOMAKE([1.13 foreign dist-xz color-tests silent-rules subdir-objects]) + +dnl configure.ac and Makefile.am expect automake 1.11.2 or a compatible later +dnl version; aclocal.m4 will generate a failure if you use a prior version of +dnl automake, so the following is not necessary (and is not defined anyway): +dnl AM_PREREQ([1.11.2]) +dnl stop configure from automagically running automake + +PNGLIB_VERSION=1.8.0.git +PNGLIB_MAJOR=1 +PNGLIB_MINOR=8 +PNGLIB_RELEASE=0 + +dnl End of version number stuff + +AC_CONFIG_SRCDIR([pngget.c]) +AC_CONFIG_HEADERS([config.h]) + +# Check the basic programs. +AC_LANG([C]) +AC_PROG_CC +AM_PROG_AS +LT_PATH_LD +AC_PROG_CPP +AC_PROG_AWK +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET + +dnl libtool/libtoolize; version 2.4.2 is the tested version. This or any +dnl compatible later version may be used +LT_INIT([win32-dll]) +LT_PREREQ([2.4.2]) + +dnl Declare the AWK variable. +AC_ARG_VAR(AWK, [AWK language processor]) + +# Some awk implementations crash when confronted with pnglibconf.dfa. +# Run a test now, to make sure this doesn't happen. +AC_MSG_CHECKING([if awk ($AWK) works]) +if ${AWK} -f "${srcdir}/scripts/pnglibconf/options.awk"\ + out="/dev/null" version=search\ + "${srcdir}/pngconf.h"\ + "${srcdir}/scripts/pnglibconf/pnglibconf.dfa"\ + "${srcdir}/pngusr.dfa" 1>&2 +then + AC_MSG_RESULT([yes]) +else + AC_MSG_FAILURE([no], 1) +fi + +# This is a remnant of the old cc -E validation, where it may have been +# necessary to use a different preprocessor for .dfn files +DFNCPP="$CPP" +AC_SUBST(DFNCPP) + +AC_ARG_ENABLE([tests], + AS_HELP_STRING([--disable-tests], + [do not build the test programs (default is to build)]), + [enable_tests="$enableval"], + [enable_tests=yes]) + +AM_CONDITIONAL([ENABLE_TESTS], + [test "$enable_tests" != "no"]) + +AC_ARG_ENABLE([tools], + AS_HELP_STRING([--disable-tools], + [do not build the auxiliary tools (default is to build)]), + [enable_tools="$enableval"], + [enable_tools=yes]) + +AM_CONDITIONAL([ENABLE_TOOLS], + [test "$enable_tools" != "no"]) + +# -Werror cannot be passed to GCC in CFLAGS because configure will fail +# (it checks the compiler with a program that generates a warning). +# Add the following option to deal with this: +AC_ARG_VAR(PNG_COPTS, + [additional flags for the C compiler, to be used for options that would] + [cause configure itself to fail]) +AC_ARG_ENABLE(werror, + AS_HELP_STRING([[[--enable-werror[=OPT]]]], + [Pass -Werror or the given argument to the compiler if it is supported]), + [test "$enable_werror" = "yes" && enable_werror="-Werror" + if test "$enable_werror" != "no"; then + sav_CFLAGS="$CFLAGS" + CFLAGS="$enable_werror $CFLAGS" + AC_MSG_CHECKING([if the compiler allows $enable_werror]) + AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([ + [int main(int argc, char **argv){] + [return argv[argc-1][0];] + [}]])], + AC_MSG_RESULT(yes) + PNG_COPTS="$PNG_COPTS $enable_werror", + AC_MSG_RESULT(no)) + CFLAGS="$sav_CFLAGS" + fi],) + +# For GCC 5 the default mode for C is -std=gnu11 instead of -std=gnu89. +# In pngpriv.h we request just the POSIX 1003.1 and C89 APIs by defining +# _POSIX_SOURCE to 1. This is incompatible with the new default mode, so +# we test for that and force the "-std=c89" compiler option: +AC_MSG_CHECKING([if we need to force back C standard to C89]) +AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([ + [#define _POSIX_SOURCE 1] + [#include ] + ])], + AC_MSG_RESULT(no),[ + if test "x$GCC" != "xyes"; then + AC_MSG_ERROR( + [Forcing back to C89 is required but the flags are only known for GCC]) + fi + AC_MSG_RESULT(yes) + CFLAGS="$CFLAGS -std=c89" +]) + +# Checks for structures and compiler characteristics. +AC_STRUCT_TM +AC_C_RESTRICT + +# Checks for library functions. +AC_CHECK_FUNCS([pow], , + [AC_CHECK_LIB([m], [pow], , [AC_MSG_ERROR([cannot find pow])])]) + +# Some later POSIX 1003.1 functions are required for test programs, failure +# here is soft (the corresponding test program is not built). +AC_CHECK_FUNC([clock_gettime], , [AC_MSG_WARN([not building timepng])]) +AM_CONDITIONAL([HAVE_CLOCK_GETTIME], [test "$ac_cv_func_clock_gettime" = "yes"]) + +AC_ARG_WITH(zlib-prefix, + AS_HELP_STRING([[[--with-zlib-prefix]]], + [prefix that may have been used in installed zlib]), + [ZPREFIX=${withval}], + [ZPREFIX='z_']) +AC_CHECK_LIB([z], [zlibVersion], , + [AC_CHECK_LIB([z], [${ZPREFIX}zlibVersion], , + [AC_MSG_ERROR([zlib not installed])])]) + +AC_MSG_CHECKING([zlib version]) +AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([ +#include +#if !defined(ZLIB_VERNUM) || ZLIB_VERNUM < 0x1280 +#error zlib version 1.2.8 or later is required +#endif +int main(void) { return 0; } +])], + [AC_MSG_RESULT([acceptable])], + [AC_MSG_RESULT([too old or ZLIB_VERNUM not defined]) + AC_MSG_ERROR([zlib version 1.2.8 or later is required])]) + +# The following is for pngvalid, to ensure it catches FP errors even on +# platforms that don't enable FP exceptions, the function appears in the math +# library (typically), it's not an error if it is not found. +AC_CHECK_LIB([m], [feenableexcept]) +AC_CHECK_FUNCS([feenableexcept]) + +AC_MSG_CHECKING([if using Solaris linker]) +SLD=`$LD --version 2>&1 | grep Solaris` +if test "$SLD"; then + have_solaris_ld=yes + AC_MSG_RESULT(yes) +else + have_solaris_ld=no + AC_MSG_RESULT(no) +fi +AM_CONDITIONAL(HAVE_SOLARIS_LD, test "$have_solaris_ld" = "yes") + +AC_MSG_CHECKING([if libraries can be versioned]) +# Special case for PE/COFF platforms: ld reports +# support for version-script, but doesn't actually +# DO anything with it. +case $host in +*cygwin* | *mingw32* | *interix* ) + have_ld_version_script=no + AC_MSG_RESULT(no) +;; +* ) + +if test "$have_solaris_ld" = "yes"; then + GLD=`$LD --help < /dev/null 2>&1 | grep 'M mapfile'` +else + GLD=`$LD --help < /dev/null 2>/dev/null | grep version-script` +fi + +if test "$GLD"; then + have_ld_version_script=yes + AC_MSG_RESULT(yes) +else + have_ld_version_script=no + AC_MSG_RESULT(no) + AC_MSG_WARN(*** You have not enabled versioned symbols.) +fi +;; +esac + +AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes") + +if test "$have_ld_version_script" = "yes"; then + AC_MSG_CHECKING([for symbol prefix]) + SYMBOL_PREFIX=`echo "PREFIX=__USER_LABEL_PREFIX__" \ + | ${CPP:-${CC:-gcc} -E} - 2>&1 \ + | ${EGREP:-grep} "^PREFIX=" \ + | ${SED:-sed} -e "s:^PREFIX=::" -e "s:__USER_LABEL_PREFIX__::"` + AC_SUBST(SYMBOL_PREFIX) + AC_MSG_RESULT($SYMBOL_PREFIX) +fi + +# Substitutions for .in files +AC_SUBST(PNGLIB_VERSION) +AC_SUBST(PNGLIB_MAJOR) +AC_SUBST(PNGLIB_MINOR) +AC_SUBST(PNGLIB_RELEASE) + +# Additional arguments (and substitutions) +# Allow the pkg-config directory to be set +AC_ARG_WITH(pkgconfigdir, + AS_HELP_STRING([[[--with-pkgconfigdir]]], + [Use the specified pkgconfig dir (default is libdir/pkgconfig)]), + [pkgconfigdir=${withval}], + [pkgconfigdir='${libdir}/pkgconfig']) + +AC_SUBST([pkgconfigdir]) +AC_MSG_NOTICE([[pkgconfig directory is ${pkgconfigdir}]]) + +# Make the *-config binary config scripts optional +AC_ARG_WITH(binconfigs, + AS_HELP_STRING([[[--with-binconfigs]]], + [Generate shell libpng-config scripts as well as pkg-config data] + [@<:@default=yes@:>@]), + [if test "${withval}" = no; then + binconfigs= + AC_MSG_NOTICE([[libpng-config scripts will not be built]]) + else + binconfigs='${binconfigs}' + fi], + [binconfigs='${binconfigs}']) +AC_SUBST([binconfigs]) + +# Support for prefixes to the API function names; this will generate defines +# at the start of the build to rename exported library functions +AC_ARG_WITH(libpng-prefix, + AS_HELP_STRING([[[--with-libpng-prefix]]], + [prefix libpng exported function (API) names with the given value]), + [if test "${withval:-no}" != "no"; then + AC_SUBST([PNG_PREFIX], [${withval}]) + fi]) +AM_CONDITIONAL([DO_PNG_PREFIX], [test "${with_libpng_prefix:-no}" != "no"]) + +# Control over what links are made for installed files. Versioned files are +# always installed, when the following options are turned on corresponding +# unversioned links are also created (normally as symbolic links): +AC_ARG_ENABLE([unversioned-links], + AS_HELP_STRING([[[--enable-unversioned-links]]], + [Installed libpng header files are placed in a versioned subdirectory] + [and installed libpng library (including DLL) files are versioned.] + [If this option is enabled unversioned links will be created pointing to] + [the corresponding installed files. If you use libpng.pc or] + [libpng-config for all builds you do not need these links, but if you] + [compile programs directly they will typically #include and] + [link with -lpng; in that case you need the links.] + [The links can be installed manually using 'make install-header-links'] + [and 'make install-library-links' and can be removed using the] + [corresponding uninstall- targets. If you do enable this option every] + [libpng 'make install' will recreate the links to point to the just] + [installed version of libpng. The default is to create the links;] + [use --disable-unversioned-links to change this])) + +# The AM_CONDITIONAL test is written so that the default is enabled; +# --disable-unversioned-links must be given to turn the option off. +AM_CONDITIONAL([DO_INSTALL_LINKS],[test "$enable_unversioned_links" != "no"]) + +AC_ARG_ENABLE([unversioned-libpng-pc], + AS_HELP_STRING([[[--enable-unversioned-libpng-pc]]], + [Install the configuration file 'libpng.pc' as a link to the versioned] + [version. This is done by default - use --disable-unversioned-libpng-pc] + [to change this.])) +AM_CONDITIONAL([DO_INSTALL_LIBPNG_PC], + [test "$enable_unversioned_libpng_pc" != "no"]) + +AC_ARG_ENABLE([unversioned-libpng-config], + AS_HELP_STRING([[[--enable-unversioned-libpng-config]]], + [Install the configuration file 'libpng-config' as a link to the] + [versioned version. This is done by default - use] + [--disable-unversioned-libpng-config to change this.])) +AM_CONDITIONAL([DO_INSTALL_LIBPNG_CONFIG], + [test "$enable_unversioned_libpng_config" != "no"]) + +# HOST-SPECIFIC OPTIONS +# ===================== +# +# DEFAULT +# ======= +# +AC_ARG_ENABLE([hardware-optimizations], + AS_HELP_STRING([[[--enable-hardware-optimizations]]], + [Enable hardware optimizations: no/off, =yes/on.]), + [case "$enableval" in + no|off) + # disable hardware optimization on all systems + AC_DEFINE([PNG_NO_HARDWARE], [1], + [Disable hardware specific optimizations]) + ;; + *) + ;; + esac]) + +AC_MSG_NOTICE([[Extra options for compiler: $PNG_COPTS]]) + +# Config files, substituting as above +AC_CONFIG_FILES([Makefile libpng.pc:libpng.pc.in]) +AC_CONFIG_FILES([libpng-config:libpng-config.in], + [chmod +x libpng-config]) + +AC_OUTPUT diff --git a/media/libpng/crashtests/374810-1.html b/media/libpng/crashtests/374810-1.html deleted file mode 100644 index 40fe1cd746..0000000000 --- a/media/libpng/crashtests/374810-1.html +++ /dev/null @@ -1 +0,0 @@ - diff --git a/media/libpng/crashtests/945912-1.html b/media/libpng/crashtests/945912-1.html deleted file mode 100644 index ada73a82ba..0000000000 --- a/media/libpng/crashtests/945912-1.html +++ /dev/null @@ -1,8 +0,0 @@ -crash test for bug #945912 - - - - diff --git a/media/libpng/crashtests/974825-1.html b/media/libpng/crashtests/974825-1.html deleted file mode 100644 index ef19df54da..0000000000 --- a/media/libpng/crashtests/974825-1.html +++ /dev/null @@ -1,7 +0,0 @@ -crash test for bug #974825 - -Crash Test bug#974825 - - diff --git a/media/libpng/crashtests/crashtests.list b/media/libpng/crashtests/crashtests.list deleted file mode 100644 index 3a9a2cba3b..0000000000 --- a/media/libpng/crashtests/crashtests.list +++ /dev/null @@ -1,3 +0,0 @@ -load 374810-1.html -load 945912-1.html -load 974825-1.html diff --git a/media/libpng/example.c b/media/libpng/example.c new file mode 100644 index 0000000000..db1915e5b1 --- /dev/null +++ b/media/libpng/example.c @@ -0,0 +1,1040 @@ +#if 0 /* in case someone actually tries to compile this */ + +/* example.c - an example of using libpng + * + * Maintained 2018-2025 Cosmin Truta + * Maintained 1998-2016 Glenn Randers-Pehrson + * Maintained 1996-1997 Andreas Dilger + * Written 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * To the extent possible under law, the authors have waived + * all copyright and related or neighboring rights to this file. + * This work is published from: United States, Canada. + */ + +/* This is an example of how to use libpng to read and write PNG files. + * The file libpng-manual.txt is much more verbose then this. If you have + * not read it, do so first. This was designed to be a starting point of an + * implementation. This is not officially part of libpng, is hereby placed + * in the public domain, and therefore does not require a copyright notice. + * + * This file does not currently compile, because it is missing certain + * parts, like allocating memory to hold an image. You will have to + * supply these parts to get it to compile. For an example of a minimal + * working PNG reader/writer, see pngtest.c, included in this distribution; + * see also the programs in the contrib directory. + */ + +/* The simple, but restricted approach to reading a PNG file or data stream + * requires just two function calls, as in the following complete program. + * Writing a file needs just one function call, so long as the data has an + * appropriate layout. + * + * The following code reads PNG image data from a file and writes it, in a + * potentially new format, to a new file. While this code will compile, there + * is minimal (insufficient) error checking. For a more realistic version, + * see contrib/examples/pngtopng.c + */ + +#include +#include +#include +#include +#include +#include + +int main(int argc, const char **argv) +{ + if (argc == 3) + { + png_image image; /* The control structure used by libpng */ + + /* Initialize the 'png_image' structure. */ + memset(&image, 0, (sizeof image)); + image.version = PNG_IMAGE_VERSION; + + /* The first argument is the file to read: */ + if (png_image_begin_read_from_file(&image, argv[1]) != 0) + { + png_byte *buffer; + + /* Set the format in which to read the PNG file; this code chooses a + * simple sRGB format with a non-associated alpha channel, adequate to + * store most images. + */ + image.format = PNG_FORMAT_RGBA; + + /* Now allocate enough memory to hold the image in this format; the + * PNG_IMAGE_SIZE macro uses the information about the image (width, + * height and format) stored in 'image'. + */ + buffer = malloc(PNG_IMAGE_SIZE(image)); + + /* If enough memory was available, read the image in the desired + * format, then write the result out to the new file. 'background' is + * not necessary when reading the image, because the alpha channel is + * preserved; if it were to be removed, for example if we requested + * PNG_FORMAT_RGB, then either a solid background color would have to + * be supplied, or the output buffer would have to be initialized to + * the actual background of the image. + * + * The fourth argument to png_image_finish_read is the 'row_stride' - + * this is the number of components allocated for the image in each + * row. It has to be at least as big as the value returned by + * PNG_IMAGE_ROW_STRIDE, but if you just allocate space for the + * default, minimum size, using PNG_IMAGE_SIZE as above, you can pass + * zero. + * + * The final argument is a pointer to a buffer for the colormap; + * colormaps have exactly the same format as a row of image pixels + * (so you choose what format to make the colormap by setting + * image.format). A colormap is only returned if + * PNG_FORMAT_FLAG_COLORMAP is also set in image.format, so in this + * case NULL is passed as the final argument. If you do want to force + * all images into an index/color-mapped format, then you can use: + * + * PNG_IMAGE_COLORMAP_SIZE(image) + * + * to find the maximum size of the colormap in bytes. + */ + if (buffer != NULL && + png_image_finish_read(&image, NULL/*background*/, buffer, + 0/*row_stride*/, NULL/*colormap*/) != 0) + { + /* Now write the image out to the second argument. In the write + * call 'convert_to_8bit' allows 16-bit data to be squashed down to + * 8 bits; this isn't necessary here because the original read was + * to the 8-bit format. + */ + if (png_image_write_to_file(&image, argv[2], 0/*convert_to_8bit*/, + buffer, 0/*row_stride*/, NULL/*colormap*/) != 0) + { + /* The image has been written successfully. */ + exit(0); + } + } + else + { + /* Calling png_image_free is optional unless the simplified API was + * not run to completion. In this case, if there wasn't enough + * memory for 'buffer', we didn't complete the read, so we must + * free the image: + */ + if (buffer == NULL) + png_image_free(&image); + else + free(buffer); + } + } + + /* Something went wrong reading or writing the image. libpng stores a + * textual message in the 'png_image' structure: + */ + fprintf(stderr, "pngtopng: error: %s\n", image.message); + exit(1); + } + + fprintf(stderr, "pngtopng: usage: pngtopng input-file output-file\n"); + exit(2); +} + +/* That's it ;-) Of course you probably want to do more with PNG files than + * just converting them all to 32-bit RGBA PNG files; you can do that between + * the call to png_image_finish_read and png_image_write_to_file. You can also + * ask for the image data to be presented in a number of different formats. + * You do this by simply changing the 'format' parameter set before allocating + * the buffer. + * + * The format parameter consists of five flags that define various aspects of + * the image. You can simply add these together to get the format, or you can + * use one of the predefined macros from png.h (as above): + * + * PNG_FORMAT_FLAG_COLOR: if set, the image will have three color components + * per pixel (red, green and blue); if not set, the image will just have one + * luminance (grayscale) component. + * + * PNG_FORMAT_FLAG_ALPHA: if set, each pixel in the image will have an + * additional alpha value; a linear value that describes the degree the + * image pixel covers (overwrites) the contents of the existing pixel on the + * display. + * + * PNG_FORMAT_FLAG_LINEAR: if set, the components of each pixel will be + * returned as a series of 16-bit linear values; if not set, the components + * will be returned as a series of 8-bit values encoded according to the + * sRGB standard. The 8-bit format is the normal format for images intended + * for direct display, because almost all display devices do the inverse of + * the sRGB transformation to the data they receive. The 16-bit format is + * more common for scientific data and image data that must be further + * processed; because it is linear, simple math can be done on the component + * values. Regardless of the setting of this flag, the alpha channel is + * always linear, although it will be 8 bits or 16 bits wide as specified by + * the flag. + * + * PNG_FORMAT_FLAG_BGR: if set, the components of a color pixel will be + * returned in the order blue, then green, then red. If not set, the pixel + * components are in the order red, then green, then blue. + * + * PNG_FORMAT_FLAG_AFIRST: if set, the alpha channel (if present) precedes the + * color or grayscale components. If not set, the alpha channel follows the + * components. + * + * You do not have to read directly from a file. You can read from memory or, + * on systems that support , from a FILE object. This is controlled + * by the particular png_image_begin_read_from_ function you call at the start. + * Likewise, on write, you can write to a FILE object if your system supports + * . The macro PNG_STDIO_SUPPORTED indicates if stdio is available + * and accessible from your libpng build. + * + * If you read 16-bit (PNG_FORMAT_FLAG_LINEAR) data, you may need to write it + * in the 8-bit format for display. You do this by setting the convert_to_8bit + * flag to 'true'. + * + * Don't repeatedly convert between the 8-bit and 16-bit forms. There is + * significant data loss when 16-bit data is converted to the 8-bit encoding, + * and the current libpng implementation of conversion to 16-bit is also + * significantly lossy. The latter will be fixed in the future, but the former + * is unavoidable - the 8-bit format just doesn't have enough resolution. + */ + +/* If your program needs more information from the PNG data it reads, or if you + * need to do more complex transformations, or minimize transformations, on the + * data you read, then you must use one of the several lower level libpng + * interfaces. + * + * All these interfaces require that you do your own error handling - your + * program must be able to arrange for control to return to your own code, any + * time libpng encounters a problem. There are several ways to do this, but + * the standard way is to use the interface to establish a return + * point within your own code. You must do this if you do not use the + * simplified interface (above). + * + * The first step is to include the header files you need, including the libpng + * header file. Include any standard headers and feature test macros your + * program requires before including png.h: + */ +#include + + /* The png_jmpbuf() macro, used in error handling, became available in + * libpng version 1.0.6. If you want to be able to run your code with older + * versions of libpng, you must define the macro yourself (but only if it + * is not already defined by libpng!) + */ + +#ifndef png_jmpbuf +# define png_jmpbuf(png_ptr) ((png_ptr)->png_jmpbuf) +#endif + +/* Check to see if a file is a PNG file using png_sig_cmp(). png_sig_cmp() + * returns zero if the image is a PNG, and nonzero otherwise. + * + * The function check_if_png() shown here, but not used, returns nonzero (true) + * if the file can be opened and is a PNG, and 0 (false) otherwise. + * + * If this call is successful, and you are going to keep the file open, + * you should call png_set_sig_bytes(png_ptr, PNG_BYTES_TO_CHECK); once + * you have created the png_ptr, so that libpng knows your application + * has read that many bytes from the start of the file. Make sure you + * don't call png_set_sig_bytes() with more than 8 bytes read or give it + * an incorrect number of bytes read, or you will either have read too + * many bytes (your fault), or you are telling libpng to read the wrong + * number of magic bytes (also your fault). + * + * Many applications already read the first 2 or 4 bytes from the start + * of the image to determine the file type, so it would be easiest just + * to pass the bytes to png_sig_cmp(), or even skip that if you know + * you have a PNG file, and call png_set_sig_bytes(). + */ +#define PNG_BYTES_TO_CHECK 4 +int check_if_png(char *file_name, FILE **fp) +{ + char buf[PNG_BYTES_TO_CHECK]; + + /* Open the prospective PNG file. */ + if ((*fp = fopen(file_name, "rb")) == NULL) + return 0; + + /* Read in some of the signature bytes. */ + if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK) + return 0; + + /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature. + * Return true if they match. + */ + return png_sig_cmp(buf, 0, PNG_BYTES_TO_CHECK) == 0; +} + +/* Read a PNG file. You may want to return an error code if the read + * fails (depending upon the failure). There are two "prototypes" given + * here - one where we are given the filename, and we need to open the + * file, and the other where we are given an open file (possibly with + * some or all of the magic bytes read - see comments above). + */ +#ifdef open_file /* prototype 1 */ +void read_png(char *file_name) /* We need to open the file */ +{ + png_struct *png_ptr; + png_info *info_ptr; + int sig_read = 0; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; + FILE *fp; + + if ((fp = fopen(file_name, "rb")) == NULL) + return ERROR; + +#else no_open_file /* prototype 2 */ +void read_png(FILE *fp, int sig_read) /* File is already open */ +{ + png_struct *png_ptr; + png_info *info_ptr; + png_uint_32 width, height; + int bit_depth, color_type, interlace_type; +#endif no_open_file /* Only use one prototype! */ + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also supply the + * the compiler header file version, so that we know if the application + * was compiled with a compatible version of the library. REQUIRED. + */ + png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + void *user_error_ptr, user_error_fn, user_warning_fn); + + if (png_ptr == NULL) + { + fclose(fp); + return ERROR; + } + + /* Allocate/initialize the memory for image information. REQUIRED. */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_read_struct(&png_ptr, NULL, NULL); + return ERROR; + } + + /* Set error handling if you are using the setjmp/longjmp method (this is + * the normal method of doing things with libpng). REQUIRED unless you + * set up your own error handlers in the png_create_read_struct() earlier. + */ + if (setjmp(png_jmpbuf(png_ptr))) + { + /* Free all of the memory associated with the png_ptr and info_ptr. */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + fclose(fp); + /* If we get here, we had a problem reading the file. */ + return ERROR; + } + + /* One of the following I/O initialization methods is REQUIRED. */ +#ifdef streams /* PNG file I/O method 1 */ + /* Set up the input control if you are using standard C streams. */ + png_init_io(png_ptr, fp); + +#else no_streams /* PNG file I/O method 2 */ + /* If you are using replacement read functions, instead of calling + * png_init_io(), you would call: + */ + png_set_read_fn(png_ptr, (void *)user_io_ptr, user_read_fn); + /* where user_io_ptr is a structure you want available to the callbacks. */ +#endif no_streams /* Use only one I/O method! */ + + /* If we have already read some of the signature */ + png_set_sig_bytes(png_ptr, sig_read); + +#ifdef hilevel + /* If you have enough memory to read in the entire image at once, + * and you need to specify only transforms that can be controlled + * with one of the PNG_TRANSFORM_* bits (this presently excludes + * quantizing, filling, setting background, and doing gamma + * adjustment), then you can read the entire image (including + * pixels) into the info structure with this call: + */ + png_read_png(png_ptr, info_ptr, png_transforms, NULL); + +#else + /* OK, you're doing it the hard way, with the lower-level functions. */ + + /* The call to png_read_info() gives us all of the information from the + * PNG file before the first IDAT (image data chunk). REQUIRED. + */ + png_read_info(png_ptr, info_ptr); + + png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, + &interlace_type, NULL, NULL); + + /* Set up the data transformations you want. Note that these are all + * optional. Only call them if you want/need them. Many of the + * transformations only work on specific types of images, and many + * are mutually exclusive. + */ + + /* Tell libpng to strip 16 bits/color files down to 8 bits/color. + * Use accurate scaling if it's available, otherwise just chop off the + * low byte. + */ +#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED + png_set_scale_16(png_ptr); +#else + png_set_strip_16(png_ptr); +#endif + + /* Strip alpha bytes from the input data without combining with the + * background (not recommended). + */ + png_set_strip_alpha(png_ptr); + + /* Extract multiple pixels with bit depths of 1, 2 or 4 from a single + * byte into separate bytes (useful for paletted and grayscale images). + */ + png_set_packing(png_ptr); + + /* Change the order of packed pixels to least significant bit first + * (not useful if you are using png_set_packing). + */ + png_set_packswap(png_ptr); + + /* Expand paletted colors into true RGB triplets. */ + if (color_type == PNG_COLOR_TYPE_PALETTE) + png_set_palette_to_rgb(png_ptr); + + /* Expand grayscale images to the full 8 bits from 1, 2 or 4 bits/pixel. */ + if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) + png_set_expand_gray_1_2_4_to_8(png_ptr); + + /* Expand paletted or RGB images with transparency to full alpha channels + * so the data will be available as RGBA quartets. + */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) != 0) + png_set_tRNS_to_alpha(png_ptr); + + /* Set the background color to draw transparent and alpha images over. + * It is possible to set the red, green and blue components directly + * for paletted images, instead of supplying a palette index. Note that, + * even if the PNG file supplies a background, you are not required to + * use it - you should use the (solid) application background if it has one. + */ + png_color_16 my_background, *image_background; + + if (png_get_bKGD(png_ptr, info_ptr, &image_background) != 0) + png_set_background(png_ptr, image_background, + PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); + else + png_set_background(png_ptr, &my_background, + PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); + + /* Some suggestions as to how to get a screen gamma value. + * + * Note that screen gamma is the display_exponent, which includes + * the CRT_exponent and any correction for viewing conditions. + */ + if (/* We have a user-defined screen gamma value */) + screen_gamma = user-defined screen_gamma; + /* This is one way that applications share the same screen gamma value. */ + else if ((gamma_str = getenv("SCREEN_GAMMA")) != NULL) + screen_gamma = atof(gamma_str); + /* If we don't have another value */ + else + { + screen_gamma = PNG_DEFAULT_sRGB; /* A good guess for a PC monitor + in a dimly lit room */ + screen_gamma = PNG_GAMMA_MAC_18 or 1.0; /* Good guesses for Mac + systems */ + } + + /* Tell libpng to handle the gamma conversion for you. The final call + * is a good guess for PC generated images, but it should be configurable + * by the user at run time. Gamma correction support in your application + * is strongly recommended. + */ + + int intent; + + if (png_get_sRGB(png_ptr, info_ptr, &intent) != 0) + png_set_gamma(png_ptr, screen_gamma, PNG_DEFAULT_sRGB); + else + { + double image_gamma; + if (png_get_gAMA(png_ptr, info_ptr, &image_gamma) != 0) + png_set_gamma(png_ptr, screen_gamma, image_gamma); + else + png_set_gamma(png_ptr, screen_gamma, 0.45455); + } + +#ifdef PNG_READ_QUANTIZE_SUPPORTED + /* Quantize RGB files down to 8-bit palette, or reduce palettes + * to the number of colors available on your screen. + */ + if ((color_type & PNG_COLOR_MASK_COLOR) != 0) + { + int num_palette; + png_color *palette; + + /* This reduces the image to the application-supplied palette. */ + if (/* We have our own palette */) + { + /* An array of colors to which the image should be quantized. */ + png_color std_color_cube[MAX_SCREEN_COLORS]; + png_set_quantize(png_ptr, std_color_cube, MAX_SCREEN_COLORS, + MAX_SCREEN_COLORS, NULL, 0); + } + /* This reduces the image to the palette supplied in the file. */ + else if (png_get_PLTE(png_ptr, info_ptr, &palette, &num_palette) != 0) + { + png_uint_16 *histogram = NULL; + png_get_hIST(png_ptr, info_ptr, &histogram); + png_set_quantize(png_ptr, palette, num_palette, + max_screen_colors, histogram, 0); + } + } +#endif /* READ_QUANTIZE */ + + /* Invert monochrome files to have 0 as white and 1 as black. */ + png_set_invert_mono(png_ptr); + + /* If you want to shift the pixel values from the range [0,255] or + * [0,65535] to the original [0,7] or [0,31], or whatever range the + * colors were originally in: + */ + if (png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT) != 0) + { + png_color_8 *sig_bit_p; + png_get_sBIT(png_ptr, info_ptr, &sig_bit_p); + png_set_shift(png_ptr, sig_bit_p); + } + + /* Flip the RGB pixels to BGR (or RGBA to BGRA). */ + if ((color_type & PNG_COLOR_MASK_COLOR) != 0) + png_set_bgr(png_ptr); + + /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR). */ + png_set_swap_alpha(png_ptr); + + /* Swap bytes of 16-bit files to least significant byte first. */ + png_set_swap(png_ptr); + + /* Add filler (or alpha) byte (before/after each RGB triplet). */ + png_set_filler(png_ptr, 0xffff, PNG_FILLER_AFTER); + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* Turn on interlace handling. REQUIRED if you are not using + * png_read_image(). To see how to handle interlacing passes, + * see the png_read_row() method below: + */ + number_passes = png_set_interlace_handling(png_ptr); +#else /* !READ_INTERLACING */ + number_passes = 1; +#endif /* READ_INTERLACING */ + + /* Optional call to gamma correct and add the background to the palette + * and update info structure. REQUIRED if you are expecting libpng to + * update the palette for you (i.e. you selected such a transform above). + */ + png_read_update_info(png_ptr, info_ptr); + + /* Allocate the memory to hold the image using the fields of info_ptr. */ + png_byte *row_pointers[height]; + for (row = 0; row < height; row++) + row_pointers[row] = NULL; /* Clear the pointer array */ + for (row = 0; row < height; row++) + row_pointers[row] = png_malloc(png_ptr, png_get_rowbytes(png_ptr, + info_ptr)); + + /* Now it's time to read the image. One of these methods is REQUIRED. */ +#ifdef entire /* Read the entire image in one go */ + png_read_image(png_ptr, row_pointers); + +#else no_entire /* Read the image one or more scanlines at a time */ + /* The other way to read images - deal with interlacing: */ + for (pass = 0; pass < number_passes; pass++) + { +#ifdef single /* Read the image a single row at a time */ + for (y = 0; y < height; y++) + png_read_rows(png_ptr, &row_pointers[y], NULL, 1); + +#else no_single /* Read the image several rows at a time */ + for (y = 0; y < height; y += number_of_rows) + { +#ifdef sparkle /* Read the image using the "sparkle" effect. */ + png_read_rows(png_ptr, &row_pointers[y], NULL, + number_of_rows); +#else no_sparkle /* Read the image using the "rectangle" effect */ + png_read_rows(png_ptr, NULL, &row_pointers[y], + number_of_rows); +#endif no_sparkle /* Use only one of these two methods */ + } + + /* If you want to display the image after every pass, do so here. */ +#endif no_single /* Use only one of these two methods */ + } +#endif no_entire /* Use only one of these two methods */ + + /* Read rest of file, and get additional chunks in info_ptr. REQUIRED. */ + png_read_end(png_ptr, info_ptr); +#endif hilevel + + /* At this point you have read the entire image. */ + + /* Clean up after the read, and free any memory allocated. REQUIRED. */ + png_destroy_read_struct(&png_ptr, &info_ptr, NULL); + + /* Close the file. */ + fclose(fp); + + /* That's it! */ + return OK; +} + +/* Progressively read a file */ + +int +initialize_png_reader(png_struct **png_ptr, png_info **info_ptr) +{ + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible, in case we are using dynamically + * linked libraries. + */ + *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + void *user_error_ptr, user_error_fn, user_warning_fn); + if (*png_ptr == NULL) + { + *info_ptr = NULL; + return ERROR; + } + *info_ptr = png_create_info_struct(png_ptr); + if (*info_ptr == NULL) + { + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return ERROR; + } + if (setjmp(png_jmpbuf((*png_ptr)))) + { + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return ERROR; + } + + /* You will need to provide all three function callbacks, + * even if you aren't using all of them. + * If you aren't using all functions, you can specify NULL + * parameters. Even when all three functions are NULL, + * you need to call png_set_progressive_read_fn(). + * These functions shouldn't be dependent on global or + * static variables if you are decoding several images + * simultaneously. You should store stream specific data + * in a separate struct, given as the second parameter, + * and retrieve the pointer from inside the callbacks using + * the function png_get_progressive_ptr(png_ptr). + */ + png_set_progressive_read_fn(*png_ptr, (void *)stream_data, + info_callback, row_callback, end_callback); + return OK; +} + +int +process_data(png_struct **png_ptr, png_info **info_ptr, + png_byte *buffer, png_uint_32 length) +{ + if (setjmp(png_jmpbuf((*png_ptr)))) + { + /* Free the png_ptr and info_ptr memory on error. */ + png_destroy_read_struct(png_ptr, info_ptr, NULL); + return ERROR; + } + + /* Give chunks of data as they arrive from the data stream + * (in order, of course). + * On segmented machines, don't give it any more than 64K. + * The library seems to run fine with sizes of 4K, although + * you can give it much less if necessary. (I assume you can + * give it chunks of 1 byte, but I haven't tried with less + * than 256 bytes yet.) When this function returns, you may + * want to display any rows that were generated in the row + * callback, if you aren't already displaying them there. + */ + png_process_data(*png_ptr, *info_ptr, buffer, length); + return OK; +} + +info_callback(png_struct *png_ptr, png_info *info) +{ + /* Do any setup here, including setting any of the transformations + * mentioned in the Reading PNG files section. For now, you _must_ + * call either png_start_read_image() or png_read_update_info() + * after all the transformations are set (even if you don't set + * any). You may start getting rows before png_process_data() + * returns, so this is your last chance to prepare for that. + */ +} + +row_callback(png_struct *png_ptr, png_byte *new_row, + png_uint_32 row_num, int pass) +{ + /* This function is called for every row in the image. If the + * image is interlaced, and you turned on the interlace handler, + * this function will be called for every row in every pass. + * + * In this function you will receive a pointer to new row data from + * libpng called new_row that is to replace a corresponding row (of + * the same data format) in a buffer allocated by your application. + * + * The new row data pointer "new_row" may be NULL, indicating there is + * no new data to be replaced (in cases of interlace loading). + * + * If new_row is not NULL, then you need to call + * png_progressive_combine_row(), to replace the corresponding row as + * shown below: + */ + + /* Get pointer to corresponding row in our PNG read buffer. */ + png_byte *old_row = ((png_byte **)our_data)[row_num]; + +#ifdef PNG_READ_INTERLACING_SUPPORTED + /* If both rows are allocated, then copy the new row + * data to the corresponding row data. + */ + if (old_row != NULL && new_row != NULL) + png_progressive_combine_row(png_ptr, old_row, new_row); + + /* The rows and passes are called in order, so you don't really + * need the row_num and pass, but I'm supplying them because it + * may make your life easier. + * + * For the non-NULL rows of interlaced images, you must call + * png_progressive_combine_row() passing in the new row and the + * old row, as demonstrated above. You can call this function for + * NULL rows (it will just return) and for non-interlaced images + * (it just does the memcpy for you) if it will make the code + * easier. Thus, you can just do this for all cases: + */ + png_progressive_combine_row(png_ptr, old_row, new_row); + + /* where old_row is what was displayed for previous rows. Note + * that the first pass (pass == 0 really) will completely cover + * the old row, so the rows do not have to be initialized. After + * the first pass (and only for interlaced images), you will have + * to pass the current row as new_row, and the function will combine + * the old row and the new row. + */ +#endif /* READ_INTERLACING */ +} + +end_callback(png_struct *png_ptr, png_info *info) +{ + /* This function is called when the whole image has been read, + * including any chunks after the image (up to and including + * the IEND). You will usually have the same info chunk as you + * had in the header, although some data may have been added + * to the comments and time fields. + * + * Most people won't do much here, perhaps setting a flag that + * marks the image as finished. + */ +} + +/* Write a png file */ +void write_png(char *file_name /* , ... other image information ... */) +{ + FILE *fp; + png_struct *png_ptr; + png_info *info_ptr; + png_color *palette; + + /* Open the file */ + fp = fopen(file_name, "wb"); + if (fp == NULL) + return ERROR; + + /* Create and initialize the png_struct with the desired error handler + * functions. If you want to use the default stderr and longjump method, + * you can supply NULL for the last three parameters. We also check that + * the library version is compatible with the one used at compile time, + * in case we are using dynamically linked libraries. REQUIRED. + */ + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + void *user_error_ptr, user_error_fn, user_warning_fn); + if (png_ptr == NULL) + { + fclose(fp); + return ERROR; + } + + /* Allocate/initialize the image information data. REQUIRED. */ + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) + { + fclose(fp); + png_destroy_write_struct(&png_ptr, NULL); + return ERROR; + } + + /* Set up error handling. REQUIRED if you aren't supplying your own + * error handling functions in the png_create_write_struct() call. + */ + if (setjmp(png_jmpbuf(png_ptr))) + { + /* If we get here, we had a problem writing the file. */ + fclose(fp); + png_destroy_write_struct(&png_ptr, &info_ptr); + return ERROR; + } + + /* One of the following I/O initialization functions is REQUIRED. */ + +#ifdef streams /* I/O initialization method 1 */ + /* Set up the output control if you are using standard C streams. */ + png_init_io(png_ptr, fp); + +#else no_streams /* I/O initialization method 2 */ + /* If you are using replacement write functions, instead of calling + * png_init_io(), you would call: + */ + png_set_write_fn(png_ptr, (void *)user_io_ptr, user_write_fn, + user_IO_flush_function); + /* where user_io_ptr is a structure you want available to the callbacks. */ +#endif no_streams /* Only use one initialization method */ + +#ifdef hilevel + /* This is the easy way. Use it if you already have all the + * image info living in the structure. You could "|" many + * PNG_TRANSFORM flags into the png_transforms integer here. + */ + png_write_png(png_ptr, info_ptr, png_transforms, NULL); + +#else + /* This is the hard way. */ + + /* Set the image information here. Width and height are up to 2^31, + * bit_depth is one of 1, 2, 4, 8 or 16, but valid values also depend on + * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY, + * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB, + * or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or + * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST + * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. + * REQUIRED. + */ + png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, + PNG_COLOR_TYPE_???, PNG_INTERLACE_????, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + /* Set the palette if there is one. REQUIRED for indexed-color images. */ + palette = (png_color *)png_malloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))); + /* ... Set palette colors ... */ + png_set_PLTE(png_ptr, info_ptr, palette, PNG_MAX_PALETTE_LENGTH); + /* You must not free palette here, because png_set_PLTE only makes a link + * to the palette that you allocated. Wait until you are about to destroy + * the png structure. + */ + + /* Optional significant bit (sBIT) chunk. */ + png_color_8 sig_bit; + + /* If we are dealing with a grayscale image then */ + sig_bit.gray = true_bit_depth; + + /* Otherwise, if we are dealing with a color image then */ + sig_bit.red = true_red_bit_depth; + sig_bit.green = true_green_bit_depth; + sig_bit.blue = true_blue_bit_depth; + + /* If the image has an alpha channel then */ + sig_bit.alpha = true_alpha_bit_depth; + + png_set_sBIT(png_ptr, info_ptr, &sig_bit); + + /* Optional gamma chunk is strongly suggested if you have any guess + * as to the correct gamma of the image. + */ + png_set_gAMA(png_ptr, info_ptr, gamma); + + /* Optionally write comments into the image. */ + { + png_text text_ptr[3]; + + char key0[] = "Title"; + char text0[] = "Mona Lisa"; + text_ptr[0].key = key0; + text_ptr[0].text = text0; + text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[0].itxt_length = 0; + text_ptr[0].lang = NULL; + text_ptr[0].lang_key = NULL; + + char key1[] = "Author"; + char text1[] = "Leonardo DaVinci"; + text_ptr[1].key = key1; + text_ptr[1].text = text1; + text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE; + text_ptr[1].itxt_length = 0; + text_ptr[1].lang = NULL; + text_ptr[1].lang_key = NULL; + + char key2[] = "Description"; + char text2[] = ""; + text_ptr[2].key = key2; + text_ptr[2].text = text2; + text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt; + text_ptr[2].itxt_length = 0; + text_ptr[2].lang = NULL; + text_ptr[2].lang_key = NULL; + + png_set_text(write_ptr, write_info_ptr, text_ptr, 3); + } + + /* Other optional chunks like cHRM, bKGD, tRNS, tIME, oFFs, pHYs. */ + + /* Note that if sRGB is present, the gAMA and cHRM chunks must be ignored + * on read and, if your application chooses to write them, they must + * be written in accordance with the sRGB profile. + */ + + /* Write the file header information. REQUIRED. */ + png_write_info(png_ptr, info_ptr); + + /* If you want, you can write the info in two steps, in case you need to + * write your private chunk ahead of PLTE: + * + * png_write_info_before_PLTE(write_ptr, write_info_ptr); + * write_my_chunk(); + * png_write_info(png_ptr, info_ptr); + * + * However, given the level of known- and unknown-chunk support in 1.2.0 + * and up, this should no longer be necessary. + */ + + /* Once we write out the header, the compression type on the text + * chunk gets changed to PNG_TEXT_COMPRESSION_NONE_WR or + * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again + * at the end. + */ + + /* Set up the transformations you want. Note that these are + * all optional. Only call them if you want them. + */ + + /* Invert monochrome pixels. */ + png_set_invert_mono(png_ptr); + + /* Shift the pixels up to a legal bit depth and fill in + * as appropriate to correctly scale the image. + */ + png_set_shift(png_ptr, &sig_bit); + + /* Pack pixels into bytes. */ + png_set_packing(png_ptr); + + /* Swap location of alpha bytes from ARGB to RGBA. */ + png_set_swap_alpha(png_ptr); + + /* Get rid of filler (OR ALPHA) bytes, pack XRGB/RGBX/ARGB/RGBA into + * RGB (4 channels -> 3 channels). The second parameter is not used. + */ + png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); + + /* Flip BGR pixels to RGB. */ + png_set_bgr(png_ptr); + + /* Swap bytes of 16-bit files to most significant byte first. */ + png_set_swap(png_ptr); + + /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats. */ + png_set_packswap(png_ptr); + + /* Turn on interlace handling if you are not using png_write_image(). */ + if (interlacing != 0) + number_passes = png_set_interlace_handling(png_ptr); + else + number_passes = 1; + + /* The easiest way to write the image (you may have a different memory + * layout, however, so choose what fits your needs best). You need to + * use the first method if you aren't handling interlacing yourself. + */ + png_uint_32 k, height, width; + + /* In this example, "image" is a one-dimensional array of bytes. */ + + /* Guard against integer overflow. */ + if (height > PNG_SIZE_MAX / (width * bytes_per_pixel)) + png_error(png_ptr, "Image data buffer would be too large"); + + png_byte image[height * width * bytes_per_pixel]; + png_byte *row_pointers[height]; + + if (height > PNG_UINT_32_MAX / (sizeof (png_byte *))) + png_error(png_ptr, "Image is too tall to process in memory"); + + /* Set up pointers into your "image" byte array. */ + for (k = 0; k < height; k++) + row_pointers[k] = image + k * width * bytes_per_pixel; + + /* One of the following output methods is REQUIRED. */ + +#ifdef entire /* Write out the entire image data in one call */ + png_write_image(png_ptr, row_pointers); + + /* The other way to write the image - deal with interlacing. */ + +#else no_entire /* Write out the image data by one or more scanlines */ + + /* The number of passes is either 1 for non-interlaced images, + * or 7 for interlaced images. + */ + for (pass = 0; pass < number_passes; pass++) + { + /* Write a few rows at a time. */ + png_write_rows(png_ptr, &row_pointers[first_row], number_of_rows); + + /* If you are only writing one row at a time, this works. */ + for (y = 0; y < height; y++) + png_write_rows(png_ptr, &row_pointers[y], 1); + } +#endif no_entire /* Use only one output method */ + + /* You can write optional chunks like tEXt, zTXt, and tIME at the end + * as well. Shouldn't be necessary in 1.2.0 and up, as all the public + * chunks are supported, and you can use png_set_unknown_chunks() to + * register unknown chunks into the info structure to be written out. + */ + + /* It is REQUIRED to call this to finish writing the rest of the file. */ + png_write_end(png_ptr, info_ptr); +#endif hilevel + + /* If you png_malloced a palette, free it here. + * (Don't free info_ptr->palette, as shown in versions 1.0.5m and earlier of + * this example; if libpng mallocs info_ptr->palette, libpng will free it). + * If you allocated it with malloc() instead of png_malloc(), use free() + * instead of png_free(). + */ + png_free(png_ptr, palette); + palette = NULL; + + /* Similarly, if you png_malloced any data that you passed in with + * png_set_something(), such as a hist or trans array, free it here, + * when you can be sure that libpng is through with it. + */ + png_free(png_ptr, trans); + trans = NULL; + + /* Whenever you use png_free(), it is a good idea to set the pointer to + * NULL in case your application inadvertently tries to png_free() it + * again. When png_free() sees a NULL it returns without action, avoiding + * the double-free problem. + */ + + /* Clean up after the write, and free any allocated memory. */ + png_destroy_write_struct(&png_ptr, &info_ptr); + + /* Close the file. */ + fclose(fp); + + /* That's it! */ + return OK; +} + +#endif /* if 0 */ diff --git a/media/libpng/libpng-config.in b/media/libpng/libpng-config.in new file mode 100644 index 0000000000..69bf8e33f0 --- /dev/null +++ b/media/libpng/libpng-config.in @@ -0,0 +1,127 @@ +#! /bin/sh + +# libpng-config +# provides configuration info for libpng. + +# Copyright (C) 2002, 2004, 2006, 2007 Glenn Randers-Pehrson + +# This code is released under the libpng license. +# For conditions of distribution and use, see the disclaimer +# and license in png.h + +# Modeled after libxml-config. + +version="@PNGLIB_VERSION@" +prefix="@prefix@" +exec_prefix="@exec_prefix@" +libdir="@libdir@" +includedir="@includedir@/libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@" +libs="-lpng@PNGLIB_MAJOR@@PNGLIB_MINOR@" +all_libs="-lpng@PNGLIB_MAJOR@@PNGLIB_MINOR@ @LIBS@" +I_opts="-I${includedir}" +L_opts="-L${libdir}" +R_opts="" +cppflags="" +ccopts="" +ldopts="" + +usage() +{ + cat < + * + * This code is released under the libpng license. See LICENSE, below. + */ +#if defined(__loongarch_sx) +# define PNG_TARGET_CODE_IMPLEMENTATION "loongarch/loongarch_lsx_init.c" +# define PNG_TARGET_IMPLEMENTS_FILTERS +# define PNG_TARGET_ROW_ALIGNMENT 16 +#endif /* __loongarch_sx */ \ No newline at end of file diff --git a/media/libpng/loongarch/filter_lsx_intrinsics.c b/media/libpng/loongarch/filter_lsx_intrinsics.c new file mode 100644 index 0000000000..3d92c27f40 --- /dev/null +++ b/media/libpng/loongarch/filter_lsx_intrinsics.c @@ -0,0 +1,417 @@ +/* filter_lsx_intrinsics.c - LSX optimized filter functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * All rights reserved. + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2016 Glenn Randers-Pehrson + * Contributed by Jin Bo (jinbo@loongson.cn) + * + * 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_LOONGARCH_LSX_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */ + +#include + +#define LSX_LD(psrc) __lsx_vld((psrc), 0) + +#define LSX_LD_2(psrc, stride, out0, out1) \ +{ \ + out0 = LSX_LD(psrc); \ + out1 = LSX_LD(psrc + stride); \ +} + +#define LSX_LD_4(psrc, stride, out0, out1, out2, out3) \ +{ \ + LSX_LD_2(psrc, stride, out0, out1); \ + LSX_LD_2(psrc + stride * 2, stride, out2, out3); \ +} + +#define LSX_ST(in, pdst) __lsx_vst(in, (pdst), 0) + +#define LSX_ST_2(in0, in1, pdst, stride) \ +{ \ + LSX_ST(in0, pdst); \ + LSX_ST(in1, pdst + stride); \ +} + +#define LSX_ST_4(in0, in1, in2, in3, pdst, stride) \ +{ \ + LSX_ST_2(in0, in1, pdst, stride); \ + LSX_ST_2(in2, in3, pdst + stride * 2, stride); \ +} + +#define LSX_ADD_B(in0, in1, out0) \ +{ \ + out0 = __lsx_vadd_b(in0, in1); \ +} + +#define LSX_ADD_B_2(in0, in1, in2, in3, out0, out1) \ +{ \ + LSX_ADD_B(in0, in1, out0); \ + LSX_ADD_B(in2, in3, out1); \ +} + +#define LSX_ADD_B_4(in0, in1, in2, in3, in4, in5, \ + in6, in7, out0, out1, out2, out3) \ +{ \ + LSX_ADD_B_2(in0, in1, in2, in3, out0, out1); \ + LSX_ADD_B_2(in4, in5, in6, in7, out2, out3); \ +} + +#define LSX_ABS_B_3(in0, in1, in2, out0, out1, out2) \ +{ \ + out0 = __lsx_vadda_h(in0, zero); \ + out1 = __lsx_vadda_h(in1, zero); \ + out2 = __lsx_vadda_h(in2, zero); \ +} + +#define LSX_ILVL_B(in_h, in_l, out0) \ +{ \ + out0 = __lsx_vilvl_b(in_h, in_l); \ +} + +#define LSX_ILVL_B_2(in0_h, in0_l, in1_h, in1_l, out0, out1) \ +{ \ + LSX_ILVL_B(in0_h, in0_l, out0); \ + LSX_ILVL_B(in1_h, in1_l, out1); \ +} + +#define LSX_HSUB_HU_BU_2(in0, in1, out0, out1) \ +{ \ + out0 = __lsx_vhsubw_hu_bu(in0, in0); \ + out1 = __lsx_vhsubw_hu_bu(in1, in1); \ +} + +#define LSX_CMP_PICK_SMALLER(in0, in1, in2, in3, in4, in5, out0) \ +{ \ + __m128i _cmph, _cmpb, _in0, _in3; \ + _cmph = __lsx_vslt_h(in1, in0); \ + _cmpb = __lsx_vpickev_b(_cmph, _cmph); \ + _in0 = __lsx_vmin_bu(in0,in1); \ + _in3 = __lsx_vbitsel_v(in3, in4, _cmpb); \ + _cmph = __lsx_vslt_h(in2, _in0); \ + _cmpb = __lsx_vpickev_b(_cmph, _cmph); \ + _in3 = __lsx_vbitsel_v(_in3, in5, _cmpb); \ + out0 = __lsx_vadd_b(out0, _in3); \ +} + +void +png_read_filter_row_up_lsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t n = row_info->rowbytes; + png_byte *rp = row; + const png_byte *pp = prev_row; + __m128i vec_0, vec_1, vec_2, vec_3; + __m128i vec_4, vec_5, vec_6, vec_7; + + while (n >= 64) + { + LSX_LD_4(rp, 16, vec_0, vec_1, vec_2, vec_3); + LSX_LD_4(pp, 16, vec_4, vec_5, vec_6, vec_7); + pp += 64; + LSX_ADD_B_4(vec_0 ,vec_4, vec_1, vec_5, vec_2, vec_6, + vec_3, vec_7, vec_0, vec_1, vec_2, vec_3); + LSX_ST_4(vec_0, vec_1, vec_2, vec_3, rp, 16); + rp += 64; + n -= 64; + } + if (n & 63) + { + if (n >= 32) + { + LSX_LD_2(rp, 16, vec_0, vec_1); + LSX_LD_2(pp, 16, vec_2, vec_3); + pp += 32; + LSX_ADD_B_2(vec_0, vec_2, vec_1, vec_3, vec_0, vec_1); + LSX_ST_2(vec_0, vec_1, rp, 16); + rp += 32; + n -= 32; + } + if (n & 31) + { + if (n >= 16) + { + vec_0 = LSX_LD(rp); + vec_1 = LSX_LD(pp); + pp += 16; + LSX_ADD_B(vec_0, vec_1, vec_0); + LSX_ST(vec_0, rp); + rp += 16; + n -= 16; + } + if (n >= 8) + { + vec_0 = __lsx_vldrepl_d(rp, 0); + vec_1 = __lsx_vldrepl_d(pp, 0); + vec_0 = __lsx_vadd_b(vec_0, vec_1); + __lsx_vstelm_d(vec_0, rp, 0, 0); + rp += 8; + pp += 8; + n -= 8; + } + while (n--) + { + *rp = *rp + *pp++; + rp++; + } + } + } +} + +void +png_read_filter_row_sub3_lsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t n = row_info->rowbytes; + png_uint_32 tmp; + png_byte *nxt = row; + __m128i vec_0, vec_1; + + PNG_UNUSED(prev_row); + + vec_0 = __lsx_vldrepl_w(nxt, 0); + nxt += 3; + n -= 3; + + while (n >= 3) + { + vec_1 = __lsx_vldrepl_w(nxt, 0); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + __lsx_vstelm_h(vec_1, nxt, 0, 0); + vec_0 = vec_1; + nxt += 2; + __lsx_vstelm_b(vec_1, nxt, 0, 2); + nxt += 1; + n -= 3; + } + + row = nxt - 3; + while (n--) + { + *nxt = *nxt + *row++; + nxt++; + } +} + +void +png_read_filter_row_sub4_lsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t n = row_info->rowbytes; + __m128i vec_0, vec_1; + + PNG_UNUSED(prev_row); + + vec_0 = __lsx_vldrepl_w(row, 0); + row += 4; + n -= 4; + + while (n >= 4) + { + vec_1 = __lsx_vldrepl_w(row, 0); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + __lsx_vstelm_w(vec_1, row, 0, 0); + vec_0 = vec_1; + row += 4; + n -= 4; + } +} + +void +png_read_filter_row_avg3_lsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t n = row_info->rowbytes; + png_byte *nxt = row; + const png_byte *prev_nxt = prev_row; + __m128i vec_0, vec_1, vec_2; + + vec_0 = __lsx_vldrepl_w(nxt, 0); + vec_1 = __lsx_vldrepl_w(prev_nxt, 0); + prev_nxt += 3; + vec_1 = __lsx_vsrli_b(vec_1, 1); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + __lsx_vstelm_h(vec_1, nxt, 0, 0); + nxt += 2; + __lsx_vstelm_b(vec_1, nxt, 0, 2); + nxt += 1; + n -= 3; + + while (n >= 3) + { + vec_2 = vec_1; + vec_0 = __lsx_vldrepl_w(nxt, 0); + vec_1 = __lsx_vldrepl_w(prev_nxt, 0); + prev_nxt += 3; + + vec_1 = __lsx_vavg_bu(vec_1, vec_2); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + + __lsx_vstelm_h(vec_1, nxt, 0, 0); + nxt += 2; + __lsx_vstelm_b(vec_1, nxt, 0, 2); + nxt += 1; + n -= 3; + } + + row = nxt - 3; + while (n--) + { + vec_2 = __lsx_vldrepl_b(row, 0); + row++; + vec_0 = __lsx_vldrepl_b(nxt, 0); + vec_1 = __lsx_vldrepl_b(prev_nxt, 0); + prev_nxt++; + + vec_1 = __lsx_vavg_bu(vec_1, vec_2); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + + __lsx_vstelm_b(vec_1, nxt, 0, 0); + nxt++; + } +} + +void +png_read_filter_row_avg4_lsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t n = row_info->rowbytes; + __m128i vec_0, vec_1, vec_2; + + vec_0 = __lsx_vldrepl_w(row, 0); + vec_1 = __lsx_vldrepl_w(prev_row, 0); + prev_row += 4; + vec_1 = __lsx_vsrli_b(vec_1, 1); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + __lsx_vstelm_w(vec_1, row, 0, 0); + row += 4; + n -= 4; + + while (n >= 4) + { + vec_2 = vec_1; + vec_0 = __lsx_vldrepl_w(row, 0); + vec_1 = __lsx_vldrepl_w(prev_row, 0); + prev_row += 4; + + vec_1 = __lsx_vavg_bu(vec_1, vec_2); + vec_1 = __lsx_vadd_b(vec_1, vec_0); + + __lsx_vstelm_w(vec_1, row, 0, 0); + row += 4; + n -= 4; + } +} + +void +png_read_filter_row_paeth3_lsx(png_row_info *row_info, + png_byte *row, const png_byte *prev_row) +{ + size_t n = row_info->rowbytes; + png_byte *nxt = row; + const png_byte *prev_nxt = prev_row; + __m128i vec_a, vec_b, vec_c, vec_d; + __m128i vec_pa, vec_pb, vec_pc; + __m128i zero = {0}; + + vec_a = __lsx_vldrepl_w(nxt, 0); + vec_b = __lsx_vldrepl_w(prev_nxt, 0); + prev_nxt += 3; + vec_d = __lsx_vadd_b(vec_a, vec_b); + __lsx_vstelm_h(vec_d, nxt, 0, 0); + nxt += 2; + __lsx_vstelm_b(vec_d, nxt, 0, 2); + nxt += 1; + n -= 3; + + while (n >= 3) + { + vec_a = vec_d; + vec_c = vec_b; + vec_b = __lsx_vldrepl_w(prev_nxt, 0); + prev_nxt += 3; + vec_d = __lsx_vldrepl_w(nxt, 0); + + LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb); + LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb); + vec_pc = __lsx_vadd_h(vec_pa, vec_pb); + LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc); + LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d); + + __lsx_vstelm_h(vec_d, nxt, 0, 0); + nxt += 2; + __lsx_vstelm_b(vec_d, nxt, 0, 2); + nxt += 1; + n -= 3; + } + + prev_row = prev_nxt - 3; + row = nxt - 3; + while (n--) + { + vec_a = __lsx_vldrepl_b(row, 0); + row++; + vec_b = __lsx_vldrepl_b(prev_nxt, 0); + prev_nxt++; + vec_c = __lsx_vldrepl_b(prev_row, 0); + prev_row++; + vec_d = __lsx_vldrepl_b(nxt, 0); + + LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb); + LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb); + vec_pc = __lsx_vadd_h(vec_pa, vec_pb); + LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc); + LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d); + + __lsx_vstelm_b(vec_d, nxt, 0, 0); + nxt++; + } +} + +void +png_read_filter_row_paeth4_lsx(png_row_info *row_info, + png_byte *row, const png_byte *prev_row) +{ + size_t n = row_info->rowbytes; + __m128i vec_a, vec_b, vec_c, vec_d; + __m128i vec_pa, vec_pb, vec_pc; + __m128i zero = {0}; + + vec_a = __lsx_vldrepl_w(row, 0); + vec_b = __lsx_vldrepl_w(prev_row, 0); + prev_row += 4; + vec_d = __lsx_vadd_b(vec_a, vec_b); + __lsx_vstelm_w(vec_d, row, 0, 0); + row += 4; + n -= 4; + + while (n >= 4) + { + vec_a = vec_d; + vec_c = vec_b; + vec_b = __lsx_vldrepl_w(prev_row, 0); + prev_row += 4; + vec_d = __lsx_vldrepl_w(row, 0); + + LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb); + LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb); + vec_pc = __lsx_vadd_h(vec_pa, vec_pb); + LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc); + LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d); + + __lsx_vstelm_w(vec_d, row, 0, 0); + row += 4; + n -= 4; + } +} + +#endif /* PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 (intrinsics) */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/media/libpng/loongarch/loongarch_lsx_init.c b/media/libpng/loongarch/loongarch_lsx_init.c new file mode 100644 index 0000000000..e88f2a3bdc --- /dev/null +++ b/media/libpng/loongarch/loongarch_lsx_init.c @@ -0,0 +1,66 @@ +/* loongarch_lsx_init.c - LSX optimized filter functions + * + * Copyright (c) 2021 Loongson Technology Corporation Limited + * All rights reserved. + * Contributed by Jin Bo + * + * 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_LOONGARCH_LSX_IMPLEMENTATION == 1 + +#include + +#define LA_HWCAP_LSX (1<<4) +static int +png_has_lsx(void) +{ + int flags = 0; + int flag = (int)getauxval(AT_HWCAP); + + if (flag & LA_HWCAP_LSX) + return 1; + + return 0; +} + +void +png_init_filter_functions_lsx(png_struct *pp, unsigned int bpp) +{ + /* 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.) + */ + + if (png_has_lsx()) + { + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_lsx; + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_lsx; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_lsx; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_lsx; + } + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_lsx; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_lsx; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_lsx; + } + } +} + +#endif /* PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/media/libpng/mips/.editorconfig b/media/libpng/mips/.editorconfig new file mode 100644 index 0000000000..de2e98ab42 --- /dev/null +++ b/media/libpng/mips/.editorconfig @@ -0,0 +1,8 @@ +# https://editorconfig.org + +root = false + +# FIXME +[*.[ch]] +max_doc_length = unset +max_line_length = unset diff --git a/media/libpng/mips/check.h b/media/libpng/mips/check.h new file mode 100644 index 0000000000..8ed2a6d233 --- /dev/null +++ b/media/libpng/mips/check.h @@ -0,0 +1,25 @@ +/* mips/check.h - MIPS optimised filter functions + * + * Copyright (c) 2024 John Bowler + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +/* Unlike other architectures the tests here are written so that they can be + * extended by the addition of other different ISA extensions. This could + * easily be done with all the other architectures too. + * + * TODO: move the ISA specific checks to sub-directories so that the code + * does not taint other implementations. + */ +#include "msacheck.h" /* Check for MSA extensions */ +/*... add other checks here (each in its own header file). */ + +#ifdef PNG_TARGET_MIPS_TARGET_CODE_SUPPORTED + /* Regardless of the optimization the following must always be the same: */ +# define PNG_TARGET_CODE_IMPLEMENTATION "mips/mips_init.c" +# define PNG_TARGET_IMPLEMENTS_FILTERS +# define PNG_TARGET_ROW_ALIGNMENT 16 +#endif diff --git a/media/libpng/mips/filter_mmi_inline_assembly.c b/media/libpng/mips/filter_mmi_inline_assembly.c new file mode 100644 index 0000000000..62e4d4ac44 --- /dev/null +++ b/media/libpng/mips/filter_mmi_inline_assembly.c @@ -0,0 +1,525 @@ +/* filter_mmi_intrinsics.c - MMI optimized filter functions + * + * Copyright (c) 2024 Cosmin Truta + * Written by zhanglixia and guxiwei, 2023 + * + * 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_MIPS_MMI_IMPLEMENTATION == 2 /* Inline Assembly */ + +/* 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. + */ + +void png_read_filter_row_up_mmi(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + int istop = row_info->rowbytes; + double rp,pp; + __asm__ volatile ( + "1: \n\t" + "ldc1 %[rp], 0x00(%[row]) \n\t" + "ldc1 %[pp], 0x00(%[prev_row]) \n\t" + "paddb %[rp], %[rp], %[pp] \n\t" + "sdc1 %[rp], 0x00(%[row]) \n\t" + + "daddiu %[row], %[row], 0x08 \n\t" + "daddiu %[prev_row], %[prev_row], 0x08 \n\t" + "daddiu %[istop], %[istop], -0x08 \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp) + : [row]"r"(row), [prev_row]"r"(prev_row), + [istop]"r"(istop) + : "memory" + ); +} + +void png_read_filter_row_sub3_mmi(png_row_info *row_info, png_byte *row, + const png_byte *prev) +{ + int istop = row_info->rowbytes; + double rp, pp, dest; + double eight, sixteen, twenty_four, forty_eight; + double tmp0; + double ftmp[2]; + + __asm__ volatile ( + "li %[tmp0], 0x08 \n\t" + "dmtc1 %[tmp0], %[eight] \n\t" + "li %[tmp0], 0x10 \n\t" + "dmtc1 %[tmp0], %[sixteen] \n\t" + "li %[tmp0], 0x18 \n\t" + "dmtc1 %[tmp0], %[twenty_four] \n\t" + "li %[tmp0], 0x30 \n\t" + "dmtc1 %[tmp0], %[forty_eight] \n\t" + "xor %[dest], %[dest], %[dest] \n\t" + + "1: \n\t" + "gsldrc1 %[rp], 0x00(%[row]) \n\t" + "gsldlc1 %[rp], 0x07(%[row]) \n\t" + "gsldrc1 %[pp], 0x08(%[row]) \n\t" + "gsldlc1 %[pp], 0x0f(%[row]) \n\t" + + "paddb %[ftmp0], %[dest], %[rp] \n\t" + "swc1 %[ftmp0], 0x00(%[row]) \n\t" + + "dsrl %[ftmp1], %[rp], %[twenty_four] \n\t" + "paddb %[dest], %[ftmp1], %[ftmp0] \n\t" + "gsswrc1 %[dest], 0x03(%[row]) \n\t" + "gsswlc1 %[dest], 0x06(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp], %[forty_eight] \n\t" + "dsll %[ftmp1], %[pp], %[sixteen] \n\t" + "or %[ftmp0], %[ftmp0], %[ftmp1] \n\t" + "paddb %[dest], %[dest], %[ftmp0] \n\t" + "gsswrc1 %[dest], 0x06(%[row]) \n\t" + "gsswlc1 %[dest], 0x09(%[row]) \n\t" + + "dsrl %[ftmp0], %[pp], %[eight] \n\t" + "paddb %[dest], %[dest], %[ftmp0] \n\t" + "gsswrc1 %[dest], 0x09(%[row]) \n\t" + "daddiu %[row], %[row], 0x0c \n\t" + "daddiu %[istop], %[istop], -0x0c \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp), [dest]"=&f"(dest), + [tmp0]"=&r"(tmp0), [ftmp0]"=&f"(ftmp[0]), + [ftmp1]"=&f"(ftmp[1]), [eight]"=&f"(eight), + [sixteen]"=&f"(sixteen), [twenty_four]"=&f"(twenty_four), + [forty_eight]"=&f"(forty_eight) + : [row]"r"(row), [istop]"r"(istop) + : "memory" + ); + + PNG_UNUSED(prev) +} + +void png_read_filter_row_sub4_mmi(png_row_info *row_info, png_byte *row, + const png_byte *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. + */ + int istop = row_info->rowbytes; + double rp,pp; + + __asm__ volatile ( + "1: \n\t" + "lwc1 %[pp], 0x00(%[row]) \n\t" + "lwc1 %[rp], 0x04(%[row]) \n\t" + "paddb %[rp], %[rp], %[pp] \n\t" + "swc1 %[rp], 0x04(%[row]) \n\t" + + "daddiu %[row], %[row], 0x04 \n\t" + "daddiu %[istop], %[istop], -0x04 \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp) + : [row]"r"(row), [istop]"r"(istop) + : "memory" + ); + + PNG_UNUSED(prev) +} + +void png_read_filter_row_avg3_mmi(png_row_info *row_info, png_byte *row, + const png_byte *prev) +{ + int istop = row_info->rowbytes; + double rp, pp, rp1, pp1; + double tmp0; + double ftmp[3]; + double one, dest; + double eight, sixteen, twenty_four, forty_eight; + + __asm__ volatile ( + "li %[tmp0], 0x08 \n\t" + "dmtc1 %[tmp0], %[eight] \n\t" + "li %[tmp0], 0x10 \n\t" + "dmtc1 %[tmp0], %[sixteen] \n\t" + "li %[tmp0], 0x18 \n\t" + "dmtc1 %[tmp0], %[twenty_four] \n\t" + "li %[tmp0], 0x30 \n\t" + "dmtc1 %[tmp0], %[forty_eight] \n\t" + "xor %[dest], %[dest], %[dest] \n\t" + + "li %[tmp0], 0x01 \n\t" + "ins %[tmp0], %[tmp0], 8, 8 \n\t" + "dmtc1 %[tmp0], %[one] \n\t" + "pshufh %[one], %[one], %[dest] \n\t" + + "1: \n\t" + "gsldrc1 %[rp], 0x00(%[row]) \n\t" + "gsldlc1 %[rp], 0x07(%[row]) \n\t" + "gsldrc1 %[pp], 0x00(%[prev]) \n\t" + "gsldlc1 %[pp], 0x07(%[prev]) \n\t" + "gsldrc1 %[rp1], 0x08(%[row]) \n\t" + "gsldlc1 %[rp1], 0x0f(%[row]) \n\t" + "gsldrc1 %[pp1], 0x08(%[prev]) \n\t" + "gsldlc1 %[pp1], 0x0f(%[prev]) \n\t" + + "xor %[ftmp0], %[pp], %[dest] \n\t" + "pavgb %[ftmp1], %[pp], %[dest] \n\t" + "and %[ftmp0], %[ftmp0], %[one] \n\t" + "psubb %[ftmp1], %[ftmp1], %[ftmp0] \n\t" + "paddb %[dest], %[rp], %[ftmp1] \n\t" + "swc1 %[dest], 0x00(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp], %[twenty_four] \n\t" + "dsrl %[ftmp1], %[pp], %[twenty_four] \n\t" + + "xor %[ftmp2], %[ftmp1], %[dest] \n\t" + "pavgb %[ftmp1], %[ftmp1], %[dest] \n\t" + "and %[ftmp2], %[ftmp2], %[one] \n\t" + "psubb %[ftmp1], %[ftmp1], %[ftmp2] \n\t" + "paddb %[dest], %[ftmp0], %[ftmp1] \n\t" + "gsswrc1 %[dest], 0x03(%[row]) \n\t" + "gsswlc1 %[dest], 0x06(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp], %[forty_eight] \n\t" + "dsll %[ftmp1], %[rp1], %[sixteen] \n\t" + "or %[ftmp0], %[ftmp0], %[ftmp1] \n\t" + "dsrl %[ftmp2], %[pp], %[forty_eight] \n\t" + "dsll %[ftmp1], %[pp1], %[sixteen] \n\t" + "or %[ftmp1], %[ftmp2], %[ftmp1] \n\t" + + "xor %[ftmp2], %[ftmp1], %[dest] \n\t" + "pavgb %[ftmp1], %[ftmp1], %[dest] \n\t" + "and %[ftmp2], %[ftmp2], %[one] \n\t" + "psubb %[ftmp1], %[ftmp1], %[ftmp2] \n\t" + "paddb %[dest], %[ftmp0], %[ftmp1] \n\t" + "gsswrc1 %[dest], 0x06(%[row]) \n\t" + "gsswlc1 %[dest], 0x09(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp1], %[eight] \n\t" + "dsrl %[ftmp1], %[pp1], %[eight] \n\t" + + "xor %[ftmp2], %[ftmp1], %[dest] \n\t" + "pavgb %[ftmp1], %[ftmp1], %[dest] \n\t" + "and %[ftmp2], %[ftmp2], %[one] \n\t" + "psubb %[ftmp1], %[ftmp1], %[ftmp2] \n\t" + "paddb %[dest], %[ftmp0], %[ftmp1] \n\t" + "gsswrc1 %[dest], 0x09(%[row]) \n\t" + "daddiu %[row], %[row], 0x0c \n\t" + "daddiu %[prev], %[prev], 0x0c \n\t" + "daddiu %[istop], %[istop], -0x0c \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp), [rp1]"=&f"(rp1), + [pp1]"=&f"(pp1), [tmp0]"=&r"(tmp0), [ftmp0]"=&f"(ftmp[0]), + [ftmp1]"=&f"(ftmp[1]), [ftmp2]"=&f"(ftmp[2]), [one]"=&f"(one), + [dest]"=&f"(dest), [eight]"=&f"(eight), [sixteen]"=&f"(sixteen), + [twenty_four]"=&f"(twenty_four), [forty_eight]"=&f"(forty_eight) + : [row]"r"(row), [prev]"r"(prev), [istop]"r"(istop) + : "memory" + ); +} + +void png_read_filter_row_avg4_mmi(png_row_info *row_info, png_byte *row, + const png_byte *prev) +{ + int istop = row_info->rowbytes; + double rp,pp; + double dest; + double ftmp[2]; + double tmp; + + __asm__ volatile ( + "xor %[dest], %[dest], %[dest] \n\t" + "li %[tmp], 0x01 \n\t" + "ins %[tmp], %[tmp], 8, 8 \n\t" + "dmtc1 %[tmp], %[ftmp1] \n\t" + "pshufh %[ftmp1], %[ftmp1], %[dest] \n\t" + + "1: \n\t" + "lwc1 %[rp], 0x00(%[row]) \n\t" + "lwc1 %[pp], 0x00(%[prev]) \n\t" + "xor %[ftmp0], %[pp], %[dest] \n\t" + "pavgb %[pp], %[pp], %[dest] \n\t" + "and %[ftmp0], %[ftmp0], %[ftmp1] \n\t" + "psubb %[pp], %[pp], %[ftmp0] \n\t" + "paddb %[dest], %[rp], %[pp] \n\t" + "swc1 %[dest], 0x00(%[row]) \n\t" + "daddiu %[row], %[row], 0x04 \n\t" + "daddiu %[prev], %[prev], 0x04 \n\t" + "daddiu %[istop], %[istop], -0x04 \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp), [ftmp0]"=&f"(ftmp[0]), + [ftmp1]"=&f"(ftmp[1]), [dest]"=&f"(dest), [tmp]"=&r"(tmp) + : [row]"r"(row), [prev]"r"(prev), [istop]"r"(istop) + : "memory" + ); +} + +void png_read_filter_row_paeth3_mmi(png_row_info *row_info, png_byte *row, + const png_byte *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. + */ + int istop = row_info->rowbytes; + double rp, pp, rp1, pp1, zero; + double a, b, c, d, pa, pb, pc; + double tmp0; + double ftmp[3]; + double eight, sixteen, twenty_four, forty_eight; + + __asm__ volatile ( + "xor %[a], %[a], %[a] \n\t" + "xor %[c], %[c], %[c] \n\t" + "xor %[zero], %[zero], %[zero] \n\t" + "li %[tmp0], 0x08 \n\t" + "dmtc1 %[tmp0], %[eight] \n\t" + "li %[tmp0], 0x10 \n\t" + "dmtc1 %[tmp0], %[sixteen] \n\t" + "li %[tmp0], 0x18 \n\t" + "dmtc1 %[tmp0], %[twenty_four] \n\t" + "li %[tmp0], 0x30 \n\t" + "dmtc1 %[tmp0], %[forty_eight] \n\t" + + "1: \n\t" + "gsldrc1 %[rp], 0x00(%[row]) \n\t" + "gsldlc1 %[rp], 0x07(%[row]) \n\t" + "gsldrc1 %[pp], 0x00(%[prev]) \n\t" + "gsldlc1 %[pp], 0x07(%[prev]) \n\t" + "gsldrc1 %[rp1], 0x08(%[row]) \n\t" + "gsldlc1 %[rp1], 0x0f(%[row]) \n\t" + "gsldrc1 %[pp1], 0x08(%[prev]) \n\t" + "gsldlc1 %[pp1], 0x0f(%[prev]) \n\t" + + "punpcklbh %[b], %[pp], %[zero] \n\t" + "punpcklbh %[d], %[rp], %[zero] \n\t" + "packushb %[ftmp0], %[c], %[c] \n\t" + "packushb %[ftmp1], %[a], %[a] \n\t" + "pasubub %[pa], %[pp], %[ftmp0] \n\t" + "pasubub %[pb], %[ftmp1], %[ftmp0] \n\t" + "psubh %[ftmp0], %[b], %[c] \n\t" + "psubh %[ftmp1], %[a], %[c] \n\t" + "paddh %[pc], %[ftmp0], %[ftmp1] \n\t" + "pcmpgth %[ftmp0], %[zero], %[pc] \n\t" + "xor %[pc], %[pc], %[ftmp0] \n\t" + "psubh %[pc], %[pc], %[ftmp0] \n\t" + "punpcklbh %[pa], %[pa], %[zero] \n\t" + "punpcklbh %[pb], %[pb], %[zero] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pb] \n\t" + "and %[ftmp1], %[b], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "pminsh %[pa], %[pa], %[pb] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pc] \n\t" + "and %[ftmp1], %[c], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "paddb %[a], %[a], %[d] \n\t" + "packushb %[d], %[a], %[a] \n\t" + "punpcklbh %[c], %[pp], %[zero] \n\t" + "swc1 %[d], 0x00(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp], %[twenty_four] \n\t" + "dsrl %[ftmp2], %[pp], %[twenty_four] \n\t" + + "punpcklbh %[b], %[ftmp2], %[zero] \n\t" + "punpcklbh %[d], %[ftmp0], %[zero] \n\t" + "packushb %[ftmp0], %[c], %[c] \n\t" + "packushb %[ftmp1], %[a], %[a] \n\t" + "pasubub %[pa], %[ftmp2], %[ftmp0] \n\t" + "pasubub %[pb], %[ftmp1], %[ftmp0] \n\t" + "psubh %[ftmp0], %[b], %[c] \n\t" + "psubh %[ftmp1], %[a], %[c] \n\t" + "paddh %[pc], %[ftmp0], %[ftmp1] \n\t" + "pcmpgth %[ftmp0], %[zero], %[pc] \n\t" + "xor %[pc], %[pc], %[ftmp0] \n\t" + "psubh %[pc], %[pc], %[ftmp0] \n\t" + "punpcklbh %[pa], %[pa], %[zero] \n\t" + "punpcklbh %[pb], %[pb], %[zero] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pb] \n\t" + "and %[ftmp1], %[b], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "pminsh %[pa], %[pa], %[pb] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pc] \n\t" + "and %[ftmp1], %[c], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "paddb %[a], %[a], %[d] \n\t" + "packushb %[d], %[a], %[a] \n\t" + "punpcklbh %[c], %[ftmp2], %[zero] \n\t" + "gsswrc1 %[d], 0x03(%[row]) \n\t" + "gsswlc1 %[d], 0x06(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp], %[forty_eight] \n\t" + "dsll %[ftmp1], %[rp1], %[sixteen] \n\t" + "or %[ftmp0], %[ftmp0], %[ftmp1] \n\t" + "dsrl %[ftmp2], %[pp], %[forty_eight] \n\t" + "dsll %[ftmp1], %[pp1], %[sixteen] \n\t" + "or %[ftmp2], %[ftmp2], %[ftmp1] \n\t" + + "punpcklbh %[b], %[ftmp2], %[zero] \n\t" + "punpcklbh %[d], %[ftmp0], %[zero] \n\t" + "packushb %[ftmp0], %[c], %[c] \n\t" + "packushb %[ftmp1], %[a], %[a] \n\t" + "pasubub %[pa], %[ftmp2], %[ftmp0] \n\t" + "pasubub %[pb], %[ftmp1], %[ftmp0] \n\t" + "psubh %[ftmp0], %[b], %[c] \n\t" + "psubh %[ftmp1], %[a], %[c] \n\t" + "paddh %[pc], %[ftmp0], %[ftmp1] \n\t" + "pcmpgth %[ftmp0], %[zero], %[pc] \n\t" + "xor %[pc], %[pc], %[ftmp0] \n\t" + "psubh %[pc], %[pc], %[ftmp0] \n\t" + "punpcklbh %[pa], %[pa], %[zero] \n\t" + "punpcklbh %[pb], %[pb], %[zero] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pb] \n\t" + "and %[ftmp1], %[b], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "pminsh %[pa], %[pa], %[pb] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pc] \n\t" + "and %[ftmp1], %[c], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "paddb %[a], %[a], %[d] \n\t" + "packushb %[d], %[a], %[a] \n\t" + "punpcklbh %[c], %[ftmp2], %[zero] \n\t" + "gsswrc1 %[d], 0x06(%[row]) \n\t" + "gsswlc1 %[d], 0x09(%[row]) \n\t" + + "dsrl %[ftmp0], %[rp1], %[eight] \n\t" + "dsrl %[ftmp2], %[pp1], %[eight] \n\t" + + "punpcklbh %[b], %[ftmp2], %[zero] \n\t" + "punpcklbh %[d], %[ftmp0], %[zero] \n\t" + "packushb %[ftmp0], %[c], %[c] \n\t" + "packushb %[ftmp1], %[a], %[a] \n\t" + "pasubub %[pa], %[ftmp2], %[ftmp0] \n\t" + "pasubub %[pb], %[ftmp1], %[ftmp0] \n\t" + "psubh %[ftmp0], %[b], %[c] \n\t" + "psubh %[ftmp1], %[a], %[c] \n\t" + "paddh %[pc], %[ftmp0], %[ftmp1] \n\t" + "pcmpgth %[ftmp0], %[zero], %[pc] \n\t" + "xor %[pc], %[pc], %[ftmp0] \n\t" + "psubh %[pc], %[pc], %[ftmp0] \n\t" + "punpcklbh %[pa], %[pa], %[zero] \n\t" + "punpcklbh %[pb], %[pb], %[zero] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pb] \n\t" + "and %[ftmp1], %[b], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "pminsh %[pa], %[pa], %[pb] \n\t" + "pcmpgth %[ftmp0], %[pa], %[pc] \n\t" + "and %[ftmp1], %[c], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "paddb %[a], %[a], %[d] \n\t" + "packushb %[d], %[a], %[a] \n\t" + "punpcklbh %[c], %[ftmp2], %[zero] \n\t" + "gsswrc1 %[d], 0x09(%[row]) \n\t" + + "daddiu %[row], %[row], 0x0c \n\t" + "daddiu %[prev], %[prev], 0x0c \n\t" + "daddiu %[istop], %[istop], -0x0c \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp), [rp1]"=&f"(rp1), [pp1]"=&f"(pp1), + [zero]"=&f"(zero), [a]"=&f"(a),[b]"=&f"(b), [c]"=&f"(c), + [d]"=&f"(d), [pa]"=&f"(pa), [pb]"=&f"(pb), [pc]"=&f"(pc), + [tmp0]"=&r"(tmp0), [ftmp0]"=&f"(ftmp[0]), [ftmp1]"=&f"(ftmp[1]), + [ftmp2]"=&f"(ftmp[2]), [eight]"=&f"(eight), [sixteen]"=&f"(sixteen), + [twenty_four]"=&f"(twenty_four), [forty_eight]"=&f"(forty_eight) + : [row]"r"(row), [prev]"r"(prev), [istop]"r"(istop) + : "memory" + ); +} + +void png_read_filter_row_paeth4_mmi(png_row_info *row_info, png_byte *row, + const png_byte *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. + */ + int istop = row_info->rowbytes; + double rp, pp, zero; + double a, b, c, d, pa, pb, pc; + double ftmp[2]; + + __asm__ volatile ( + "xor %[a], %[a], %[a] \n\t" + "xor %[c], %[c], %[c] \n\t" + "xor %[zero], %[zero], %[zero] \n\t" + + "1: \n\t" + "lwc1 %[rp], 0x00(%[row]) \n\t" + "lwc1 %[pp], 0x00(%[prev]) \n\t" + "punpcklbh %[b], %[pp], %[zero] \n\t" + "punpcklbh %[d], %[rp], %[zero] \n\t" + + "packushb %[ftmp0], %[c], %[c] \n\t" + "packushb %[ftmp1], %[a], %[a] \n\t" + "pasubub %[pa], %[pp], %[ftmp0] \n\t" + "pasubub %[pb], %[ftmp1], %[ftmp0] \n\t" + "psubh %[ftmp0], %[b], %[c] \n\t" + "psubh %[ftmp1], %[a], %[c] \n\t" + "paddh %[pc], %[ftmp0], %[ftmp1] \n\t" + "pcmpgth %[ftmp0], %[zero], %[pc] \n\t" + "xor %[pc], %[pc], %[ftmp0] \n\t" + "psubh %[pc], %[pc], %[ftmp0] \n\t" + + "punpcklbh %[pa], %[pa], %[zero] \n\t" + "punpcklbh %[pb], %[pb], %[zero] \n\t" + + "pcmpgth %[ftmp0], %[pa], %[pb] \n\t" + "and %[ftmp1], %[b], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "pminsh %[pa], %[pa], %[pb] \n\t" + + "pcmpgth %[ftmp0], %[pa], %[pc] \n\t" + "and %[ftmp1], %[c], %[ftmp0] \n\t" + "pandn %[a], %[ftmp0], %[a] \n\t" + "or %[a], %[a], %[ftmp1] \n\t" + "paddb %[a], %[a], %[d] \n\t" + "packushb %[d], %[a], %[a] \n\t" + "swc1 %[d], 0x00(%[row]) \n\t" + "punpcklbh %[c], %[pp], %[zero] \n\t" + "daddiu %[row], %[row], 0x04 \n\t" + "daddiu %[prev], %[prev], 0x04 \n\t" + "daddiu %[istop], %[istop], -0x04 \n\t" + "bgtz %[istop], 1b \n\t" + : [rp]"=&f"(rp), [pp]"=&f"(pp), [zero]"=&f"(zero), + [a]"=&f"(a), [b]"=&f"(b), [c]"=&f"(c), [d]"=&f"(d), + [pa]"=&f"(pa), [pb]"=&f"(pb), [pc]"=&f"(pc), + [ftmp0]"=&f"(ftmp[0]), [ftmp1]"=&f"(ftmp[1]) + : [row]"r"(row), [prev]"r"(prev), [istop]"r"(istop) + : "memory" + ); +} + +#endif /* PNG_MIPS_MMI_IMPLEMENTATION > 0 */ +#endif /* READ */ diff --git a/media/libpng/mips/filter_msa_intrinsics.c b/media/libpng/mips/filter_msa_intrinsics.c new file mode 100644 index 0000000000..34b150b9f9 --- /dev/null +++ b/media/libpng/mips/filter_msa_intrinsics.c @@ -0,0 +1,797 @@ +/* filter_msa_intrinsics.c - MSA optimised filter functions + * + * Copyright (c) 2018-2024 Cosmin Truta + * Copyright (c) 2016 Glenn Randers-Pehrson + * Written by Mandar Sahastrabuddhe, August 2016 + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ +#include +#include + +/* libpng row pointers are not necessarily aligned to any particular boundary, + * however this code will only work with appropriate alignment. mips/mips_init.c + * checks for this (and will not compile unless it is done). This code uses + * variants of png_aligncast to avoid compiler warnings. + */ +#define png_ptr(type,pointer) png_aligncast(type *,pointer) +#define png_ptrc(type,pointer) png_aligncastconst(const type *,pointer) + +/* The following relies on a variable 'temp_pointer' being declared with type + * 'type'. This is written this way just to hide the GCC strict aliasing + * warning; note that the code is safe because there never is an alias between + * the input and output pointers. + */ +#define png_ldr(type,pointer)\ + (temp_pointer = png_ptr(type,pointer), *temp_pointer) + +#ifdef CLANG_BUILD + #define MSA_SRLI_B(a, b) __msa_srli_b((v16i8) a, b) + + #define LW(psrc) \ + ( { \ + uint8_t *psrc_lw_m = (uint8_t *) (psrc); \ + uint32_t val_m; \ + \ + __asm__ volatile ( \ + "lw %[val_m], %[psrc_lw_m] \n\t" \ + \ + : [val_m] "=r" (val_m) \ + : [psrc_lw_m] "m" (*psrc_lw_m) \ + ); \ + \ + val_m; \ + } ) + + #define SH(val, pdst) \ + { \ + uint8_t *pdst_sh_m = (uint8_t *) (pdst); \ + uint16_t val_m = (val); \ + \ + __asm__ volatile ( \ + "sh %[val_m], %[pdst_sh_m] \n\t" \ + \ + : [pdst_sh_m] "=m" (*pdst_sh_m) \ + : [val_m] "r" (val_m) \ + ); \ + } + + #define SW(val, pdst) \ + { \ + uint8_t *pdst_sw_m = (uint8_t *) (pdst); \ + uint32_t val_m = (val); \ + \ + __asm__ volatile ( \ + "sw %[val_m], %[pdst_sw_m] \n\t" \ + \ + : [pdst_sw_m] "=m" (*pdst_sw_m) \ + : [val_m] "r" (val_m) \ + ); \ + } + + #if __mips == 64 + #define SD(val, pdst) \ + { \ + uint8_t *pdst_sd_m = (uint8_t *) (pdst); \ + uint64_t val_m = (val); \ + \ + __asm__ volatile ( \ + "sd %[val_m], %[pdst_sd_m] \n\t" \ + \ + : [pdst_sd_m] "=m" (*pdst_sd_m) \ + : [val_m] "r" (val_m) \ + ); \ + } + #else + #define SD(val, pdst) \ + { \ + uint8_t *pdst_sd_m = (uint8_t *) (pdst); \ + uint32_t val0_m, val1_m; \ + \ + val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF); \ + val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF); \ + \ + SW(val0_m, pdst_sd_m); \ + SW(val1_m, pdst_sd_m + 4); \ + } + #endif /* __mips == 64 */ +#else + #define MSA_SRLI_B(a, b) (a >> b) + +#if __mips_isa_rev >= 6 + #define LW(psrc) \ + ( { \ + uint8_t *psrc_lw_m = (uint8_t *) (psrc); \ + uint32_t val_m; \ + \ + __asm__ volatile ( \ + "lw %[val_m], %[psrc_lw_m] \n\t" \ + \ + : [val_m] "=r" (val_m) \ + : [psrc_lw_m] "m" (*psrc_lw_m) \ + ); \ + \ + val_m; \ + } ) + + #define SH(val, pdst) \ + { \ + uint8_t *pdst_sh_m = (uint8_t *) (pdst); \ + uint16_t val_m = (val); \ + \ + __asm__ volatile ( \ + "sh %[val_m], %[pdst_sh_m] \n\t" \ + \ + : [pdst_sh_m] "=m" (*pdst_sh_m) \ + : [val_m] "r" (val_m) \ + ); \ + } + + #define SW(val, pdst) \ + { \ + uint8_t *pdst_sw_m = (uint8_t *) (pdst); \ + uint32_t val_m = (val); \ + \ + __asm__ volatile ( \ + "sw %[val_m], %[pdst_sw_m] \n\t" \ + \ + : [pdst_sw_m] "=m" (*pdst_sw_m) \ + : [val_m] "r" (val_m) \ + ); \ + } + + #if __mips == 64 + #define SD(val, pdst) \ + { \ + uint8_t *pdst_sd_m = (uint8_t *) (pdst); \ + uint64_t val_m = (val); \ + \ + __asm__ volatile ( \ + "sd %[val_m], %[pdst_sd_m] \n\t" \ + \ + : [pdst_sd_m] "=m" (*pdst_sd_m) \ + : [val_m] "r" (val_m) \ + ); \ + } + #else + #define SD(val, pdst) \ + { \ + uint8_t *pdst_sd_m = (uint8_t *) (pdst); \ + uint32_t val0_m, val1_m; \ + \ + val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF); \ + val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF); \ + \ + SW(val0_m, pdst_sd_m); \ + SW(val1_m, pdst_sd_m + 4); \ + } + #endif /* __mips == 64 */ +#else + #define LW(psrc) \ + ( { \ + uint8_t *psrc_lw_m = (uint8_t *) (psrc); \ + uint32_t val_m; \ + \ + __asm__ volatile ( \ + "ulw %[val_m], %[psrc_lw_m] \n\t" \ + \ + : [val_m] "=r" (val_m) \ + : [psrc_lw_m] "m" (*psrc_lw_m) \ + ); \ + \ + val_m; \ + } ) + + #define SH(val, pdst) \ + { \ + uint8_t *pdst_sh_m = (uint8_t *) (pdst); \ + uint16_t val_m = (val); \ + \ + __asm__ volatile ( \ + "ush %[val_m], %[pdst_sh_m] \n\t" \ + \ + : [pdst_sh_m] "=m" (*pdst_sh_m) \ + : [val_m] "r" (val_m) \ + ); \ + } + + #define SW(val, pdst) \ + { \ + uint8_t *pdst_sw_m = (uint8_t *) (pdst); \ + uint32_t val_m = (val); \ + \ + __asm__ volatile ( \ + "usw %[val_m], %[pdst_sw_m] \n\t" \ + \ + : [pdst_sw_m] "=m" (*pdst_sw_m) \ + : [val_m] "r" (val_m) \ + ); \ + } + + #define SD(val, pdst) \ + { \ + uint8_t *pdst_sd_m = (uint8_t *) (pdst); \ + uint32_t val0_m, val1_m; \ + \ + val0_m = (uint32_t) ((val) & 0x00000000FFFFFFFF); \ + val1_m = (uint32_t) (((val) >> 32) & 0x00000000FFFFFFFF); \ + \ + SW(val0_m, pdst_sd_m); \ + SW(val1_m, pdst_sd_m + 4); \ + } + + #define SW_ZERO(pdst) \ + { \ + uint8_t *pdst_m = (uint8_t *) (pdst); \ + \ + __asm__ volatile ( \ + "usw $0, %[pdst_m] \n\t" \ + \ + : [pdst_m] "=m" (*pdst_m) \ + : \ + ); \ + } +#endif /* __mips_isa_rev >= 6 */ +#endif + +#define LD_B(RTYPE, psrc) *((RTYPE *) (psrc)) +#define LD_UB(...) LD_B(v16u8, __VA_ARGS__) +#define LD_B2(RTYPE, psrc, stride, out0, out1) \ +{ \ + out0 = LD_B(RTYPE, (psrc)); \ + out1 = LD_B(RTYPE, (psrc) + stride); \ +} +#define LD_UB2(...) LD_B2(v16u8, __VA_ARGS__) +#define LD_B4(RTYPE, psrc, stride, out0, out1, out2, out3) \ +{ \ + LD_B2(RTYPE, (psrc), stride, out0, out1); \ + LD_B2(RTYPE, (psrc) + 2 * stride , stride, out2, out3); \ +} +#define LD_UB4(...) LD_B4(v16u8, __VA_ARGS__) + +#define ST_B(RTYPE, in, pdst) *((RTYPE *) (pdst)) = (in) +#define ST_UB(...) ST_B(v16u8, __VA_ARGS__) +#define ST_B2(RTYPE, in0, in1, pdst, stride) \ +{ \ + ST_B(RTYPE, in0, (pdst)); \ + ST_B(RTYPE, in1, (pdst) + stride); \ +} +#define ST_UB2(...) ST_B2(v16u8, __VA_ARGS__) +#define ST_B4(RTYPE, in0, in1, in2, in3, pdst, stride) \ +{ \ + ST_B2(RTYPE, in0, in1, (pdst), stride); \ + ST_B2(RTYPE, in2, in3, (pdst) + 2 * stride, stride); \ +} +#define ST_UB4(...) ST_B4(v16u8, __VA_ARGS__) + +#define ADD2(in0, in1, in2, in3, out0, out1) \ +{ \ + out0 = in0 + in1; \ + out1 = in2 + in3; \ +} +#define ADD3(in0, in1, in2, in3, in4, in5, \ + out0, out1, out2) \ +{ \ + ADD2(in0, in1, in2, in3, out0, out1); \ + out2 = in4 + in5; \ +} +#define ADD4(in0, in1, in2, in3, in4, in5, in6, in7, \ + out0, out1, out2, out3) \ +{ \ + ADD2(in0, in1, in2, in3, out0, out1); \ + ADD2(in4, in5, in6, in7, out2, out3); \ +} + +#define ILVR_B2(RTYPE, in0, in1, in2, in3, out0, out1) \ +{ \ + out0 = (RTYPE) __msa_ilvr_b((v16i8) in0, (v16i8) in1); \ + out1 = (RTYPE) __msa_ilvr_b((v16i8) in2, (v16i8) in3); \ +} +#define ILVR_B2_SH(...) ILVR_B2(v8i16, __VA_ARGS__) + +#define HSUB_UB2(RTYPE, in0, in1, out0, out1) \ +{ \ + out0 = (RTYPE) __msa_hsub_u_h((v16u8) in0, (v16u8) in0); \ + out1 = (RTYPE) __msa_hsub_u_h((v16u8) in1, (v16u8) in1); \ +} +#define HSUB_UB2_SH(...) HSUB_UB2(v8i16, __VA_ARGS__) + +#define SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val) \ +{ \ + v16i8 zero_m = { 0 }; \ + out0 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in0, slide_val); \ + out1 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in1, slide_val); \ +} +#define SLDI_B2_0_UB(...) SLDI_B2_0(v16u8, __VA_ARGS__) + +#define SLDI_B3_0(RTYPE, in0, in1, in2, out0, out1, out2, slide_val) \ +{ \ + v16i8 zero_m = { 0 }; \ + SLDI_B2_0(RTYPE, in0, in1, out0, out1, slide_val); \ + out2 = (RTYPE) __msa_sldi_b((v16i8) zero_m, (v16i8) in2, slide_val); \ +} +#define SLDI_B3_0_UB(...) SLDI_B3_0(v16u8, __VA_ARGS__) + +#define ILVEV_W2(RTYPE, in0, in1, in2, in3, out0, out1) \ +{ \ + out0 = (RTYPE) __msa_ilvev_w((v4i32) in1, (v4i32) in0); \ + out1 = (RTYPE) __msa_ilvev_w((v4i32) in3, (v4i32) in2); \ +} +#define ILVEV_W2_UB(...) ILVEV_W2(v16u8, __VA_ARGS__) + +#define ADD_ABS_H3(RTYPE, in0, in1, in2, out0, out1, out2) \ +{ \ + RTYPE zero = {0}; \ + \ + out0 = __msa_add_a_h((v8i16) zero, in0); \ + out1 = __msa_add_a_h((v8i16) zero, in1); \ + out2 = __msa_add_a_h((v8i16) zero, in2); \ +} +#define ADD_ABS_H3_SH(...) ADD_ABS_H3(v8i16, __VA_ARGS__) + +#define VSHF_B2(RTYPE, in0, in1, in2, in3, mask0, mask1, out0, out1) \ +{ \ + out0 = (RTYPE) __msa_vshf_b((v16i8) mask0, (v16i8) in1, (v16i8) in0); \ + out1 = (RTYPE) __msa_vshf_b((v16i8) mask1, (v16i8) in3, (v16i8) in2); \ +} +#define VSHF_B2_UB(...) VSHF_B2(v16u8, __VA_ARGS__) + +#define CMP_AND_SELECT(inp0, inp1, inp2, inp3, inp4, inp5, out0) \ +{ \ + v8i16 _sel_h0, _sel_h1; \ + v16u8 _sel_b0, _sel_b1; \ + _sel_h0 = (v8i16) __msa_clt_u_h((v8u16) inp1, (v8u16) inp0); \ + _sel_b0 = (v16u8) __msa_pckev_b((v16i8) _sel_h0, (v16i8) _sel_h0); \ + inp0 = (v8i16) __msa_bmnz_v((v16u8) inp0, (v16u8) inp1, (v16u8) _sel_h0); \ + inp4 = (v16u8) __msa_bmnz_v(inp3, inp4, _sel_b0); \ + _sel_h1 = (v8i16) __msa_clt_u_h((v8u16) inp2, (v8u16) inp0); \ + _sel_b1 = (v16u8) __msa_pckev_b((v16i8) _sel_h1, (v16i8) _sel_h1); \ + inp4 = (v16u8) __msa_bmnz_v(inp4, inp5, _sel_b1); \ + out0 += inp4; \ +} + +static void +png_read_filter_row_up_msa(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t i, cnt, cnt16, cnt32; + size_t istop = row_info->rowbytes; + png_byte *rp = row; + const png_byte *pp = prev_row; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7; + + for (i = 0; i < (istop >> 6); i++) + { + LD_UB4(rp, 16, src0, src1, src2, src3); + LD_UB4(pp, 16, src4, src5, src6, src7); + pp += 64; + + ADD4(src0, src4, src1, src5, src2, src6, src3, src7, + src0, src1, src2, src3); + + ST_UB4(src0, src1, src2, src3, rp, 16); + rp += 64; + } + + if (istop & 0x3F) + { + cnt32 = istop & 0x20; + cnt16 = istop & 0x10; + cnt = istop & 0xF; + + if(cnt32) + { + if (cnt16 && cnt) + { + LD_UB4(rp, 16, src0, src1, src2, src3); + LD_UB4(pp, 16, src4, src5, src6, src7); + + ADD4(src0, src4, src1, src5, src2, src6, src3, src7, + src0, src1, src2, src3); + + ST_UB4(src0, src1, src2, src3, rp, 16); + rp += 64; + } + else if (cnt16 || cnt) + { + LD_UB2(rp, 16, src0, src1); + LD_UB2(pp, 16, src4, src5); + pp += 32; + src2 = LD_UB(rp + 32); + src6 = LD_UB(pp); + + ADD3(src0, src4, src1, src5, src2, src6, src0, src1, src2); + + ST_UB2(src0, src1, rp, 16); + rp += 32; + ST_UB(src2, rp); + rp += 16; + } + else + { + LD_UB2(rp, 16, src0, src1); + LD_UB2(pp, 16, src4, src5); + + ADD2(src0, src4, src1, src5, src0, src1); + + ST_UB2(src0, src1, rp, 16); + rp += 32; + } + } + else if (cnt16 && cnt) + { + LD_UB2(rp, 16, src0, src1); + LD_UB2(pp, 16, src4, src5); + + ADD2(src0, src4, src1, src5, src0, src1); + + ST_UB2(src0, src1, rp, 16); + rp += 32; + } + else if (cnt16 || cnt) + { + src0 = LD_UB(rp); + src4 = LD_UB(pp); + pp += 16; + + src0 += src4; + + ST_UB(src0, rp); + rp += 16; + } + } +} + +static void +png_read_filter_row_sub4_msa(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t count; + size_t istop = row_info->rowbytes; + png_byte *src = row; + png_byte *nxt = row + 4; + int32_t inp0; + v16u8 src0, src1, src2, src3, src4; + v16u8 dst0, dst1; + v16u8 zero = { 0 }; + + istop -= 4; + + inp0 = LW(src); + src += 4; + src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0); + + for (count = 0; count < istop; count += 16) + { + src1 = LD_UB(src); + src += 16; + + src2 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 4); + src3 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 8); + src4 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 12); + src1 += src0; + src2 += src1; + src3 += src2; + src4 += src3; + src0 = src4; + ILVEV_W2_UB(src1, src2, src3, src4, dst0, dst1); + dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0); + + ST_UB(dst0, nxt); + nxt += 16; + } +} + +static void +png_read_filter_row_sub3_msa(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t count; + size_t istop = row_info->rowbytes; + png_byte *src = row; + png_byte *nxt = row + 3; + int64_t out0; + int32_t inp0, out1; + v16u8 src0, src1, src2, src3, src4, dst0, dst1; + v16u8 zero = { 0 }; + v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 }; + + istop -= 3; + + inp0 = LW(src); + src += 3; + src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0); + + for (count = 0; count < istop; count += 12) + { + src1 = LD_UB(src); + src += 12; + + src2 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 3); + src3 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 6); + src4 = (v16u8) __msa_sldi_b((v16i8) zero, (v16i8) src1, 9); + src1 += src0; + src2 += src1; + src3 += src2; + src4 += src3; + src0 = src4; + VSHF_B2_UB(src1, src2, src3, src4, mask0, mask0, dst0, dst1); + dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0); + out0 = __msa_copy_s_d((v2i64) dst0, 0); + out1 = __msa_copy_s_w((v4i32) dst0, 2); + + SD(out0, nxt); + nxt += 8; + SW(out1, nxt); + nxt += 4; + } +} + +static void +png_read_filter_row_avg4_msa(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t i; + png_byte *src = row; + png_byte *nxt = row; + const png_byte *pp = prev_row; + size_t istop = row_info->rowbytes - 4; + int32_t inp0, inp1, out0; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1; + v16u8 zero = { 0 }; + + inp0 = LW(pp); + pp += 4; + inp1 = LW(src); + src += 4; + src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0); + src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1); + src0 = (v16u8) MSA_SRLI_B(src0, 1); + src1 += src0; + out0 = __msa_copy_s_w((v4i32) src1, 0); + SW(out0, nxt); + nxt += 4; + + for (i = 0; i < istop; i += 16) + { + src2 = LD_UB(pp); + pp += 16; + src6 = LD_UB(src); + src += 16; + + SLDI_B2_0_UB(src2, src6, src3, src7, 4); + SLDI_B2_0_UB(src2, src6, src4, src8, 8); + SLDI_B2_0_UB(src2, src6, src5, src9, 12); + src2 = __msa_ave_u_b(src2, src1); + src6 += src2; + src3 = __msa_ave_u_b(src3, src6); + src7 += src3; + src4 = __msa_ave_u_b(src4, src7); + src8 += src4; + src5 = __msa_ave_u_b(src5, src8); + src9 += src5; + src1 = src9; + ILVEV_W2_UB(src6, src7, src8, src9, dst0, dst1); + dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0); + + ST_UB(dst0, nxt); + nxt += 16; + } +} + +static void +png_read_filter_row_avg3_msa(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t i; + png_byte *src = row; + png_byte *nxt = row; + const png_byte *pp = prev_row; + size_t istop = row_info->rowbytes - 3; + int64_t out0; + int32_t inp0, inp1, out1; + int16_t out2; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1; + v16u8 zero = { 0 }; + v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 }; + + inp0 = LW(pp); + pp += 3; + inp1 = LW(src); + src += 3; + src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0); + src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1); + src0 = (v16u8) MSA_SRLI_B(src0, 1); + src1 += src0; + out2 = __msa_copy_s_h((v8i16) src1, 0); + SH(out2, nxt); + nxt += 2; + nxt[0] = src1[2]; + nxt++; + + for (i = 0; i < istop; i += 12) + { + src2 = LD_UB(pp); + pp += 12; + src6 = LD_UB(src); + src += 12; + + SLDI_B2_0_UB(src2, src6, src3, src7, 3); + SLDI_B2_0_UB(src2, src6, src4, src8, 6); + SLDI_B2_0_UB(src2, src6, src5, src9, 9); + src2 = __msa_ave_u_b(src2, src1); + src6 += src2; + src3 = __msa_ave_u_b(src3, src6); + src7 += src3; + src4 = __msa_ave_u_b(src4, src7); + src8 += src4; + src5 = __msa_ave_u_b(src5, src8); + src9 += src5; + src1 = src9; + VSHF_B2_UB(src6, src7, src8, src9, mask0, mask0, dst0, dst1); + dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0); + out0 = __msa_copy_s_d((v2i64) dst0, 0); + out1 = __msa_copy_s_w((v4i32) dst0, 2); + + SD(out0, nxt); + nxt += 8; + SW(out1, nxt); + nxt += 4; + } +} + +static void +png_read_filter_row_paeth4_msa(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + int32_t count, rp_end; + png_byte *nxt; + const png_byte *prev_nxt; + int32_t inp0, inp1, res0; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9; + v16u8 src10, src11, src12, src13, dst0, dst1; + v8i16 vec0, vec1, vec2; + v16u8 zero = { 0 }; + + nxt = row; + prev_nxt = prev_row; + + inp0 = LW(nxt); + inp1 = LW(prev_nxt); + prev_nxt += 4; + src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0); + src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1); + + src1 += src0; + res0 = __msa_copy_s_w((v4i32) src1, 0); + + SW(res0, nxt); + nxt += 4; + + /* Remainder */ + rp_end = row_info->rowbytes - 4; + + for (count = 0; count < rp_end; count += 16) + { + src2 = LD_UB(prev_nxt); + prev_nxt += 16; + src6 = LD_UB(prev_row); + prev_row += 16; + src10 = LD_UB(nxt); + + SLDI_B3_0_UB(src2, src6, src10, src3, src7, src11, 4); + SLDI_B3_0_UB(src2, src6, src10, src4, src8, src12, 8); + SLDI_B3_0_UB(src2, src6, src10, src5, src9, src13, 12); + ILVR_B2_SH(src2, src6, src1, src6, vec0, vec1); + HSUB_UB2_SH(vec0, vec1, vec0, vec1); + vec2 = vec0 + vec1; + ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2); + CMP_AND_SELECT(vec0, vec1, vec2, src1, src2, src6, src10); + ILVR_B2_SH(src3, src7, src10, src7, vec0, vec1); + HSUB_UB2_SH(vec0, vec1, vec0, vec1); + vec2 = vec0 + vec1; + ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2); + CMP_AND_SELECT(vec0, vec1, vec2, src10, src3, src7, src11); + ILVR_B2_SH(src4, src8, src11, src8, vec0, vec1); + HSUB_UB2_SH(vec0, vec1, vec0, vec1); + vec2 = vec0 + vec1; + ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2); + CMP_AND_SELECT(vec0, vec1, vec2, src11, src4, src8, src12); + ILVR_B2_SH(src5, src9, src12, src9, vec0, vec1); + HSUB_UB2_SH(vec0, vec1, vec0, vec1); + vec2 = vec0 + vec1; + ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2); + CMP_AND_SELECT(vec0, vec1, vec2, src12, src5, src9, src13); + src1 = src13; + ILVEV_W2_UB(src10, src11, src12, src1, dst0, dst1); + dst0 = (v16u8) __msa_pckev_d((v2i64) dst1, (v2i64) dst0); + + ST_UB(dst0, nxt); + nxt += 16; + } +} + +static void +png_read_filter_row_paeth3_msa(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + int32_t count, rp_end; + png_byte *nxt; + const png_byte *prev_nxt; + int64_t out0; + int32_t inp0, inp1, out1; + int16_t out2; + v16u8 src0, src1, src2, src3, src4, src5, src6, src7, src8, src9, dst0, dst1; + v16u8 src10, src11, src12, src13; + v8i16 vec0, vec1, vec2; + v16u8 zero = { 0 }; + v16i8 mask0 = { 0, 1, 2, 16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + v16i8 mask1 = { 0, 1, 2, 3, 4, 5, 16, 17, 18, 19, 20, 21, 0, 0, 0, 0 }; + + nxt = row; + prev_nxt = prev_row; + + inp0 = LW(nxt); + inp1 = LW(prev_nxt); + prev_nxt += 3; + src0 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp0); + src1 = (v16u8) __msa_insert_w((v4i32) zero, 0, inp1); + + src1 += src0; + out2 = __msa_copy_s_h((v8i16) src1, 0); + + SH(out2, nxt); + nxt += 2; + nxt[0] = src1[2]; + nxt++; + + /* Remainder */ + rp_end = row_info->rowbytes - 3; + + for (count = 0; count < rp_end; count += 12) + { + src2 = LD_UB(prev_nxt); + prev_nxt += 12; + src6 = LD_UB(prev_row); + prev_row += 12; + src10 = LD_UB(nxt); + + SLDI_B3_0_UB(src2, src6, src10, src3, src7, src11, 3); + SLDI_B3_0_UB(src2, src6, src10, src4, src8, src12, 6); + SLDI_B3_0_UB(src2, src6, src10, src5, src9, src13, 9); + ILVR_B2_SH(src2, src6, src1, src6, vec0, vec1); + HSUB_UB2_SH(vec0, vec1, vec0, vec1); + vec2 = vec0 + vec1; + ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2); + CMP_AND_SELECT(vec0, vec1, vec2, src1, src2, src6, src10); + ILVR_B2_SH(src3, src7, src10, src7, vec0, vec1); + HSUB_UB2_SH(vec0, vec1, vec0, vec1); + vec2 = vec0 + vec1; + ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2); + CMP_AND_SELECT(vec0, vec1, vec2, src10, src3, src7, src11); + ILVR_B2_SH(src4, src8, src11, src8, vec0, vec1); + HSUB_UB2_SH(vec0, vec1, vec0, vec1); + vec2 = vec0 + vec1; + ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2); + CMP_AND_SELECT(vec0, vec1, vec2, src11, src4, src8, src12); + ILVR_B2_SH(src5, src9, src12, src9, vec0, vec1); + HSUB_UB2_SH(vec0, vec1, vec0, vec1); + vec2 = vec0 + vec1; + ADD_ABS_H3_SH(vec0, vec1, vec2, vec0, vec1, vec2); + CMP_AND_SELECT(vec0, vec1, vec2, src12, src5, src9, src13); + src1 = src13; + VSHF_B2_UB(src10, src11, src12, src13, mask0, mask0, dst0, dst1); + dst0 = (v16u8) __msa_vshf_b(mask1, (v16i8) dst1, (v16i8) dst0); + out0 = __msa_copy_s_d((v2i64) dst0, 0); + out1 = __msa_copy_s_w((v4i32) dst0, 2); + + SD(out0, nxt); + nxt += 8; + SW(out1, nxt); + nxt += 4; + } +} diff --git a/media/libpng/mips/mips_init.c b/media/libpng/mips/mips_init.c new file mode 100644 index 0000000000..070c0df209 --- /dev/null +++ b/media/libpng/mips/mips_init.c @@ -0,0 +1,35 @@ +/* mips_init.c - MSA optimised filter functions + * + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2016 Glenn Randers-Pehrson + * Written by Mandar Sahastrabuddhe, 2016 + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ +#define png_target_impl "mips-msa" + +#include "filter_msa_intrinsics.c" + +static void +png_init_filter_functions_msa(png_struct *pp, unsigned int bpp) +{ + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_msa; + + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_msa; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_msa; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_msa; + } + + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_msa; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_msa; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_msa; + } +} + +# define png_target_init_filter_functions_impl png_init_filter_functions_msa diff --git a/media/libpng/mips/msacheck.h b/media/libpng/mips/msacheck.h new file mode 100644 index 0000000000..a31e131b20 --- /dev/null +++ b/media/libpng/mips/msacheck.h @@ -0,0 +1,26 @@ +/* mips/msacheck.h - MIPS optimised filter functions + * + * Copyright (c) 2018-2022 Cosmin Truta + * Copyright (c) 2014,2016 Glenn Randers-Pehrson + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This code has been moved from the original in pngpriv.h. + */ +/* MIPS MSA checks: */ +#if defined(__mips_msa) && (__mips_isa_rev >= 5) + /* MIPS MSA support requires gcc >= 4.7: */ +# ifdef __GNUC__ +# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) +# define PNG_TARGET_MIPS_MSA_SUPPORTED +# endif +# else /* !GNUC */ +# define PNG_TARGET_MIPS_MSA_SUPPORTED +# endif /* !GNUC */ +#endif /* !__mips_msa || __mips_isa_rev < 5 */ + +#ifdef PNG_TARGET_MIPS_MSA_SUPPORTED +# define PNG_TARGET_MIPS_TARGET_CODE_SUPPORTED +#endif diff --git a/media/libpng/moz.build b/media/libpng/moz.build index ff4b9e9cb1..c22f95ff29 100644 --- a/media/libpng/moz.build +++ b/media/libpng/moz.build @@ -9,7 +9,7 @@ EXPORTS += [ 'pnglibconf.h' ] -UNIFIED_SOURCES += [ +SOURCES += [ 'png.c', 'pngerror.c', 'pngget.c', @@ -20,30 +20,14 @@ UNIFIED_SOURCES += [ 'pngrtran.c', 'pngrutil.c', 'pngset.c', + 'pngsimd.c', 'pngtrans.c', 'pngwio.c', 'pngwrite.c', - 'pngwutil.c' + 'pngwtran.c', + 'pngwutil.c', ] -if CONFIG['CPU_ARCH'] == 'arm': - DEFINES['MOZ_PNG_USE_ARM_NEON'] = True - UNIFIED_SOURCES += [ - 'arm/arm_init.c', - 'arm/filter_neon_intrinsics.c' - ] - - SOURCES += [ - 'arm/filter_neon.S' - ] - -if CONFIG['INTEL_ARCHITECTURE']: - DEFINES['MOZ_PNG_USE_INTEL_SSE'] = True - UNIFIED_SOURCES += [ - 'sse2/filter_sse2_intrinsics.c', - 'sse2/intel_init.c' - ] - Library('mozpng') if CONFIG['GKMEDIAS_SHARED_LIBRARY']: diff --git a/media/libpng/png.c b/media/libpng/png.c index 3630b1f734..aacba1a61d 100644 --- a/media/libpng/png.c +++ b/media/libpng/png.c @@ -1,10 +1,9 @@ - /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -14,7 +13,34 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_26 Your_png_h_is_not_version_1_6_26; +typedef png_libpng_version_1_8_0_git Your_png_h_is_not_version_1_8_0_git; + +/* Sanity check the chunks definitions - PNG_KNOWN_CHUNKS from pngpriv.h and the + * corresponding macro definitions. This causes a compile time failure if + * something is wrong but generates no code. + * + * (1) The first check is that the PNG_CHUNK(cHNK, index) 'index' values must + * increment from 0 to the last value. + */ +#define PNG_CHUNK(cHNK, index) != (index) || ((index)+1) + +#if 0 PNG_KNOWN_CHUNKS < 0 +# error PNG_KNOWN_CHUNKS chunk definitions are not in order +#endif + +#undef PNG_CHUNK + +/* (2) The chunk name macros, png_cHNK, must all be valid and defined. Since + * this is a preprocessor test undefined pp-tokens come out as zero and will + * fail this test. + */ +#define PNG_CHUNK(cHNK, index) !PNG_CHUNK_NAME_VALID(png_ ## cHNK) || + +#if PNG_KNOWN_CHUNKS 0 +# error png_cHNK not defined for some known cHNK +#endif + +#undef PNG_CHUNK /* 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 @@ -23,8 +49,8 @@ typedef png_libpng_version_1_6_26 Your_png_h_is_not_version_1_6_26; */ #ifdef PNG_READ_SUPPORTED -void PNGAPI -png_set_sig_bytes(png_structrp png_ptr, int num_bytes) +void +png_set_sig_bytes(png_struct *png_ptr, int num_bytes) { unsigned int nb = (unsigned int)num_bytes; @@ -50,24 +76,21 @@ png_set_sig_bytes(png_structrp png_ptr, int num_bytes) * respectively, to be less than, to match, or be greater than the correct * PNG signature (this is the same behavior as strcmp, memcmp, etc). */ -int PNGAPI -png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) +int +png_sig_cmp(const png_byte *sig, size_t start, size_t num_to_check) { - png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; - - if (num_to_check > 8) - num_to_check = 8; + static const png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; - else if (num_to_check < 1) - return (-1); + if (num_to_check < 1) + return -1; if (start > 7) - return (-1); + return -1; - if (start + num_to_check > 8) + if (num_to_check > 8 - start) num_to_check = 8 - start; - return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check))); + return memcmp(&sig[start], &png_signature[start], num_to_check); } #endif /* READ */ @@ -75,36 +98,43 @@ png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) /* Function to allocate memory for zlib */ PNG_FUNCTION(voidpf /* PRIVATE */, -png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) +png_zalloc,(voidpf png_ptr, uInt items, uInt size), + PNG_ALLOCATED) { png_alloc_size_t num_bytes = size; if (png_ptr == NULL) return NULL; - if (items >= (~(png_alloc_size_t)0)/size) + /* This check against overflow is vestigial, dating back from + * the old times when png_zalloc used to be an exported function. + * We're still keeping it here for now, as an extra-cautious + * prevention against programming errors inside zlib, although it + * should rather be a debug-time assertion instead. + */ + if (size != 0 && items >= (~(png_alloc_size_t)0) / size) { - png_warning (png_voidcast(png_structrp, png_ptr), - "Potential overflow in png_zalloc()"); + png_warning(png_voidcast(png_struct *, png_ptr), + "Potential overflow in png_zalloc()"); return NULL; } num_bytes *= items; - return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes); + return png_malloc_warn(png_voidcast(png_struct *, png_ptr), num_bytes); } /* Function to free memory for zlib */ void /* PRIVATE */ png_zfree(voidpf png_ptr, voidpf ptr) { - png_free(png_voidcast(png_const_structrp,png_ptr), ptr); + png_free(png_voidcast(const png_struct *,png_ptr), ptr); } /* Reset the CRC variable to 32 bits of 1's. Care must be taken * in case CRC is > 32 bits to leave the top bits 0. */ void /* PRIVATE */ -png_reset_crc(png_structrp png_ptr) +png_reset_crc(png_struct *png_ptr) { /* The cast is safe because the crc is a 32-bit value. */ png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0); @@ -116,7 +146,7 @@ png_reset_crc(png_structrp png_ptr) * trouble of calculating it. */ void /* PRIVATE */ -png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) +png_calculate_crc(png_struct *png_ptr, const png_byte *ptr, size_t length) { int need_crc = 1; @@ -170,7 +200,7 @@ png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) * functions that create a png_struct. */ int -png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) +png_user_version_check(png_struct *png_ptr, const char *user_png_ver) { /* Libpng versions 1.0.0 and later are binary compatible if the version * string matches through the second '.'; we must recompile any @@ -212,10 +242,6 @@ png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) png_warning(png_ptr, m); #endif -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - png_ptr->flags = 0; -#endif - return 0; } @@ -226,10 +252,11 @@ png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) /* Generic function to create a png_struct for either read or write - this * contains the common initialization. */ -PNG_FUNCTION(png_structp /* PRIVATE */, -png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +PNG_FUNCTION(png_struct * /* PRIVATE */, +png_create_png_struct,(const char *user_png_ver, void *error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, void *mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED) { png_struct create_struct; # ifdef PNG_SETJMP_SUPPORTED @@ -242,21 +269,23 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, */ memset(&create_struct, 0, (sizeof create_struct)); - /* Added at libpng-1.2.6 */ # ifdef PNG_USER_LIMITS_SUPPORTED create_struct.user_width_max = PNG_USER_WIDTH_MAX; create_struct.user_height_max = PNG_USER_HEIGHT_MAX; # ifdef PNG_USER_CHUNK_CACHE_MAX - /* Added at libpng-1.2.43 and 1.4.0 */ create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; # endif -# ifdef PNG_USER_CHUNK_MALLOC_MAX - /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists - * in png_struct regardless. - */ +# if PNG_USER_CHUNK_MALLOC_MAX > 0 /* default to compile-time limit */ create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; + + /* No compile-time limit, so initialize to the system limit: */ +# elif defined PNG_MAX_MALLOC_64K /* legacy system limit */ + create_struct.user_chunk_malloc_max = 65536U; + +# else /* modern system limit SIZE_MAX (C99) */ + create_struct.user_chunk_malloc_max = PNG_SIZE_MAX; # endif # endif @@ -296,7 +325,7 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, */ if (png_user_version_check(&create_struct, user_png_ver) != 0) { - png_structrp png_ptr = png_voidcast(png_structrp, + png_struct *png_ptr = png_voidcast(png_struct *, png_malloc_warn(&create_struct, (sizeof *png_ptr))); if (png_ptr != NULL) @@ -330,10 +359,11 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, } /* Allocate the memory for an info_struct for the application. */ -PNG_FUNCTION(png_infop,PNGAPI -png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED) +PNG_FUNCTION(png_info *, +png_create_info_struct,(const png_struct *png_ptr), + PNG_ALLOCATED) { - png_inforp info_ptr; + png_info *info_ptr; png_debug(1, "in png_create_info_struct"); @@ -345,7 +375,7 @@ png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED) * error handling *after* creating the info_struct because this is the way it * has always been done in 'example.c'. */ - info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr, + info_ptr = png_voidcast(png_info *, png_malloc_base(png_ptr, (sizeof *info_ptr))); if (info_ptr != NULL) @@ -362,10 +392,10 @@ png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED) * APIs. This ensures that all possible approaches free the same data (all of * it). */ -void PNGAPI -png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr) +void +png_destroy_info_struct(const png_struct *png_ptr, png_info **info_ptr_ptr) { - png_inforp info_ptr = NULL; + png_info *info_ptr = NULL; png_debug(1, "in png_destroy_info_struct"); @@ -400,11 +430,11 @@ png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr) * the user-memory mechanism and the user error handling/warning mechanisms in * those cases where it does anything other than a memset. */ -PNG_FUNCTION(void,PNGAPI -png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), +PNG_FUNCTION(void, +png_info_init_3,(png_info **ptr_ptr, size_t png_info_struct_size), PNG_DEPRECATED) { - png_inforp info_ptr = *ptr_ptr; + png_info *info_ptr = *ptr_ptr; png_debug(1, "in png_info_init_3"); @@ -416,7 +446,7 @@ png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), *ptr_ptr = NULL; /* The following line is why this API should not be used: */ free(info_ptr); - info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL, + info_ptr = png_voidcast(png_info *, png_malloc_base(NULL, (sizeof *info_ptr))); if (info_ptr == NULL) return; @@ -427,9 +457,8 @@ png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), memset(info_ptr, 0, (sizeof *info_ptr)); } -/* The following API is not called internally */ -void PNGAPI -png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr, +void +png_data_freer(const png_struct *png_ptr, png_info *info_ptr, int freer, png_uint_32 mask) { png_debug(1, "in png_data_freer"); @@ -447,8 +476,8 @@ png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr, png_error(png_ptr, "Unknown freer parameter in png_data_freer"); } -void PNGAPI -png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, +void +png_free_data(const png_struct *png_ptr, png_info *info_ptr, png_uint_32 mask, int num) { png_debug(1, "in png_free_data"); @@ -477,6 +506,7 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, png_free(png_ptr, info_ptr->text); info_ptr->text = NULL; info_ptr->num_text = 0; + info_ptr->max_text = 0; } } #endif @@ -594,6 +624,19 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, } #endif +#ifdef PNG_eXIf_SUPPORTED + /* Free any eXIf entry */ + if (((mask & PNG_FREE_EXIF) & info_ptr->free_me) != 0) + { + 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 /* Free any hIST entry */ if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0) @@ -641,13 +684,13 @@ png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, * functions. The application should free any memory associated with this * pointer before png_write_destroy() or png_read_destroy() are called. */ -png_voidp PNGAPI -png_get_io_ptr(png_const_structrp png_ptr) +void * +png_get_io_ptr(const png_struct *png_ptr) { if (png_ptr == NULL) - return (NULL); + return NULL; - return (png_ptr->io_ptr); + return png_ptr->io_ptr; } #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) @@ -658,15 +701,15 @@ png_get_io_ptr(png_const_structrp png_ptr) * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a * function of your own because "FILE *" isn't necessarily available. */ -void PNGAPI -png_init_io(png_structrp png_ptr, png_FILE_p fp) +void +png_init_io(png_struct *png_ptr, FILE *fp) { png_debug(1, "in png_init_io"); if (png_ptr == NULL) return; - png_ptr->io_ptr = (png_voidp)fp; + png_ptr->io_ptr = (void *)fp; } # endif @@ -679,10 +722,10 @@ png_init_io(png_structrp png_ptr, png_FILE_p fp) * * Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the * negative integral value is added the result will be an unsigned value - * correspnding to the 2's complement representation. + * corresponding to the 2's complement representation. */ -void PNGAPI -png_save_int_32(png_bytep buf, png_int_32 i) +void +png_save_int_32(png_byte *buf, png_int_32 i) { png_save_uint_32(buf, (png_uint_32)i); } @@ -692,10 +735,10 @@ png_save_int_32(png_bytep buf, png_int_32 i) /* Convert the supplied time into an RFC 1123 string suitable for use in * a "Creation Time" or other text-based time string. */ -int PNGAPI -png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) +int +png_convert_to_rfc1123_buffer(char out[29], const png_time *ptime) { - static PNG_CONST char short_months[12][4] = + static const char short_months[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; @@ -711,7 +754,7 @@ png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) { size_t pos = 0; - char number_buf[5]; /* enough for a four-digit year */ + char number_buf[5] = {0, 0, 0, 0, 0}; /* enough for a four-digit year */ # define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string)) # define APPEND_NUMBER(format, value)\ @@ -739,58 +782,23 @@ png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) return 1; } - -# if PNG_LIBPNG_VER < 10700 -/* To do: remove the following from libpng-1.7 */ -/* Original API that uses a private buffer in png_struct. - * Deprecated because it causes png_struct to carry a spurious temporary - * buffer (png_struct::time_buffer), better to have the caller pass this in. - */ -png_const_charp PNGAPI -png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime) -{ - if (png_ptr != NULL) - { - /* The only failure above if png_ptr != NULL is from an invalid ptime */ - if (png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime) == 0) - png_warning(png_ptr, "Ignoring invalid time value"); - - else - return png_ptr->time_buffer; - } - - return NULL; -} -# endif /* LIBPNG_VER < 10700 */ # endif /* TIME_RFC1123 */ #endif /* READ || WRITE */ -png_const_charp PNGAPI -png_get_copyright(png_const_structrp png_ptr) +const char * +png_get_copyright(const png_struct *png_ptr) { PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ #ifdef PNG_STRING_COPYRIGHT return PNG_STRING_COPYRIGHT #else -# ifdef __STDC__ - return PNG_STRING_NEWLINE \ - "libpng version 1.6.26+apng - October 20, 2016" PNG_STRING_NEWLINE \ - "Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson" \ - PNG_STRING_NEWLINE \ - "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ - "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ - PNG_STRING_NEWLINE \ - "Portions Copyright (c) 2006-2007 Andrew Smith" PNG_STRING_NEWLINE \ - "Portions Copyright (c) 2008-2016 Max Stepin" PNG_STRING_NEWLINE ; -# else - return "libpng version 1.6.26+apng - October 20, 2016\ - Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson\ - Copyright (c) 1996-1997 Andreas Dilger\ - Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\ - Portions Copyright (c) 2006-2007 Andrew Smith\ - Portions Copyright (c) 2008-2016 Max Stepin"; -# endif + return "\n" + "libpng version 1.8.0.git\n" + "Copyright (c) 2018-2026 Cosmin Truta\n" + "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson\n" + "Copyright (c) 1996-1997 Andreas Dilger\n" + "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.\n"; #endif } @@ -802,23 +810,23 @@ png_get_copyright(png_const_structrp png_ptr) * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, * it is guaranteed that png.c uses the correct version of png.h. */ -png_const_charp PNGAPI -png_get_libpng_ver(png_const_structrp png_ptr) +const char * +png_get_libpng_ver(const png_struct *png_ptr) { /* Version of *.c files used when building libpng */ return png_get_header_ver(png_ptr); } -png_const_charp PNGAPI -png_get_header_ver(png_const_structrp png_ptr) +const char * +png_get_header_ver(const png_struct *png_ptr) { /* Version of *.h files used when building libpng */ PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ return PNG_LIBPNG_VER_STRING; } -png_const_charp PNGAPI -png_get_header_version(png_const_structrp png_ptr) +const char * +png_get_header_version(const png_struct *png_ptr) { /* Returns longer string containing both version and date */ PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ @@ -827,7 +835,7 @@ png_get_header_version(png_const_structrp png_ptr) # ifndef PNG_READ_SUPPORTED " (NO READ SUPPORT)" # endif - PNG_STRING_NEWLINE; + "\n"; #else return PNG_HEADER_VERSION_STRING; #endif @@ -840,8 +848,8 @@ png_get_header_version(png_const_structrp png_ptr) * paletted. Most useful for gamma correction and simplification * of code. This API is not used internally. */ -void PNGAPI -png_build_grayscale_palette(int bit_depth, png_colorp palette) +void +png_build_grayscale_palette(int bit_depth, png_color *palette) { int num_palette; int color_inc; @@ -891,11 +899,11 @@ png_build_grayscale_palette(int bit_depth, png_colorp palette) #endif #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED -int PNGAPI -png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name) +int +png_handle_as_unknown(const png_struct *png_ptr, const png_byte *chunk_name) { /* Check chunk_name and return "keep" value if it's on the list, else 0 */ - png_const_bytep p, p_end; + const png_byte *p, *p_end; if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0) return PNG_HANDLE_CHUNK_AS_DEFAULT; @@ -905,7 +913,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 * 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 */ { @@ -927,7 +935,7 @@ png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name) #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) int /* PRIVATE */ -png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name) +png_chunk_unknown_handling(const png_struct *png_ptr, png_uint_32 chunk_name) { png_byte chunk_string[5]; @@ -939,23 +947,23 @@ png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name) #ifdef PNG_READ_SUPPORTED /* This function, added to libpng-1.0.6g, is untested. */ -int PNGAPI -png_reset_zstream(png_structrp png_ptr) +int +png_reset_zstream(png_struct *png_ptr) { if (png_ptr == NULL) return Z_STREAM_ERROR; /* WARNING: this resets the window bits to the maximum! */ - return (inflateReset(&png_ptr->zstream)); + return inflateReset(&png_ptr->zstream); } #endif /* READ */ /* This function was added to libpng-1.0.7 */ -png_uint_32 PNGAPI +png_uint_32 png_access_version_number(void) { /* Version of *.c files used when building libpng */ - return((png_uint_32)PNG_LIBPNG_VER); + return (png_uint_32)PNG_LIBPNG_VER; } #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) @@ -964,7 +972,7 @@ png_access_version_number(void) * like Z_OK or Z_STREAM_END where the error code is apparently a success code. */ void /* PRIVATE */ -png_zstream_error(png_structrp png_ptr, int ret) +png_zstream_error(png_struct *png_ptr, int ret) { /* Translate 'ret' into an appropriate error string, priority is given to the * one in zstream if set. This always returns a string, even in cases like @@ -974,48 +982,48 @@ png_zstream_error(png_structrp png_ptr, int ret) { default: case Z_OK: - png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code"); + png_ptr->zstream.msg = "unexpected zlib return code"; break; case Z_STREAM_END: /* Normal exit */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream"); + png_ptr->zstream.msg = "unexpected end of LZ stream"; break; case Z_NEED_DICT: /* This means the deflate stream did not have a dictionary; this * indicates a bogus PNG. */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary"); + png_ptr->zstream.msg = "missing LZ dictionary"; break; case Z_ERRNO: /* gz APIs only: should not happen */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error"); + png_ptr->zstream.msg = "zlib IO error"; break; case Z_STREAM_ERROR: /* internal libpng error */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib"); + png_ptr->zstream.msg = "bad parameters to zlib"; break; case Z_DATA_ERROR: - png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream"); + png_ptr->zstream.msg = "damaged LZ stream"; break; case Z_MEM_ERROR: - png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory"); + png_ptr->zstream.msg = "insufficient memory"; break; case Z_BUF_ERROR: /* End of input or output; not a problem if the caller is doing * incremental read or write. */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated"); + png_ptr->zstream.msg = "truncated"; break; case Z_VERSION_ERROR: - png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version"); + png_ptr->zstream.msg = "unsupported zlib version"; break; case PNG_UNEXPECTED_ZLIB_RETURN: @@ -1024,215 +1032,137 @@ png_zstream_error(png_structrp png_ptr, int ret) * and change pngpriv.h. Note that this message is "... return", * whereas the default/Z_OK one is "... return code". */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return"); + png_ptr->zstream.msg = "unexpected zlib return"; break; } } -/* png_convert_size: a PNGAPI but no longer in png.h, so deleted - * at libpng 1.5.5! - */ - -/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ -#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */ -static int -png_colorspace_check_gamma(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_fixed_point gAMA, int from) - /* This is called to check a new gamma value against an existing one. The - * routine returns false if the new gamma value should not be written. - * - * 'from' says where the new gamma value comes from: - * - * 0: the new gamma value is the libpng estimate for an ICC profile - * 1: the new gamma value comes from a gAMA chunk - * 2: the new gamma value comes from an sRGB chunk - */ +#ifdef PNG_COLORSPACE_SUPPORTED +static png_int_32 +png_fp_add(png_int_32 addend0, png_int_32 addend1, int *error) { - png_fixed_point gtest; - - if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && - (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0 || - png_gamma_significant(gtest) != 0)) + /* Safely add two fixed point values setting an error flag and returning 0.5 + * on overflow. + * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore + * relying on addition of two positive values producing a negative one is not + * safe. + */ + if (addend0 > 0) { - /* Either this is an sRGB image, in which case the calculated gamma - * approximation should match, or this is an image with a profile and the - * value libpng calculates for the gamma of the profile does not match the - * value recorded in the file. The former, sRGB, case is an error, the - * latter is just a warning. - */ - if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2) - { - png_chunk_report(png_ptr, "gamma value does not match sRGB", - PNG_CHUNK_ERROR); - /* Do not overwrite an sRGB value */ - return from == 2; - } - - else /* sRGB tag not involved */ - { - png_chunk_report(png_ptr, "gamma value does not match libpng estimate", - PNG_CHUNK_WARNING); - return from == 1; - } + if (0x7fffffff - addend0 >= addend1) + return addend0+addend1; } - - return 1; -} - -void /* PRIVATE */ -png_colorspace_set_gamma(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_fixed_point gAMA) -{ - /* 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 - * 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 - * safety the limits here are a little narrower. The values are 0.00016 to - * 6250.0, which are truly ridiculous gamma values (and will produce - * displays that are all black or all white.) - * - * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk - * handling code, which only required the value to be >0. - */ - png_const_charp errmsg; - - if (gAMA < 16 || gAMA > 625000000) - errmsg = "gamma value out of range"; - -# ifdef PNG_READ_gAMA_SUPPORTED - /* Allow the application to set the gamma value more than once */ - else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && - (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0) - errmsg = "duplicate"; -# endif - - /* Do nothing if the colorspace is already invalid */ - else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) - return; - - else + else if (addend0 < 0) { - if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA, - 1/*from gAMA*/) != 0) - { - /* Store this gamma value. */ - colorspace->gamma = gAMA; - colorspace->flags |= - (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA); - } - - /* At present if the check_gamma test fails the gamma of the colorspace is - * not updated however the colorspace is not invalidated. This - * corresponds to the case where the existing gamma comes from an sRGB - * chunk or profile. An error message has already been output. - */ - return; + if (-0x7fffffff - addend0 <= addend1) + return addend0+addend1; } + else + return addend1; - /* Error exit - errmsg has been set. */ - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR); + *error = 1; + return PNG_FP_1/2; } -void /* PRIVATE */ -png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr) +static png_int_32 +png_fp_sub(png_int_32 addend0, png_int_32 addend1, int *error) { - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0) + /* As above but calculate addend0-addend1. */ + if (addend1 > 0) { - /* Everything is invalid */ - info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB| - PNG_INFO_iCCP); - -# ifdef PNG_COLORSPACE_SUPPORTED - /* Clean up the iCCP profile now if it won't be used. */ - png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/); -# else - PNG_UNUSED(png_ptr) -# endif + if (-0x7fffffff + addend1 <= addend0) + return addend0-addend1; } - - else + else if (addend1 < 0) { -# ifdef PNG_COLORSPACE_SUPPORTED - /* Leave the INFO_iCCP flag set if the pngset.c code has already set - * it; this allows a PNG to contain a profile which matches sRGB and - * yet still have that profile retrievable by the application. - */ - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) != 0) - info_ptr->valid |= PNG_INFO_sRGB; - - else - info_ptr->valid &= ~PNG_INFO_sRGB; - - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) - info_ptr->valid |= PNG_INFO_cHRM; - - else - info_ptr->valid &= ~PNG_INFO_cHRM; -# endif - - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0) - info_ptr->valid |= PNG_INFO_gAMA; - - else - info_ptr->valid &= ~PNG_INFO_gAMA; + if (0x7fffffff + addend1 >= addend0) + return addend0-addend1; } + else + return addend0; + + *error = 1; + return PNG_FP_1/2; } -#ifdef PNG_READ_SUPPORTED -void /* PRIVATE */ -png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr) +static int +png_safe_add(png_int_32 *addend0_and_result, png_int_32 addend1, + png_int_32 addend2) { - if (info_ptr == NULL) /* reduce code size; check here not in the caller */ - return; - - info_ptr->colorspace = png_ptr->colorspace; - png_colorspace_sync_info(png_ptr, info_ptr); + /* Safely add three integers. Returns 0 on success, 1 on overflow. Does not + * set the result on overflow. + */ + int error = 0; + int result = png_fp_add(*addend0_and_result, + png_fp_add(addend1, addend2, &error), + &error); + if (!error) *addend0_and_result = result; + return error; } -#endif -#endif /* GAMMA */ -#ifdef PNG_COLORSPACE_SUPPORTED /* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for * cHRM, as opposed to using chromaticities. These internal APIs return * non-zero on a parameter error. The X, Y and Z values are required to be * positive and less than 1.0. */ -static int +int /* PRIVATE */ png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ) { - png_int_32 d, dwhite, whiteX, whiteY; + /* NOTE: returns 0 on success, 1 means error. */ + png_int_32 d, dred, dgreen, dblue, dwhite, whiteX, whiteY; - d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z; - if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0) + /* 'd' in each of the blocks below is just X+Y+Z for each component, + * x, y and z are X,Y,Z/(X+Y+Z). + */ + d = XYZ->red_X; + if (png_safe_add(&d, XYZ->red_Y, XYZ->red_Z)) return 1; - if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0) + dred = d; + if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, dred) == 0) + return 1; + if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, dred) == 0) return 1; - dwhite = d; - whiteX = XYZ->red_X; - whiteY = XYZ->red_Y; - d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z; - if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0) + d = XYZ->green_X; + if (png_safe_add(&d, XYZ->green_Y, XYZ->green_Z)) return 1; - if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0) + dgreen = d; + if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, dgreen) == 0) + return 1; + if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, dgreen) == 0) return 1; - dwhite += d; - whiteX += XYZ->green_X; - whiteY += XYZ->green_Y; - d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z; - if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0) + d = XYZ->blue_X; + if (png_safe_add(&d, XYZ->blue_Y, XYZ->blue_Z)) + return 1; + dblue = d; + if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, dblue) == 0) return 1; - if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0) + if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, dblue) == 0) return 1; - dwhite += d; - whiteX += XYZ->blue_X; - whiteY += XYZ->blue_Y; - /* The reference white is simply the sum of the end-point (X,Y,Z) vectors, - * thus: + /* The reference white is simply the sum of the end-point (X,Y,Z) vectors so + * the following calculates (X+Y+Z) of the reference white (media white, + * encoding white) itself: + */ + d = dblue; + if (png_safe_add(&d, dred, dgreen)) + return 1; + dwhite = d; + + /* Find the white X,Y values from the sum of the red, green and blue X,Y + * values. */ + d = XYZ->red_X; + if (png_safe_add(&d, XYZ->green_X, XYZ->blue_X)) + return 1; + whiteX = d; + + d = XYZ->red_Y; + if (png_safe_add(&d, XYZ->green_Y, XYZ->blue_Y)) + return 1; + whiteY = d; + if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0) return 1; if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0) @@ -1241,9 +1171,10 @@ png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ) return 0; } -static int +int /* PRIVATE */ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) { + /* NOTE: returns 0 on success, 1 means error. */ png_fixed_point red_inverse, green_inverse, blue_scale; png_fixed_point left, right, denominator; @@ -1251,15 +1182,24 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) * have end points with 0 tristimulus values (these are impossible end * points, but they are used to cover the possible colors). We check * xy->whitey against 5, not 0, to avoid a possible integer overflow. + * + * The limits here will *not* accept ACES AP0, where bluey is -7700 + * (-0.0770) because the PNG spec itself requires the xy values to be + * unsigned. whitey is also required to be 5 or more to avoid overflow. + * + * Instead the upper limits have been relaxed to accommodate ACES AP1 where + * redz ends up as -600 (-0.006). ProPhotoRGB was already "in range." + * The new limit accommodates the AP0 and AP1 ranges for z but not AP0 redy. */ - if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1; - if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1; - if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1; - if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1; - if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1; - if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1; - if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1; - if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1; + const png_fixed_point fpLimit = PNG_FP_1+(PNG_FP_1/10); + if (xy->redx < 0 || xy->redx > fpLimit) return 1; + if (xy->redy < 0 || xy->redy > fpLimit-xy->redx) return 1; + if (xy->greenx < 0 || xy->greenx > fpLimit) return 1; + if (xy->greeny < 0 || xy->greeny > fpLimit-xy->greenx) return 1; + if (xy->bluex < 0 || xy->bluex > fpLimit) return 1; + if (xy->bluey < 0 || xy->bluey > fpLimit-xy->bluex) return 1; + if (xy->whitex < 0 || xy->whitex > fpLimit) return 1; + if (xy->whitey < 5 || xy->whitey > fpLimit-xy->whitex) return 1; /* The reverse calculation is more difficult because the original tristimulus * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 @@ -1360,7 +1300,7 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) * red-scale + green-scale + blue-scale = 1/white-y = white-scale * * So now we have a Cramer's rule solution where the determinants are just - * 3x3 - far more tractible. Unfortunately 3x3 determinants still involve + * 3x3 - far more tractable. Unfortunately 3x3 determinants still involve * multiplication of three coefficients so we can't guarantee to avoid * overflow in the libpng fixed point representation. Using Cramer's rule in * floating point is probably a good choice here, but it's not an option for @@ -1404,18 +1344,23 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) * * Accuracy: - * The input values have 5 decimal digits of accuracy. The values are all in - * the range 0 < value < 1, so simple products are in the same range but may - * need up to 10 decimal digits to preserve the original precision and avoid - * underflow. Because we are using a 32-bit signed representation we cannot - * match this; the best is a little over 9 decimal digits, less than 10. + * The input values have 5 decimal digits of accuracy. + * + * In the previous implementation the values were all in the range 0 < value + * < 1, so simple products are in the same range but may need up to 10 + * decimal digits to preserve the original precision and avoid underflow. + * Because we are using a 32-bit signed representation we cannot match this; + * the best is a little over 9 decimal digits, less than 10. + * + * This range has now been extended to allow values up to 1.1, or 110,000 in + * fixed point. * * The approach used here is to preserve the maximum precision within the * signed representation. Because the red-scale calculation above uses the - * difference between two products of values that must be in the range -1..+1 - * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The - * factor is irrelevant in the calculation because it is applied to both - * numerator and denominator. + * difference between two products of values that must be in the range + * -1.1..+1.1 it is sufficient to divide the product by 8; + * ceil(121,000/32767*2). The factor is irrelevant in the calculation + * because it is applied to both numerator and denominator. * * Note that the values of the differences of the products of the * chromaticities in the above equations tend to be small, for example for @@ -1437,49 +1382,64 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) * Adobe Wide Gamut RGB * 0.258728243040113 0.724682314948566 0.016589442011321 */ - /* By the argument, above overflow should be impossible here. The return - * value of 2 indicates an internal error to the caller. - */ - if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0) - return 2; - if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0) - return 2; - denominator = left - right; - - /* Now find the red numerator. */ - if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0) - return 2; - if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0) - return 2; - - /* Overflow is possible here and it indicates an extreme set of PNG cHRM - * chunk values. This calculation actually returns the reciprocal of the - * scale value because this allows us to delay the multiplication of white-y - * into the denominator, which tends to produce a small number. - */ - if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 || - red_inverse <= xy->whitey /* r+g+b scales = white scale */) - return 1; + { + int error = 0; - /* Similarly for green_inverse: */ - if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0) - return 2; - if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0) - return 2; - if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 || - green_inverse <= xy->whitey) - return 1; + /* By the argument above overflow should be impossible here, however the + * code now simply returns a failure code. The xy subtracts in the + * arguments to png_muldiv are *not* checked for overflow because the + * checks at the start guarantee they are in the range 0..110000 and + * png_fixed_point is a 32-bit signed number. + */ + if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 8) == 0) + return 1; + if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 8) == + 0) + return 1; + denominator = png_fp_sub(left, right, &error); + if (error) return 1; - /* And the blue scale, the checks above guarantee this can't overflow but it - * can still produce 0 for extreme cHRM values. - */ - blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) - - png_reciprocal(green_inverse); - if (blue_scale <= 0) - return 1; + /* Now find the red numerator. */ + if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 8) == 0) + return 1; + if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 8) == + 0) + return 1; + /* Overflow is possible here and it indicates an extreme set of PNG cHRM + * chunk values. This calculation actually returns the reciprocal of the + * scale value because this allows us to delay the multiplication of + * white-y into the denominator, which tends to produce a small number. + */ + if (png_muldiv(&red_inverse, xy->whitey, denominator, + png_fp_sub(left, right, &error)) == 0 || error || + red_inverse <= xy->whitey /* r+g+b scales = white scale */) + return 1; + + /* Similarly for green_inverse: */ + if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 8) == 0) + return 1; + if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 8) == 0) + return 1; + if (png_muldiv(&green_inverse, xy->whitey, denominator, + png_fp_sub(left, right, &error)) == 0 || error || + green_inverse <= xy->whitey) + return 1; + + /* And the blue scale, the checks above guarantee this can't overflow but + * it can still produce 0 for extreme cHRM values. + */ + blue_scale = png_fp_sub(png_fp_sub(png_reciprocal(xy->whitey), + png_reciprocal(red_inverse), &error), + png_reciprocal(green_inverse), &error); + if (error || blue_scale <= 0) + return 1; + } - /* And fill in the png_XYZ: */ + /* And fill in the png_XYZ. Again the subtracts are safe because of the + * checks on the xy values at the start (the subtracts just calculate the + * corresponding z values.) + */ if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0) return 1; if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0) @@ -1506,250 +1466,9 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) return 0; /*success*/ } +#endif /* COLORSPACE */ -static int -png_XYZ_normalize(png_XYZ *XYZ) -{ - png_int_32 Y; - - if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 || - XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 || - XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0) - return 1; - - /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. - * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore - * relying on addition of two positive values producing a negative one is not - * safe. - */ - Y = XYZ->red_Y; - if (0x7fffffff - Y < XYZ->green_X) - return 1; - Y += XYZ->green_Y; - if (0x7fffffff - Y < XYZ->blue_X) - return 1; - Y += XYZ->blue_Y; - - if (Y != PNG_FP_1) - { - if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0) - return 1; - if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0) - return 1; - if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0) - return 1; - - if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0) - return 1; - if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0) - return 1; - if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0) - return 1; - - if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0) - return 1; - if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0) - return 1; - if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0) - return 1; - } - - return 0; -} - -static int -png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta) -{ - /* Allow an error of +/-0.01 (absolute value) on each chromaticity */ - if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) || - PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) || - PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) || - PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) || - PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) || - PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) || - PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) || - PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta)) - return 0; - return 1; -} - -/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM - * chunk chromaticities. Earlier checks used to simply look for the overflow - * condition (where the determinant of the matrix to solve for XYZ ends up zero - * because the chromaticity values are not all distinct.) Despite this it is - * theoretically possible to produce chromaticities that are apparently valid - * but that rapidly degrade to invalid, potentially crashing, sets because of - * arithmetic inaccuracies when calculations are performed on them. The new - * check is to round-trip xy -> XYZ -> xy and then check that the result is - * within a small percentage of the original. - */ -static int -png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy) -{ - int result; - png_xy xy_test; - - /* As a side-effect this routine also returns the XYZ endpoints. */ - result = png_XYZ_from_xy(XYZ, xy); - if (result != 0) - return result; - - result = png_xy_from_XYZ(&xy_test, XYZ); - if (result != 0) - return result; - - if (png_colorspace_endpoints_match(xy, &xy_test, - 5/*actually, the math is pretty accurate*/) != 0) - return 0; - - /* Too much slip */ - return 1; -} - -/* This is the check going the other way. The XYZ is modified to normalize it - * (another side-effect) and the xy chromaticities are returned. - */ -static int -png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ) -{ - int result; - png_XYZ XYZtemp; - - result = png_XYZ_normalize(XYZ); - if (result != 0) - return result; - - result = png_xy_from_XYZ(xy, XYZ); - if (result != 0) - return result; - - XYZtemp = *XYZ; - return png_colorspace_check_xy(&XYZtemp, xy); -} - -/* Used to check for an endpoint match against sRGB */ -static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */ -{ - /* color x y */ - /* red */ 64000, 33000, - /* green */ 30000, 60000, - /* blue */ 15000, 6000, - /* white */ 31270, 32900 -}; - -static int -png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ, - int preferred) -{ - if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) - return 0; - - /* The consistency check is performed on the chromaticities; this factors out - * variations because of the normalization (or not) of the end point Y - * values. - */ - if (preferred < 2 && - (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) - { - /* The end points must be reasonably close to any we already have. The - * following allows an error of up to +/-.001 - */ - if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy, - 100) == 0) - { - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_benign_error(png_ptr, "inconsistent chromaticities"); - return 0; /* failed */ - } - - /* Only overwrite with preferred values */ - if (preferred == 0) - return 1; /* ok, but no change */ - } - - colorspace->end_points_xy = *xy; - colorspace->end_points_XYZ = *XYZ; - colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS; - - /* The end points are normally quoted to two decimal digits, so allow +/-0.01 - * on this test. - */ - if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0) - colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB; - - else - colorspace->flags &= PNG_COLORSPACE_CANCEL( - PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); - - return 2; /* ok and changed */ -} - -int /* PRIVATE */ -png_colorspace_set_chromaticities(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_xy *xy, int preferred) -{ - /* We must check the end points to ensure they are reasonable - in the past - * color management systems have crashed as a result of getting bogus - * colorant values, while this isn't the fault of libpng it is the - * responsibility of libpng because PNG carries the bomb and libpng is in a - * position to protect against it. - */ - png_XYZ XYZ; - - switch (png_colorspace_check_xy(&XYZ, xy)) - { - case 0: /* success */ - return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ, - preferred); - - case 1: - /* We can't invert the chromaticities so we can't produce value XYZ - * values. Likely as not a color management system will fail too. - */ - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_benign_error(png_ptr, "invalid chromaticities"); - break; - - default: - /* libpng is broken; this should be a warning but if it happens we - * want error reports so for the moment it is an error. - */ - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_error(png_ptr, "internal error checking chromaticities"); - } - - return 0; /* failed */ -} - -int /* PRIVATE */ -png_colorspace_set_endpoints(png_const_structrp png_ptr, - png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred) -{ - png_XYZ XYZ = *XYZ_in; - png_xy xy; - - switch (png_colorspace_check_XYZ(&xy, &XYZ)) - { - case 0: - return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ, - preferred); - - case 1: - /* End points are invalid. */ - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_benign_error(png_ptr, "invalid end points"); - break; - - default: - colorspace->flags |= PNG_COLORSPACE_INVALID; - png_error(png_ptr, "internal error checking chromaticities"); - } - - return 0; /* failed */ -} - -#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED) +#ifdef PNG_READ_iCCP_SUPPORTED /* Error message generation */ static char png_icc_tag_char(png_uint_32 byte) @@ -1789,15 +1508,12 @@ is_ICC_signature(png_alloc_size_t it) } static int -png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_alloc_size_t value, png_const_charp reason) +png_icc_profile_error(const png_struct *png_ptr, const char *name, + png_alloc_size_t value, const char *reason) { size_t pos; char message[196]; /* see below for calculation */ - if (colorspace != NULL) - colorspace->flags |= PNG_COLORSPACE_INVALID; - pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */ pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */ pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */ @@ -1811,122 +1527,24 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, } # ifdef PNG_WARNINGS_SUPPORTED else - { - char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/ + { + char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114 */ - pos = png_safecat(message, (sizeof message), pos, - png_format_number(number, number+(sizeof number), - PNG_NUMBER_FORMAT_x, value)); - pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/ - } + pos = png_safecat(message, (sizeof message), pos, + png_format_number(number, number+(sizeof number), + PNG_NUMBER_FORMAT_x, value)); + pos = png_safecat(message, (sizeof message), pos, "h: "); /* +2 = 116 */ + } # endif /* The 'reason' is an arbitrary message, allow +79 maximum 195 */ pos = png_safecat(message, (sizeof message), pos, reason); PNG_UNUSED(pos) - /* This is recoverable, but make it unconditionally an app_error on write to - * avoid writing invalid ICC profiles into PNG files (i.e., we handle them - * on read, with a warning, but on write unless the app turns off - * application errors the PNG won't be written.) - */ - png_chunk_report(png_ptr, message, - (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR); + png_chunk_benign_error(png_ptr, message); return 0; } -#endif /* sRGB || iCCP */ - -#ifdef PNG_sRGB_SUPPORTED -int /* PRIVATE */ -png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, - int intent) -{ - /* sRGB sets known gamma, end points and (from the chunk) intent. */ - /* IMPORTANT: these are not necessarily the values found in an ICC profile - * because ICC profiles store values adapted to a D50 environment; it is - * expected that the ICC profile mediaWhitePointTag will be D50; see the - * checks and code elsewhere to understand this better. - * - * These XYZ values, which are accurate to 5dp, produce rgb to gray - * coefficients of (6968,23435,2366), which are reduced (because they add up - * to 32769 not 32768) to (6968,23434,2366). These are the values that - * libpng has traditionally used (and are the best values given the 15bit - * algorithm used by the rgb to gray code.) - */ - static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */ - { - /* color X Y Z */ - /* red */ 41239, 21264, 1933, - /* green */ 35758, 71517, 11919, - /* blue */ 18048, 7219, 95053 - }; - - /* Do nothing if the colorspace is already invalidated. */ - if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) - return 0; - - /* Check the intent, then check for existing settings. It is valid for the - * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must - * be consistent with the correct values. If, however, this function is - * called below because an iCCP chunk matches sRGB then it is quite - * conceivable that an older app recorded incorrect gAMA and cHRM because of - * an incorrect calculation based on the values in the profile - this does - * *not* invalidate the profile (though it still produces an error, which can - * be ignored.) - */ - if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) - return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "invalid sRGB rendering intent"); - - if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && - colorspace->rendering_intent != intent) - return png_icc_profile_error(png_ptr, colorspace, "sRGB", - (unsigned)intent, "inconsistent rendering intents"); - - if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) - { - png_benign_error(png_ptr, "duplicate sRGB information ignored"); - return 0; - } - - /* If the standard sRGB cHRM chunk does not match the one from the PNG file - * warn but overwrite the value with the correct one. - */ - if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 && - !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy, - 100)) - png_chunk_report(png_ptr, "cHRM chunk does not match sRGB", - PNG_CHUNK_ERROR); - - /* This check is just done for the error reporting - the routine always - * returns true when the 'from' argument corresponds to sRGB (2). - */ - (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE, - 2/*from sRGB*/); - - /* intent: bugs in GCC force 'int' to be used as the parameter type. */ - colorspace->rendering_intent = (png_uint_16)intent; - colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT; - - /* endpoints */ - colorspace->end_points_xy = sRGB_xy; - colorspace->end_points_XYZ = sRGB_XYZ; - colorspace->flags |= - (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); - - /* gamma */ - colorspace->gamma = PNG_GAMMA_sRGB_INVERSE; - colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA; - - /* Finally record that we have an sRGB profile */ - colorspace->flags |= - (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB); - - return 1; /* set */ -} -#endif /* sRGB */ -#ifdef PNG_iCCP_SUPPORTED /* Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value * is XYZ(0.9642,1.0,0.8249), which scales to: * @@ -1936,22 +1554,19 @@ static const png_byte D50_nCIEXYZ[12] = { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; static int /* bool */ -icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length) +icc_check_length(const png_struct *png_ptr, const char *name, + png_uint_32 profile_length) { if (profile_length < 132) - return png_icc_profile_error(png_ptr, colorspace, name, profile_length, - "too short"); - + return png_icc_profile_error(png_ptr, name, profile_length, "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) +png_icc_check_length(const png_struct *png_ptr, const char *name, + png_uint_32 profile_length) { - if (!icc_check_length(png_ptr, colorspace, name, profile_length)) + if (!icc_check_length(png_ptr, name, profile_length)) return 0; /* This needs to be here because the 'normal' check is in @@ -1960,30 +1575,17 @@ png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, * 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 */ + if (profile_length > png_chunk_max(png_ptr)) + return png_icc_profile_error(png_ptr, name, profile_length, + "profile too long"); return 1; } -#endif /* READ_iCCP */ int /* PRIVATE */ -png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, - png_const_bytep profile/* first 132 bytes only */, int color_type) +png_icc_check_header(const png_struct *png_ptr, const char *name, + png_uint_32 profile_length, + const png_byte *profile/* first 132 bytes only */, int color_type) { png_uint_32 temp; @@ -1994,18 +1596,18 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, */ temp = png_get_uint_32(profile); if (temp != profile_length) - return png_icc_profile_error(png_ptr, colorspace, name, temp, + return png_icc_profile_error(png_ptr, name, temp, "length does not match profile"); temp = (png_uint_32) (*(profile+8)); if (temp > 3 && (profile_length & 3)) - return png_icc_profile_error(png_ptr, colorspace, name, profile_length, + return png_icc_profile_error(png_ptr, name, profile_length, "invalid length"); temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */ if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */ profile_length < 132+12*temp) /* truncated tag table */ - return png_icc_profile_error(png_ptr, colorspace, name, temp, + return png_icc_profile_error(png_ptr, name, temp, "tag count too large"); /* The 'intent' must be valid or we can't store it, ICC limits the intent to @@ -2013,14 +1615,14 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, */ temp = png_get_uint_32(profile+64); if (temp >= 0xffff) /* The ICC limit */ - return png_icc_profile_error(png_ptr, colorspace, name, temp, + return png_icc_profile_error(png_ptr, name, temp, "invalid rendering intent"); /* This is just a warning because the profile may be valid in future * versions. */ if (temp >= PNG_sRGB_INTENT_LAST) - (void)png_icc_profile_error(png_ptr, NULL, name, temp, + (void)png_icc_profile_error(png_ptr, name, temp, "intent outside defined range"); /* At this point the tag table can't be checked because it hasn't necessarily @@ -2031,13 +1633,13 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, */ /* 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 * data.) */ temp = png_get_uint_32(profile+36); /* signature 'ascp' */ if (temp != 0x61637370) - return png_icc_profile_error(png_ptr, colorspace, name, temp, + return png_icc_profile_error(png_ptr, name, temp, "invalid signature"); /* Currently the PCS illuminant/adopted white point (the computational @@ -2048,7 +1650,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * following is just a warning. */ if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0) - (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/, + (void)png_icc_profile_error(png_ptr, name, 0/*no tag value*/, "PCS illuminant is not D50"); /* The PNG spec requires this: @@ -2067,7 +1669,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * into R, G and B channels. * * Previously it was suggested that an RGB profile on grayscale data could be - * handled. However it it is clear that using an RGB profile in this context + * handled. However it is clear that using an RGB profile in this context * must be an error - there is no specification of what it means. Thus it is * almost certainly more correct to ignore the profile. */ @@ -2076,18 +1678,18 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, { case 0x52474220: /* 'RGB ' */ if ((color_type & PNG_COLOR_MASK_COLOR) == 0) - return png_icc_profile_error(png_ptr, colorspace, name, temp, + return png_icc_profile_error(png_ptr, name, temp, "RGB color space not permitted on grayscale PNG"); break; case 0x47524159: /* 'GRAY' */ if ((color_type & PNG_COLOR_MASK_COLOR) != 0) - return png_icc_profile_error(png_ptr, colorspace, name, temp, + return png_icc_profile_error(png_ptr, name, temp, "Gray color space not permitted on RGB PNG"); break; default: - return png_icc_profile_error(png_ptr, colorspace, name, temp, + return png_icc_profile_error(png_ptr, name, temp, "invalid ICC profile color space"); } @@ -2112,7 +1714,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, case 0x61627374: /* 'abst' */ /* May not be embedded in an image */ - return png_icc_profile_error(png_ptr, colorspace, name, temp, + return png_icc_profile_error(png_ptr, name, temp, "invalid embedded Abstract ICC profile"); case 0x6c696e6b: /* 'link' */ @@ -2122,7 +1724,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * therefore a DeviceLink profile should not be found embedded in a * PNG. */ - return png_icc_profile_error(png_ptr, colorspace, name, temp, + return png_icc_profile_error(png_ptr, name, temp, "unexpected DeviceLink ICC profile class"); case 0x6e6d636c: /* 'nmcl' */ @@ -2130,7 +1732,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * contain an AToB0 tag that is open to misinterpretation. Almost * certainly it will fail the tests below. */ - (void)png_icc_profile_error(png_ptr, NULL, name, temp, + (void)png_icc_profile_error(png_ptr, name, temp, "unexpected NamedColor ICC profile class"); break; @@ -2140,7 +1742,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, * tag content to ensure they are backward compatible with one of the * understood profiles. */ - (void)png_icc_profile_error(png_ptr, NULL, name, temp, + (void)png_icc_profile_error(png_ptr, name, temp, "unrecognized ICC profile class"); break; } @@ -2156,7 +1758,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, break; default: - return png_icc_profile_error(png_ptr, colorspace, name, temp, + return png_icc_profile_error(png_ptr, name, temp, "unexpected ICC PCS encoding"); } @@ -2164,13 +1766,13 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, } int /* PRIVATE */ -png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, - png_const_bytep profile /* header plus whole tag table */) +png_icc_check_tag_table(const png_struct *png_ptr, const char *name, + png_uint_32 profile_length, + const png_byte *profile /* header plus whole tag table */) { png_uint_32 tag_count = png_get_uint_32(profile+128); png_uint_32 itag; - png_const_bytep tag = profile+132; /* The first tag */ + const png_byte *tag = profile+132; /* The first tag */ /* First scan all the tags in the table and add bits to the icc_info value * (temporarily in 'tags'). @@ -2187,333 +1789,148 @@ 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 * type signature then 0. */ + + /* This is a hard error; potentially it can cause read outside the + * profile. + */ + if (tag_start > profile_length || tag_length > profile_length - tag_start) + return png_icc_profile_error(png_ptr, name, tag_id, + "ICC profile tag outside profile"); + if ((tag_start & 3) != 0) { - /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is + /* 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, + (void)png_icc_profile_error(png_ptr, name, tag_id, "ICC profile tag start not a multiple of 4"); } - - /* This is a hard error; potentially it can cause read outside the - * profile. - */ - if (tag_start > profile_length || tag_length > profile_length - tag_start) - return png_icc_profile_error(png_ptr, colorspace, name, tag_id, - "ICC profile tag outside profile"); } return 1; /* success, maybe with warnings */ } +#endif /* READ_iCCP */ -#ifdef PNG_sRGB_SUPPORTED -#if PNG_sRGB_PROFILE_CHECKS >= 0 -/* Information about the known ICC sRGB profiles */ -static const struct -{ - png_uint_32 adler, crc, length; - png_uint_32 md5[4]; - png_byte have_md5; - png_byte is_broken; - png_uint_16 intent; - -# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0) -# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\ - { adler, crc, length, md5, broke, intent }, - -} png_sRGB_checks[] = -{ - /* This data comes from contrib/tools/checksum-icc run on downloads of - * all four ICC sRGB profiles from www.color.org. - */ - /* adler32, crc32, MD5[4], intent, date, length, file-name */ - PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9, - PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0, - "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") - - /* ICC sRGB v2 perceptual no black-compensation: */ - PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21, - PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0, - "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") - - PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae, - PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0, - "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") - - /* ICC sRGB v4 perceptual */ - PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812, - PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0, - "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") - - /* The following profiles have no known MD5 checksum. If there is a match - * on the (empty) MD5 the other fields are used to attempt a match and - * a warning is produced. The first two of these profiles have a 'cprt' tag - * which suggests that they were also made by Hewlett Packard. - */ - PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0, - "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") - - /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not - * match the D50 PCS illuminant in the header (it is in fact the D65 values, - * so the white point is recorded as the un-adapted value.) The profiles - * below only differ in one byte - the intent - and are basically the same as - * the previous profile except for the mediaWhitePointTag error and a missing - * chromaticAdaptationTag. - */ - PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, - "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") - - PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d, - PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, - "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") -}; - +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +#if (defined PNG_READ_mDCV_SUPPORTED) || (defined PNG_READ_cHRM_SUPPORTED) static int -png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, - png_const_bytep profile, uLong adler) +have_chromaticities(const png_struct *png_ptr) { - /* The quick check is to verify just the MD5 signature and trust the - * rest of the data. Because the profile has already been verified for - * correctness this is safe. png_colorspace_set_sRGB will check the 'intent' - * field too, so if the profile has been edited with an intent not defined - * by sRGB (but maybe defined by a later ICC specification) the read of - * the profile will fail at that point. + /* Handle new PNGv3 chunks and the precedence rules to determine whether + * png_struct::chromaticities must be processed. Only required for RGB to + * gray. + * + * mDCV: this is the mastering colour space and it is independent of the + * encoding so it needs to be used regardless of the encoded space. + * + * cICP: first in priority but not yet implemented - the chromaticities come + * from the 'primaries'. + * + * iCCP: not supported by libpng (so ignored) + * + * sRGB: the defaults match sRGB + * + * cHRM: calculate the coefficients */ +# ifdef PNG_READ_mDCV_SUPPORTED + if (png_has_chunk(png_ptr, mDCV)) + return 1; +# define check_chromaticities 1 +# endif /*mDCV*/ - png_uint_32 length = 0; - png_uint_32 intent = 0x10000; /* invalid */ -#if PNG_sRGB_PROFILE_CHECKS > 1 - uLong crc = 0; /* the value for 0 length data */ -#endif - unsigned int i; - -#ifdef PNG_SET_OPTION_SUPPORTED - /* First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on" */ - if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) == - PNG_OPTION_ON) - return 0; -#endif - - for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i) - { - if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] && - png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] && - png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] && - png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3]) - { - /* This may be one of the old HP profiles without an MD5, in that - * case we can only use the length and Adler32 (note that these - * are not used by default if there is an MD5!) - */ -# if PNG_sRGB_PROFILE_CHECKS == 0 - if (png_sRGB_checks[i].have_md5 != 0) - return 1+png_sRGB_checks[i].is_broken; -# endif - - /* Profile is unsigned or more checks have been configured in. */ - if (length == 0) - { - length = png_get_uint_32(profile); - intent = png_get_uint_32(profile+64); - } - - /* Length *and* intent must match */ - if (length == (png_uint_32) png_sRGB_checks[i].length && - intent == (png_uint_32) png_sRGB_checks[i].intent) - { - /* Now calculate the adler32 if not done already. */ - if (adler == 0) - { - adler = adler32(0, NULL, 0); - adler = adler32(adler, profile, length); - } - - if (adler == png_sRGB_checks[i].adler) - { - /* These basic checks suggest that the data has not been - * modified, but if the check level is more than 1 perform - * our own crc32 checksum on the data. - */ -# if PNG_sRGB_PROFILE_CHECKS > 1 - if (crc == 0) - { - crc = crc32(0, NULL, 0); - crc = crc32(crc, profile, length); - } - - /* So this check must pass for the 'return' below to happen. - */ - if (crc == png_sRGB_checks[i].crc) -# endif - { - if (png_sRGB_checks[i].is_broken != 0) - { - /* These profiles are known to have bad data that may cause - * problems if they are used, therefore attempt to - * discourage their use, skip the 'have_md5' warning below, - * which is made irrelevant by this error. - */ - png_chunk_report(png_ptr, "known incorrect sRGB profile", - PNG_CHUNK_ERROR); - } - - /* Warn that this being done; this isn't even an error since - * the profile is perfectly valid, but it would be nice if - * people used the up-to-date ones. - */ - else if (png_sRGB_checks[i].have_md5 == 0) - { - png_chunk_report(png_ptr, - "out-of-date sRGB profile with no signature", - PNG_CHUNK_WARNING); - } - - return 1+png_sRGB_checks[i].is_broken; - } - } +# ifdef PNG_READ_sRGB_SUPPORTED + if (png_has_chunk(png_ptr, sRGB)) + return 0; +# endif /*sRGB*/ -# if PNG_sRGB_PROFILE_CHECKS > 0 - /* The signature matched, but the profile had been changed in some - * way. This probably indicates a data error or uninformed hacking. - * Fall through to "no match". - */ - png_chunk_report(png_ptr, - "Not recognizing known sRGB profile that has been edited", - PNG_CHUNK_WARNING); - break; -# endif - } - } - } +# ifdef PNG_READ_cHRM_SUPPORTED + if (png_has_chunk(png_ptr, cHRM)) + return 1; +# define check_chromaticities 1 +# endif /*cHRM*/ - return 0; /* no match */ + return 0; /* sRGB defaults */ } +#endif /* READ_mDCV || READ_cHRM */ void /* PRIVATE */ -png_icc_set_sRGB(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_bytep profile, uLong adler) +png_set_rgb_coefficients(png_struct *png_ptr) { - /* Is this profile one of the known ICC sRGB profiles? If it is, just set - * the sRGB information. + /* Set the rgb_to_gray coefficients from the colorspace if available. Note + * that '_set' means that png_rgb_to_gray was called **and** it successfully + * set up the coefficients. */ - if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0) - (void)png_colorspace_set_sRGB(png_ptr, colorspace, - (int)/*already checked*/png_get_uint_32(profile+64)); -} -#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */ -#endif /* sRGB */ - -int /* PRIVATE */ -png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_charp name, png_uint_32 profile_length, png_const_bytep profile, - int color_type) -{ - if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) - return 0; - - if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && - png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, - color_type) != 0 && - png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, - profile) != 0) + if (png_ptr->rgb_to_gray_coefficients_set == 0) { -# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0 - /* If no sRGB support, don't try storing sRGB information */ - png_icc_set_sRGB(png_ptr, colorspace, profile, 0); -# endif - return 1; - } - - /* Failure case */ - return 0; -} -#endif /* iCCP */ +# if check_chromaticities + png_XYZ xyz; -#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -void /* PRIVATE */ -png_colorspace_set_rgb_coefficients(png_structrp png_ptr) -{ - /* Set the rgb_to_gray coefficients from the colorspace. */ - if (png_ptr->rgb_to_gray_coefficients_set == 0 && - (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) - { - /* png_set_background has not been called, get the coefficients from the Y - * values of the colorspace colorants. - */ - png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y; - png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y; - png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y; - png_fixed_point total = r+g+b; - - if (total > 0 && - r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 && - g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 && - b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 && - r+g+b <= 32769) + if (have_chromaticities(png_ptr) && + png_XYZ_from_xy(&xyz, &png_ptr->chromaticities) == 0) { - /* We allow 0 coefficients here. r+g+b may be 32769 if two or - * all of the coefficients were rounded up. Handle this by - * reducing the *largest* coefficient by 1; this matches the - * approach used for the default coefficients in pngrtran.c + /* png_set_rgb_to_gray has not set the coefficients, get them from the + * Y * values of the colorspace colorants. */ - int add = 0; + png_fixed_point r = xyz.red_Y; + png_fixed_point g = xyz.green_Y; + png_fixed_point b = xyz.blue_Y; + png_fixed_point total = r+g+b; + + if (total > 0 && + r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 && + g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 && + b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 && + r+g+b <= 32769) + { + /* We allow 0 coefficients here. r+g+b may be 32769 if two or + * all of the coefficients were rounded up. Handle this by + * reducing the *largest* coefficient by 1; this matches the + * approach used for the default coefficients in pngrtran.c + */ + int add = 0; - if (r+g+b > 32768) - add = -1; - else if (r+g+b < 32768) - add = 1; + if (r+g+b > 32768) + add = -1; + else if (r+g+b < 32768) + add = 1; - if (add != 0) - { - if (g >= r && g >= b) - g += add; - else if (r >= g && r >= b) - r += add; - else - b += add; - } + if (add != 0) + { + if (g >= r && g >= b) + g += add; + else if (r >= g && r >= b) + r += add; + else + b += add; + } - /* Check for an internal error. */ - if (r+g+b != 32768) - png_error(png_ptr, - "internal error handling cHRM coefficients"); + /* Check for an internal error. */ + if (r+g+b != 32768) + png_error(png_ptr, + "internal error handling cHRM coefficients"); - else - { - png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r; - png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g; + else + { + png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r; + png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g; + } } } - - /* This is a png_error at present even though it could be ignored - - * it should never happen, but it is important that if it does, the - * bug is fixed. - */ else - png_error(png_ptr, "internal error handling cHRM->XYZ"); +# endif /* check_chromaticities */ + { + /* Use the historical REC 709 (etc) values: */ + png_ptr->rgb_to_gray_red_coeff = 6968; + png_ptr->rgb_to_gray_green_coeff = 23434; + /* png_ptr->rgb_to_gray_blue_coeff = 2366; */ + } } } #endif /* READ_RGB_TO_GRAY */ -#endif /* COLORSPACE */ - -#ifdef __GNUC__ -/* This exists solely to work round a warning from GNU C. */ -static int /* PRIVATE */ -png_gt(size_t a, size_t b) -{ - return a > b; -} -#else -# define png_gt(a,b) ((a) > (b)) -#endif - void /* PRIVATE */ -png_check_IHDR(png_const_structrp png_ptr, +png_check_IHDR(const png_struct *png_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, int interlace_type, int compression_type, int filter_type) @@ -2533,8 +1950,16 @@ png_check_IHDR(png_const_structrp png_ptr, error = 1; } - if (png_gt(((width + 7) & (~7U)), - ((PNG_SIZE_MAX + /* The bit mask on the first line below must be at least as big as a + * png_uint_32. "~7U" is not adequate on 16-bit systems because it will + * be an unsigned 16-bit value. Casting to (png_alloc_size_t) makes the + * type of the result at least as bit (in bits) as the RHS of the > operator + * which also avoids a common warning on 64-bit systems that the comparison + * of (png_uint_32) against the constant value on the RHS will always be + * false. + */ + if (((width + 7) & ~(png_alloc_size_t)7) > + (((PNG_SIZE_MAX - 48 /* big_row_buf hack */ - 1) /* filter byte */ / 8) /* 8-byte RGBA pixels */ @@ -2670,7 +2095,7 @@ png_check_IHDR(png_const_structrp png_ptr, #if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) /* 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 */ /* The following is used internally to preserve the sticky flags */ @@ -2678,11 +2103,11 @@ png_check_IHDR(png_const_structrp png_ptr, #define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) int /* PRIVATE */ -png_check_fp_number(png_const_charp string, png_size_t size, int *statep, - png_size_tp whereami) +png_check_fp_number(const char *string, size_t size, int *statep, + size_t *whereami) { int state = *statep; - png_size_t i = *whereami; + size_t i = *whereami; while (i < size) { @@ -2805,10 +2230,10 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep, /* The same but for a complete string. */ int -png_check_fp_string(png_const_charp string, png_size_t size) +png_check_fp_string(const char *string, size_t size) { - int state=0; - png_size_t char_index=0; + int state = 0; + size_t char_index = 0; if (png_check_fp_number(string, size, &state, &char_index) != 0 && (char_index == size || string[char_index] == 0)) @@ -2835,7 +2260,7 @@ png_pow10(int power) if (power < 0) { if (power < DBL_MIN_10_EXP) return 0; - recip = 1, power = -power; + recip = 1; power = -power; } if (power > 0) @@ -2861,7 +2286,7 @@ png_pow10(int power) * precision. */ void /* PRIVATE */ -png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, +png_ascii_from_fp(const png_struct *png_ptr, char *ascii, size_t size, double fp, unsigned int precision) { /* We use standard functions from math.h, but not printf because @@ -2913,7 +2338,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, double test = png_pow10(exp_b10+1); if (test <= DBL_MAX) - ++exp_b10, base = test; + { + ++exp_b10; base = test; + } else break; @@ -2927,7 +2354,10 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, * test on DBL_MAX above. */ 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 * less than .1, this is ok because the code below can @@ -2944,7 +2374,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 */ { - czero = (unsigned int)(-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. */ } else @@ -2978,7 +2408,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, /* Rounding up to 10, handle that here. */ if (czero > 0) { - --czero, d = 1; + --czero; d = 1; if (cdigits == 0) --clead; } else @@ -2992,7 +2422,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, else if (ch == 46) { - ch = *--ascii, ++size; + ch = *--ascii; ++size; /* Advance exp_b10 to '1', so that the * decimal point happens after the * previous digit. @@ -3019,7 +2449,9 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, int ch = *--ascii; if (ch == 46) - ++size, exp_b10 = 1; + { + ++size; exp_b10 = 1; + } /* Else lost a leading zero, so 'exp_b10' is * still ok at (-1) @@ -3055,21 +2487,26 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ if (exp_b10 != (-1)) { - if (exp_b10 == 0) *ascii++ = 46, --size; + if (exp_b10 == 0) + { + *ascii++ = 46; --size; + } /* PLUS 1: TOTAL 4 */ --exp_b10; } - *ascii++ = 48, --czero; + *ascii++ = 48; --czero; } if (exp_b10 != (-1)) { if (exp_b10 == 0) - *ascii++ = 46, --size; /* counted above */ + { + *ascii++ = 46; --size; /* counted above */ + } --exp_b10; } - *ascii++ = (char)(48 + (int)d), ++cdigits; + *ascii++ = (char)(48 + (int)d); ++cdigits; } } while (cdigits+czero < precision+clead && fp > DBL_MIN); @@ -3077,11 +2514,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 */ /* Check for an exponent, if we don't need one we are - * done and just need to terminate the string. At - * this point exp_b10==(-1) is effectively if flag - it got - * to '-1' because of the decrement after outputting - * the decimal point above (the exponent required is - * *not* -1!) + * done and just need to terminate the string. At this + * point, exp_b10==(-1) is effectively a flag: it got + * to '-1' because of the decrement, after outputting + * the decimal point above. (The exponent required is + * *not* -1.) */ if (exp_b10 >= (-1) && exp_b10 <= 2) { @@ -3092,7 +2529,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 * the output count. */ - while (--exp_b10 >= 0) *ascii++ = 48; + while (exp_b10-- > 0) *ascii++ = 48; *ascii = 0; @@ -3110,7 +2547,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ 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 signed arithmetic on exp_b10 and permits GCC at least to do @@ -3121,12 +2558,12 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, if (exp_b10 < 0) { - *ascii++ = 45, --size; /* '-': PLUS 1 TOTAL 3+precision */ - uexp_b10 = (unsigned int)(-exp_b10); + *ascii++ = 45; --size; /* '-': PLUS 1 TOTAL 3+precision */ + uexp_b10 = 0U-exp_b10; } else - uexp_b10 = (unsigned int)exp_b10; + uexp_b10 = 0U+exp_b10; cdigits = 0; @@ -3169,15 +2606,14 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, /* Here on buffer too small. */ png_error(png_ptr, "ASCII conversion buffer too small"); } - # endif /* FLOATING_POINT */ # ifdef PNG_FIXED_POINT_SUPPORTED /* Function to format a fixed point value in ASCII. */ void /* PRIVATE */ -png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, - png_size_t size, png_fixed_point fp) +png_ascii_from_fixed(const png_struct *png_ptr, char *ascii, + size_t size, png_fixed_point fp) { /* Require space for 10 decimal digits, a decimal point, a minus sign and a * trailing \0, 13 characters: @@ -3188,14 +2624,16 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, /* Avoid overflow here on the minimum integer. */ if (fp < 0) - *ascii++ = 45, num = (png_uint_32)(-fp); + { + *ascii++ = 45; num = (png_uint_32)(-fp); + } else num = (png_uint_32)fp; if (num <= 0x80000000) /* else overflowed */ { unsigned int ndigits = 0, first = 16 /* flag value */; - char digits[10]; + char digits[10] = {0}; while (num) { @@ -3226,7 +2664,10 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, * then ndigits digits to first: */ i = 5; - while (ndigits < i) *ascii++ = 48, --i; + while (ndigits < i) + { + *ascii++ = 48; --i; + } while (ndigits >= first) *ascii++ = digits[--ndigits]; /* Don't output the trailing zeros! */ } @@ -3254,7 +2695,7 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, (defined(PNG_sCAL_SUPPORTED) && \ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)) png_fixed_point -png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text) +png_fixed(const png_struct *png_ptr, double fp, const char *text) { double r = floor(100000 * fp + .5); @@ -3269,7 +2710,27 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text) } #endif -#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\ +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \ + (defined(PNG_cLLI_SUPPORTED) || defined(PNG_mDCV_SUPPORTED)) +png_uint_32 +png_fixed_ITU(const png_struct *png_ptr, double fp, const char *text) +{ + double r = floor(10000 * fp + .5); + + if (r > 2147483647. || r < 0) + png_fixed_error(png_ptr, text); + +# ifndef PNG_ERROR_TEXT_SUPPORTED + PNG_UNUSED(text) +# endif + + return (png_uint_32)r; +} +#endif + + +#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\ defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) /* muldiv functions */ /* This API takes signed arguments and rounds the result to the nearest @@ -3277,8 +2738,8 @@ 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 result, a boolean - true on success, false on overflow. */ -int -png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, +int /* PRIVATE */ +png_muldiv(png_fixed_point *res, png_fixed_point a, png_int_32 times, png_int_32 divisor) { /* Return a * times / divisor, rounded. */ @@ -3391,27 +2852,7 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, return 0; } -#endif /* READ_GAMMA || INCH_CONVERSIONS */ - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) -/* The following is for when the caller doesn't much care about the - * result. - */ -png_fixed_point -png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times, - png_int_32 divisor) -{ - png_fixed_point result; - if (png_muldiv(&result, a, times, divisor) != 0) - return result; - - png_warning(png_ptr, "fixed point overflow ignored"); - return 0; -} -#endif - -#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */ /* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ png_fixed_point png_reciprocal(png_fixed_point a) @@ -3430,26 +2871,38 @@ png_reciprocal(png_fixed_point a) return 0; /* error/overflow */ } +#endif /* READ_GAMMA || COLORSPACE || INCH_CONVERSIONS || READ_pHYS */ +#ifdef PNG_READ_GAMMA_SUPPORTED /* This is the shared test on whether a gamma value is 'significant' - whether * it is worth doing gamma correction. */ int /* PRIVATE */ png_gamma_significant(png_fixed_point gamma_val) { + /* sRGB: 1/2.2 == 0.4545(45) + * AdobeRGB: 1/(2+51/256) ~= 0.45471 5dp + * + * So the correction from AdobeRGB to sRGB (output) is: + * + * 2.2/(2+51/256) == 1.00035524 + * + * I.e. vanishingly small (<4E-4) but still detectable in 16-bit linear (+/- + * 23). Note that the Adobe choice seems to be something intended to give an + * exact number with 8 binary fractional digits - it is the closest to 2.2 + * that is possible a base 2 .8p representation. + */ return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED || gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; } -#endif -#ifdef PNG_READ_GAMMA_SUPPORTED -#ifdef PNG_16BIT_SUPPORTED +#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED /* A local convenience routine. */ static png_fixed_point png_product2(png_fixed_point a, png_fixed_point b) { - /* The required result is 1/a * 1/b; the following preserves accuracy. */ -#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED + /* The required result is a * b; the following preserves accuracy. */ +#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED /* Should now be unused */ double r = a * 1E-5; r *= b; r = floor(r+.5); @@ -3465,9 +2918,8 @@ png_product2(png_fixed_point a, png_fixed_point b) return 0; /* overflow */ } -#endif /* 16BIT */ +#endif /* FLOATING_ARITHMETIC */ -/* The inverse of the above. */ png_fixed_point png_reciprocal2(png_fixed_point a, png_fixed_point b) { @@ -3684,7 +3136,7 @@ png_log16bit(png_uint_32 x) * of getting this accuracy in practice. * * 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. */ static const png_uint_32 @@ -3873,7 +3325,7 @@ png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) * 8-bit (as are the arguments.) */ png_uint_16 /* PRIVATE */ -png_gamma_correct(png_structrp png_ptr, unsigned int value, +png_gamma_correct(png_struct *png_ptr, unsigned int value, png_fixed_point gamma_val) { if (png_ptr->bit_depth == 8) @@ -3898,28 +3350,28 @@ png_gamma_correct(png_structrp png_ptr, unsigned int value, * should be somewhere that will be cleaned. */ static void -png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +png_build_16bit_table(png_struct *png_ptr, png_uint_16 ***ptable, + unsigned int shift, png_fixed_point gamma_val) { /* Various values derived from 'shift': */ - PNG_CONST unsigned int num = 1U << (8U - shift); + unsigned int num = 1U << (8U - shift); #ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED /* CSE the division and work round wacky GCC warnings (see the comments * 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 - PNG_CONST unsigned int max = (1U << (16U - shift))-1U; - PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); + unsigned int max = (1U << (16U - shift)) - 1U; + unsigned int max_by_2 = 1U << (15U - shift); unsigned int i; - png_uint_16pp table = *ptable = - (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p))); + png_uint_16 **table = *ptable = + (png_uint_16 **)png_calloc(png_ptr, num * (sizeof (png_uint_16 *))); for (i = 0; i < num; i++) { - png_uint_16p sub_table = table[i] = - (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16))); + png_uint_16 *sub_table = table[i] = + (png_uint_16 *)png_malloc(png_ptr, 256 * (sizeof (png_uint_16))); /* The 'threshold' test is repeated here because it can arise for one of * the 16-bit tables even if the others don't hit it. @@ -3975,23 +3427,23 @@ png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, * required. */ static void -png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, - PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) +png_build_16to8_table(png_struct *png_ptr, png_uint_16 ***ptable, + unsigned int shift, png_fixed_point gamma_val) { - PNG_CONST unsigned int num = 1U << (8U - shift); - PNG_CONST unsigned int max = (1U << (16U - shift))-1U; + unsigned int num = 1U << (8U - shift); + unsigned int max = (1U << (16U - shift))-1U; unsigned int i; png_uint_32 last; - png_uint_16pp table = *ptable = - (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p))); + png_uint_16 **table = *ptable = + (png_uint_16 **)png_calloc(png_ptr, num * (sizeof (png_uint_16 *))); /* 'num' is the number of tables and also the number of low bits of low * bits of the input 16-bit value used to select a table. Each table is * itself indexed by the high 8 bits of the value. */ for (i = 0; i < num; i++) - table[i] = (png_uint_16p)png_malloc(png_ptr, + table[i] = (png_uint_16 *)png_malloc(png_ptr, 256 * (sizeof (png_uint_16))); /* 'gamma_val' is set to the reciprocal of the value calculated above, so @@ -4043,11 +3495,11 @@ png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, * (apparently contrary to the spec) so a 256-entry table is always generated. */ static void -png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable, - PNG_CONST png_fixed_point gamma_val) +png_build_8bit_table(png_struct *png_ptr, png_byte **ptable, + png_fixed_point gamma_val) { unsigned int i; - png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); + png_byte *table = *ptable = (png_byte *)png_malloc(png_ptr, 256); if (png_gamma_significant(gamma_val) != 0) for (i=0; i<256; i++) @@ -4062,7 +3514,7 @@ png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable, * tables. */ void /* PRIVATE */ -png_destroy_gamma_table(png_structrp png_ptr) +png_destroy_gamma_table(png_struct *png_ptr) { png_free(png_ptr, png_ptr->gamma_table); png_ptr->gamma_table = NULL; @@ -4120,10 +3572,27 @@ png_destroy_gamma_table(png_structrp png_ptr) * tables, we don't make a full table if we are reducing to 8-bit in * the future. Note also how the gamma_16 tables are segmented so that * we don't need to allocate > 64K chunks for a full 16-bit table. + * + * TODO: move this to pngrtran.c and make it static. Better yet create + * pngcolor.c and put all the PNG_COLORSPACE stuff in there. */ +#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ + defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +# define GAMMA_TRANSFORMS 1 /* #ifdef CSE */ +#else +# define GAMMA_TRANSFORMS 0 +#endif + void /* PRIVATE */ -png_build_gamma_table(png_structrp png_ptr, int bit_depth) +png_build_gamma_table(png_struct *png_ptr, int bit_depth) { + png_fixed_point file_gamma, screen_gamma; + png_fixed_point correction; +# if GAMMA_TRANSFORMS + png_fixed_point file_to_linear, linear_to_screen; +# endif + png_debug(1, "in png_build_gamma_table"); /* Remove any existing table; this copes with multiple calls to @@ -4138,27 +3607,44 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth) png_destroy_gamma_table(png_ptr); } + /* The following fields are set, finally, in png_init_read_transformations. + * If file_gamma is 0 (unset) nothing can be done otherwise if screen_gamma + * is 0 (unset) there is no gamma correction but to/from linear is possible. + */ + file_gamma = png_ptr->file_gamma; + screen_gamma = png_ptr->screen_gamma; +# if GAMMA_TRANSFORMS + file_to_linear = png_reciprocal(file_gamma); +# endif + + if (screen_gamma > 0) + { +# if GAMMA_TRANSFORMS + linear_to_screen = png_reciprocal(screen_gamma); +# endif + correction = png_reciprocal2(screen_gamma, file_gamma); + } + else /* screen gamma unknown */ + { +# if GAMMA_TRANSFORMS + linear_to_screen = file_gamma; +# endif + correction = PNG_FP_1; + } + if (bit_depth <= 8) { - 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) : PNG_FP_1); + png_build_8bit_table(png_ptr, &png_ptr->gamma_table, correction); -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +#if GAMMA_TRANSFORMS if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) { - png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, - png_reciprocal(png_ptr->colorspace.gamma)); + png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, file_to_linear); png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, - png_ptr->screen_gamma > 0 ? - png_reciprocal(png_ptr->screen_gamma) : - png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); + linear_to_screen); } -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ +#endif /* GAMMA_TRANSFORMS */ } #ifdef PNG_16BIT_SUPPORTED else @@ -4224,64 +3710,56 @@ png_build_gamma_table(png_structrp png_ptr, int bit_depth) * reduced to 8 bits. */ 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_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); - + png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, + png_reciprocal(correction)); else - png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, - png_ptr->screen_gamma) : PNG_FP_1); + png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, + correction); -#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ - defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ - defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +# if GAMMA_TRANSFORMS if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) { png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, - png_reciprocal(png_ptr->colorspace.gamma)); + file_to_linear); /* Notice that the '16 from 1' table should be full precision, however * the lookup on this table still uses gamma_shift, so it can't be. * TODO: fix this. */ png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, - png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : - png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); + linear_to_screen); } -#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ +#endif /* GAMMA_TRANSFORMS */ } #endif /* 16BIT */ } #endif /* READ_GAMMA */ /* HARDWARE OR SOFTWARE OPTION SUPPORT */ -#ifdef PNG_SET_OPTION_SUPPORTED -int PNGAPI -png_set_option(png_structrp png_ptr, int option, int onoff) +int +png_set_option(png_struct *png_ptr, int option, int onoff) { if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT && (option & 1) == 0) { - int mask = 3 << option; - int setting = (2 + (onoff != 0)) << option; - int current = png_ptr->options; + png_uint_32 mask = 3U << option; + png_uint_32 setting = (2U + (onoff != 0)) << option; + png_uint_32 current = png_ptr->options; - png_ptr->options = (png_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; } -#endif /* sRGB support */ #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) /* sRGB conversion tables; these are machine generated with the code in * contrib/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. * The sRGB to linear table is exact (to the nearest 16-bit linear fraction). * The inverse (linear to sRGB) table has accuracies as follows: @@ -4448,10 +3926,10 @@ const png_byte png_sRGB_delta[512] = #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) static int -png_image_free_function(png_voidp argument) +png_image_free_function(void *argument) { - png_imagep image = png_voidcast(png_imagep, argument); - png_controlp cp = image->opaque; + png_image *image = png_voidcast(png_image *, argument); + png_control *cp = image->opaque; png_control c; /* Double check that we have a png_ptr - it should be impossible to get here @@ -4464,7 +3942,7 @@ png_image_free_function(png_voidp argument) # ifdef PNG_STDIO_SUPPORTED if (cp->owned_file != 0) { - FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr); + FILE *fp = png_voidcast(FILE *, cp->png_ptr->io_ptr); cp->owned_file = 0; /* Ignore errors here. */ @@ -4507,8 +3985,8 @@ png_image_free_function(png_voidp argument) return 1; } -void PNGAPI -png_image_free(png_imagep image) +void +png_image_free(png_image *image) { /* Safely call the real function, but only if doing so is safe at this point * (if not inside an error handling context). Otherwise assume @@ -4523,7 +4001,7 @@ png_image_free(png_imagep image) } int /* PRIVATE */ -png_image_error(png_imagep image, png_const_charp error_message) +png_image_error(png_image *image, const char *error_message) { /* Utility to log an error. */ png_safecat(image->message, (sizeof image->message), 0, error_message); diff --git a/media/libpng/png.h b/media/libpng/png.h index 7c9c0f1fbf..d01b371f61 100644 --- a/media/libpng/png.h +++ b/media/libpng/png.h @@ -1,85 +1,104 @@ - /* png.h - header file for PNG reference library * - * libpng version 1.6.26, October 20, 2016 + * libpng version 1.8.0.git * - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * 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: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.26, October 20, 2016: - * Glenn Randers-Pehrson. + * 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.58, April 2026: + * Cosmin Truta * 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 - * this sentence. + * PNG Reference Library License version 2 + * --------------------------------------- * - * This modified version of libpng code adds animated PNG support and is - * released under the libpng license described below. The modifications are - * Copyright (c) 2006-2007 Andrew Smith, Copyright (c) 2008-2016 Max Stepin, - * and are delimited by "#ifdef PNG_APNG_SUPPORTED / #endif" directives - * surrounding them in the modified libpng source files. + * * Copyright (c) 1995-2026 The PNG Reference Library Authors. + * * Copyright (c) 2018-2026 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. * - * This modified version of libpng code adds Intel-SSE support and is - * released under the libpng license described below. The modifications are - * Copyright (c) 2016 Google, Inc., and consist of the source files in the - * "sse2" subdirectory and added code in pngpriv.h delimited by - * #ifndef PNG_INTEL_SSE_OPT / #endif directives. + * The software is supplied "as is", without warranty of any kind, + * 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. * - * This code is released under the libpng license. + * 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: * - * 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. + * 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. * - * libpng versions 1.0.7, July 1, 2000 through 1.6.26, October 20, 2016 are - * Copyright (c) 2000-2002, 2004, 2006-2016 Glenn Randers-Pehrson, are + * + * 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 * disclaimer and license as libpng-1.0.6 with the following individuals * added to the list of Contributing Authors: * - * Simon-Pierre Cadieux - * Eric S. Raymond - * Mans Rullgard - * Cosmin Truta - * Gilles Vollant - * James Yu - * Mandar Sahastrabuddhe + * Simon-Pierre Cadieux + * Eric S. Raymond + * Mans Rullgard + * Cosmin Truta + * Gilles Vollant + * James Yu + * Mandar Sahastrabuddhe + * Google Inc. + * Vadim Barkov * * and with the following additions to the disclaimer: * - * There is no warranty against interference with your enjoyment of the - * library or against infringement. There is no warranty that our - * efforts or the library will fulfill any of your particular purposes - * or needs. This library is provided with all faults, and the entire - * risk of satisfactory quality, performance, accuracy, and effort is with - * the user. + * There is no warranty against interference with your enjoyment of + * the library or against infringement. There is no warranty that our + * efforts or the library will fulfill any of your particular purposes + * or needs. This library is provided with all faults, and the entire + * risk of satisfactory quality, performance, accuracy, and effort is + * with the user. * - * Some files in the "contrib" directory have other copyright owners and + * 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 * Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from * 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 - * of Contributing Authors: - * - * Tom Lane - * Glenn Randers-Pehrson - * Willem van Schaik + * license as libpng-0.96, with the following individuals added to the + * list of Contributing Authors: * - * Some files in the "scripts" directory have different copyright owners - * but are also released under this license. + * Tom Lane + * Glenn Randers-Pehrson + * Willem van Schaik * * libpng versions 0.89, June 1996, through 0.96, May 1997, are * Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, @@ -87,14 +106,14 @@ * libpng-0.88, with the following individuals added to the list of * Contributing Authors: * - * John Bowler - * Kevin Bracey - * Sam Bushell - * Magnus Holmgren - * Greg Roelofs - * Tom Tanner + * John Bowler + * Kevin Bracey + * Sam Bushell + * Magnus Holmgren + * Greg Roelofs + * Tom Tanner * - * Some files in the "scripts" directory have other copyright owners + * 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 @@ -103,62 +122,49 @@ * For the purposes of this copyright and license, "Contributing Authors" * is defined as the following set of individuals: * - * Andreas Dilger - * Dave Martindale - * Guy Eric Schalnat - * Paul Schmidt - * Tim Wegner - * - * The PNG Reference Library is supplied "AS IS". The Contributing Authors - * and Group 42, Inc. disclaim all warranties, expressed or implied, - * including, without limitation, the warranties of merchantability and of - * fitness for any purpose. The Contributing Authors and Group 42, Inc. - * assume no liability for direct, indirect, incidental, special, exemplary, - * or consequential damages, which may result from the use of the PNG - * Reference Library, even if advised of the possibility of such damage. + * Andreas Dilger + * Dave Martindale + * Guy Eric Schalnat + * Paul Schmidt + * Tim Wegner + * + * The PNG Reference Library is supplied "AS IS". The Contributing + * Authors and Group 42, Inc. disclaim all warranties, expressed or + * implied, including, without limitation, the warranties of + * merchantability and of fitness for any purpose. The Contributing + * Authors and Group 42, Inc. assume no liability for direct, indirect, + * incidental, special, exemplary, or consequential damages, which may + * 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 * source code, or portions hereof, for any purpose, without fee, subject * to the following restrictions: * - * 1. The origin of this source code must not be misrepresented. + * 1. The origin of this source code must not be misrepresented. * - * 2. Altered versions must be plainly marked as such and must not - * be misrepresented as being the original source. + * 2. Altered versions must be plainly marked as such and must not + * be misrepresented as being the original source. * - * 3. This Copyright notice may not be removed or altered from any - * source or altered source distribution. + * 3. This Copyright notice may not be removed or altered from any + * source or altered source distribution. * - * The Contributing Authors and Group 42, Inc. specifically permit, without - * fee, and encourage the use of this source code as a component to - * supporting the PNG file format in commercial products. If you use this - * source code in a product, acknowledgment is not required but would be - * appreciated. + * The Contributing Authors and Group 42, Inc. specifically permit, + * without fee, and encourage the use of this source code as a component + * to supporting the PNG file format in commercial products. If you use + * this source code in a product, acknowledgment is not required but would + * be appreciated. * * END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. * - * TRADEMARK: + * TRADEMARK + * ========= * - * The name "libpng" has not been registered by the Copyright owner + * 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 owner claims "common-law trademark protection" in any + * the Copyright owners claim "common-law trademark protection" in any * jurisdiction where common-law trademark is recognized. - * - * OSI CERTIFICATION: - * - * Libpng is OSI Certified Open Source Software. OSI Certified Open Source is - * a certification mark of the Open Source Initiative. OSI has not addressed - * the additional disclaimers inserted at version 1.0.7. - * - * EXPORT CONTROL: - * - * The Copyright owner believes that the Export Control Classification - * Number (ECCN) for libpng is EAR99, which means not subject to export - * controls or International Traffic in Arms Regulations (ITAR) because - * it is open source, publicly available software, that does not contain - * any encryption software. See the EAR, paragraphs 734.3(b)(3) and - * 734.7(b). */ /* @@ -179,176 +185,33 @@ * Thanks to Frank J. T. Wojcik for helping with the documentation. */ -/* Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * ... - * 1.0.19 10 10019 10.so.0.19[.0] - * ... - * 1.2.56 13 10256 12.so.0.56[.0] - * ... - * 1.5.27 15 10527 15.so.15.27[.0] - * ... - * 1.6.26 16 10626 16.so.16.26[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcNN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng.txt or libpng.3 for more information. The PNG specification - * is available as a W3C Recommendation and as an ISO Specification, - * - * - * If you just need to read a PNG file and don't want to read the documentation - * skip to the end of this file and read the section entitled 'simplified API'. - */ - /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.26+apng" -#define PNG_HEADER_VERSION_STRING \ - " libpng version 1.6.26+apng - October 20, 2016\n" - -#define PNG_LIBPNG_VER_SONUM 16 -#define PNG_LIBPNG_VER_DLLNUM 16 +#define PNG_LIBPNG_VER_STRING "1.8.0.git" +#define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n" /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 -#define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 26 +#define PNG_LIBPNG_VER_MINOR 8 +#define PNG_LIBPNG_VER_RELEASE 0 -/* This should match the numeric part of the final component of - * PNG_LIBPNG_VER_STRING, omitting any leading zero: - */ +/* The versions of shared library builds should stay in sync, going forward */ +#define PNG_LIBPNG_VER_SHAREDLIB 18 +#define PNG_LIBPNG_VER_SONUM PNG_LIBPNG_VER_SHAREDLIB /* [Deprecated] */ +#define PNG_LIBPNG_VER_DLLNUM PNG_LIBPNG_VER_SHAREDLIB /* [Deprecated] */ -#define PNG_LIBPNG_VER_BUILD 0 +/* This should be zero for a public release, or non-zero for a + * development version. + */ +#define PNG_LIBPNG_VER_BUILD 1 /* Release Status */ -#define PNG_LIBPNG_BUILD_ALPHA 1 -#define PNG_LIBPNG_BUILD_BETA 2 -#define PNG_LIBPNG_BUILD_RC 3 -#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 #define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 /* Release-Specific Flags */ @@ -359,30 +222,27 @@ #define PNG_LIBPNG_BUILD_SPECIAL 32 /* Cannot be OR'ed with PNG_LIBPNG_BUILD_PRIVATE */ -#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_STABLE +#define PNG_LIBPNG_BUILD_BASE_TYPE PNG_LIBPNG_BUILD_BETA -/* Careful here. At one time, Guy wanted to use 082, but that 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 - * version 1.0.0 was mis-numbered 100 instead of 10000). From - * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release +/* Careful here. At one time, Guy wanted to use 082, but that + * 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 version 1.0.0 was mis-numbered 100 instead of 10000). + * From version 1.0.1 it is: + * XXYYZZ, where XX=major, YY=minor, ZZ=release */ -#define PNG_LIBPNG_VER 10626 /* 1.6.26 */ +#define PNG_LIBPNG_VER 10800 /* 1.8.0.git */ /* Library configuration: these options cannot be changed after * the library has been built. */ #ifndef PNGLCONF_H -/* If pnglibconf.h is missing, you can - * copy scripts/pnglibconf.h.prebuilt to pnglibconf.h +/* If pnglibconf.h is missing, you can copy + * pnglibconf.h.prebuilt to pnglibconf.h */ # include "pnglibconf.h" #endif -#define PNG_APNG_SUPPORTED -#define PNG_READ_APNG_SUPPORTED -#define PNG_WRITE_APNG_SUPPORTED - #ifndef PNG_VERSION_INFO_ONLY /* Machine specific configuration. */ # include "pngconf.h" @@ -478,62 +338,48 @@ extern "C" { * See pngconf.h for base types that vary by machine/system */ -#ifdef PNG_APNG_SUPPORTED -/* dispose_op flags from inside fcTL */ -#define PNG_DISPOSE_OP_NONE 0x00 -#define PNG_DISPOSE_OP_BACKGROUND 0x01 -#define PNG_DISPOSE_OP_PREVIOUS 0x02 - -/* blend_op flags from inside fcTL */ -#define PNG_BLEND_OP_SOURCE 0x00 -#define PNG_BLEND_OP_OVER 0x01 -#endif /* APNG */ - /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_26; +typedef char *png_libpng_version_1_8_0_git; -/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. +/* Basic control structures: png_struct, png_info, etc. + * + * The type names ending in 'p', 'pp' and 'rp' denote pointer, + * pointer-to-pointer and restricted-pointer types, respectively. + * Although these types are deprecated as of libpng 1.8.0, their + * declarations remain in the public headers to ensure continued + * compatibility with the existing PNG-supporting applications. * - * png_struct is the cache of information used while reading or writing a single + * See the libpng manual for more information. + */ + +/* png_struct is the cache of information used while reading or writing a * PNG file. One of these is always required, although the simplified API * (below) hides the creation and destruction of it. */ -typedef struct png_struct_def png_struct; -typedef const png_struct * png_const_structp; -typedef png_struct * png_structp; -typedef png_struct * * png_structpp; - -/* png_info contains information read from or to be written to a PNG file. One - * or more of these must exist while reading or creating a PNG file. The - * information is not used by libpng during read but is used to control what - * gets written when a PNG file is created. "png_get_" function calls read - * information during read and "png_set_" functions calls write information - * when creating a PNG. - * been moved into a separate header file that is not accessible to - * applications. Read libpng-manual.txt or libpng.3 for more info. - */ -typedef struct png_info_def png_info; -typedef png_info * png_infop; -typedef const png_info * png_const_infop; -typedef png_info * * png_infopp; - -/* Types with names ending 'p' are pointer types. The corresponding types with - * names ending 'rp' are identical pointer types except that the pointer is - * marked 'restrict', which means that it is the only pointer to the object - * passed to the function. Applications should not use the 'restrict' types; - * it is always valid to pass 'p' to a pointer with a function argument of the - * corresponding 'rp' type. Different compilers have different rules with - * regard to type matching in the presence of 'restrict'. For backward - * compatibility libpng callbacks never have 'restrict' in their parameters and, - * consequentially, writing portable application code is extremely difficult if - * an attempt is made to use 'restrict'. - */ -typedef png_struct * PNG_RESTRICT png_structrp; -typedef const png_struct * PNG_RESTRICT png_const_structrp; -typedef png_info * PNG_RESTRICT png_inforp; -typedef const png_info * PNG_RESTRICT png_const_inforp; +typedef struct png_struct_def png_struct; /* [Opaque] */ + +typedef const png_struct *png_const_structp; /* [Deprecated] */ +typedef png_struct *png_structp; /* [Deprecated] */ +typedef png_struct **png_structpp; /* [Deprecated] */ +typedef png_struct *PNG_RESTRICT png_structrp; /* [Deprecated] */ +typedef const png_struct *PNG_RESTRICT png_const_structrp; /* [Deprecated] */ + +/* png_info contains information read from or to be written to a PNG file. + * One or more of these must exist while reading or creating a PNG file. + * The information is not used by libpng during read, but is used to control + * what gets written when a PNG file is created. "png_get_" function calls + * read information during decoding, while "png_set_" function calls write + * information during encoding. + */ +typedef struct png_info_def png_info; /* [Opaque] */ + +typedef png_info *png_infop; /* [Deprecated] */ +typedef const png_info *png_const_infop; /* [Deprecated] */ +typedef png_info **png_infopp; /* [Deprecated] */ +typedef png_info *PNG_RESTRICT png_inforp; /* [Deprecated] */ +typedef const png_info *PNG_RESTRICT png_const_inforp; /* [Deprecated] */ /* Three color definitions. The order of the red, green, and blue, (and the * exact size) is not important, although the size of the fields need to @@ -545,9 +391,10 @@ typedef struct png_color_struct png_byte green; png_byte blue; } png_color; -typedef png_color * png_colorp; -typedef const png_color * png_const_colorp; -typedef png_color * * png_colorpp; + +typedef png_color *png_colorp; /* [Deprecated] */ +typedef const png_color *png_const_colorp; /* [Deprecated] */ +typedef png_color **png_colorpp; /* [Deprecated] */ typedef struct png_color_16_struct { @@ -557,9 +404,10 @@ typedef struct png_color_16_struct png_uint_16 blue; png_uint_16 gray; /* for use in grayscale files */ } png_color_16; -typedef png_color_16 * png_color_16p; -typedef const png_color_16 * png_const_color_16p; -typedef png_color_16 * * png_color_16pp; + +typedef png_color_16 *png_color_16p; /* [Deprecated] */ +typedef const png_color_16 *png_const_color_16p; /* [Deprecated] */ +typedef png_color_16 **png_color_16pp; /* [Deprecated] */ typedef struct png_color_8_struct { @@ -569,9 +417,10 @@ typedef struct png_color_8_struct png_byte gray; /* for use in grayscale files */ png_byte alpha; /* for alpha channel files */ } png_color_8; -typedef png_color_8 * png_color_8p; -typedef const png_color_8 * png_const_color_8p; -typedef png_color_8 * * png_color_8pp; + +typedef png_color_8 *png_color_8p; /* [Deprecated] */ +typedef const png_color_8 *png_const_color_8p; /* [Deprecated] */ +typedef png_color_8 **png_color_8pp; /* [Deprecated] */ /* * The following two structures are used for the in-core representation @@ -585,9 +434,10 @@ typedef struct png_sPLT_entry_struct png_uint_16 alpha; png_uint_16 frequency; } png_sPLT_entry; -typedef png_sPLT_entry * png_sPLT_entryp; -typedef const png_sPLT_entry * png_const_sPLT_entryp; -typedef png_sPLT_entry * * png_sPLT_entrypp; + +typedef png_sPLT_entry *png_sPLT_entryp; /* [Deprecated] */ +typedef const png_sPLT_entry *png_const_sPLT_entryp; /* [Deprecated] */ +typedef png_sPLT_entry **png_sPLT_entrypp; /* [Deprecated] */ /* When the depth of the sPLT palette is 8 bits, the color and alpha samples * occupy the LSB of their respective members, and the MSB of each member @@ -596,14 +446,15 @@ typedef png_sPLT_entry * * png_sPLT_entrypp; typedef struct png_sPLT_struct { - png_charp name; /* palette name */ + char *name; /* palette name */ png_byte depth; /* depth of palette samples */ - png_sPLT_entryp entries; /* palette entries */ + png_sPLT_entry *entries; /* palette entries */ png_int_32 nentries; /* number of palette entries */ } png_sPLT_t; -typedef png_sPLT_t * png_sPLT_tp; -typedef const png_sPLT_t * png_const_sPLT_tp; -typedef png_sPLT_t * * png_sPLT_tpp; + +typedef png_sPLT_t *png_sPLT_tp; /* [Deprecated] */ +typedef const png_sPLT_t *png_const_sPLT_tp; /* [Deprecated] */ +typedef png_sPLT_t **png_sPLT_tpp; /* [Deprecated] */ #ifdef PNG_TEXT_SUPPORTED /* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file, @@ -630,19 +481,20 @@ typedef struct png_text_struct 0: zTXt, deflate 1: iTXt, none 2: iTXt, deflate */ - png_charp key; /* keyword, 1-79 character description of "text" */ - png_charp text; /* comment, may be an empty string (ie "") + char *key; /* keyword, 1-79 character description of "text" */ + char *text; /* comment, may be an empty string (ie "") or a NULL pointer */ - png_size_t text_length; /* length of the text string */ - png_size_t itxt_length; /* length of the itxt string */ - png_charp lang; /* language code, 0-79 characters + size_t text_length; /* length of the text string */ + size_t itxt_length; /* length of the itxt string */ + char *lang; /* language code, 0-79 characters or a NULL pointer */ - png_charp lang_key; /* keyword translated UTF-8 string, 0 or more + char *lang_key; /* keyword translated UTF-8 string, 0 or more chars or a NULL pointer */ } png_text; -typedef png_text * png_textp; -typedef const png_text * png_const_textp; -typedef png_text * * png_textpp; + +typedef png_text *png_textp; /* [Deprecated] */ +typedef const png_text *png_const_textp; /* [Deprecated] */ +typedef png_text **png_textpp; /* [Deprecated] */ #endif /* Supported compression types for text in PNG files (tEXt, and zTXt). @@ -670,9 +522,10 @@ typedef struct png_time_struct png_byte minute; /* minute of hour, 0 - 59 */ png_byte second; /* second of minute, 0 - 60 (for leap seconds) */ } png_time; -typedef png_time * png_timep; -typedef const png_time * png_const_timep; -typedef png_time * * png_timepp; + +typedef png_time *png_timep; /* [Deprecated] */ +typedef const png_time *png_const_timep; /* [Deprecated] */ +typedef png_time **png_timepp; /* [Deprecated] */ #if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\ defined(PNG_USER_CHUNKS_SUPPORTED) @@ -687,7 +540,7 @@ typedef struct png_unknown_chunk_t { png_byte name[5]; /* Textual chunk name with '\0' terminator */ png_byte *data; /* Data, should not be modified on read! */ - png_size_t size; + size_t size; /* 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 @@ -699,9 +552,9 @@ typedef struct png_unknown_chunk_t } png_unknown_chunk; -typedef png_unknown_chunk * png_unknown_chunkp; -typedef const png_unknown_chunk * png_const_unknown_chunkp; -typedef png_unknown_chunk * * png_unknown_chunkpp; +typedef png_unknown_chunk *png_unknown_chunkp; /* [Deprecated] */ +typedef const png_unknown_chunk *png_const_unknown_chunkp; /* [Deprecated] */ +typedef png_unknown_chunk **png_unknown_chunkpp; /* [Deprecated] */ #endif /* Flag values for the unknown chunk location byte. */ @@ -712,7 +565,7 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; /* Maximum positive integer used in PNG is (2^31)-1 */ #define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL) #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 * PNG specification manner (x100000) @@ -782,6 +635,17 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; #define PNG_sRGB_INTENT_ABSOLUTE 3 #define PNG_sRGB_INTENT_LAST 4 /* Not a valid value */ +/* These are for the fcTL chunk. These values should NOT be changed. */ +#define PNG_fcTL_DISPOSE_OP_NONE 0 +#define PNG_fcTL_DISPOSE_OP_BACKGROUND 1 +#define PNG_fcTL_DISPOSE_OP_PREVIOUS 2 +#define PNG_fcTL_DISPOSE_OP_LAST 3 /* Not a valid value */ + +/* These are also for the fcTL chunk, and they should also NOT be changed. */ +#define PNG_fcTL_BLEND_OP_SOURCE 0 +#define PNG_fcTL_BLEND_OP_OVER 1 +#define PNG_fcTL_BLEND_OP_LAST 2 /* Not a valid value */ + /* This is for text chunks */ #define PNG_KEYWORD_MAX_LENGTH 79 @@ -809,10 +673,22 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; #define PNG_INFO_sPLT 0x2000U /* ESR, 1.0.6 */ #define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */ #define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */ -#ifdef PNG_APNG_SUPPORTED -#define PNG_INFO_acTL 0x10000U -#define PNG_INFO_fcTL 0x20000U -#endif +#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */ +#define PNG_INFO_cICP 0x20000U /* PNGv3: 1.6.45 */ +#define PNG_INFO_cLLI 0x40000U /* PNGv3: 1.6.45 */ +#define PNG_INFO_mDCV 0x80000U /* PNGv3: 1.6.45 */ +/* APNG: these chunks are stored as unknown, these flags are never set + * however they are provided as a convenience for implementors of APNG and + * avoids any merge conflicts. + * + * Private chunks: these chunk names violate the chunk name recommendations + * because the chunk definitions have no signature and because the private + * chunks with these names have been reserved. Private definitions should + * avoid them. + */ +#define PNG_INFO_acTL 0x100000U /* PNGv3: 1.6.45: unknown */ +#define PNG_INFO_fcTL 0x200000U /* PNGv3: 1.6.45: unknown */ +#define PNG_INFO_fdAT 0x400000U /* PNGv3: 1.6.45: unknown */ /* This is used for the transformation routines, as some of them * change these values for the row. It also should enable using @@ -821,15 +697,15 @@ typedef png_unknown_chunk * * png_unknown_chunkpp; typedef struct png_row_info_struct { 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 bit_depth; /* bit depth of row */ png_byte channels; /* number of channels (1, 2, 3, or 4) */ png_byte pixel_depth; /* bits per pixel (depth * channels) */ } png_row_info; -typedef png_row_info * png_row_infop; -typedef png_row_info * * png_row_infopp; +typedef png_row_info *png_row_infop; /* [Deprecated] */ +typedef png_row_info **png_row_infopp; /* [Deprecated] */ /* These are the function types for the I/O functions and for the functions * that allow the user to override the default I/O functions with his or her @@ -839,24 +715,29 @@ typedef png_row_info * * png_row_infopp; * modify the buffer it is passed. The 'read' function, on the other hand, is * 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_rw_ptr, (png_structp, png_bytep, png_size_t)); -typedef PNG_CALLBACK(void, *png_flush_ptr, (png_structp)); -typedef PNG_CALLBACK(void, *png_read_status_ptr, (png_structp, png_uint_32, - int)); -typedef PNG_CALLBACK(void, *png_write_status_ptr, (png_structp, png_uint_32, - int)); +typedef PNG_CALLBACK(void, *png_error_ptr, + (png_struct *, const char *)); +typedef PNG_CALLBACK(void, *png_rw_ptr, + (png_struct *, png_byte *, size_t)); +typedef PNG_CALLBACK(void, *png_flush_ptr, + (png_struct *)); +typedef PNG_CALLBACK(void, *png_read_status_ptr, + (png_struct *, png_uint_32, int)); +typedef PNG_CALLBACK(void, *png_write_status_ptr, + (png_struct *, png_uint_32, int)); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED -typedef PNG_CALLBACK(void, *png_progressive_info_ptr, (png_structp, png_infop)); -typedef PNG_CALLBACK(void, *png_progressive_end_ptr, (png_structp, png_infop)); +typedef PNG_CALLBACK(void, *png_progressive_info_ptr, + (png_struct *, png_info *)); +typedef PNG_CALLBACK(void, *png_progressive_end_ptr, + (png_struct *, png_info *)); #ifdef PNG_APNG_SUPPORTED -typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp, - png_uint_32)); +typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, + (png_struct *, png_uint_32)); #endif /* The following callback receives png_uint_32 row_number, int pass for the - * png_bytep data of the row. When transforming an interlaced image the + * png_byte* data of the row. When transforming an interlaced image the * row number is the row number within the sub-image of the interlace pass, so * the value will increase to the height of the sub-image (not the full image) * then reset to 0 for the next pass. @@ -865,23 +746,23 @@ typedef PNG_CALLBACK(void, *png_progressive_frame_ptr, (png_structp, * find the output pixel (x,y) given an interlaced sub-image pixel * (row,col,pass). (See below for these macros.) */ -typedef PNG_CALLBACK(void, *png_progressive_row_ptr, (png_structp, png_bytep, - png_uint_32, int)); +typedef PNG_CALLBACK(void, *png_progressive_row_ptr, + (png_struct *, png_byte *, png_uint_32, int)); #endif #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -typedef PNG_CALLBACK(void, *png_user_transform_ptr, (png_structp, png_row_infop, - png_bytep)); +typedef PNG_CALLBACK(void, *png_user_transform_ptr, + (png_struct *, png_row_info *, png_byte *)); #endif #ifdef PNG_USER_CHUNKS_SUPPORTED -typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, - png_unknown_chunkp)); +typedef PNG_CALLBACK(int, *png_user_chunk_ptr, + (png_struct *, png_unknown_chunk *)); #endif #ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED /* not used anywhere */ -/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */ +/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_struct *)); */ #endif #ifdef PNG_SETJMP_SUPPORTED @@ -896,7 +777,7 @@ typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, * your compiler. This may be very difficult - try using a different compiler * to build the library! */ -PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +PNG_FUNCTION(void, (*png_longjmp_ptr), (jmp_buf, int), typedef); #endif /* Transform masks for the high-level interface */ @@ -920,7 +801,7 @@ PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); #define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ /* Added to libpng-1.5.4 */ #define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ -#if INT_MAX >= 0x8000 /* else this might break */ +#if ~0U > 0xffffU /* or else this might break on a 16-bit machine */ #define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ #endif @@ -935,9 +816,10 @@ PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); * ignores the first argument) should be completely compatible with the * following. */ -typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, - png_alloc_size_t)); -typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); +typedef PNG_CALLBACK(void *, *png_malloc_ptr, + (png_struct *, png_alloc_size_t)); +typedef PNG_CALLBACK(void, *png_free_ptr, + (png_struct *, void *)); /* Section 4: exported functions * Here are the function definitions most commonly used. This is not @@ -948,13 +830,8 @@ typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); * The PNG_EXPORT() and PNG_EXPORTA() macros used below are defined in * pngconf.h and in the *.dfn files in the scripts directory. * - * PNG_EXPORT(ordinal, type, name, (args)); + * PNG_EXPORT(type, name, (args)); * - * ordinal: ordinal that is used while building - * *.def files. The ordinal value is only - * relevant when preprocessing png.h with - * the *.dfn files for building symbol table - * entries, and are removed by pngconf.h. * type: return type of the function * name: function name * args: function arguments, with types @@ -962,50 +839,47 @@ typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); * When we wish to append attributes to a function prototype we use * the PNG_EXPORTA() macro instead. * - * PNG_EXPORTA(ordinal, type, name, (args), attributes); + * PNG_EXPORTA(type, name, (args), attributes); * - * ordinal, type, name, and args: same as in PNG_EXPORT(). + * type, name, and args: same as in PNG_EXPORT(). * attributes: function attributes */ /* Returns the version number of the library */ -PNG_EXPORT(1, png_uint_32, png_access_version_number, (void)); +PNG_EXPORT(png_uint_32, png_access_version_number, + (void)); /* Tell lib we have already handled the first magic bytes. * Handling more than 8 bytes from the beginning of the file is an error. */ -PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes)); +PNG_EXPORT(void, png_set_sig_bytes, + (png_struct *png_ptr, int num_bytes)); /* Check sig[start] through sig[start + num_to_check - 1] to see if it's a * PNG file. Returns zero if the supplied bytes match the 8-byte PNG * 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 (i.e. return non-zero). */ -PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, png_size_t start, - png_size_t num_to_check)); - -/* Simple signature checking function. This is the same as calling - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n). - */ -#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n)) +PNG_EXPORT(int, png_sig_cmp, + (const png_byte *sig, size_t start, size_t num_to_check)); /* Allocate and initialize png_ptr struct for reading, and any other memory. */ -PNG_EXPORTA(4, png_structp, png_create_read_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn), - PNG_ALLOCATED); +PNG_EXPORTA(png_struct *, png_create_read_struct, + (const char *user_png_ver, + void *error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); /* Allocate and initialize png_ptr struct for writing, and any other memory */ -PNG_EXPORTA(5, png_structp, png_create_write_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn), - PNG_ALLOCATED); +PNG_EXPORTA(png_struct *, png_create_write_struct, + (const char *user_png_ver, + void *error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED); -PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size, - (png_const_structrp png_ptr)); +PNG_EXPORT(size_t, png_get_compression_buffer_size, + (const png_struct *png_ptr)); -PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, - png_size_t size)); +PNG_EXPORT(void, png_set_compression_buffer_size, + (png_struct *png_ptr, size_t size)); /* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp * match up. @@ -1018,8 +892,8 @@ PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr, * allocated by the library - the call will return NULL on a mismatch * indicating an ABI mismatch. */ -PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, - png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); +PNG_EXPORT(jmp_buf*, png_set_longjmp_fn, + (png_struct *png_ptr, png_longjmp_ptr longjmp_fn, size_t jmp_buf_size)); # define png_jmpbuf(png_ptr) \ (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf)))) #else @@ -1031,67 +905,77 @@ PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr, * will use it; otherwise it will call PNG_ABORT(). This function was * added in libpng-1.5.0. */ -PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val), - PNG_NORETURN); +PNG_EXPORTA(void, png_longjmp, + (const png_struct *png_ptr, int val), + PNG_NORETURN); #ifdef PNG_READ_SUPPORTED /* Reset the compression stream */ -PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED); +PNG_EXPORTA(int, png_reset_zstream, + (png_struct *png_ptr), + PNG_DEPRECATED); #endif /* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */ #ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(11, png_structp, png_create_read_struct_2, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), - PNG_ALLOCATED); -PNG_EXPORTA(12, png_structp, png_create_write_struct_2, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, - png_voidp mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), - PNG_ALLOCATED); +PNG_EXPORTA(png_struct *, png_create_read_struct_2, + (const char *user_png_ver, + void *error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, + void *mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); +PNG_EXPORTA(png_struct *, png_create_write_struct_2, + (const char *user_png_ver, + void *error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, + void *mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); #endif /* Write the PNG file signature. */ -PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr)); +PNG_EXPORT(void, png_write_sig, + (png_struct *png_ptr)); /* Write a PNG chunk - size, type, (optional) data, CRC. */ -PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep - chunk_name, png_const_bytep data, png_size_t length)); +PNG_EXPORT(void, png_write_chunk, + (png_struct *png_ptr, + const png_byte *chunk_name, const png_byte *data, size_t length)); /* Write the start of a PNG chunk - length and chunk name. */ -PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, - png_const_bytep chunk_name, png_uint_32 length)); +PNG_EXPORT(void, png_write_chunk_start, + (png_struct *png_ptr, + const png_byte *chunk_name, png_uint_32 length)); /* 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_const_bytep data, png_size_t length)); +PNG_EXPORT(void, png_write_chunk_data, + (png_struct *png_ptr, + const png_byte *data, size_t length)); /* 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(void, png_write_chunk_end, + (png_struct *png_ptr)); /* Allocate and initialize the info structure */ -PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr), - PNG_ALLOCATED); +PNG_EXPORTA(png_info *, png_create_info_struct, + (const png_struct *png_ptr), + PNG_ALLOCATED); /* DEPRECATED: this function allowed init structures to be created using the * default allocation method (typically malloc). Use is deprecated in 1.6.0 and * the API will be removed in the future. */ -PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr, - png_size_t png_info_struct_size), PNG_DEPRECATED); +PNG_EXPORTA(void, png_info_init_3, + (png_info **info_ptr, size_t png_info_struct_size), + PNG_DEPRECATED); /* Writes all the PNG information before the image. */ -PNG_EXPORT(20, void, png_write_info_before_PLTE, - (png_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(21, void, png_write_info, - (png_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(void, png_write_info_before_PLTE, + (png_struct *png_ptr, const png_info *info_ptr)); +PNG_EXPORT(void, png_write_info, + (png_struct *png_ptr, const png_info *info_ptr)); #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read the information before the actual image data. */ -PNG_EXPORT(22, void, png_read_info, - (png_structrp png_ptr, png_inforp info_ptr)); +PNG_EXPORT(void, png_read_info, + (png_struct *png_ptr, png_info *info_ptr)); #endif #ifdef PNG_TIME_RFC1123_SUPPORTED @@ -1099,47 +983,55 @@ PNG_EXPORT(22, void, png_read_info, * routine. The original implementation used a 29 character buffer in * png_struct, this will be removed in future versions. */ -#if PNG_LIBPNG_VER < 10700 -/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */ -PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr, - png_const_timep ptime),PNG_DEPRECATED); -#endif -PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29], - png_const_timep ptime)); +PNG_EXPORT(int, png_convert_to_rfc1123_buffer, + (char out[29], const png_time *ptime)); + +/* Removed from libpng 1.7 onwards; use png_convert_to_rfc1123_buffer. */ +PNG_REMOVED(const char *, png_convert_to_rfc1123, + (png_struct *png_ptr, const png_time *ptime), + PNG_DEPRECATED) #endif #ifdef PNG_CONVERT_tIME_SUPPORTED /* Convert from a struct tm to png_time */ -PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime, - const struct tm * ttime)); +PNG_EXPORT(void, png_convert_from_struct_tm, + (png_time *ptime, const struct tm * ttime)); /* Convert from time_t to png_time. Uses gmtime() */ -PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime)); +PNG_EXPORT(void, png_convert_from_time_t, + (png_time *ptime, time_t ttime)); #endif /* CONVERT_tIME */ #ifdef PNG_READ_EXPAND_SUPPORTED /* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */ -PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr)); -PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr)); -PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr)); -PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_expand, + (png_struct *png_ptr)); +PNG_EXPORT(void, png_set_expand_gray_1_2_4_to_8, + (png_struct *png_ptr)); +PNG_EXPORT(void, png_set_palette_to_rgb, + (png_struct *png_ptr)); +PNG_EXPORT(void, png_set_tRNS_to_alpha, + (png_struct *png_ptr)); #endif #ifdef PNG_READ_EXPAND_16_SUPPORTED /* Expand to 16-bit channels, forces conversion of palette to RGB and expansion * of a tRNS chunk if present. */ -PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_expand_16, + (png_struct *png_ptr)); #endif #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) /* Use blue, green, red order for pixels. */ -PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_bgr, + (png_struct *png_ptr)); #endif #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* Expand the grayscale to 24-bit RGB if necessary. */ -PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_gray_to_rgb, + (png_struct *png_ptr)); #endif #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED @@ -1149,18 +1041,20 @@ PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr)); #define PNG_ERROR_ACTION_ERROR 3 #define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/ -PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr, +PNG_FP_EXPORT(void, png_set_rgb_to_gray, + (png_struct *png_ptr, int error_action, double red, double green)) -PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr, +PNG_FIXED_EXPORT(void, png_set_rgb_to_gray_fixed, + (png_struct *png_ptr, int error_action, png_fixed_point red, png_fixed_point green)) -PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp - png_ptr)); +PNG_EXPORT(png_byte, png_get_rgb_to_gray_status, + (const png_struct *png_ptr)); #endif #ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED -PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, - png_colorp palette)); +PNG_EXPORT(void, png_build_grayscale_palette, + (int bit_depth, png_color *palette)); #endif #ifdef PNG_READ_ALPHA_MODE_SUPPORTED @@ -1177,7 +1071,7 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, * corresponding composited pixel, and the color channels are unassociated * (not premultiplied). The gamma encoded color channels must be scaled * 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 alternative is to 'associate' the alpha with the color information by @@ -1205,10 +1099,10 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth, #define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */ #define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */ -PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode, - double output_gamma)) -PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, - int mode, png_fixed_point output_gamma)) +PNG_FP_EXPORT(void, png_set_alpha_mode, + (png_struct *png_ptr, int mode, double output_gamma)) +PNG_FIXED_EXPORT(void, png_set_alpha_mode_fixed, + (png_struct *png_ptr, int mode, png_fixed_point output_gamma)) #endif #if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED) @@ -1233,7 +1127,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); * 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. * * png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR); @@ -1280,7 +1174,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. * 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 * 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 @@ -1298,51 +1192,57 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr, */ #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_strip_alpha, + (png_struct *png_ptr)); #endif #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_swap_alpha, + (png_struct *png_ptr)); #endif #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_invert_alpha, + (png_struct *png_ptr)); #endif #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) /* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ -PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, - int flags)); +PNG_EXPORT(void, png_set_filler, + (png_struct *png_ptr, png_uint_32 filler, int flags)); /* The values of the PNG_FILLER_ defines should NOT be changed */ # define PNG_FILLER_BEFORE 0 # define PNG_FILLER_AFTER 1 /* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ -PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, - png_uint_32 filler, int flags)); +PNG_EXPORT(void, png_set_add_alpha, + (png_struct *png_ptr, png_uint_32 filler, int flags)); #endif /* READ_FILLER || WRITE_FILLER */ #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) /* Swap bytes in 16-bit depth files. */ -PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_swap, + (png_struct *png_ptr)); #endif #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) /* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */ -PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_packing, + (png_struct *png_ptr)); #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ defined(PNG_WRITE_PACKSWAP_SUPPORTED) /* Swap packing order of pixels in bytes. */ -PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_packswap, + (png_struct *png_ptr)); #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) /* Converts files to legal bit depths. */ -PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p - true_bits)); +PNG_EXPORT(void, png_set_shift, + (png_struct *png_ptr, const png_color_8 *true_bits)); #endif #if defined(PNG_READ_INTERLACING_SUPPORTED) || \ @@ -1353,12 +1253,14 @@ PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p * necessary to call png_read_row or png_read_rows png_get_image_height * times for each pass. */ -PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr)); +PNG_EXPORT(int, png_set_interlace_handling, + (png_struct *png_ptr)); #endif #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) /* Invert monochrome files */ -PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_invert_mono, + (png_struct *png_ptr)); #endif #ifdef PNG_READ_BACKGROUND_SUPPORTED @@ -1367,11 +1269,13 @@ PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr)); * read. Doing so will result in unexpected behavior and possible warnings or * errors if the PNG file contains a bKGD chunk. */ -PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr, - png_const_color_16p background_color, int background_gamma_code, +PNG_FP_EXPORT(void, png_set_background, + (png_struct *png_ptr, + const png_color_16 *background_color, int background_gamma_code, int need_expand, double background_gamma)) -PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, - png_const_color_16p background_color, int background_gamma_code, +PNG_FIXED_EXPORT(void, png_set_background_fixed, + (png_struct *png_ptr, + const png_color_16 *background_color, int background_gamma_code, int need_expand, png_fixed_point background_gamma)) #endif #ifdef PNG_READ_BACKGROUND_SUPPORTED @@ -1383,22 +1287,25 @@ PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr, #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* Scale a 16-bit depth file down to 8-bit, accurately. */ -PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_scale_16, + (png_struct *png_ptr)); #endif #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED #define PNG_READ_16_TO_8_SUPPORTED /* Name prior to 1.5.4 */ /* Strip the second byte of information from a 16-bit depth file. */ -PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr)); +PNG_EXPORT(void, png_set_strip_16, + (png_struct *png_ptr)); #endif #ifdef PNG_READ_QUANTIZE_SUPPORTED /* Turn on quantizing, and reduce the palette to the number of colors * available. */ -PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, - png_colorp palette, int num_palette, int maximum_colors, - png_const_uint_16p histogram, int full_quantize)); +PNG_EXPORT(void, png_set_quantize, + (png_struct *png_ptr, + png_color *palette, int num_palette, int maximum_colors, + const png_uint_16 *histogram, int full_quantize)); #endif #ifdef PNG_READ_GAMMA_SUPPORTED @@ -1418,82 +1325,92 @@ PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr, * API (floating point or fixed.) Notice, however, that the 'file_gamma' value * is the inverse of a 'screen gamma' value. */ -PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr, +PNG_FP_EXPORT(void, png_set_gamma, + (png_struct *png_ptr, double screen_gamma, double override_file_gamma)) -PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr, +PNG_FIXED_EXPORT(void, png_set_gamma_fixed, + (png_struct *png_ptr, png_fixed_point screen_gamma, png_fixed_point override_file_gamma)) #endif #ifdef PNG_WRITE_FLUSH_SUPPORTED /* Set how many lines between output flushes - 0 for no flushing */ -PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows)); +PNG_EXPORT(void, png_set_flush, + (png_struct *png_ptr, int nrows)); /* Flush the current PNG output buffer */ -PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr)); +PNG_EXPORT(void, png_write_flush, + (png_struct *png_ptr)); #endif /* Optional update palette with requested transformations */ -PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr)); +PNG_EXPORT(void, png_start_read_image, + (png_struct *png_ptr)); /* Optional call to update the users info structure */ -PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr, - png_inforp info_ptr)); +PNG_EXPORT(void, png_read_update_info, + (png_struct *png_ptr, png_info *info_ptr)); #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read one or more rows of image data. */ -PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row, - png_bytepp display_row, png_uint_32 num_rows)); +PNG_EXPORT(void, png_read_rows, + (png_struct *png_ptr, png_byte **row, + png_byte **display_row, png_uint_32 num_rows)); #endif #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read a row of data. */ -PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row, - png_bytep display_row)); +PNG_EXPORT(void, png_read_row, + (png_struct *png_ptr, png_byte *row, png_byte *display_row)); #endif #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read the whole image into memory at once. */ -PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image)); +PNG_EXPORT(void, png_read_image, + (png_struct *png_ptr, png_byte **image)); #endif /* Write a row of image data */ -PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr, - png_const_bytep row)); +PNG_EXPORT(void, png_write_row, + (png_struct *png_ptr, const png_byte *row)); /* Write a few rows of image data: (*row) is not written; however, the type * is declared as writeable to maintain compatibility with previous versions * of libpng and to allow the 'display_row' array from read_rows to be passed * unchanged to write_rows. */ -PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row, - png_uint_32 num_rows)); +PNG_EXPORT(void, png_write_rows, + (png_struct *png_ptr, png_byte **row, png_uint_32 num_rows)); /* Write the image data */ -PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image)); +PNG_EXPORT(void, png_write_image, + (png_struct *png_ptr, png_byte **image)); /* Write the end of the PNG file. */ -PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr, - png_inforp info_ptr)); +PNG_EXPORT(void, png_write_end, + (png_struct *png_ptr, png_info *info_ptr)); #ifdef PNG_SEQUENTIAL_READ_SUPPORTED /* Read the end of the PNG file. */ -PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr)); +PNG_EXPORT(void, png_read_end, + (png_struct *png_ptr, png_info *info_ptr)); #endif /* Free any memory associated with the png_info_struct */ -PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr, - png_infopp info_ptr_ptr)); +PNG_EXPORT(void, png_destroy_info_struct, + (const png_struct *png_ptr, png_info **info_ptr_ptr)); /* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(64, void, png_destroy_read_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr, png_infopp end_info_ptr_ptr)); +PNG_EXPORT(void, png_destroy_read_struct, + (png_struct **png_ptr_ptr, + png_info **info_ptr_ptr, png_info **end_info_ptr_ptr)); /* Free any memory associated with the png_struct and the png_info_structs */ -PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr, - png_infopp info_ptr_ptr)); +PNG_EXPORT(void, png_destroy_write_struct, + (png_struct **png_ptr_ptr, png_info **info_ptr_ptr)); /* Set the libpng method of handling chunk CRC errors */ -PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, - int ancil_action)); +PNG_EXPORT(void, png_set_crc_action, + (png_struct *png_ptr, int crit_action, int ancil_action)); /* Values for png_set_crc_action() say how to handle CRC errors in * ancillary and critical chunks, and whether to use the data contained @@ -1517,14 +1434,14 @@ PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action, * mainly useful for testing, as the defaults should work with most users. * Those users who are tight on memory or want faster performance at the * expense of compression can modify them. See the compression library - * header file (zlib.h) for an explination of the compression functions. + * header file (zlib.h) for an explanation of the compression functions. */ /* Set the filtering method(s) used by libpng. Currently, the only valid * value for "method" is 0. */ -PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, - int filters)); +PNG_EXPORT(void, png_set_filter, + (png_struct *png_ptr, int method, int filters)); #endif /* WRITE */ /* Flags for png_set_filter() to say which filters to use. The flags @@ -1552,69 +1469,66 @@ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, #define PNG_FILTER_VALUE_LAST 5 #ifdef PNG_WRITE_SUPPORTED -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ -PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, - int heuristic_method, int num_weights, png_const_doublep filter_weights, - png_const_doublep filter_costs)) -PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, - (png_structrp png_ptr, int heuristic_method, int num_weights, - png_const_fixed_point_p filter_weights, - png_const_fixed_point_p filter_costs)) -#endif /* WRITE_WEIGHTED_FILTER */ - -/* The following are no longer used and will be removed from libpng-1.7: */ -#define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ -#define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ -#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ -#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */ - /* Set the library compression level. Currently, valid values range from * 0 - 9, corresponding directly to the zlib compression levels 0 - 9 * (0 - no compression, 9 - "maximal" compression). Note that tests have * shown that zlib compression levels 3-6 usually perform as well as level 9 - * for PNG images, and do considerably fewer caclulations. In the future, + * for PNG images, and do considerably fewer calculations. In the future, * these values may not correspond directly to the zlib compression levels. */ #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED -PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr, - int level)); +PNG_EXPORT(void, png_set_compression_level, + (png_struct *png_ptr, int level)); -PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr, - int mem_level)); +PNG_EXPORT(void, png_set_compression_mem_level, + (png_struct *png_ptr, int mem_level)); -PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr, - int strategy)); +PNG_EXPORT(void, png_set_compression_strategy, + (png_struct *png_ptr, int strategy)); /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a * smaller value of window_bits if it can do so safely. */ -PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr, - int window_bits)); +PNG_EXPORT(void, png_set_compression_window_bits, + (png_struct *png_ptr, int window_bits)); -PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr, - int method)); +PNG_EXPORT(void, png_set_compression_method, + (png_struct *png_ptr, int method)); #endif /* WRITE_CUSTOMIZE_COMPRESSION */ #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED /* Also set zlib parameters for compressing non-IDAT chunks */ -PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr, - int level)); +PNG_EXPORT(void, png_set_text_compression_level, + (png_struct *png_ptr, int level)); -PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr, - int mem_level)); +PNG_EXPORT(void, png_set_text_compression_mem_level, + (png_struct *png_ptr, int mem_level)); -PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr, - int strategy)); +PNG_EXPORT(void, png_set_text_compression_strategy, + (png_struct *png_ptr, int strategy)); /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a * smaller value of window_bits if it can do so safely. */ -PNG_EXPORT(225, void, png_set_text_compression_window_bits, - (png_structrp png_ptr, int window_bits)); +PNG_EXPORT(void, png_set_text_compression_window_bits, + (png_struct *png_ptr, int window_bits)); -PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, - int method)); +PNG_EXPORT(void, png_set_text_compression_method, + (png_struct *png_ptr, int method)); #endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ + +PNG_REMOVED(void, png_set_filter_heuristics, + (png_struct *png_ptr, + int heuristic_method, int num_weights, + const double *filter_weights, + const double *filter_costs), + PNG_DEPRECATED) +PNG_REMOVED(void, png_set_filter_heuristics_fixed, + (png_struct *png_ptr, + int heuristic_method, int num_weights, + const png_fixed_point *filter_weights, + const png_fixed_point *filter_costs), + PNG_DEPRECATED) #endif /* WRITE */ /* These next functions are called for input/output, memory, and error @@ -1628,7 +1542,8 @@ PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr, #ifdef PNG_STDIO_SUPPORTED /* Initialize the input/output for the PNG file to the default functions. */ -PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); +PNG_EXPORT(void, png_init_io, + (png_struct *png_ptr, FILE *fp)); #endif /* Replace the (error and abort), and warning functions with user @@ -1639,11 +1554,13 @@ PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp)); * default function will be used. */ -PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr, - png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); +PNG_EXPORT(void, png_set_error_fn, + (png_struct *png_ptr, + void *error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn)); /* Return the user pointer associated with the error functions */ -PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); +PNG_EXPORT(void *, png_get_error_ptr, + (const png_struct *png_ptr)); /* Replace the default data output functions with a user supplied one(s). * If buffered output is not used, then output_flush_fn can be set to NULL. @@ -1655,47 +1572,54 @@ PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr)); * default flush function, which uses the standard *FILE structure, will * be used. */ -PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr, +PNG_EXPORT(void, png_set_write_fn, + (png_struct *png_ptr, + void *io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)); /* Replace the default data input function with a user supplied one. */ -PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr, - png_rw_ptr read_data_fn)); +PNG_EXPORT(void, png_set_read_fn, + (png_struct *png_ptr, + void *io_ptr, png_rw_ptr read_data_fn)); /* Return the user pointer associated with the I/O functions */ -PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr)); +PNG_EXPORT(void *, png_get_io_ptr, + (const png_struct *png_ptr)); -PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr, - png_read_status_ptr read_row_fn)); +PNG_EXPORT(void, png_set_read_status_fn, + (png_struct *png_ptr, png_read_status_ptr read_row_fn)); -PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr, - png_write_status_ptr write_row_fn)); +PNG_EXPORT(void, png_set_write_status_fn, + (png_struct *png_ptr, png_write_status_ptr write_row_fn)); #ifdef PNG_USER_MEM_SUPPORTED /* Replace the default memory allocation functions with user supplied one(s). */ -PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn)); +PNG_EXPORT(void, png_set_mem_fn, + (png_struct *png_ptr, + void *mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn)); /* Return the user pointer associated with the memory functions */ -PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr)); +PNG_EXPORT(void *, png_get_mem_ptr, + (const png_struct *png_ptr)); #endif #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr, - png_user_transform_ptr read_user_transform_fn)); +PNG_EXPORT(void, png_set_read_user_transform_fn, + (png_struct *png_ptr, png_user_transform_ptr read_user_transform_fn)); #endif #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr, - png_user_transform_ptr write_user_transform_fn)); +PNG_EXPORT(void, png_set_write_user_transform_fn, + (png_struct *png_ptr, png_user_transform_ptr write_user_transform_fn)); #endif #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr, - png_voidp user_transform_ptr, int user_transform_depth, - int user_transform_channels)); +PNG_EXPORT(void, png_set_user_transform_info, + (png_struct *png_ptr, + void *user_transform_ptr, + int user_transform_depth, int user_transform_channels)); /* Return the user pointer associated with the user transform functions */ -PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, - (png_const_structrp png_ptr)); +PNG_EXPORT(void *, png_get_user_transform_ptr, + (const png_struct *png_ptr)); #endif #ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED @@ -1710,8 +1634,10 @@ PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr, * find the output pixel (x,y) given an interlaced sub-image pixel * (row,col,pass). (See below for these macros.) */ -PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp)); -PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp)); +PNG_EXPORT(png_uint_32, png_get_current_row_number, + (const png_struct *)); +PNG_EXPORT(png_byte, png_get_current_pass_number, + (const png_struct *)); #endif #ifdef PNG_READ_USER_CHUNKS_SUPPORTED @@ -1731,32 +1657,36 @@ 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. * 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 */ -PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr, - png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); +PNG_EXPORT(void, png_set_read_user_chunk_fn, + (png_struct *png_ptr, + void *user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn)); #endif #ifdef PNG_USER_CHUNKS_SUPPORTED -PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr)); +PNG_EXPORT(void *, png_get_user_chunk_ptr, + (const png_struct *png_ptr)); #endif #ifdef PNG_PROGRESSIVE_READ_SUPPORTED /* Sets the function callbacks for the push reader, and a pointer to a * user-defined structure available to the callback functions. */ -PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr, - png_voidp progressive_ptr, png_progressive_info_ptr info_fn, +PNG_EXPORT(void, png_set_progressive_read_fn, + (png_struct *png_ptr, + void *progressive_ptr, png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn)); /* Returns the user pointer associated with the push read functions */ -PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, - (png_const_structrp png_ptr)); +PNG_EXPORT(void *, png_get_progressive_ptr, + (const png_struct *png_ptr)); /* Function to be called when data becomes available */ -PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr, - png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size)); +PNG_EXPORT(void, png_process_data, + (png_struct *png_ptr, + png_info *info_ptr, png_byte *buffer, size_t buffer_size)); /* 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 @@ -1765,7 +1695,8 @@ 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 * will always return 0. */ -PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save)); +PNG_EXPORT(size_t, png_process_data_pause, + (png_struct *, int save)); /* 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 @@ -1773,48 +1704,53 @@ PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save)); * application must skip than number of bytes of input data and pass the * following data to the next call to png_process_data. */ -PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp)); +PNG_EXPORT(png_uint_32, png_process_data_skip, + (png_struct *)); /* Function that combines rows. 'new_row' is a flag that should come from * the callback and be non-NULL if anything needs to be done; the library * stores its own version of the new data internally and ignores the passed * in value. */ -PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr, - png_bytep old_row, png_const_bytep new_row)); +PNG_EXPORT(void, png_progressive_combine_row, + (const png_struct *png_ptr, + png_byte *old_row, const png_byte *new_row)); #endif /* PROGRESSIVE_READ */ -PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); +PNG_EXPORTA(void *, png_malloc, + (const png_struct *png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); /* Added at libpng version 1.4.0 */ -PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); +PNG_EXPORTA(void *, png_calloc, + (const png_struct *png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); /* Added at libpng version 1.2.4 */ -PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED); +PNG_EXPORTA(void *, png_malloc_warn, + (const png_struct *png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); /* Frees a pointer allocated by png_malloc() */ -PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr)); +PNG_EXPORT(void, png_free, + (const png_struct *png_ptr, void *ptr)); /* Free data that was allocated internally */ -PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_32 free_me, int num)); +PNG_EXPORT(void, png_free_data, + (const png_struct *png_ptr, png_info *info_ptr, + png_uint_32 free_me, int num)); -/* Reassign responsibility for freeing existing data, whether allocated +/* Reassign the responsibility for freeing existing data, whether allocated * by libpng or by the application; this works on the png_info structure passed - * in, it does not change the state for other png_info structures. - * - * It is unlikely that this function works correctly as of 1.6.0 and using it - * may result either in memory leaks or double free of allocated data. + * in, without changing the state for other png_info structures. */ -PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, - png_inforp info_ptr, int freer, png_uint_32 mask)); +PNG_EXPORT(void, png_data_freer, + (const png_struct *png_ptr, png_info *info_ptr, + int freer, png_uint_32 mask)); /* Assignments for png_data_freer */ #define PNG_DESTROY_WILL_FREE_DATA 1 -#define PNG_SET_WILL_FREE_DATA 1 -#define PNG_USER_WILL_FREE_DATA 2 +#define PNG_SET_WILL_FREE_DATA 1 +#define PNG_USER_WILL_FREE_DATA 2 /* Flags for png_ptr->free_me and info_ptr->free_me */ #define PNG_FREE_HIST 0x0008U #define PNG_FREE_ICCP 0x0010U @@ -1829,40 +1765,47 @@ PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr, #define PNG_FREE_PLTE 0x1000U #define PNG_FREE_TRNS 0x2000U #define PNG_FREE_TEXT 0x4000U -#define PNG_FREE_ALL 0x7fffU +#define PNG_FREE_EXIF 0x8000U /* Added at libpng-1.6.31 */ +#define PNG_FREE_ALL 0xffffU #define PNG_FREE_MUL 0x4220U /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */ #ifdef PNG_USER_MEM_SUPPORTED -PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr, - png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED); -PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr, - png_voidp ptr), PNG_DEPRECATED); +PNG_EXPORTA(void *, png_malloc_default, + (const png_struct *png_ptr, png_alloc_size_t size), + PNG_ALLOCATED PNG_DEPRECATED); +PNG_EXPORTA(void, png_free_default, + (const png_struct *png_ptr, void *ptr), + PNG_DEPRECATED); #endif #ifdef PNG_ERROR_TEXT_SUPPORTED /* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr, - png_const_charp error_message), PNG_NORETURN); +PNG_EXPORTA(void, png_error, + (const png_struct *png_ptr, const char *error_message), + PNG_NORETURN); /* The same, but the chunk name is prepended to the error string. */ -PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr, - png_const_charp error_message), PNG_NORETURN); +PNG_EXPORTA(void, png_chunk_error, + (const png_struct *png_ptr, const char *error_message), + PNG_NORETURN); #else /* Fatal error in PNG image of libpng - can't continue */ -PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN); +PNG_EXPORTA(void, png_err, + (const png_struct *png_ptr), + PNG_NORETURN); # define png_error(s1,s2) png_err(s1) # define png_chunk_error(s1,s2) png_err(s1) #endif #ifdef PNG_WARNINGS_SUPPORTED /* Non-fatal error in libpng. Can continue, but may have a problem. */ -PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr, - png_const_charp warning_message)); +PNG_EXPORT(void, png_warning, + (const png_struct *png_ptr, const char *warning_message)); /* Non-fatal error in libpng, chunk name is prepended to message. */ -PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, - png_const_charp warning_message)); +PNG_EXPORT(void, png_chunk_warning, + (const png_struct *png_ptr, const char *warning_message)); #else # define png_warning(s1,s2) ((void)(s1)) # define png_chunk_warning(s1,s2) ((void)(s1)) @@ -1871,17 +1814,17 @@ PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr, #ifdef PNG_BENIGN_ERRORS_SUPPORTED /* Benign error in libpng. Can continue, but may have a problem. * User can choose whether to handle as a fatal error or as a warning. */ -PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr, - png_const_charp warning_message)); +PNG_EXPORT(void, png_benign_error, + (const png_struct *png_ptr, const char *warning_message)); #ifdef PNG_READ_SUPPORTED /* Same, chunk name is prepended to message (only during read) */ -PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr, - png_const_charp warning_message)); +PNG_EXPORT(void, png_chunk_benign_error, + (const png_struct *png_ptr, const char *warning_message)); #endif -PNG_EXPORT(109, void, png_set_benign_errors, - (png_structrp png_ptr, int allowed)); +PNG_EXPORT(void, png_set_benign_errors, + (png_struct *png_ptr, int allowed)); #else # ifdef PNG_ALLOW_BENIGN_ERRORS # define png_benign_error png_warning @@ -1905,313 +1848,460 @@ PNG_EXPORT(109, void, png_set_benign_errors, * png_info_struct. */ /* Returns "flag" if chunk data is valid in info_ptr. */ -PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 flag)); +PNG_EXPORT(png_uint_32, png_get_valid, + (const png_struct *png_ptr, const png_info *info_ptr, png_uint_32 flag)); /* 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_const_inforp info_ptr)); +PNG_EXPORT(size_t, png_get_rowbytes, + (const png_struct *png_ptr, const png_info *info_ptr)); #ifdef PNG_INFO_IMAGE_SUPPORTED /* Returns row_pointers, which is an array of pointers to scanlines that was * returned from png_read_png(). */ -PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); +PNG_EXPORT(png_byte **, png_get_rows, + (const png_struct *png_ptr, const png_info *info_ptr)); /* Set row_pointers, which is an array of pointers to scanlines for use * by png_write_png(). */ -PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr, - png_inforp info_ptr, png_bytepp row_pointers)); +PNG_EXPORT(void, png_set_rows, + (const png_struct *png_ptr, png_info *info_ptr, png_byte **row_pointers)); #endif /* Returns number of color channels in image. */ -PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); +PNG_EXPORT(png_byte, png_get_channels, + (const png_struct *png_ptr, const png_info *info_ptr)); #ifdef PNG_EASY_ACCESS_SUPPORTED /* Returns image width in pixels. */ -PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); +PNG_EXPORT(png_uint_32, png_get_image_width, + (const png_struct *png_ptr, const png_info *info_ptr)); /* Returns image height in pixels. */ -PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); +PNG_EXPORT(png_uint_32, png_get_image_height, + (const png_struct *png_ptr, const png_info *info_ptr)); /* Returns image bit_depth. */ -PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); +PNG_EXPORT(png_byte, png_get_bit_depth, + (const png_struct *png_ptr, const png_info *info_ptr)); /* Returns image color_type. */ -PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); +PNG_EXPORT(png_byte, png_get_color_type, + (const png_struct *png_ptr, const png_info *info_ptr)); /* Returns image filter_type. */ -PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); +PNG_EXPORT(png_byte, png_get_filter_type, + (const png_struct *png_ptr, const png_info *info_ptr)); /* Returns image interlace_type. */ -PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); +PNG_EXPORT(png_byte, png_get_interlace_type, + (const png_struct *png_ptr, const png_info *info_ptr)); /* Returns image compression_type. */ -PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); +PNG_EXPORT(png_byte, png_get_compression_type, + (const png_struct *png_ptr, const png_info *info_ptr)); /* Returns image resolution in pixels per meter, from pHYs chunk data. */ -PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(png_uint_32, png_get_pixels_per_meter, + (const png_struct *png_ptr, const png_info *info_ptr)); +PNG_EXPORT(png_uint_32, png_get_x_pixels_per_meter, + (const png_struct *png_ptr, const png_info *info_ptr)); +PNG_EXPORT(png_uint_32, png_get_y_pixels_per_meter, + (const png_struct *png_ptr, const png_info *info_ptr)); /* Returns pixel aspect ratio, computed from pHYs chunk data. */ -PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) -PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FP_EXPORT(float, png_get_pixel_aspect_ratio, + (const png_struct *png_ptr, const png_info *info_ptr)) +PNG_FIXED_EXPORT(png_fixed_point, png_get_pixel_aspect_ratio_fixed, + (const png_struct *png_ptr, const png_info *info_ptr)) /* Returns image x, y offset in pixels or microns, from oFFs chunk data. */ -PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(128, png_int_32, png_get_x_offset_microns, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); -PNG_EXPORT(129, png_int_32, png_get_y_offset_microns, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(png_int_32, png_get_x_offset_pixels, + (const png_struct *png_ptr, const png_info *info_ptr)); +PNG_EXPORT(png_int_32, png_get_y_offset_pixels, + (const png_struct *png_ptr, const png_info *info_ptr)); +PNG_EXPORT(png_int_32, png_get_x_offset_microns, + (const png_struct *png_ptr, const png_info *info_ptr)); +PNG_EXPORT(png_int_32, png_get_y_offset_microns, + (const png_struct *png_ptr, const png_info *info_ptr)); #endif /* EASY_ACCESS */ #ifdef PNG_READ_SUPPORTED /* Returns pointer to signature string read from PNG header */ -PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr, - png_const_inforp info_ptr)); +PNG_EXPORT(const png_byte *, png_get_signature, + (const png_struct *png_ptr, const png_info *info_ptr)); #endif #ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr, - png_inforp info_ptr, png_color_16p *background)); +PNG_EXPORT(png_uint_32, png_get_bKGD, + (const png_struct *png_ptr, png_info *info_ptr, + png_color_16 **background)); #endif #ifdef PNG_bKGD_SUPPORTED -PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_color_16p background)); +PNG_EXPORT(void, png_set_bKGD, + (const png_struct *png_ptr, png_info *info_ptr, + const png_color_16 *background)); #endif #ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr, - png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x, - double *red_y, double *green_x, double *green_y, double *blue_x, - double *blue_y)) -PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr, - png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z, - double *green_X, double *green_Y, double *green_Z, double *blue_X, - double *blue_Y, double *blue_Z)) -PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, +PNG_FP_EXPORT(png_uint_32, png_get_cHRM, + (const png_struct *png_ptr, const png_info *info_ptr, + double *white_x, double *white_y, + double *red_x, double *red_y, + double *green_x, double *green_y, + double *blue_x, double *blue_y)) +PNG_FP_EXPORT(png_uint_32, png_get_cHRM_XYZ, + (const png_struct *png_ptr, const png_info *info_ptr, + double *red_X, double *red_Y, double *red_Z, + double *green_X, double *green_Y, double *green_Z, + double *blue_X, double *blue_Y, double *blue_Z)) +PNG_FIXED_EXPORT(png_uint_32, png_get_cHRM_fixed, + (const png_struct *png_ptr, const png_info *info_ptr, png_fixed_point *int_white_x, png_fixed_point *int_white_y, png_fixed_point *int_red_x, png_fixed_point *int_red_y, png_fixed_point *int_green_x, png_fixed_point *int_green_y, png_fixed_point *int_blue_x, png_fixed_point *int_blue_y)) -PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, +PNG_FIXED_EXPORT(png_uint_32, png_get_cHRM_XYZ_fixed, + (const png_struct *png_ptr, const png_info *info_ptr, png_fixed_point *int_red_X, png_fixed_point *int_red_Y, - png_fixed_point *int_red_Z, png_fixed_point *int_green_X, - png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, + png_fixed_point *int_red_Z, + png_fixed_point *int_green_X, png_fixed_point *int_green_Y, + png_fixed_point *int_green_Z, png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, png_fixed_point *int_blue_Z)) #endif #ifdef PNG_cHRM_SUPPORTED -PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr, - png_inforp info_ptr, - double white_x, double white_y, double red_x, double red_y, double green_x, - double green_y, double blue_x, double blue_y)) -PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr, - png_inforp info_ptr, double red_X, double red_Y, double red_Z, - double green_X, double green_Y, double green_Z, double blue_X, - double blue_Y, double blue_Z)) -PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, png_fixed_point int_white_x, - png_fixed_point int_white_y, png_fixed_point int_red_x, - png_fixed_point int_red_y, png_fixed_point int_green_x, - png_fixed_point int_green_y, png_fixed_point int_blue_x, - png_fixed_point int_blue_y)) -PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, - png_fixed_point int_red_Z, png_fixed_point int_green_X, - png_fixed_point int_green_Y, png_fixed_point int_green_Z, +PNG_FP_EXPORT(void, png_set_cHRM, + (const png_struct *png_ptr, png_info *info_ptr, + double white_x, double white_y, + double red_x, double red_y, + double green_x, double green_y, + double blue_x, double blue_y)) +PNG_FP_EXPORT(void, png_set_cHRM_XYZ, + (const png_struct *png_ptr, png_info *info_ptr, + double red_X, double red_Y, double red_Z, + double green_X, double green_Y, double green_Z, + double blue_X, double blue_Y, double blue_Z)) +PNG_FIXED_EXPORT(void, png_set_cHRM_fixed, + (const png_struct *png_ptr, png_info *info_ptr, + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, + png_fixed_point int_green_x, png_fixed_point int_green_y, + png_fixed_point int_blue_x, png_fixed_point int_blue_y)) +PNG_FIXED_EXPORT(void, png_set_cHRM_XYZ_fixed, + (const png_struct *png_ptr, png_info *info_ptr, + png_fixed_point int_red_X, png_fixed_point int_red_Y, + png_fixed_point int_red_Z, + png_fixed_point int_green_X, png_fixed_point int_green_Y, + png_fixed_point int_green_Z, png_fixed_point int_blue_X, png_fixed_point int_blue_Y, png_fixed_point int_blue_Z)) #endif -#ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr, - png_const_inforp info_ptr, double *file_gamma)) -PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *int_file_gamma)) +#ifdef PNG_cICP_SUPPORTED +PNG_EXPORT(png_uint_32, png_get_cICP, + (const png_struct *png_ptr, const png_info *info_ptr, + png_byte *colour_primaries, png_byte *transfer_function, + png_byte *matrix_coefficients, png_byte *video_full_range_flag)); +#endif + +#ifdef PNG_cICP_SUPPORTED +PNG_EXPORT(void, png_set_cICP, + (const png_struct *png_ptr, png_info *info_ptr, + png_byte colour_primaries, png_byte transfer_function, + png_byte matrix_coefficients, png_byte video_full_range_flag)); +#endif + +#ifdef PNG_cLLI_SUPPORTED +PNG_FP_EXPORT(png_uint_32, png_get_cLLI, + (const png_struct *png_ptr, const png_info *info_ptr, + double *maximum_content_light_level, + double *maximum_frame_average_light_level)) +PNG_FIXED_EXPORT(png_uint_32, png_get_cLLI_fixed, + (const png_struct *png_ptr, const png_info *info_ptr, + /* The values below are in cd/m2 (nits) and are scaled by 10,000; not + * 100,000 as in the case of png_fixed_point. + */ + png_uint_32 *maximum_content_light_level_scaled_by_10000, + png_uint_32 *maximum_frame_average_light_level_scaled_by_10000)) +#endif + +#ifdef PNG_cLLI_SUPPORTED +PNG_FP_EXPORT(void, png_set_cLLI, + (const png_struct *png_ptr, png_info *info_ptr, + double maximum_content_light_level, + double maximum_frame_average_light_level)) +PNG_FIXED_EXPORT(void, png_set_cLLI_fixed, + (const png_struct *png_ptr, png_info *info_ptr, + /* The values below are in cd/m2 (nits) and are scaled by 10,000; not + * 100,000 as in the case of png_fixed_point. + */ + png_uint_32 maximum_content_light_level_scaled_by_10000, + png_uint_32 maximum_frame_average_light_level_scaled_by_10000)) +#endif + +#ifdef PNG_eXIf_SUPPORTED +PNG_REMOVED(png_uint_32, png_get_eXIf, + (const png_struct *png_ptr, png_info *info_ptr, png_byte **exif), + PNG_DEPRECATED) +PNG_REMOVED(void, png_set_eXIf, + (const png_struct *png_ptr, png_info *info_ptr, png_byte *exif), + PNG_DEPRECATED) + +PNG_EXPORT(png_uint_32, png_get_eXIf_1, + (const png_struct *png_ptr, const png_info *info_ptr, + png_uint_32 *num_exif, png_byte **exif)); +PNG_EXPORT(void, png_set_eXIf_1, + (const png_struct *png_ptr, png_info *info_ptr, + png_uint_32 num_exif, png_byte *exif)); #endif #ifdef PNG_gAMA_SUPPORTED -PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr, - png_inforp info_ptr, double file_gamma)) -PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, png_fixed_point int_file_gamma)) +PNG_FP_EXPORT(png_uint_32, png_get_gAMA, + (const png_struct *png_ptr, const png_info *info_ptr, + double *file_gamma)) +PNG_FIXED_EXPORT(png_uint_32, png_get_gAMA_fixed, + (const png_struct *png_ptr, const png_info *info_ptr, + png_fixed_point *int_file_gamma)) #endif -#ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_16p *hist)); +#ifdef PNG_gAMA_SUPPORTED +PNG_FP_EXPORT(void, png_set_gAMA, + (const png_struct *png_ptr, png_info *info_ptr, + double file_gamma)) +PNG_FIXED_EXPORT(void, png_set_gAMA_fixed, + (const png_struct *png_ptr, png_info *info_ptr, + png_fixed_point int_file_gamma)) #endif #ifdef PNG_hIST_SUPPORTED -PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_uint_16p hist)); +PNG_EXPORT(png_uint_32, png_get_hIST, + (const png_struct *png_ptr, png_info *info_ptr, png_uint_16 **hist)); +PNG_EXPORT(void, png_set_hIST, + (const png_struct *png_ptr, png_info *info_ptr, const png_uint_16 *hist)); +#endif + +PNG_EXPORT(png_uint_32, png_get_IHDR, + (const png_struct *png_ptr, const png_info *info_ptr, + png_uint_32 *width, png_uint_32 *height, + int *bit_depth, int *color_type, + int *interlace_method, int *compression_method, int *filter_method)); + +PNG_EXPORT(void, png_set_IHDR, + (const png_struct *png_ptr, png_info *info_ptr, + png_uint_32 width, png_uint_32 height, + int bit_depth, int color_type, + int interlace_method, int compression_method, int filter_method)); + +#ifdef PNG_mDCV_SUPPORTED +PNG_FP_EXPORT(png_uint_32, png_get_mDCV, + (const png_struct *png_ptr, const png_info *info_ptr, + /* The chromaticities of the mastering display. As cHRM, but independent of + * the encoding endpoints in cHRM, or cICP, or iCCP. These values will + * always be in the range 0 to 1.3107. + */ + double *white_x, double *white_y, + double *red_x, double *red_y, + double *green_x, double *green_y, + double *blue_x, double *blue_y, + /* Mastering display luminance in cd/m2 (nits). */ + double *mastering_display_maximum_luminance, + double *mastering_display_minimum_luminance)) + +PNG_FIXED_EXPORT(png_uint_32, png_get_mDCV_fixed, + (const png_struct *png_ptr, const png_info *info_ptr, + png_fixed_point *int_white_x, png_fixed_point *int_white_y, + png_fixed_point *int_red_x, png_fixed_point *int_red_y, + png_fixed_point *int_green_x, png_fixed_point *int_green_y, + png_fixed_point *int_blue_x, png_fixed_point *int_blue_y, + /* Mastering display luminance in cd/m2 (nits) multiplied (scaled) by + * 10,000. + */ + png_uint_32 *mastering_display_maximum_luminance_scaled_by_10000, + png_uint_32 *mastering_display_minimum_luminance_scaled_by_10000)) +#endif + +#ifdef PNG_mDCV_SUPPORTED +PNG_FP_EXPORT(void, png_set_mDCV, + (const png_struct *png_ptr, png_info *info_ptr, + /* The chromaticities of the mastering display. As cHRM, but independent of + * the encoding endpoints in cHRM, or cICP, or iCCP. + */ + double white_x, double white_y, + double red_x, double red_y, + double green_x, double green_y, + double blue_x, double blue_y, + /* Mastering display luminance in cd/m2 (nits). */ + double mastering_display_maximum_luminance, + double mastering_display_minimum_luminance)) + +PNG_FIXED_EXPORT(void, png_set_mDCV_fixed, + (const png_struct *png_ptr, png_info *info_ptr, + /* The admissible range of these values is not the full range of a PNG + * fixed point value. Negative values cannot be encoded and the maximum + * value is about 1.3 */ + png_fixed_point int_white_x, png_fixed_point int_white_y, + png_fixed_point int_red_x, png_fixed_point int_red_y, + png_fixed_point int_green_x, png_fixed_point int_green_y, + png_fixed_point int_blue_x, png_fixed_point int_blue_y, + /* These are PNG unsigned 4 byte values: 31-bit unsigned values. The MSB + * must be zero. + */ + png_uint_32 mastering_display_maximum_luminance_scaled_by_10000, + png_uint_32 mastering_display_minimum_luminance_scaled_by_10000)) #endif -PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height, - int *bit_depth, int *color_type, int *interlace_method, - int *compression_method, int *filter_method)); - -PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_method, int compression_method, - int filter_method)); - #ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, - int *unit_type)); +PNG_EXPORT(png_uint_32, png_get_oFFs, + (const png_struct *png_ptr, const png_info *info_ptr, + png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)); #endif #ifdef PNG_oFFs_SUPPORTED -PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr, - png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y, - int unit_type)); +PNG_EXPORT(void, png_set_oFFs, + (const png_struct *png_ptr, png_info *info_ptr, + png_int_32 offset_x, png_int_32 offset_y, int unit_type)); #endif #ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr, - png_inforp info_ptr, png_charp *purpose, png_int_32 *X0, - png_int_32 *X1, int *type, int *nparams, png_charp *units, - png_charpp *params)); +PNG_EXPORT(png_uint_32, png_get_pCAL, + (const png_struct *png_ptr, png_info *info_ptr, + char **purpose, png_int_32 *X0, png_int_32 *X1, + int *type, int *nparams, char **units, char ***params)); #endif #ifdef PNG_pCAL_SUPPORTED -PNG_EXPORT(148, void, 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, int nparams, png_const_charp units, png_charpp params)); +PNG_EXPORT(void, png_set_pCAL, + (const png_struct *png_ptr, png_info *info_ptr, + const char *purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, const char *units, char **params)); #endif #ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, - int *unit_type)); +PNG_EXPORT(png_uint_32, png_get_pHYs, + (const png_struct *png_ptr, const png_info *info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); #endif #ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr, - png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type)); +PNG_EXPORT(void, png_set_pHYs, + (const png_struct *png_ptr, png_info *info_ptr, + png_uint_32 res_x, png_uint_32 res_y, int unit_type)); #endif -PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr, - png_inforp info_ptr, png_colorp *palette, int *num_palette)); +PNG_EXPORT(png_uint_32, png_get_PLTE, + (const png_struct *png_ptr, png_info *info_ptr, + png_color **palette, int *num_palette)); -PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr, - png_inforp info_ptr, png_const_colorp palette, int num_palette)); +PNG_EXPORT(void, png_set_PLTE, + (png_struct *png_ptr, png_info *info_ptr, + const png_color *palette, int num_palette)); #ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_color_8p *sig_bit)); +PNG_EXPORT(png_uint_32, png_get_sBIT, + (const png_struct *png_ptr, png_info *info_ptr, + png_color_8 **sig_bit)); #endif #ifdef PNG_sBIT_SUPPORTED -PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_color_8p sig_bit)); +PNG_EXPORT(void, png_set_sBIT, + (const png_struct *png_ptr, png_info *info_ptr, + const png_color_8 *sig_bit)); #endif #ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr, - png_const_inforp info_ptr, int *file_srgb_intent)); +PNG_EXPORT(png_uint_32, png_get_sRGB, + (const png_struct *png_ptr, const png_info *info_ptr, + int *file_srgb_intent)); #endif #ifdef PNG_sRGB_SUPPORTED -PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr, - png_inforp info_ptr, int srgb_intent)); -PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr, - png_inforp info_ptr, int srgb_intent)); +PNG_EXPORT(void, png_set_sRGB, + (const png_struct *png_ptr, png_info *info_ptr, int srgb_intent)); +PNG_EXPORT(void, png_set_sRGB_gAMA_and_cHRM, + (const png_struct *png_ptr, png_info *info_ptr, int srgb_intent)); #endif #ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr, - png_inforp info_ptr, png_charpp name, int *compression_type, - png_bytepp profile, png_uint_32 *proflen)); +PNG_EXPORT(png_uint_32, png_get_iCCP, + (const png_struct *png_ptr, png_info *info_ptr, + char **name, int *compression_type, + png_byte **profile, png_uint_32 *proflen)); #endif #ifdef PNG_iCCP_SUPPORTED -PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_charp name, int compression_type, - png_const_bytep profile, png_uint_32 proflen)); +PNG_EXPORT(void, png_set_iCCP, + (const png_struct *png_ptr, png_info *info_ptr, + const char *name, int compression_type, + const png_byte *profile, png_uint_32 proflen)); #endif #ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_sPLT_tpp entries)); +PNG_EXPORT(int, png_get_sPLT, + (const png_struct *png_ptr, png_info *info_ptr, + png_sPLT_t **entries)); #endif #ifdef PNG_sPLT_SUPPORTED -PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)); +PNG_EXPORT(void, png_set_sPLT, + (const png_struct *png_ptr, png_info *info_ptr, + const png_sPLT_t *entries, int nentries)); #endif #ifdef PNG_TEXT_SUPPORTED /* png_get_text also returns the number of text chunks in *num_text */ -PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr, - png_inforp info_ptr, png_textp *text_ptr, int *num_text)); +PNG_EXPORT(int, png_get_text, + (const png_struct *png_ptr, png_info *info_ptr, + png_text **text_ptr, int *num_text)); #endif /* Note while png_set_text() will accept a structure whose text, - * language, and translated keywords are NULL pointers, the structure + * language, and translated keywords are NULL pointers, the structure * returned by png_get_text will always contain regular * zero-terminated C strings. They might be empty strings but * they will never be NULL pointers. */ #ifdef PNG_TEXT_SUPPORTED -PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_textp text_ptr, int num_text)); +PNG_EXPORT(void, png_set_text, + (const png_struct *png_ptr, png_info *info_ptr, + const png_text *text_ptr, int num_text)); #endif #ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr, - png_inforp info_ptr, png_timep *mod_time)); +PNG_EXPORT(png_uint_32, png_get_tIME, + (const png_struct *png_ptr, png_info *info_ptr, + png_time **mod_time)); #endif #ifdef PNG_tIME_SUPPORTED -PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_timep mod_time)); +PNG_EXPORT(void, png_set_tIME, + (const png_struct *png_ptr, png_info *info_ptr, + const png_time *mod_time)); #endif #ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr, - png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans, - png_color_16p *trans_color)); +PNG_EXPORT(png_uint_32, png_get_tRNS, + (const png_struct *png_ptr, png_info *info_ptr, + png_byte **trans_alpha, int *num_trans, + png_color_16 **trans_color)); #endif #ifdef PNG_tRNS_SUPPORTED -PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr, - png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans, - png_const_color_16p trans_color)); +PNG_EXPORT(void, png_set_tRNS, + (png_struct *png_ptr, png_info *info_ptr, + const png_byte *trans_alpha, int num_trans, + const png_color_16 *trans_color)); #endif #ifdef PNG_sCAL_SUPPORTED -PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, - png_const_inforp info_ptr, int *unit, double *width, double *height)) +PNG_FP_EXPORT(png_uint_32, png_get_sCAL, + (const png_struct *png_ptr, const png_info *info_ptr, + int *unit, double *width, double *height)) #if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ defined(PNG_FLOATING_POINT_SUPPORTED) /* NOTE: this API is currently implemented using floating point arithmetic, @@ -2219,22 +2309,23 @@ PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr, * In any case the range of values supported by png_fixed_point is small and it * is highly recommended that png_get_sCAL_s be used instead. */ -PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, - png_fixed_point *width, png_fixed_point *height)) -#endif -PNG_EXPORT(169, png_uint_32, png_get_sCAL_s, - (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit, - png_charpp swidth, png_charpp sheight)); - -PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr, - png_inforp info_ptr, int unit, double width, double height)) -PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr, - png_inforp info_ptr, int unit, png_fixed_point width, - png_fixed_point height)) -PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, - png_inforp info_ptr, int unit, - png_const_charp swidth, png_const_charp sheight)); +PNG_FIXED_EXPORT(png_uint_32, png_get_sCAL_fixed, + (const png_struct *png_ptr, const png_info *info_ptr, + int *unit, png_fixed_point *width, png_fixed_point *height)) +#endif +PNG_EXPORT(png_uint_32, png_get_sCAL_s, + (const png_struct *png_ptr, const png_info *info_ptr, + int *unit, char **swidth, char **sheight)); + +PNG_FP_EXPORT(void, png_set_sCAL, + (const png_struct *png_ptr, png_info *info_ptr, + int unit, double width, double height)) +PNG_FIXED_EXPORT(void, png_set_sCAL_fixed, + (const png_struct *png_ptr, png_info *info_ptr, + int unit, png_fixed_point width, png_fixed_point height)) +PNG_EXPORT(void, png_set_sCAL_s, + (const png_struct *png_ptr, png_info *info_ptr, + int unit, const char *swidth, const char *sheight)); #endif /* sCAL */ #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED @@ -2269,7 +2360,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 * 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 * 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 @@ -2337,22 +2428,23 @@ PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr, * be processed by libpng. */ #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED -PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr, - int keep, png_const_bytep chunk_list, int num_chunks)); +PNG_EXPORT(void, png_set_keep_unknown_chunks, + (png_struct *png_ptr, + int keep, const png_byte *chunk_list, int num_chunks)); #endif /* HANDLE_AS_UNKNOWN */ /* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned; * the result is therefore true (non-zero) if special handling is required, * false for the default handling. */ -PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr, - png_const_bytep chunk_name)); +PNG_EXPORT(int, png_handle_as_unknown, + (const png_struct *png_ptr, const png_byte *chunk_name)); #endif /* SET_UNKNOWN_CHUNKS */ #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, - png_inforp info_ptr, png_const_unknown_chunkp unknowns, - int num_unknowns)); +PNG_EXPORT(void, png_set_unknown_chunks, + (const png_struct *png_ptr, png_info *info_ptr, + const png_unknown_chunk *unknowns, int num_unknowns)); /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added * unknowns to the location currently stored in the png_struct. This is * invariably the wrong value on write. To fix this call the following API @@ -2362,44 +2454,48 @@ PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr, * the correct thing. */ -PNG_EXPORT(175, void, png_set_unknown_chunk_location, - (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location)); +PNG_EXPORT(void, png_set_unknown_chunk_location, + (const png_struct *png_ptr, png_info *info_ptr, + int chunk, int location)); -PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr, - png_inforp info_ptr, png_unknown_chunkpp entries)); +PNG_EXPORT(int, png_get_unknown_chunks, + (const png_struct *png_ptr, png_info *info_ptr, + png_unknown_chunk **entries)); #endif /* Png_free_data() will turn off the "valid" flag for anything it frees. * If you need to turn it off for a chunk that your application has freed, * you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK); */ -PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr, - png_inforp info_ptr, int mask)); +PNG_EXPORT(void, png_set_invalid, + (const png_struct *png_ptr, png_info *info_ptr, int mask)); #ifdef PNG_INFO_IMAGE_SUPPORTED /* The "params" pointer is currently not used and is for future expansion. */ #ifdef PNG_SEQUENTIAL_READ_SUPPORTED -PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr, - int transforms, png_voidp params)); +PNG_EXPORT(void, png_read_png, + (png_struct *png_ptr, png_info *info_ptr, + int transforms, void *params)); #endif #ifdef PNG_WRITE_SUPPORTED -PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr, - int transforms, png_voidp params)); +PNG_EXPORT(void, png_write_png, + (png_struct *png_ptr, png_info *info_ptr, + int transforms, void *params)); #endif #endif -PNG_EXPORT(180, png_const_charp, png_get_copyright, - (png_const_structrp png_ptr)); -PNG_EXPORT(181, png_const_charp, png_get_header_ver, - (png_const_structrp png_ptr)); -PNG_EXPORT(182, png_const_charp, png_get_header_version, - (png_const_structrp png_ptr)); -PNG_EXPORT(183, png_const_charp, png_get_libpng_ver, - (png_const_structrp png_ptr)); +PNG_EXPORT(const char *, png_get_copyright, + (const png_struct *png_ptr)); +PNG_EXPORT(const char *, png_get_header_ver, + (const png_struct *png_ptr)); +PNG_EXPORT(const char *, png_get_header_version, + (const png_struct *png_ptr)); +PNG_EXPORT(const char *, png_get_libpng_ver, + (const png_struct *png_ptr)); #ifdef PNG_MNG_FEATURES_SUPPORTED -PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, - png_uint_32 mng_features_permitted)); +PNG_EXPORT(png_uint_32, png_permit_mng_features, + (png_struct *png_ptr, png_uint_32 mng_features_permitted)); #endif /* For use in png_set_keep_unknown, added to version 1.2.6 */ @@ -2409,75 +2505,70 @@ PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr, #define PNG_HANDLE_CHUNK_ALWAYS 3 #define PNG_HANDLE_CHUNK_LAST 4 -/* Strip the prepended error numbers ("#nnn ") from error and warning - * messages before passing them to the error or warning handler. - */ -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr, - png_uint_32 strip_mode)); -#endif - /* Added in libpng-1.2.6 */ #ifdef PNG_SET_USER_LIMITS_SUPPORTED -PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr, +PNG_EXPORT(void, png_set_user_limits, + (png_struct *png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max)); -PNG_EXPORT(187, png_uint_32, png_get_user_width_max, - (png_const_structrp png_ptr)); -PNG_EXPORT(188, png_uint_32, png_get_user_height_max, - (png_const_structrp png_ptr)); +PNG_EXPORT(png_uint_32, png_get_user_width_max, + (const png_struct *png_ptr)); +PNG_EXPORT(png_uint_32, png_get_user_height_max, + (const png_struct *png_ptr)); /* Added in libpng-1.4.0 */ -PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr, - png_uint_32 user_chunk_cache_max)); -PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max, - (png_const_structrp png_ptr)); +PNG_EXPORT(void, png_set_chunk_cache_max, + (png_struct *png_ptr, png_uint_32 user_chunk_cache_max)); +PNG_EXPORT(png_uint_32, png_get_chunk_cache_max, + (const png_struct *png_ptr)); /* Added in libpng-1.4.1 */ -PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr, - png_alloc_size_t user_chunk_cache_max)); -PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max, - (png_const_structrp png_ptr)); +PNG_EXPORT(void, png_set_chunk_malloc_max, + (png_struct *png_ptr, png_alloc_size_t user_chunk_cache_max)); +PNG_EXPORT(png_alloc_size_t, png_get_chunk_malloc_max, + (const png_struct *png_ptr)); #endif #if defined(PNG_INCH_CONVERSIONS_SUPPORTED) -PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(png_uint_32, png_get_pixels_per_inch, + (const png_struct *png_ptr, const png_info *info_ptr)); -PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(png_uint_32, png_get_x_pixels_per_inch, + (const png_struct *png_ptr, const png_info *info_ptr)); -PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch, - (png_const_structrp png_ptr, png_const_inforp info_ptr)); +PNG_EXPORT(png_uint_32, png_get_y_pixels_per_inch, + (const png_struct *png_ptr, const png_info *info_ptr)); -PNG_FP_EXPORT(196, float, png_get_x_offset_inches, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FP_EXPORT(float, png_get_x_offset_inches, + (const png_struct *png_ptr, const png_info *info_ptr)) #ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(png_fixed_point, png_get_x_offset_inches_fixed, + (const png_struct *png_ptr, const png_info *info_ptr)) #endif -PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr, - png_const_inforp info_ptr)) +PNG_FP_EXPORT(float, png_get_y_offset_inches, + (const png_struct *png_ptr, const png_info *info_ptr)) #ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */ -PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed, - (png_const_structrp png_ptr, png_const_inforp info_ptr)) +PNG_FIXED_EXPORT(png_fixed_point, png_get_y_offset_inches_fixed, + (const png_struct *png_ptr, const png_info *info_ptr)) #endif # ifdef PNG_pHYs_SUPPORTED -PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr, - png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, - int *unit_type)); +PNG_EXPORT(png_uint_32, png_get_pHYs_dpi, + (const png_struct *png_ptr, const png_info *info_ptr, + png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)); # endif /* pHYs */ #endif /* INCH_CONVERSIONS */ /* Added in libpng-1.4.0 */ #ifdef PNG_IO_STATE_SUPPORTED -PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr)); +PNG_EXPORT(png_uint_32, png_get_io_state, + (const png_struct *png_ptr)); /* Removed from libpng 1.6; use png_get_io_chunk_type. */ -PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr), - PNG_DEPRECATED) +PNG_REMOVED(const png_byte *, png_get_io_chunk_name, + (png_struct *png_ptr), + PNG_DEPRECATED) -PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, - (png_const_structrp png_ptr)); +PNG_EXPORT(png_uint_32, png_get_io_chunk_type, + (const png_struct *png_ptr)); /* The flags returned by png_get_io_state() are the following: */ # define PNG_IO_NONE 0x0000 /* no I/O at this moment */ @@ -2602,21 +2693,26 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type, #endif /* READ_COMPOSITE_NODIV */ #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf)); -PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf)); -PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf)); +PNG_EXPORT(png_uint_32, png_get_uint_32, + (const png_byte *buf)); +PNG_EXPORT(png_uint_16, png_get_uint_16, + (const png_byte *buf)); +PNG_EXPORT(png_int_32, png_get_int_32, + (const png_byte *buf)); #endif -PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr, - png_const_bytep buf)); +PNG_EXPORT(png_uint_32, png_get_uint_31, + (const png_struct *png_ptr, const png_byte *buf)); /* No png_get_int_16 -- may be added if there's a real need for it. */ /* Place a 32-bit number into a buffer in PNG byte order (big-endian). */ #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(205, void, png_save_uint_32, (png_bytep buf, png_uint_32 i)); +PNG_EXPORT(void, png_save_uint_32, + (png_byte *buf, png_uint_32 i)); #endif #ifdef PNG_SAVE_INT_32_SUPPORTED -PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); +PNG_EXPORT(void, png_save_int_32, + (png_byte *buf, png_int_32 i)); #endif /* Place a 16-bit number into a buffer in PNG byte order. @@ -2624,7 +2720,8 @@ PNG_EXPORT(206, void, png_save_int_32, (png_bytep buf, png_int_32 i)); * just to avoid potential problems on pre-ANSI C compilers. */ #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED -PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); +PNG_EXPORT(void, png_save_uint_16, + (png_byte *buf, unsigned int i)); /* No png_save_int_16 -- may be added if there's a real need for it. */ #endif @@ -2670,11 +2767,11 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); #endif #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED -PNG_EXPORT(242, void, png_set_check_for_invalid_index, - (png_structrp png_ptr, int allowed)); +PNG_EXPORT(void, png_set_check_for_invalid_index, + (png_struct *png_ptr, int allowed)); # ifdef PNG_GET_PALETTE_MAX_SUPPORTED -PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, - png_const_infop info_ptr)); +PNG_EXPORT(int, png_get_palette_max, + (const png_struct *png_ptr, const png_info *info_ptr)); # endif #endif /* CHECK_FOR_INVALID_INDEX */ @@ -2688,7 +2785,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 * itself. It allows PNG files to be read into a very limited number of * in-memory bitmap formats or to be written from the same formats. If these - * formats do not accomodate your needs then you can, and should, use the more + * 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 * and a wide variety of sophisticated transformations to those formats as well * as a wide variety of APIs to manipulate ancillary information. @@ -2729,10 +2826,12 @@ PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, #define PNG_IMAGE_VERSION 1 -typedef struct png_control *png_controlp; +typedef struct png_control_def png_control; /* [Opaque] */ +typedef png_control *png_controlp; /* [Deprecated] */ + typedef struct { - png_controlp opaque; /* Initialize to NULL, free with png_image_free */ + png_control *opaque; /* Initialize to NULL, free with png_image_free */ png_uint_32 version; /* Set to PNG_IMAGE_VERSION */ png_uint_32 width; /* Image width in pixels (columns) */ png_uint_32 height; /* Image height in pixels (rows) */ @@ -2766,7 +2865,9 @@ typedef struct png_uint_32 warning_or_error; char message[64]; -} png_image, *png_imagep; +} png_image; + +typedef png_image *png_imagep; /* [Deprecated] */ /* The samples of the image have one to four channels whose components have * original values in the range 0 to 1.0: @@ -2794,7 +2895,7 @@ typedef struct * * When the simplified API needs to convert between sRGB and linear colorspaces, * 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 ) is used, not the gamma=1/2.2 * approximation used elsewhere in libpng. * * When an alpha channel is present it is expected to denote pixel coverage @@ -2849,6 +2950,8 @@ typedef struct # define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */ #endif +#define PNG_FORMAT_FLAG_ASSOCIATED_ALPHA 0x40U /* alpha channel is associated */ + /* Commonly used formats have predefined macros. * * First the single byte (sRGB) formats: @@ -2995,7 +3098,7 @@ typedef struct * 'flags' field of png_image. */ #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. */ @@ -3033,27 +3136,28 @@ typedef struct * --------- * * The png_image passed to the read APIs must have been initialized by setting - * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.) + * the png_control* field 'opaque' to NULL (or, safer, memset the whole thing.) */ #ifdef PNG_STDIO_SUPPORTED -PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image, - const char *file_name)); +PNG_EXPORT(int, png_image_begin_read_from_file, + (png_image *image, const char *file_name)); /* The named file is opened for read and the image header is filled in * from the PNG header in the file. */ -PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image, - FILE* file)); +PNG_EXPORT(int, png_image_begin_read_from_stdio, + (png_image *image, FILE *file)); /* The PNG header is read from the stdio FILE object. */ #endif /* STDIO */ -PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image, - png_const_voidp memory, png_size_t size)); +PNG_EXPORT(int, png_image_begin_read_from_memory, + (png_image *image, const void *memory, size_t size)); /* The PNG header is read from the given memory buffer. */ -PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, - png_const_colorp background, void *buffer, png_int_32 row_stride, - void *colormap)); +PNG_EXPORT(int, png_image_finish_read, + (png_image *image, + const png_color *background, void *buffer, png_int_32 row_stride, + void *colormap)); /* Finish reading the image into the supplied buffer and clean up the * png_image structure. * @@ -3086,7 +3190,8 @@ PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image, * written to the colormap; this may be less than the original value. */ -PNG_EXPORT(238, void, png_image_free, (png_imagep image)); +PNG_EXPORT(void, png_image_free, + (png_image *image)); /* Free any data allocated by libpng in image->opaque, setting the pointer to * NULL. May be called at any time after the structure is initialized. */ @@ -3110,15 +3215,17 @@ PNG_EXPORT(238, void, png_image_free, (png_imagep image)); * colormap_entries: set to the number of entries in the color-map (0 to 256) */ #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED -PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image, - const char *file, int convert_to_8bit, const void *buffer, - png_int_32 row_stride, const void *colormap)); +PNG_EXPORT(int, png_image_write_to_file, + (png_image *image, + const char *file, int convert_to_8bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); /* Write the image to the named file. */ -PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, - int convert_to_8_bit, const void *buffer, png_int_32 row_stride, - const void *colormap)); - /* Write the image to the given (FILE*). */ +PNG_EXPORT(int, png_image_write_to_stdio, + (png_image *image, + FILE *file, int convert_to_8_bit, const void *buffer, + png_int_32 row_stride, const void *colormap)); + /* Write the image to the given FILE object. */ #endif /* SIMPLIFIED_WRITE_STDIO */ /* With all write APIs if image is in one of the linear formats with 16-bit @@ -3142,9 +3249,10 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, * 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)); +PNG_EXPORT(int, png_image_write_to_memory, + (png_image *image, + void *memory, png_alloc_size_t *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. @@ -3161,7 +3269,7 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, * than or equal to the original value. * * If the function returns false and *memory_bytes was not changed an error - * occured during write. If *memory_bytes was changed, or is not 0 if + * 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. @@ -3245,127 +3353,152 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory, * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given * by the PNG_OPTION_ defines below. * - * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions, - * 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 - * the capabilities in an OS specific way. Such capabilities are - * listed here when libpng has support for them and must be turned - * ON by the application if present. + * HARDWARE: [[changed in libpng 1.8]] + * Hardware options are now controlled globally to be 'on' or 'off'. + * For backward compatibility the original options are defined as + * the 'new' hardware option. libpng can be compiled without + * hardware support (check PNG_TARGET_SPECIFIC_CODE_SUPPORTED and + * the documentation in pngtarget.h). * * SOFTWARE: sometimes software optimizations actually result in performance * decrease on some architectures or systems, or with some sets of * PNG images. 'Software' options allow such optimizations to be * selected at run time. + * + * The initial setting for HARDWARE is determined by whether or not any + * hardware-specific optimizations are available; the setting will be "ON" if + * so otherwise it will be UNSET. + * + * the option starts of UNSET and this is treated as OFF. */ -#ifdef PNG_SET_OPTION_SUPPORTED -#ifdef PNG_ARM_NEON_API_SUPPORTED -# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */ -#endif -#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */ -#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */ -#ifdef PNG_MIPS_MSA_API_SUPPORTED -# define PNG_MIPS_MSA 6 /* HARDWARE: MIPS Msa SIMD instructions supported */ +#define PNG_SET_OPTION_SUPPORTED + +/* HARDWARE: disable cpu specific code */ +#define PNG_TARGET_SPECIFIC_CODE 0 + +/* HARDWARE: compatibility */ +#define PNG_ARM_NEON 0 + +/* HARDWARE: compatibility */ +#define PNG_MIPS_MSA 0 + +/* HARDWARE: compatibility */ +#define PNG_POWERPC_VSX 0 + +/* HARDWARE: compatibility */ +#define PNG_RISCV_RVV 0 + +/* HARDWARE: MIPS: chose MMI over MSA */ +#define PNG_MIPS_MMI 2 + +/* SOFTWARE: Force maximum window */ +#define PNG_MAXIMUM_INFLATE_WINDOW 4 + +/* SOFTWARE: Check ICC profile for sRGB */ +#define PNG_SKIP_sRGB_CHECK_PROFILE 6 + +/* SOFTWARE: Disable Adler32 check on IDAT */ +#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED + /* This has to be disabled in some builds because of the lack of + * functionality in zlib. Check the _SUPPORTED macro. + */ +# define PNG_IGNORE_ADLER32 8 #endif -#define PNG_OPTION_NEXT 8 /* Next option - numbers must be even */ + +#define PNG_OPTION_NEXT 10 /* 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 as above */ #define PNG_OPTION_INVALID 1 /* Option number out of range */ #define PNG_OPTION_OFF 2 #define PNG_OPTION_ON 3 -PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option, +PNG_EXPORT(int, png_set_option, (png_struct *png_ptr, int option, int onoff)); -#endif /* SET_OPTION */ /******************************************************************************* * END OF HARDWARE AND SOFTWARE OPTIONS ******************************************************************************/ #ifdef PNG_APNG_SUPPORTED -PNG_EXPORT(246, png_uint_32, png_get_acTL, (png_structp png_ptr, - png_infop info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays)); - -PNG_EXPORT(247, png_uint_32, png_set_acTL, (png_structp png_ptr, - png_infop info_ptr, png_uint_32 num_frames, png_uint_32 num_plays)); - -PNG_EXPORT(248, png_uint_32, png_get_num_frames, (png_structp png_ptr, - png_infop info_ptr)); - -PNG_EXPORT(249, png_uint_32, png_get_num_plays, (png_structp png_ptr, - png_infop info_ptr)); - -PNG_EXPORT(250, png_uint_32, png_get_next_frame_fcTL, - (png_structp png_ptr, png_infop info_ptr, png_uint_32 *width, - png_uint_32 *height, png_uint_32 *x_offset, png_uint_32 *y_offset, - png_uint_16 *delay_num, png_uint_16 *delay_den, png_byte *dispose_op, - png_byte *blend_op)); - -PNG_EXPORT(251, png_uint_32, png_set_next_frame_fcTL, - (png_structp png_ptr, png_infop info_ptr, png_uint_32 width, - png_uint_32 height, png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, - png_byte blend_op)); - -PNG_EXPORT(252, png_uint_32, png_get_next_frame_width, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(253, png_uint_32, png_get_next_frame_height, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(254, png_uint_32, png_get_next_frame_x_offset, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(255, png_uint_32, png_get_next_frame_y_offset, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(256, png_uint_16, png_get_next_frame_delay_num, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(257, png_uint_16, png_get_next_frame_delay_den, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(258, png_byte, png_get_next_frame_dispose_op, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(259, png_byte, png_get_next_frame_blend_op, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(260, png_byte, png_get_first_frame_is_hidden, - (png_structp png_ptr, png_infop info_ptr)); -PNG_EXPORT(261, png_uint_32, png_set_first_frame_is_hidden, - (png_structp png_ptr, png_infop info_ptr, png_byte is_hidden)); +PNG_EXPORT(png_uint_32, png_get_acTL, + (png_struct *png_ptr, png_info *info_ptr, + png_uint_32 *num_frames, png_uint_32 *num_plays)); + +PNG_EXPORT(png_uint_32, png_set_acTL, + (png_struct *png_ptr, png_info *info_ptr, + png_uint_32 num_frames, png_uint_32 num_plays)); + +PNG_EXPORT(png_uint_32, png_get_num_frames, + (png_struct *png_ptr, png_info *info_ptr)); + +PNG_EXPORT(png_uint_32, png_get_num_plays, + (png_struct *png_ptr, png_info *info_ptr)); + +PNG_EXPORT(png_uint_32, png_get_next_frame_fcTL, + (png_struct *png_ptr, png_info *info_ptr, + png_uint_32 *width, png_uint_32 *height, + png_uint_32 *x_offset, png_uint_32 *y_offset, + png_uint_16 *delay_num, png_uint_16 *delay_den, + png_byte *dispose_op, png_byte *blend_op)); + +PNG_EXPORT(png_uint_32, png_set_next_frame_fcTL, + (png_struct *png_ptr, png_info *info_ptr, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op)); + +PNG_EXPORT(png_uint_32, png_get_next_frame_width, + (png_struct *png_ptr, png_info *info_ptr)); +PNG_EXPORT(png_uint_32, png_get_next_frame_height, + (png_struct *png_ptr, png_info *info_ptr)); +PNG_EXPORT(png_uint_32, png_get_next_frame_x_offset, + (png_struct *png_ptr, png_info *info_ptr)); +PNG_EXPORT(png_uint_32, png_get_next_frame_y_offset, + (png_struct *png_ptr, png_info *info_ptr)); +PNG_EXPORT(png_uint_16, png_get_next_frame_delay_num, + (png_struct *png_ptr, png_info *info_ptr)); +PNG_EXPORT(png_uint_16, png_get_next_frame_delay_den, + (png_struct *png_ptr, png_info *info_ptr)); +PNG_EXPORT(png_byte, png_get_next_frame_dispose_op, + (png_struct *png_ptr, png_info *info_ptr)); +PNG_EXPORT(png_byte, png_get_next_frame_blend_op, + (png_struct *png_ptr, png_info *info_ptr)); +PNG_EXPORT(png_byte, png_get_first_frame_is_hidden, + (png_struct *png_ptr, png_info *info_ptr)); +PNG_EXPORT(png_uint_32, png_set_first_frame_is_hidden, + (png_struct *png_ptr, png_info *info_ptr, png_byte is_hidden)); #ifdef PNG_READ_APNG_SUPPORTED -PNG_EXPORT(262, void, png_read_frame_head, (png_structp png_ptr, - png_infop info_ptr)); +PNG_EXPORT(void, png_read_frame_head, + (png_struct *png_ptr, png_info *info_ptr)); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_EXPORT(263, void, png_set_progressive_frame_fn, (png_structp png_ptr, - png_progressive_frame_ptr frame_info_fn, - png_progressive_frame_ptr frame_end_fn)); -#endif /* PROGRESSIVE_READ */ -#endif /* READ_APNG */ +PNG_EXPORT(void, png_set_progressive_frame_fn, + (png_struct *png_ptr, + png_progressive_frame_ptr frame_info_fn, + png_progressive_frame_ptr frame_end_fn)); +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ +#endif /* PNG_READ_APNG_SUPPORTED */ #ifdef PNG_WRITE_APNG_SUPPORTED -PNG_EXPORT(264, void, png_write_frame_head, (png_structp png_ptr, - png_infop info_ptr, png_bytepp row_pointers, - png_uint_32 width, png_uint_32 height, - png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, - png_byte blend_op)); - -PNG_EXPORT(265, void, png_write_frame_tail, (png_structp png_ptr, - png_infop info_ptr)); -#endif /* WRITE_APNG */ -#endif /* APNG */ +PNG_EXPORT(void, png_write_frame_head, + (png_struct *png_ptr, png_info *info_ptr, + png_byte **row_pointers, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op)); + +PNG_EXPORT(void, png_write_frame_tail, + (png_struct *png_ptr, png_info *info_ptr)); +#endif /* PNG_WRITE_APNG_SUPPORTED */ +#endif /* PNG_APNG_SUPPORTED */ /* Maintainer: Put new public prototypes here ^, in libpng.3, in project * defs, and in scripts/symbols.def. */ -/* The last ordinal number (this is the *last* one already used; the next - * one to use is one more than this.) - */ -#ifdef PNG_EXPORT_LAST_ORDINAL -#ifdef PNG_APNG_SUPPORTED - PNG_EXPORT_LAST_ORDINAL(265); -#else - PNG_EXPORT_LAST_ORDINAL(245); -#endif /* APNG */ -#endif - #ifdef __cplusplus } #endif diff --git a/media/libpng/pngbar.jpg b/media/libpng/pngbar.jpg new file mode 100644 index 0000000000..70ba8d817c Binary files /dev/null and b/media/libpng/pngbar.jpg differ diff --git a/media/libpng/pngbar.png b/media/libpng/pngbar.png new file mode 100644 index 0000000000..49798c8ed9 Binary files /dev/null and b/media/libpng/pngbar.png differ diff --git a/media/libpng/pngconf.h b/media/libpng/pngconf.h index 5c891eb8b8..7b224c0894 100644 --- a/media/libpng/pngconf.h +++ b/media/libpng/pngconf.h @@ -1,11 +1,11 @@ - -/* pngconf.h - machine configurable file for libpng +/* pngconf.h - machine-configurable file for libpng * - * libpng version 1.6.26, October 20, 2016 + * libpng version 1.8.0.git * - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -57,14 +57,13 @@ #endif /* PNG_BUILDING_SYMBOL_TABLE */ -/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using - * PNG_NO_CONST; this is no longer supported except for data declarations which - * apparently still cause problems in 2011 on some compilers. +/* Prior to 1.6.0, it was possible to turn off 'const' in declarations, + * using PNG_NO_CONST. This is no longer supported. */ #define PNG_CONST const /* backward compatibility only */ -/* This controls optimization of the reading of 16-bit and 32-bit values - * from PNG files. It can be set on a per-app-file basis - it +/* This controls optimization of the reading of 16-bit and 32-bit + * 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. * The library builder sets the default; if read functions are not * built into the library the macro implementation is forced on. @@ -88,52 +87,26 @@ /* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect * against legacy (pre ISOC90) compilers that did not understand function - * prototypes. It is not required for modern C compilers. + * prototypes. [Deprecated.] */ #ifndef PNGARG # define PNGARG(arglist) arglist #endif -/* Function calling conventions. - * ============================= - * Normally it is not necessary to specify to the compiler how to call - * a function - it just does it - however on x86 systems derived from - * Microsoft and Borland C compilers ('IBM PC', 'DOS', 'Windows' systems - * and some others) there are multiple ways to call a function and the - * default can be changed on the compiler command line. For this reason - * libpng specifies the calling convention of every exported function and - * every function called via a user supplied function pointer. This is - * done in this file by defining the following macros: - * - * PNGAPI Calling convention for exported functions. - * PNGCBAPI Calling convention for user provided (callback) functions. - * PNGCAPI Calling convention used by the ANSI-C library (required - * for longjmp callbacks and sometimes used internally to - * specify the calling convention for zlib). - * - * These macros should never be overridden. If it is necessary to - * change calling convention in a private build this can be done - * by setting PNG_API_RULE (which defaults to 0) to one of the values - * below to select the correct 'API' variants. - * - * PNG_API_RULE=0 Use PNGCAPI - the 'C' calling convention - throughout. - * This is correct in every known environment. - * PNG_API_RULE=1 Use the operating system convention for PNGAPI and - * the 'C' calling convention (from PNGCAPI) for - * callbacks (PNGCBAPI). This is no longer required - * in any known environment - if it has to be used - * please post an explanation of the problem to the - * libpng mailing list. - * - * These cases only differ if the operating system does not use the C - * calling convention, at present this just means the above cases - * (x86 DOS/Windows sytems) and, even then, this does not apply to - * Cygwin running on those systems. - * - * Note that the value must be defined in pnglibconf.h so that what - * the application uses to call the library matches the conventions - * set when building the library. +/* The PNGAPI, PNGCAPI and PNGCBAPI macros were used in versions of libpng + * prior to 1.8.0 to allow the use of custom calling conventions on x86 systems + * like DOS, OS/2 and Windows, for interoperability with non-C compilers like + * the pre-Delphi Borland Pascal and the pre-.NET Visual Basic. [Deprecated.] */ +#ifndef PNGCAPI +# define PNGCAPI +#endif +#ifndef PNGCBAPI +# define PNGCBAPI PNGCAPI +#endif +#ifndef PNGAPI +# define PNGAPI PNGCAPI +#endif /* Symbol export * ============= @@ -176,90 +149,15 @@ * ========================== * This code is used at build time to find PNG_IMPEXP, the API settings * and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL - * import processing is possible. On Windows systems it also sets - * compiler-specific macros to the values required to change the calling - * conventions of the various functions. + * import processing is possible. */ -#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\ - defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) - /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or - * MinGW on any architecture currently supported by Windows. Also includes - * Watcom builds but these need special treatment because they are not - * compatible with GCC or Visual C because of different calling conventions. - */ -# if PNG_API_RULE == 2 - /* If this line results in an error, either because __watcall is not - * understood or because of a redefine just below you cannot use *this* - * build of the library with the compiler you are using. *This* build was - * build using Watcom and applications must also be built using Watcom! - */ -# define PNGCAPI __watcall -# endif - -# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800)) -# define PNGCAPI __cdecl -# if PNG_API_RULE == 1 - /* If this line results in an error __stdcall is not understood and - * PNG_API_RULE should not have been set to '1'. - */ -# define PNGAPI __stdcall -# endif -# else - /* An older compiler, or one not detected (erroneously) above, - * if necessary override on the command line to get the correct - * variants for the compiler. - */ -# ifndef PNGCAPI -# define PNGCAPI _cdecl -# endif -# if PNG_API_RULE == 1 && !defined(PNGAPI) -# define PNGAPI _stdcall -# endif -# endif /* compiler/api */ - - /* NOTE: PNGCBAPI always defaults to PNGCAPI. */ - -# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD) -# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed" +#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || \ + defined(__CYGWIN__) +# define PNG_DLL_EXPORT __declspec(dllexport) +# ifndef PNG_DLL_IMPORT +# define PNG_DLL_IMPORT __declspec(dllimport) # endif - -# if (defined(_MSC_VER) && _MSC_VER < 800) ||\ - (defined(__BORLANDC__) && __BORLANDC__ < 0x500) - /* older Borland and MSC - * compilers used '__export' and required this to be after - * the type. - */ -# ifndef PNG_EXPORT_TYPE -# define PNG_EXPORT_TYPE(type) type PNG_IMPEXP -# endif -# define PNG_DLL_EXPORT __export -# else /* newer compiler */ -# define PNG_DLL_EXPORT __declspec(dllexport) -# ifndef PNG_DLL_IMPORT -# define PNG_DLL_IMPORT __declspec(dllimport) -# endif -# endif /* compiler */ - -#else /* !Windows */ -# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__) -# define PNGAPI _System -# else /* !Windows/x86 && !OS/2 */ - /* Use the defaults, or define PNG*API on the command line (but - * this will have to be done for every compile!) - */ -# endif /* other system, !OS/2 */ -#endif /* !Windows/x86 */ - -/* Now do all the defaulting . */ -#ifndef PNGCAPI -# define PNGCAPI -#endif -#ifndef PNGCBAPI -# define PNGCBAPI PNGCAPI -#endif -#ifndef PNGAPI -# define PNGAPI PNGCAPI -#endif +#endif /* Windows */ /* PNG_IMPEXP may be set on the compilation system command line or (if not set) * then in an internal header file when building the library, otherwise (when @@ -291,14 +189,9 @@ # define PNG_EXPORT_TYPE(type) PNG_IMPEXP type #endif - /* The ordinal value is only relevant when preprocessing png.h for symbol - * table entries, so we discard it here. See the .dfn files in the - * scripts directory. - */ - #ifndef PNG_EXPORTA -# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ - PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ +# define PNG_EXPORTA(type, name, args, attributes) \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (name), args, \ PNG_LINKAGE_API attributes) #endif @@ -307,16 +200,15 @@ */ #define PNG_EMPTY /*empty list*/ -#define PNG_EXPORT(ordinal, type, name, args) \ - PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) +#define PNG_EXPORT(type, name, args) PNG_EXPORTA(type, name, args, PNG_EMPTY) /* Use PNG_REMOVED to comment out a removed interface. */ #ifndef PNG_REMOVED -# define PNG_REMOVED(ordinal, type, name, args, attributes) +# define PNG_REMOVED(type, name, args, attributes) #endif #ifndef PNG_CALLBACK -# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +# define PNG_CALLBACK(type, name, args) type (name) args #endif /* Support for compiler specific function attributes. These are used @@ -447,18 +339,16 @@ #ifndef PNG_FP_EXPORT /* A floating point API. */ # ifdef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FP_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args); +# define PNG_FP_EXPORT(type, name, args) PNG_EXPORT(type, name, args); # else /* No floating point APIs */ -# define PNG_FP_EXPORT(ordinal, type, name, args) +# define PNG_FP_EXPORT(type, name, args) # endif #endif #ifndef PNG_FIXED_EXPORT /* A fixed point API. */ # ifdef PNG_FIXED_POINT_SUPPORTED -# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ - PNG_EXPORT(ordinal, type, name, args); +# define PNG_FIXED_EXPORT(type, name, args) PNG_EXPORT(type, name, args); # else /* No fixed point APIs */ -# define PNG_FIXED_EXPORT(ordinal, type, name, args) +# define PNG_FIXED_EXPORT(type, name, args) # endif #endif @@ -480,7 +370,7 @@ #if CHAR_BIT == 8 && UCHAR_MAX == 255 typedef unsigned char png_byte; #else -# error "libpng requires 8-bit bytes" +# error libpng requires 8-bit bytes #endif #if INT_MIN == -32768 && INT_MAX == 32767 @@ -488,7 +378,7 @@ #elif SHRT_MIN == -32768 && SHRT_MAX == 32767 typedef short png_int_16; #else -# error "libpng requires a signed 16-bit type" +# error libpng requires a signed 16-bit integer type #endif #if UINT_MAX == 65535 @@ -496,7 +386,7 @@ #elif USHRT_MAX == 65535 typedef unsigned short png_uint_16; #else -# error "libpng requires an unsigned 16-bit type" +# error libpng requires an unsigned 16-bit integer type #endif #if INT_MIN < -2147483646 && INT_MAX > 2147483646 @@ -504,7 +394,7 @@ #elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 typedef long int png_int_32; #else -# error "libpng requires a signed 32-bit (or more) type" +# error libpng requires a signed 32-bit (or longer) integer type #endif #if UINT_MAX > 4294967294U @@ -512,11 +402,13 @@ #elif ULONG_MAX > 4294967294U typedef unsigned long int png_uint_32; #else -# error "libpng requires an unsigned 32-bit (or more) type" +# error libpng requires an unsigned 32-bit (or longer) integer type #endif -/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, - * requires an ISOC90 compiler and relies on consistent behavior of sizeof. +/* Prior to 1.6.0, it was possible to disable the use of size_t and ptrdiff_t. + * 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 ptrdiff_t png_ptrdiff_t; @@ -537,13 +429,12 @@ typedef ptrdiff_t png_ptrdiff_t; # endif #endif -/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no - * smaller than png_uint_32. Casts from png_size_t or png_uint_32 to - * png_alloc_size_t are not necessary; in fact, it is recommended not to use - * them at all so that the compiler can complain when something turns out to be - * problematic. +/* png_alloc_size_t is guaranteed to be no smaller than size_t, and no smaller + * than png_uint_32. Casts from size_t or png_uint_32 to png_alloc_size_t are + * not necessary; in fact, it is recommended not to use them at all, so that + * the compiler can complain when something turns out to be 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 * encounter practical situations that require such conversions. * @@ -553,7 +444,7 @@ typedef ptrdiff_t png_ptrdiff_t; #ifdef PNG_SMALL_SIZE_T typedef png_uint_32 png_alloc_size_t; #else - typedef png_size_t png_alloc_size_t; + typedef size_t png_alloc_size_t; #endif /* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler @@ -572,50 +463,57 @@ typedef ptrdiff_t png_ptrdiff_t; */ typedef png_int_32 png_fixed_point; -/* Add typedefs for pointers */ -typedef void * png_voidp; -typedef const void * png_const_voidp; -typedef png_byte * png_bytep; -typedef const png_byte * png_const_bytep; -typedef png_uint_32 * png_uint_32p; -typedef const png_uint_32 * png_const_uint_32p; -typedef png_int_32 * png_int_32p; -typedef const png_int_32 * png_const_int_32p; -typedef png_uint_16 * png_uint_16p; -typedef const png_uint_16 * png_const_uint_16p; -typedef png_int_16 * png_int_16p; -typedef const png_int_16 * png_const_int_16p; -typedef char * png_charp; -typedef const char * png_const_charp; -typedef png_fixed_point * png_fixed_point_p; -typedef const png_fixed_point * png_const_fixed_point_p; -typedef png_size_t * png_size_tp; -typedef const png_size_t * png_const_size_tp; - -#ifdef PNG_STDIO_SUPPORTED -typedef FILE * png_FILE_p; -#endif +/* [Deprecated] */ +typedef void *png_voidp; +typedef const void *png_const_voidp; +typedef png_byte *png_bytep; +typedef const png_byte *png_const_bytep; +typedef png_uint_32 *png_uint_32p; +typedef const png_uint_32 *png_const_uint_32p; +typedef png_int_32 *png_int_32p; +typedef const png_int_32 *png_const_int_32p; +typedef png_uint_16 *png_uint_16p; +typedef const png_uint_16 *png_const_uint_16p; +typedef png_int_16 *png_int_16p; +typedef const png_int_16 *png_const_int_16p; +typedef char *png_charp; +typedef const char *png_const_charp; +typedef png_fixed_point *png_fixed_point_p; +typedef const png_fixed_point *png_const_fixed_point_p; +typedef size_t *png_size_tp; +typedef const size_t *png_const_size_tp; #ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double * png_doublep; -typedef const double * png_const_doublep; -#endif - -/* Pointers to pointers; i.e. arrays */ -typedef png_byte * * png_bytepp; -typedef png_uint_32 * * png_uint_32pp; -typedef png_int_32 * * png_int_32pp; -typedef png_uint_16 * * png_uint_16pp; -typedef png_int_16 * * png_int_16pp; -typedef const char * * png_const_charpp; -typedef char * * png_charpp; -typedef png_fixed_point * * png_fixed_point_pp; +/* [Deprecated] */ +typedef double *png_doublep; +typedef const double *png_const_doublep; +#endif + +/* [Deprecated] */ +typedef png_byte **png_bytepp; +typedef png_uint_32 **png_uint_32pp; +typedef png_int_32 **png_int_32pp; +typedef png_uint_16 **png_uint_16pp; +typedef png_int_16 **png_int_16pp; +typedef const char **png_const_charpp; +typedef char **png_charpp; +typedef png_fixed_point **png_fixed_point_pp; #ifdef PNG_FLOATING_POINT_SUPPORTED -typedef double * * png_doublepp; +typedef double **png_doublepp; #endif -/* Pointers to pointers to pointers; i.e., pointer to array */ -typedef char * * * png_charppp; +/* [Deprecated] */ +typedef char ***png_charppp; + +#ifdef PNG_STDIO_SUPPORTED +/* With PNG_STDIO_SUPPORTED it was possible to use I/O streams that were + * not necessarily stdio FILE streams, to allow building Windows applications + * before Win32 and Windows CE applications before WinCE 3.0, but that kind + * of support has long been discontinued. + */ +/* [Deprecated] */ +typedef FILE *png_FILE_p; +#endif #endif /* PNG_BUILDING_SYMBOL_TABLE */ diff --git a/media/libpng/pngdebug.h b/media/libpng/pngdebug.h index 15a7ed0c95..18bd7628d9 100644 --- a/media/libpng/pngdebug.h +++ b/media/libpng/pngdebug.h @@ -1,16 +1,19 @@ - -/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c +/* pngdebug.h - internal debugging macros for libpng * - * Last changed in libpng 1.6.8 [December 19, 2013] + * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ +#ifndef PNGPRIV_H +# error This file must not be included by applications; please include +#endif + /* Define PNG_DEBUG at compile time for debugging information. Higher * numbers for PNG_DEBUG mean more debugging information. This has * only been added since version 0.95 so it is not implemented throughout @@ -33,20 +36,6 @@ */ #ifndef PNGDEBUG_H #define PNGDEBUG_H -/* These settings control the formatting of messages in png.c and pngerror.c */ -/* Moved to pngdebug.h at 1.5.0 */ -# ifndef PNG_LITERAL_SHARP -# define PNG_LITERAL_SHARP 0x23 -# endif -# ifndef PNG_LITERAL_LEFT_SQUARE_BRACKET -# define PNG_LITERAL_LEFT_SQUARE_BRACKET 0x5b -# endif -# ifndef PNG_LITERAL_RIGHT_SQUARE_BRACKET -# define PNG_LITERAL_RIGHT_SQUARE_BRACKET 0x5d -# endif -# ifndef PNG_STRING_NEWLINE -# define PNG_STRING_NEWLINE "\n" -# endif #ifdef PNG_DEBUG # if (PNG_DEBUG > 0) @@ -57,14 +46,14 @@ # define _DEBUG # endif # ifndef png_debug -# define png_debug(l,m) _RPT0(_CRT_WARN,m PNG_STRING_NEWLINE) +# define png_debug(l,m) _RPT0(_CRT_WARN,m "\n") # endif # ifndef png_debug1 -# define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m PNG_STRING_NEWLINE,p1) +# define png_debug1(l,m,p1) _RPT1(_CRT_WARN,m "\n",p1) # endif # ifndef png_debug2 # define png_debug2(l,m,p1,p2) \ - _RPT2(_CRT_WARN,m PNG_STRING_NEWLINE,p1,p2) + _RPT2(_CRT_WARN,m "\n",p1,p2) # endif # endif # else /* PNG_DEBUG_FILE || !_MSC_VER */ @@ -81,7 +70,7 @@ # define png_debug(l,m) \ do { \ int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \ + fprintf(PNG_DEBUG_FILE,"%s" m "\n",(num_tabs==1 ? " " : \ (num_tabs==2 ? " " : (num_tabs>2 ? " " : "")))); \ } while (0) # endif @@ -89,7 +78,7 @@ # define png_debug1(l,m,p1) \ do { \ int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \ + fprintf(PNG_DEBUG_FILE,"%s" m "\n",(num_tabs==1 ? " " : \ (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1); \ } while (0) # endif @@ -97,7 +86,7 @@ # define png_debug2(l,m,p1,p2) \ do { \ int num_tabs=l; \ - fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \ + fprintf(PNG_DEBUG_FILE,"%s" m "\n",(num_tabs==1 ? " " : \ (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1,p2);\ } while (0) # endif @@ -107,9 +96,9 @@ do { \ int num_tabs=l; \ char format[256]; \ - snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + snprintf(format,256,"%s%s\n",(num_tabs==1 ? "\t" : \ (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ - m,PNG_STRING_NEWLINE); \ + m); \ fprintf(PNG_DEBUG_FILE,format); \ } while (0) # endif @@ -118,9 +107,9 @@ do { \ int num_tabs=l; \ char format[256]; \ - snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + snprintf(format,256,"%s%s\n",(num_tabs==1 ? "\t" : \ (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ - m,PNG_STRING_NEWLINE); \ + m); \ fprintf(PNG_DEBUG_FILE,format,p1); \ } while (0) # endif @@ -129,9 +118,9 @@ do { \ int num_tabs=l; \ char format[256]; \ - snprintf(format,256,"%s%s%s",(num_tabs==1 ? "\t" : \ + snprintf(format,256,"%s%s\n",(num_tabs==1 ? "\t" : \ (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))), \ - m,PNG_STRING_NEWLINE); \ + m); \ fprintf(PNG_DEBUG_FILE,format,p1,p2); \ } while (0) # endif diff --git a/media/libpng/pngerror.c b/media/libpng/pngerror.c index 00d76f7c05..63527fc787 100644 --- a/media/libpng/pngerror.c +++ b/media/libpng/pngerror.c @@ -1,10 +1,9 @@ - -/* pngerror.c - stub functions for i/o and memory allocation +/* pngerror.c - functions for warnings and error handling * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2025 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -20,13 +19,26 @@ #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr, - png_const_charp error_message)),PNG_NORETURN); +#define png_isalpha(c) \ + (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z')) + +#if defined(PNG_WARNINGS_SUPPORTED) || \ + (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)) || \ + defined(PNG_TIME_RFC1123_SUPPORTED) +static const char png_digits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F' +}; +#endif + +static PNG_FUNCTION(void /* PRIVATE */, +png_default_error,(const png_struct *png_ptr, const char *error_message), + PNG_NORETURN); #ifdef PNG_WARNINGS_SUPPORTED static void /* PRIVATE */ -png_default_warning PNGARG((png_const_structrp png_ptr, - png_const_charp warning_message)); +png_default_warning(const png_struct *png_ptr, + const char *warning_message); #endif /* WARNINGS */ /* This function is called whenever there is a fatal error. This function @@ -35,52 +47,12 @@ png_default_warning PNGARG((png_const_structrp png_ptr, * to replace the error function at run-time. */ #ifdef PNG_ERROR_TEXT_SUPPORTED -PNG_FUNCTION(void,PNGAPI -png_error,(png_const_structrp png_ptr, png_const_charp error_message), +PNG_FUNCTION(void, +png_error,(const png_struct *png_ptr, const char *error_message), PNG_NORETURN) { -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - char msg[16]; - if (png_ptr != NULL) - { - if ((png_ptr->flags & - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0) - { - if (*error_message == PNG_LITERAL_SHARP) - { - /* Strip "#nnnn " from beginning of error message. */ - int offset; - for (offset = 1; offset<15; offset++) - if (error_message[offset] == ' ') - break; - - if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0) - { - int i; - for (i = 0; i < offset - 1; i++) - msg[i] = error_message[i + 1]; - msg[i - 1] = '\0'; - error_message = msg; - } - - else - error_message += offset; - } - - else - { - if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0) - { - msg[0] = '0'; - msg[1] = '\0'; - error_message = msg; - } - } - } - } -#endif if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), + (*(png_ptr->error_fn))(png_constcast(png_struct *,png_ptr), error_message); /* If the custom handler doesn't exist, or if it returns, @@ -88,8 +60,9 @@ png_error,(png_const_structrp png_ptr, png_const_charp error_message), png_default_error(png_ptr, error_message); } #else -PNG_FUNCTION(void,PNGAPI -png_err,(png_const_structrp png_ptr),PNG_NORETURN) +PNG_FUNCTION(void, +png_err,(const png_struct *png_ptr), + PNG_NORETURN) { /* Prior to 1.5.2 the error_fn received a NULL pointer, expressed * erroneously as '\0', instead of the empty string "". This was @@ -97,7 +70,7 @@ png_err,(png_const_structrp png_ptr),PNG_NORETURN) * will crash in this case. */ if (png_ptr != NULL && png_ptr->error_fn != NULL) - (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), ""); + (*(png_ptr->error_fn))(png_constcast(png_struct *,png_ptr), ""); /* If the custom handler doesn't exist, or if it returns, use the default handler, which will not return. */ @@ -105,12 +78,12 @@ png_err,(png_const_structrp png_ptr),PNG_NORETURN) } #endif /* ERROR_TEXT */ -/* Utility to safely appends strings to a buffer. This never errors out so +/* Utility to safely append strings to a buffer. This never errors out so * error checking is not required in the caller. */ size_t -png_safecat(png_charp buffer, size_t bufsize, size_t pos, - png_const_charp string) +png_safecat(char *buffer, size_t bufsize, size_t pos, + const char *string) { if (buffer != NULL && pos < bufsize) { @@ -126,11 +99,11 @@ png_safecat(png_charp buffer, size_t bufsize, size_t pos, #if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) /* Utility to dump an unsigned value into a buffer, given a start pointer and - * and end pointer (which should point just *beyond* the end of the buffer!) + * an end pointer (which should point just *beyond* the end of the buffer!). * Returns the pointer to the start of the formatted string. */ -png_charp -png_format_number(png_const_charp start, png_charp end, int format, +char * +png_format_number(const char *start, char *end, int format, png_alloc_size_t number) { int count = 0; /* number of digits output */ @@ -144,9 +117,6 @@ png_format_number(png_const_charp start, png_charp end, int format, */ while (end > start && (number != 0 || count < mincount)) { - - static const char digits[] = "0123456789ABCDEF"; - switch (format) { case PNG_NUMBER_FORMAT_fixed: @@ -154,7 +124,7 @@ png_format_number(png_const_charp start, png_charp end, int format, mincount = 5; if (output != 0 || number % 10 != 0) { - *--end = digits[number % 10]; + *--end = png_digits[number % 10]; output = 1; } number /= 10; @@ -163,20 +133,20 @@ png_format_number(png_const_charp start, png_charp end, int format, case PNG_NUMBER_FORMAT_02u: /* Expects at least 2 digits. */ mincount = 2; - /* FALL THROUGH */ + /* FALLTHROUGH */ case PNG_NUMBER_FORMAT_u: - *--end = digits[number % 10]; + *--end = png_digits[number % 10]; number /= 10; break; case PNG_NUMBER_FORMAT_02x: /* This format expects at least two digits */ mincount = 2; - /* FALL THROUGH */ + /* FALLTHROUGH */ case PNG_NUMBER_FORMAT_x: - *--end = digits[number & 0xf]; + *--end = png_digits[number & 0xf]; number >>= 4; break; @@ -212,30 +182,14 @@ png_format_number(png_const_charp start, png_charp end, int format, * you should supply a replacement warning function and use * png_set_error_fn() to replace the warning function at run-time. */ -void PNGAPI -png_warning(png_const_structrp png_ptr, png_const_charp warning_message) +void +png_warning(const png_struct *png_ptr, const char *warning_message) { - int offset = 0; - if (png_ptr != NULL) - { -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - if ((png_ptr->flags & - (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0) -#endif - { - if (*warning_message == PNG_LITERAL_SHARP) - { - for (offset = 1; offset < 15; offset++) - if (warning_message[offset] == ' ') - break; - } - } - } if (png_ptr != NULL && png_ptr->warning_fn != NULL) - (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr), - warning_message + offset); + (*(png_ptr->warning_fn))(png_constcast(png_struct *,png_ptr), + warning_message); else - png_default_warning(png_ptr, warning_message + offset); + png_default_warning(png_ptr, warning_message); } /* These functions support 'formatted' warning messages with up to @@ -245,7 +199,7 @@ png_warning(png_const_structrp png_ptr, png_const_charp warning_message) */ void png_warning_parameter(png_warning_parameters p, int number, - png_const_charp string) + const char *string) { if (number > 0 && number <= PNG_WARNING_PARAMETER_COUNT) (void)png_safecat(p[number-1], (sizeof p[number-1]), 0, string); @@ -255,7 +209,7 @@ void png_warning_parameter_unsigned(png_warning_parameters p, int number, int format, png_alloc_size_t value) { - char buffer[PNG_NUMBER_BUFFER_SIZE]; + char buffer[PNG_NUMBER_BUFFER_SIZE] = {0}; png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value)); } @@ -264,8 +218,8 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format, png_int_32 value) { png_alloc_size_t u; - png_charp str; - char buffer[PNG_NUMBER_BUFFER_SIZE]; + char *str; + char buffer[PNG_NUMBER_BUFFER_SIZE] = {0}; /* Avoid overflow by doing the negate in a png_alloc_size_t: */ u = (png_alloc_size_t)value; @@ -281,8 +235,8 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format, } void -png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, - png_const_charp message) +png_formatted_warning(const png_struct *png_ptr, png_warning_parameters p, + const char *message) { /* The internal buffer is just 192 bytes - enough for all our messages, * overflow doesn't happen because this code checks! If someone figures @@ -292,11 +246,10 @@ png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, size_t i = 0; /* Index in the msg[] buffer: */ char msg[192]; - /* Each iteration through the following loop writes at most one character - * to msg[i++] then returns here to validate that there is still space for - * the trailing '\0'. It may (in the case of a parameter) read more than - * one character from message[]; it must check for '\0' and continue to the - * test if it finds the end of string. + /* Iterate through characters in message and resolve encountered + * parameters, which consist of @ followed by parameter number. Either + * add the resolved parameter or the raw character at msg[i]. Always check + * that there is still space for the trailing '\0'. */ while (i<(sizeof msg)-1 && *message != '\0') { @@ -305,23 +258,16 @@ png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, */ if (p != NULL && *message == '@' && message[1] != '\0') { - int parameter_char = *++message; /* Consume the '@' */ - static const char valid_parameters[] = "123456789"; - int parameter = 0; - - /* Search for the parameter digit, the index in the string is the - * parameter to use. - */ - while (valid_parameters[parameter] != parameter_char && - valid_parameters[parameter] != '\0') - ++parameter; + const int parameter_char = *++message; /* Consume the '@' */ /* If the parameter digit is out of range it will just get printed. */ - if (parameter < PNG_WARNING_PARAMETER_COUNT) + if (parameter_char >= '1' && parameter_char <= '9') { + const int parameter = parameter_char - '1'; + /* Append this parameter */ - png_const_charp parm = p[parameter]; - png_const_charp pend = p[parameter] + (sizeof p[parameter]); + const char *parm = p[parameter]; + const char *pend = p[parameter] + (sizeof p[parameter]); /* No need to copy the trailing '\0' here, but there is no guarantee * that parm[] has been initialized, so there is no guarantee of a @@ -358,8 +304,8 @@ png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p, #endif /* WARNINGS */ #ifdef PNG_BENIGN_ERRORS_SUPPORTED -void PNGAPI -png_benign_error(png_const_structrp png_ptr, png_const_charp error_message) +void +png_benign_error(const png_struct *png_ptr, const char *error_message) { if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0) { @@ -389,7 +335,7 @@ png_benign_error(png_const_structrp png_ptr, png_const_charp error_message) } void /* PRIVATE */ -png_app_warning(png_const_structrp png_ptr, png_const_charp error_message) +png_app_warning(const png_struct *png_ptr, const char *error_message) { if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0) png_warning(png_ptr, error_message); @@ -402,7 +348,7 @@ png_app_warning(png_const_structrp png_ptr, png_const_charp error_message) } void /* PRIVATE */ -png_app_error(png_const_structrp png_ptr, png_const_charp error_message) +png_app_error(const png_struct *png_ptr, const char *error_message) { if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0) png_warning(png_ptr, error_message); @@ -424,30 +370,23 @@ png_app_error(png_const_structrp png_ptr, png_const_charp error_message) * to 63 bytes. The name characters are output as hex digits wrapped in [] * if the character is invalid. */ -#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) -static PNG_CONST char png_digit[16] = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F' -}; - static void /* PRIVATE */ -png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp - error_message) +png_format_buffer(const png_struct *png_ptr, char *buffer, + const char *error_message) { png_uint_32 chunk_name = png_ptr->chunk_name; - int iout = 0, ishift = 24; + int iout = 0, ishift; - while (ishift >= 0) + for (ishift = 24; ishift >= 0; ishift -= 8) { int c = (int)(chunk_name >> ishift) & 0xff; - ishift -= 8; - if (isnonalpha(c) != 0) + if (!png_isalpha(c)) { - buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET; - buffer[iout++] = png_digit[(c & 0xf0) >> 4]; - buffer[iout++] = png_digit[c & 0x0f]; - buffer[iout++] = PNG_LITERAL_RIGHT_SQUARE_BRACKET; + buffer[iout++] = '['; + buffer[iout++] = png_digits[(c & 0xf0) >> 4]; + buffer[iout++] = png_digits[c & 0x0f]; + buffer[iout++] = ']'; } else @@ -476,8 +415,8 @@ png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp #endif /* WARNINGS || ERROR_TEXT */ #if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) -PNG_FUNCTION(void,PNGAPI -png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message), +PNG_FUNCTION(void, +png_chunk_error,(const png_struct *png_ptr, const char *error_message), PNG_NORETURN) { char msg[18+PNG_MAX_ERROR_TEXT]; @@ -493,8 +432,8 @@ png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message), #endif /* READ && ERROR_TEXT */ #ifdef PNG_WARNINGS_SUPPORTED -void PNGAPI -png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message) +void +png_chunk_warning(const png_struct *png_ptr, const char *warning_message) { char msg[18+PNG_MAX_ERROR_TEXT]; if (png_ptr == NULL) @@ -510,9 +449,9 @@ png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message) #ifdef PNG_READ_SUPPORTED #ifdef PNG_BENIGN_ERRORS_SUPPORTED -void PNGAPI -png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp - error_message) +void +png_chunk_benign_error(const png_struct *png_ptr, + const char *error_message) { if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0) png_chunk_warning(png_ptr, error_message); @@ -528,7 +467,7 @@ png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp #endif /* READ */ void /* PRIVATE */ -png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error) +png_chunk_report(const png_struct *png_ptr, const char *message, int error) { # ifndef PNG_WARNINGS_SUPPORTED PNG_UNUSED(message) @@ -569,7 +508,8 @@ png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error) #ifdef PNG_ERROR_TEXT_SUPPORTED #ifdef PNG_FLOATING_POINT_SUPPORTED PNG_FUNCTION(void, -png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN) +png_fixed_error,(const png_struct *png_ptr, const char *name), + PNG_NORETURN) { # define fixed_message "fixed point overflow in " # define fixed_message_ln ((sizeof fixed_message)-1) @@ -593,8 +533,8 @@ png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN) /* This API only exists if ANSI-C style error handling is used, * otherwise it is necessary for png_default_error to be overridden. */ -jmp_buf* PNGAPI -png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn, +jmp_buf* +png_set_longjmp_fn(png_struct *png_ptr, png_longjmp_ptr longjmp_fn, size_t jmp_buf_size) { /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value @@ -663,7 +603,7 @@ png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn, } void /* PRIVATE */ -png_free_jmpbuf(png_structrp png_ptr) +png_free_jmpbuf(png_struct *png_ptr) { if (png_ptr != NULL) { @@ -708,54 +648,21 @@ png_free_jmpbuf(png_structrp png_ptr) * error function pointer in png_set_error_fn(). */ static PNG_FUNCTION(void /* PRIVATE */, -png_default_error,(png_const_structrp png_ptr, png_const_charp error_message), +png_default_error,(const png_struct *png_ptr, const char *error_message), PNG_NORETURN) { #ifdef PNG_CONSOLE_IO_SUPPORTED -#ifdef PNG_ERROR_NUMBERS_SUPPORTED - /* Check on NULL only added in 1.5.4 */ - if (error_message != NULL && *error_message == PNG_LITERAL_SHARP) - { - /* Strip "#nnnn " from beginning of error message. */ - int offset; - char error_number[16]; - for (offset = 0; offset<15; offset++) - { - error_number[offset] = error_message[offset + 1]; - if (error_message[offset] == ' ') - break; - } - - if ((offset > 1) && (offset < 15)) - { - error_number[offset - 1] = '\0'; - fprintf(stderr, "libpng error no. %s: %s", - error_number, error_message + offset + 1); - fprintf(stderr, PNG_STRING_NEWLINE); - } - - else - { - fprintf(stderr, "libpng error: %s, offset=%d", - error_message, offset); - fprintf(stderr, PNG_STRING_NEWLINE); - } - } - else -#endif - { - fprintf(stderr, "libpng error: %s", error_message ? error_message : - "undefined"); - fprintf(stderr, PNG_STRING_NEWLINE); - } + fprintf(stderr, "libpng error: %s\n", error_message ? error_message : + "undefined"); #else PNG_UNUSED(error_message) /* Make compiler happy */ #endif png_longjmp(png_ptr, 1); } -PNG_FUNCTION(void,PNGAPI -png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) +PNG_FUNCTION(void, +png_longjmp,(const png_struct *png_ptr, int val), + PNG_NORETURN) { #ifdef PNG_SETJMP_SUPPORTED if (png_ptr != NULL && png_ptr->longjmp_fn != NULL && @@ -782,43 +689,10 @@ png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN) * not used, but it is passed in case it may be useful. */ static void /* PRIVATE */ -png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message) +png_default_warning(const png_struct *png_ptr, const char *warning_message) { #ifdef PNG_CONSOLE_IO_SUPPORTED -# ifdef PNG_ERROR_NUMBERS_SUPPORTED - if (*warning_message == PNG_LITERAL_SHARP) - { - int offset; - char warning_number[16]; - for (offset = 0; offset < 15; offset++) - { - warning_number[offset] = warning_message[offset + 1]; - if (warning_message[offset] == ' ') - break; - } - - if ((offset > 1) && (offset < 15)) - { - warning_number[offset + 1] = '\0'; - fprintf(stderr, "libpng warning no. %s: %s", - warning_number, warning_message + offset); - fprintf(stderr, PNG_STRING_NEWLINE); - } - - else - { - fprintf(stderr, "libpng warning: %s", - warning_message); - fprintf(stderr, PNG_STRING_NEWLINE); - } - } - else -# endif - - { - fprintf(stderr, "libpng warning: %s", warning_message); - fprintf(stderr, PNG_STRING_NEWLINE); - } + fprintf(stderr, "libpng warning: %s\n", warning_message); #else PNG_UNUSED(warning_message) /* Make compiler happy */ #endif @@ -829,10 +703,10 @@ png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message) /* This function is called when the application wants to use another method * of handling errors and warnings. Note that the error function MUST NOT * return to the calling routine or serious problems will occur. The return - * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1) + * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1). */ -void PNGAPI -png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr, +void +png_set_error_fn(png_struct *png_ptr, void *error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn) { if (png_ptr == NULL) @@ -852,41 +726,28 @@ png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr, * functions. The application should free any memory associated with this * pointer before png_write_destroy and png_read_destroy are called. */ -png_voidp PNGAPI -png_get_error_ptr(png_const_structrp png_ptr) +void * +png_get_error_ptr(const png_struct *png_ptr) { if (png_ptr == NULL) return NULL; - return ((png_voidp)png_ptr->error_ptr); + return (void *)png_ptr->error_ptr; } -#ifdef PNG_ERROR_NUMBERS_SUPPORTED -void PNGAPI -png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode) -{ - if (png_ptr != NULL) - { - png_ptr->flags &= - ((~(PNG_FLAG_STRIP_ERROR_NUMBERS | - PNG_FLAG_STRIP_ERROR_TEXT))&strip_mode); - } -} -#endif - #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) /* Currently the above both depend on SETJMP_SUPPORTED, however it would be * possible to implement without setjmp support just so long as there is some * way to handle the error return here: */ -PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI -png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), +PNG_FUNCTION(void /* PRIVATE */, +png_safe_error,(png_struct *png_nonconst_ptr, const char *error_message), PNG_NORETURN) { - const png_const_structrp png_ptr = png_nonconst_ptr; - png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); + const png_struct *png_ptr = png_nonconst_ptr; + png_image *image = png_voidcast(png_image *, png_ptr->error_ptr); /* An error is always logged here, overwriting anything (typically a warning) * that is already there: @@ -917,11 +778,11 @@ png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message), } #ifdef PNG_WARNINGS_SUPPORTED -void /* PRIVATE */ PNGCBAPI -png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message) +void /* PRIVATE */ +png_safe_warning(png_struct *png_nonconst_ptr, const char *warning_message) { - const png_const_structrp png_ptr = png_nonconst_ptr; - png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr); + const png_struct *png_ptr = png_nonconst_ptr; + png_image *image = png_voidcast(png_image *, png_ptr->error_ptr); /* A warning is only logged if there is no prior warning or error. */ if (image->warning_or_error == 0) @@ -933,31 +794,39 @@ png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message) #endif int /* PRIVATE */ -png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg) +png_safe_execute(png_image *image, int (*function)(void *), void *arg) { - volatile png_imagep image = image_in; - volatile int result; - volatile png_voidp saved_error_buf; + void *saved_error_buf = image->opaque->error_buf; jmp_buf safe_jmpbuf; - /* Safely execute function(arg) with png_error returning to this function. */ - saved_error_buf = image->opaque->error_buf; - result = setjmp(safe_jmpbuf) == 0; - - if (result != 0) + /* Safely execute function(arg), with png_error returning back here. */ + if (setjmp(safe_jmpbuf) == 0) { + int result; image->opaque->error_buf = safe_jmpbuf; result = function(arg); + image->opaque->error_buf = saved_error_buf; + + if (result) + return 1; /* success */ } + /* The function failed either because of a caught png_error and a regular + * return of false above or because of an uncaught png_error from the + * function itself. Ensure that the error_buf is always set back to the + * value saved above: + */ image->opaque->error_buf = saved_error_buf; - /* And do the cleanup prior to any failure return. */ - if (result == 0) + /* On the final false return, when about to return control to the caller, the + * image is freed (png_image_free does this check but it is duplicated here + * for clarity: + */ + if (saved_error_buf == NULL) png_image_free(image); - return result; + return 0; /* failure */ } #endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */ #endif /* READ || WRITE */ diff --git a/media/libpng/pngget.c b/media/libpng/pngget.c index b92a7cdb2d..e5d26428f4 100644 --- a/media/libpng/pngget.c +++ b/media/libpng/pngget.c @@ -1,10 +1,9 @@ - /* pngget.c - retrieval of values from info struct * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2025 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -16,196 +15,207 @@ #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -png_uint_32 PNGAPI -png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_valid(const png_struct *png_ptr, const png_info *info_ptr, png_uint_32 flag) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->valid & flag); + { +#ifdef PNG_READ_tRNS_SUPPORTED + /* png_handle_PLTE() may have canceled a valid tRNS chunk but left the + * 'valid' flag for the detection of duplicate chunks. Do not report a + * valid tRNS chunk in this case. + */ + if (flag == PNG_INFO_tRNS && png_ptr->num_trans == 0) + return 0; +#endif + + return info_ptr->valid & flag; + } - return(0); + return 0; } -png_size_t PNGAPI -png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr) +size_t +png_get_rowbytes(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->rowbytes); + return info_ptr->rowbytes; - return(0); + return 0; } #ifdef PNG_INFO_IMAGE_SUPPORTED -png_bytepp PNGAPI -png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_byte ** +png_get_rows(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->row_pointers); + return info_ptr->row_pointers; - return(0); + return 0; } #endif #ifdef PNG_EASY_ACCESS_SUPPORTED /* Easy access to info, added in libpng-0.99 */ -png_uint_32 PNGAPI -png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_uint_32 +png_get_image_width(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) return info_ptr->width; - return (0); + return 0; } -png_uint_32 PNGAPI -png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_uint_32 +png_get_image_height(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) return info_ptr->height; - return (0); + return 0; } -png_byte PNGAPI -png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_byte +png_get_bit_depth(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) return info_ptr->bit_depth; - return (0); + return 0; } -png_byte PNGAPI -png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_byte +png_get_color_type(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) return info_ptr->color_type; - return (0); + return 0; } -png_byte PNGAPI -png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_byte +png_get_filter_type(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) return info_ptr->filter_type; - return (0); + return 0; } -png_byte PNGAPI -png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_byte +png_get_interlace_type(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) return info_ptr->interlace_type; - return (0); + return 0; } -png_byte PNGAPI -png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_byte +png_get_compression_type(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) return info_ptr->compression_type; - return (0); + return 0; } -png_uint_32 PNGAPI -png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp - info_ptr) +png_uint_32 +png_get_x_pixels_per_meter(const png_struct *png_ptr, + const png_info *info_ptr) { #ifdef PNG_pHYs_SUPPORTED + png_debug(1, "in png_get_x_pixels_per_meter"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) - { - png_debug1(1, "in %s retrieval function", - "png_get_x_pixels_per_meter"); - - if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) - return (info_ptr->x_pixels_per_unit); - } + { + if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) + return info_ptr->x_pixels_per_unit; + } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } -png_uint_32 PNGAPI -png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp - info_ptr) +png_uint_32 +png_get_y_pixels_per_meter(const png_struct *png_ptr, + const png_info *info_ptr) { #ifdef PNG_pHYs_SUPPORTED + png_debug(1, "in png_get_y_pixels_per_meter"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) { - png_debug1(1, "in %s retrieval function", - "png_get_y_pixels_per_meter"); - if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER) - return (info_ptr->y_pixels_per_unit); + return info_ptr->y_pixels_per_unit; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } -png_uint_32 PNGAPI -png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_uint_32 +png_get_pixels_per_meter(const png_struct *png_ptr, const png_info *info_ptr) { #ifdef PNG_pHYs_SUPPORTED + png_debug(1, "in png_get_pixels_per_meter"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter"); - if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER && info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit) - return (info_ptr->x_pixels_per_unit); + return info_ptr->x_pixels_per_unit; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } #ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp - info_ptr) +float +png_get_pixel_aspect_ratio(const png_struct *png_ptr, + const png_info *info_ptr) { #ifdef PNG_READ_pHYs_SUPPORTED + png_debug(1, "in png_get_pixel_aspect_ratio"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio"); - if (info_ptr->x_pixels_per_unit != 0) - return ((float)((float)info_ptr->y_pixels_per_unit - /(float)info_ptr->x_pixels_per_unit)); + return (float)info_ptr->y_pixels_per_unit + / (float)info_ptr->x_pixels_per_unit; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return ((float)0.0); + return (float)0.0; } #endif #ifdef PNG_FIXED_POINT_SUPPORTED -png_fixed_point PNGAPI -png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr, - png_const_inforp info_ptr) +png_fixed_point +png_get_pixel_aspect_ratio_fixed(const png_struct *png_ptr, + const png_info *info_ptr) { #ifdef PNG_READ_pHYs_SUPPORTED + png_debug(1, "in png_get_pixel_aspect_ratio_fixed"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0 && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 && @@ -214,8 +224,6 @@ png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr, { png_fixed_point res; - png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed"); - /* The following casts work because a PNG 4 byte integer only has a valid * range of 0..2^31-1; otherwise the cast might overflow. */ @@ -232,84 +240,84 @@ png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr, } #endif -png_int_32 PNGAPI -png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_int_32 +png_get_x_offset_microns(const png_struct *png_ptr, const png_info *info_ptr) { #ifdef PNG_oFFs_SUPPORTED + png_debug(1, "in png_get_x_offset_microns"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns"); - if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) - return (info_ptr->x_offset); + return info_ptr->x_offset; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } -png_int_32 PNGAPI -png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_int_32 +png_get_y_offset_microns(const png_struct *png_ptr, const png_info *info_ptr) { #ifdef PNG_oFFs_SUPPORTED + png_debug(1, "in png_get_y_offset_microns"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns"); - if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER) - return (info_ptr->y_offset); + return info_ptr->y_offset; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } -png_int_32 PNGAPI -png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_int_32 +png_get_x_offset_pixels(const png_struct *png_ptr, const png_info *info_ptr) { #ifdef PNG_oFFs_SUPPORTED + png_debug(1, "in png_get_x_offset_pixels"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels"); - if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) - return (info_ptr->x_offset); + return info_ptr->x_offset; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } -png_int_32 PNGAPI -png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_int_32 +png_get_y_offset_pixels(const png_struct *png_ptr, const png_info *info_ptr) { #ifdef PNG_oFFs_SUPPORTED + png_debug(1, "in png_get_y_offset_pixels"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0) { - png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels"); - if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL) - return (info_ptr->y_offset); + return info_ptr->y_offset; } #else PNG_UNUSED(png_ptr) PNG_UNUSED(info_ptr) #endif - return (0); + return 0; } #ifdef PNG_INCH_CONVERSIONS_SUPPORTED @@ -345,49 +353,55 @@ ppi_from_ppm(png_uint_32 ppm) #endif } -png_uint_32 PNGAPI -png_get_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_uint_32 +png_get_pixels_per_inch(const png_struct *png_ptr, const png_info *info_ptr) { return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr)); } -png_uint_32 PNGAPI -png_get_x_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_uint_32 +png_get_x_pixels_per_inch(const png_struct *png_ptr, const png_info *info_ptr) { return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr)); } -png_uint_32 PNGAPI -png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_uint_32 +png_get_y_pixels_per_inch(const png_struct *png_ptr, const png_info *info_ptr) { return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr)); } #ifdef PNG_FIXED_POINT_SUPPORTED static png_fixed_point -png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns) +png_fixed_inches_from_microns(const png_struct *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. * Notice that this can overflow - a warning is output and 0 is * returned. */ - return png_muldiv_warn(png_ptr, microns, 500, 127); + png_fixed_point result; + + if (png_muldiv(&result, microns, 500, 127) != 0) + return result; + + png_warning(png_ptr, "fixed point overflow ignored"); + return 0; } -png_fixed_point PNGAPI -png_get_x_offset_inches_fixed(png_const_structrp png_ptr, - png_const_inforp info_ptr) +png_fixed_point +png_get_x_offset_inches_fixed(const png_struct *png_ptr, + const png_info *info_ptr) { return png_fixed_inches_from_microns(png_ptr, png_get_x_offset_microns(png_ptr, info_ptr)); } -#endif +#endif /* FIXED_POINT */ #ifdef PNG_FIXED_POINT_SUPPORTED -png_fixed_point PNGAPI -png_get_y_offset_inches_fixed(png_const_structrp png_ptr, - png_const_inforp info_ptr) +png_fixed_point +png_get_y_offset_inches_fixed(const png_struct *png_ptr, + const png_info *info_ptr) { return png_fixed_inches_from_microns(png_ptr, png_get_y_offset_microns(png_ptr, info_ptr)); @@ -395,8 +409,8 @@ png_get_y_offset_inches_fixed(png_const_structrp png_ptr, #endif #ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_x_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr) +float +png_get_x_offset_inches(const png_struct *png_ptr, const png_info *info_ptr) { /* To avoid the overflow do the conversion directly in floating * point. @@ -406,8 +420,8 @@ png_get_x_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr) #endif #ifdef PNG_FLOATING_POINT_SUPPORTED -float PNGAPI -png_get_y_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr) +float +png_get_y_offset_inches(const png_struct *png_ptr, const png_info *info_ptr) { /* To avoid the overflow do the conversion directly in floating * point. @@ -417,17 +431,17 @@ png_get_y_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr) #endif #ifdef PNG_pHYs_SUPPORTED -png_uint_32 PNGAPI -png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_pHYs_dpi(const png_struct *png_ptr, const png_info *info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) { png_uint_32 retval = 0; + png_debug1(1, "in %s retrieval function", "pHYs"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) { - png_debug1(1, "in %s retrieval function", "pHYs"); - if (res_x != NULL) { *res_x = info_ptr->x_pixels_per_unit; @@ -453,7 +467,7 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr, } } - return (retval); + return retval; } #endif /* pHYs */ #endif /* INCH_CONVERSIONS */ @@ -463,42 +477,42 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr, #endif /* EASY_ACCESS */ -png_byte PNGAPI -png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr) +png_byte +png_get_channels(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->channels); + return info_ptr->channels; - return (0); + return 0; } #ifdef PNG_READ_SUPPORTED -png_const_bytep PNGAPI -png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr) +const png_byte * +png_get_signature(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) - return(info_ptr->signature); + return info_ptr->signature; - return (NULL); + return NULL; } #endif #ifdef PNG_bKGD_SUPPORTED -png_uint_32 PNGAPI -png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, - png_color_16p *background) +png_uint_32 +png_get_bKGD(const png_struct *png_ptr, png_info *info_ptr, + png_color_16 **background) { + png_debug1(1, "in %s retrieval function", "bKGD"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0 && background != NULL) { - png_debug1(1, "in %s retrieval function", "bKGD"); - *background = &(info_ptr->background); - return (PNG_INFO_bKGD); + return PNG_INFO_bKGD; } - return (0); + return 0; } #endif @@ -508,241 +522,208 @@ png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, * cHRM chunk in 1.5.4 */ # ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr, - double *white_x, double *white_y, double *red_x, double *red_y, - double *green_x, double *green_y, double *blue_x, double *blue_y) +png_uint_32 +png_get_cHRM(const png_struct *png_ptr, const png_info *info_ptr, + double *whitex, double *whitey, double *redx, double *redy, + double *greenx, double *greeny, double *bluex, double *bluey) { - /* Quiet API change: this code used to only return the end points if a cHRM - * chunk was present, but the end points can also come from iCCP or sRGB - * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and - * the png_set_ APIs merely check that set end points are mutually - * consistent. - */ + png_debug1(1, "in %s retrieval function", "cHRM"); + + /* PNGv3: this just returns the values store from the cHRM, if any. */ if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) + (info_ptr->valid & PNG_INFO_cHRM) != 0) { - png_debug1(1, "in %s retrieval function", "cHRM"); - - if (white_x != NULL) - *white_x = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.whitex, "cHRM white X"); - if (white_y != NULL) - *white_y = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y"); - if (red_x != NULL) - *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx, - "cHRM red X"); - if (red_y != NULL) - *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy, - "cHRM red Y"); - if (green_x != NULL) - *green_x = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.greenx, "cHRM green X"); - if (green_y != NULL) - *green_y = png_float(png_ptr, - info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y"); - if (blue_x != NULL) - *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex, - "cHRM blue X"); - if (blue_y != NULL) - *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey, - "cHRM blue Y"); - return (PNG_INFO_cHRM); + if (whitex != NULL) + *whitex = png_float(png_ptr, info_ptr->cHRM.whitex, "cHRM wx"); + if (whitey != NULL) + *whitey = png_float(png_ptr, info_ptr->cHRM.whitey, "cHRM wy"); + if (redx != NULL) + *redx = png_float(png_ptr, info_ptr->cHRM.redx, "cHRM rx"); + if (redy != NULL) + *redy = png_float(png_ptr, info_ptr->cHRM.redy, "cHRM ry"); + if (greenx != NULL) + *greenx = png_float(png_ptr, info_ptr->cHRM.greenx, "cHRM gx"); + if (greeny != NULL) + *greeny = png_float(png_ptr, info_ptr->cHRM.greeny, "cHRM gy"); + if (bluex != NULL) + *bluex = png_float(png_ptr, info_ptr->cHRM.bluex, "cHRM bx"); + if (bluey != NULL) + *bluey = png_float(png_ptr, info_ptr->cHRM.bluey, "cHRM by"); + return PNG_INFO_cHRM; } - return (0); + return 0; } -png_uint_32 PNGAPI -png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_cHRM_XYZ(const png_struct *png_ptr, const png_info *info_ptr, double *red_X, double *red_Y, double *red_Z, double *green_X, double *green_Y, double *green_Z, double *blue_X, double *blue_Y, double *blue_Z) { + png_XYZ XYZ; + png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)"); + if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) + (info_ptr->valid & PNG_INFO_cHRM) != 0 && + png_XYZ_from_xy(&XYZ, &info_ptr->cHRM) == 0) { - png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)"); - if (red_X != NULL) - *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X, - "cHRM red X"); + *red_X = png_float(png_ptr, XYZ.red_X, "cHRM red X"); if (red_Y != NULL) - *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y, - "cHRM red Y"); + *red_Y = png_float(png_ptr, XYZ.red_Y, "cHRM red Y"); if (red_Z != NULL) - *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z, - "cHRM red Z"); + *red_Z = png_float(png_ptr, XYZ.red_Z, "cHRM red Z"); if (green_X != NULL) - *green_X = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X"); + *green_X = png_float(png_ptr, XYZ.green_X, "cHRM green X"); if (green_Y != NULL) - *green_Y = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y"); + *green_Y = png_float(png_ptr, XYZ.green_Y, "cHRM green Y"); if (green_Z != NULL) - *green_Z = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z"); + *green_Z = png_float(png_ptr, XYZ.green_Z, "cHRM green Z"); if (blue_X != NULL) - *blue_X = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X"); + *blue_X = png_float(png_ptr, XYZ.blue_X, "cHRM blue X"); if (blue_Y != NULL) - *blue_Y = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y"); + *blue_Y = png_float(png_ptr, XYZ.blue_Y, "cHRM blue Y"); if (blue_Z != NULL) - *blue_Z = png_float(png_ptr, - info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z"); - return (PNG_INFO_cHRM); + *blue_Z = png_float(png_ptr, XYZ.blue_Z, "cHRM blue Z"); + return PNG_INFO_cHRM; } - return (0); + return 0; } # endif # ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_cHRM_XYZ_fixed(const png_struct *png_ptr, const png_info *info_ptr, png_fixed_point *int_red_X, png_fixed_point *int_red_Y, png_fixed_point *int_red_Z, png_fixed_point *int_green_X, png_fixed_point *int_green_Y, png_fixed_point *int_green_Z, png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y, png_fixed_point *int_blue_Z) { + png_XYZ XYZ; + png_debug1(1, "in %s retrieval function", "cHRM_XYZ"); + if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) + (info_ptr->valid & PNG_INFO_cHRM) != 0U && + png_XYZ_from_xy(&XYZ, &info_ptr->cHRM) == 0) { - png_debug1(1, "in %s retrieval function", "cHRM_XYZ"); - - if (int_red_X != NULL) - *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X; - if (int_red_Y != NULL) - *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y; - if (int_red_Z != NULL) - *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z; - if (int_green_X != NULL) - *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X; - if (int_green_Y != NULL) - *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y; - if (int_green_Z != NULL) - *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z; - if (int_blue_X != NULL) - *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X; - if (int_blue_Y != NULL) - *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y; - if (int_blue_Z != NULL) - *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z; - return (PNG_INFO_cHRM); + if (int_red_X != NULL) *int_red_X = XYZ.red_X; + if (int_red_Y != NULL) *int_red_Y = XYZ.red_Y; + if (int_red_Z != NULL) *int_red_Z = XYZ.red_Z; + if (int_green_X != NULL) *int_green_X = XYZ.green_X; + if (int_green_Y != NULL) *int_green_Y = XYZ.green_Y; + if (int_green_Z != NULL) *int_green_Z = XYZ.green_Z; + if (int_blue_X != NULL) *int_blue_X = XYZ.blue_X; + if (int_blue_Y != NULL) *int_blue_Y = XYZ.blue_Y; + if (int_blue_Z != NULL) *int_blue_Z = XYZ.blue_Z; + return PNG_INFO_cHRM; } - return (0); + return 0; } -png_uint_32 PNGAPI -png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, - png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x, - png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y, - png_fixed_point *blue_x, png_fixed_point *blue_y) +png_uint_32 +png_get_cHRM_fixed(const png_struct *png_ptr, const png_info *info_ptr, + png_fixed_point *whitex, png_fixed_point *whitey, png_fixed_point *redx, + png_fixed_point *redy, png_fixed_point *greenx, png_fixed_point *greeny, + png_fixed_point *bluex, png_fixed_point *bluey) { png_debug1(1, "in %s retrieval function", "cHRM"); + /* PNGv3: this just returns the values store from the cHRM, if any. */ if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) + (info_ptr->valid & PNG_INFO_cHRM) != 0) { - if (white_x != NULL) - *white_x = info_ptr->colorspace.end_points_xy.whitex; - if (white_y != NULL) - *white_y = info_ptr->colorspace.end_points_xy.whitey; - if (red_x != NULL) - *red_x = info_ptr->colorspace.end_points_xy.redx; - if (red_y != NULL) - *red_y = info_ptr->colorspace.end_points_xy.redy; - if (green_x != NULL) - *green_x = info_ptr->colorspace.end_points_xy.greenx; - if (green_y != NULL) - *green_y = info_ptr->colorspace.end_points_xy.greeny; - if (blue_x != NULL) - *blue_x = info_ptr->colorspace.end_points_xy.bluex; - if (blue_y != NULL) - *blue_y = info_ptr->colorspace.end_points_xy.bluey; - return (PNG_INFO_cHRM); + if (whitex != NULL) *whitex = info_ptr->cHRM.whitex; + if (whitey != NULL) *whitey = info_ptr->cHRM.whitey; + if (redx != NULL) *redx = info_ptr->cHRM.redx; + if (redy != NULL) *redy = info_ptr->cHRM.redy; + if (greenx != NULL) *greenx = info_ptr->cHRM.greenx; + if (greeny != NULL) *greeny = info_ptr->cHRM.greeny; + if (bluex != NULL) *bluex = info_ptr->cHRM.bluex; + if (bluey != NULL) *bluey = info_ptr->cHRM.bluey; + return PNG_INFO_cHRM; } - return (0); + return 0; } # endif #endif #ifdef PNG_gAMA_SUPPORTED # ifdef PNG_FIXED_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_gAMA_fixed(const png_struct *png_ptr, const png_info *info_ptr, png_fixed_point *file_gamma) { png_debug1(1, "in %s retrieval function", "gAMA"); + /* PNGv3 compatibility: only report gAMA if it is really present. */ if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && - file_gamma != NULL) + (info_ptr->valid & PNG_INFO_gAMA) != 0) { - *file_gamma = info_ptr->colorspace.gamma; - return (PNG_INFO_gAMA); + if (file_gamma != NULL) *file_gamma = info_ptr->gamma; + return PNG_INFO_gAMA; } - return (0); + return 0; } # endif # ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_gAMA(const png_struct *png_ptr, const png_info *info_ptr, double *file_gamma) { png_debug1(1, "in %s retrieval function", "gAMA(float)"); + /* PNGv3 compatibility: only report gAMA if it is really present. */ if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && - file_gamma != NULL) + (info_ptr->valid & PNG_INFO_gAMA) != 0) { - *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma, - "png_get_gAMA"); - return (PNG_INFO_gAMA); + if (file_gamma != NULL) + *file_gamma = png_float(png_ptr, info_ptr->gamma, "gAMA"); + + return PNG_INFO_gAMA; } - return (0); + return 0; } # endif #endif #ifdef PNG_sRGB_SUPPORTED -png_uint_32 PNGAPI -png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_sRGB(const png_struct *png_ptr, const png_info *info_ptr, int *file_srgb_intent) { png_debug1(1, "in %s retrieval function", "sRGB"); if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL) + (info_ptr->valid & PNG_INFO_sRGB) != 0) { - *file_srgb_intent = info_ptr->colorspace.rendering_intent; - return (PNG_INFO_sRGB); + if (file_srgb_intent != NULL) + *file_srgb_intent = info_ptr->rendering_intent; + return PNG_INFO_sRGB; } - return (0); + return 0; } #endif #ifdef PNG_iCCP_SUPPORTED -png_uint_32 PNGAPI -png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, - png_charpp name, int *compression_type, - png_bytepp profile, png_uint_32 *proflen) +png_uint_32 +png_get_iCCP(const png_struct *png_ptr, png_info *info_ptr, + char **name, int *compression_type, + png_byte **profile, png_uint_32 *proflen) { png_debug1(1, "in %s retrieval function", "iCCP"); if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP) != 0 && - name != NULL && compression_type != NULL && profile != NULL && - proflen != NULL) + name != NULL && profile != NULL && proflen != NULL) { *name = info_ptr->iccp_name; *profile = info_ptr->iccp_profile; @@ -750,33 +731,185 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, /* This is somewhat irrelevant since the profile data returned has * actually been uncompressed. */ - *compression_type = PNG_COMPRESSION_TYPE_BASE; - return (PNG_INFO_iCCP); + if (compression_type != NULL) + *compression_type = PNG_COMPRESSION_TYPE_BASE; + return PNG_INFO_iCCP; } - return (0); + return 0; } #endif #ifdef PNG_sPLT_SUPPORTED -int PNGAPI -png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr, - png_sPLT_tpp spalettes) +int +png_get_sPLT(const png_struct *png_ptr, png_info *info_ptr, + png_sPLT_t **spalettes) { + png_debug1(1, "in %s retrieval function", "sPLT"); + if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL) { *spalettes = info_ptr->splt_palettes; return info_ptr->splt_palettes_num; } - return (0); + return 0; +} +#endif + +#ifdef PNG_cICP_SUPPORTED +png_uint_32 +png_get_cICP(const png_struct *png_ptr, + const png_info *info_ptr, png_byte *colour_primaries, + png_byte *transfer_function, png_byte *matrix_coefficients, + png_byte *video_full_range_flag) +{ + png_debug1(1, "in %s retrieval function", "cICP"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_cICP) != 0 && + colour_primaries != NULL && transfer_function != NULL && + matrix_coefficients != NULL && video_full_range_flag != NULL) + { + *colour_primaries = info_ptr->cicp_colour_primaries; + *transfer_function = info_ptr->cicp_transfer_function; + *matrix_coefficients = info_ptr->cicp_matrix_coefficients; + *video_full_range_flag = info_ptr->cicp_video_full_range_flag; + return (PNG_INFO_cICP); + } + + return 0; +} +#endif + +#ifdef PNG_cLLI_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 +png_get_cLLI_fixed(const png_struct *png_ptr, const png_info *info_ptr, + png_uint_32 *maxCLL, + png_uint_32 *maxFALL) +{ + png_debug1(1, "in %s retrieval function", "cLLI"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_cLLI) != 0) + { + if (maxCLL != NULL) *maxCLL = info_ptr->maxCLL; + if (maxFALL != NULL) *maxFALL = info_ptr->maxFALL; + return PNG_INFO_cLLI; + } + + return 0; +} +# endif + +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 +png_get_cLLI(const png_struct *png_ptr, const png_info *info_ptr, + double *maxCLL, double *maxFALL) +{ + png_debug1(1, "in %s retrieval function", "cLLI(float)"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_cLLI) != 0) + { + if (maxCLL != NULL) *maxCLL = info_ptr->maxCLL * .0001; + if (maxFALL != NULL) *maxFALL = info_ptr->maxFALL * .0001; + return PNG_INFO_cLLI; + } + + return 0; +} +# endif +#endif /* cLLI */ + +#ifdef PNG_mDCV_SUPPORTED +# ifdef PNG_FIXED_POINT_SUPPORTED +png_uint_32 +png_get_mDCV_fixed(const png_struct *png_ptr, const png_info *info_ptr, + png_fixed_point *white_x, png_fixed_point *white_y, + png_fixed_point *red_x, png_fixed_point *red_y, + png_fixed_point *green_x, png_fixed_point *green_y, + png_fixed_point *blue_x, png_fixed_point *blue_y, + png_uint_32 *mastering_maxDL, png_uint_32 *mastering_minDL) +{ + png_debug1(1, "in %s retrieval function", "mDCV"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_mDCV) != 0) + { + if (white_x != NULL) *white_x = info_ptr->mastering_white_x * 2; + if (white_y != NULL) *white_y = info_ptr->mastering_white_y * 2; + if (red_x != NULL) *red_x = info_ptr->mastering_red_x * 2; + if (red_y != NULL) *red_y = info_ptr->mastering_red_y * 2; + if (green_x != NULL) *green_x = info_ptr->mastering_green_x * 2; + if (green_y != NULL) *green_y = info_ptr->mastering_green_y * 2; + if (blue_x != NULL) *blue_x = info_ptr->mastering_blue_x * 2; + if (blue_y != NULL) *blue_y = info_ptr->mastering_blue_y * 2; + if (mastering_maxDL != NULL) *mastering_maxDL = info_ptr->mastering_maxDL; + if (mastering_minDL != NULL) *mastering_minDL = info_ptr->mastering_minDL; + return PNG_INFO_mDCV; + } + + return 0; +} +# endif + +# ifdef PNG_FLOATING_POINT_SUPPORTED +png_uint_32 +png_get_mDCV(const png_struct *png_ptr, const png_info *info_ptr, + double *white_x, double *white_y, double *red_x, double *red_y, + double *green_x, double *green_y, double *blue_x, double *blue_y, + double *mastering_maxDL, double *mastering_minDL) +{ + png_debug1(1, "in %s retrieval function", "mDCV(float)"); + + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_mDCV) != 0) + { + if (white_x != NULL) *white_x = info_ptr->mastering_white_x * .00002; + if (white_y != NULL) *white_y = info_ptr->mastering_white_y * .00002; + if (red_x != NULL) *red_x = info_ptr->mastering_red_x * .00002; + if (red_y != NULL) *red_y = info_ptr->mastering_red_y * .00002; + if (green_x != NULL) *green_x = info_ptr->mastering_green_x * .00002; + if (green_y != NULL) *green_y = info_ptr->mastering_green_y * .00002; + if (blue_x != NULL) *blue_x = info_ptr->mastering_blue_x * .00002; + if (blue_y != NULL) *blue_y = info_ptr->mastering_blue_y * .00002; + if (mastering_maxDL != NULL) + *mastering_maxDL = info_ptr->mastering_maxDL * .0001; + if (mastering_minDL != NULL) + *mastering_minDL = info_ptr->mastering_minDL * .0001; + return PNG_INFO_mDCV; + } + + return 0; +} +# endif /* FLOATING_POINT */ +#endif /* mDCV */ + +#ifdef PNG_eXIf_SUPPORTED +png_uint_32 +png_get_eXIf_1(const png_struct *png_ptr, const png_info *info_ptr, + png_uint_32 *num_exif, png_byte **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 -png_uint_32 PNGAPI -png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr, - png_uint_16p *hist) +png_uint_32 +png_get_hIST(const png_struct *png_ptr, png_info *info_ptr, + png_uint_16 **hist) { png_debug1(1, "in %s retrieval function", "hIST"); @@ -784,15 +917,15 @@ png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr, (info_ptr->valid & PNG_INFO_hIST) != 0 && hist != NULL) { *hist = info_ptr->hist; - return (PNG_INFO_hIST); + return PNG_INFO_hIST; } - return (0); + return 0; } #endif -png_uint_32 PNGAPI -png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_IHDR(const png_struct *png_ptr, const png_info *info_ptr, png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type, int *interlace_type, int *compression_type, int *filter_type) @@ -800,7 +933,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr, png_debug1(1, "in %s retrieval function", "IHDR"); if (png_ptr == NULL || info_ptr == NULL) - return (0); + return 0; if (width != NULL) *width = info_ptr->width; @@ -832,12 +965,12 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr, info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type, info_ptr->compression_type, info_ptr->filter_type); - return (1); + return 1; } #ifdef PNG_oFFs_SUPPORTED -png_uint_32 PNGAPI -png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_oFFs(const png_struct *png_ptr, const png_info *info_ptr, png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type) { png_debug1(1, "in %s retrieval function", "oFFs"); @@ -849,18 +982,18 @@ png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr, *offset_x = info_ptr->x_offset; *offset_y = info_ptr->y_offset; *unit_type = (int)info_ptr->offset_unit_type; - return (PNG_INFO_oFFs); + return PNG_INFO_oFFs; } - return (0); + return 0; } #endif #ifdef PNG_pCAL_SUPPORTED -png_uint_32 PNGAPI -png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, - png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, - png_charp *units, png_charpp *params) +png_uint_32 +png_get_pCAL(const png_struct *png_ptr, png_info *info_ptr, + char **purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams, + char **units, char ***params) { png_debug1(1, "in %s retrieval function", "pCAL"); @@ -876,10 +1009,10 @@ png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, *nparams = (int)info_ptr->pcal_nparams; *units = info_ptr->pcal_units; *params = info_ptr->pcal_params; - return (PNG_INFO_pCAL); + return PNG_INFO_pCAL; } - return (0); + return 0; } #endif @@ -887,10 +1020,12 @@ png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, # ifdef PNG_FIXED_POINT_SUPPORTED # if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \ defined(PNG_FLOATING_POINT_SUPPORTED) -png_uint_32 PNGAPI -png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_sCAL_fixed(const png_struct *png_ptr, const png_info *info_ptr, int *unit, png_fixed_point *width, png_fixed_point *height) { + png_debug1(1, "in %s retrieval function", "sCAL"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0) { @@ -902,50 +1037,54 @@ png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr, *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width"); *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height), "sCAL height"); - return (PNG_INFO_sCAL); + return PNG_INFO_sCAL; } - return(0); + return 0; } # endif /* FLOATING_ARITHMETIC */ # endif /* FIXED_POINT */ # ifdef PNG_FLOATING_POINT_SUPPORTED -png_uint_32 PNGAPI -png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_sCAL(const png_struct *png_ptr, const png_info *info_ptr, int *unit, double *width, double *height) { + png_debug1(1, "in %s retrieval function", "sCAL(float)"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0) { *unit = info_ptr->scal_unit; *width = atof(info_ptr->scal_s_width); *height = atof(info_ptr->scal_s_height); - return (PNG_INFO_sCAL); + return PNG_INFO_sCAL; } - return(0); + return 0; } # endif /* FLOATING POINT */ -png_uint_32 PNGAPI -png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr, - int *unit, png_charpp width, png_charpp height) +png_uint_32 +png_get_sCAL_s(const png_struct *png_ptr, const png_info *info_ptr, + int *unit, char **width, char **height) { + png_debug1(1, "in %s retrieval function", "sCAL(str)"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0) { *unit = info_ptr->scal_unit; *width = info_ptr->scal_s_width; *height = info_ptr->scal_s_height; - return (PNG_INFO_sCAL); + return PNG_INFO_sCAL; } - return(0); + return 0; } #endif /* sCAL */ #ifdef PNG_pHYs_SUPPORTED -png_uint_32 PNGAPI -png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr, +png_uint_32 +png_get_pHYs(const png_struct *png_ptr, const png_info *info_ptr, png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type) { png_uint_32 retval = 0; @@ -974,13 +1113,13 @@ png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr, } } - return (retval); + return retval; } #endif /* pHYs */ -png_uint_32 PNGAPI -png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr, - png_colorp *palette, int *num_palette) +png_uint_32 +png_get_PLTE(const png_struct *png_ptr, png_info *info_ptr, + png_color **palette, int *num_palette) { png_debug1(1, "in %s retrieval function", "PLTE"); @@ -990,16 +1129,16 @@ png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr, *palette = info_ptr->palette; *num_palette = info_ptr->num_palette; png_debug1(3, "num_palette = %d", *num_palette); - return (PNG_INFO_PLTE); + return PNG_INFO_PLTE; } - return (0); + return 0; } #ifdef PNG_sBIT_SUPPORTED -png_uint_32 PNGAPI -png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, - png_color_8p *sig_bit) +png_uint_32 +png_get_sBIT(const png_struct *png_ptr, png_info *info_ptr, + png_color_8 **sig_bit) { png_debug1(1, "in %s retrieval function", "sBIT"); @@ -1007,21 +1146,21 @@ png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, (info_ptr->valid & PNG_INFO_sBIT) != 0 && sig_bit != NULL) { *sig_bit = &(info_ptr->sig_bit); - return (PNG_INFO_sBIT); + return PNG_INFO_sBIT; } - return (0); + return 0; } #endif #ifdef PNG_TEXT_SUPPORTED -int PNGAPI -png_get_text(png_const_structrp png_ptr, png_inforp info_ptr, - png_textp *text_ptr, int *num_text) +int +png_get_text(const png_struct *png_ptr, png_info *info_ptr, + png_text **text_ptr, int *num_text) { if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0) { - png_debug1(1, "in 0x%lx retrieval function", + png_debug1(1, "in text retrieval function, chunk typeid = 0x%lx", (unsigned long)png_ptr->chunk_name); if (text_ptr != NULL) @@ -1036,14 +1175,14 @@ png_get_text(png_const_structrp png_ptr, png_inforp info_ptr, if (num_text != NULL) *num_text = 0; - return(0); + return 0; } #endif #ifdef PNG_tIME_SUPPORTED -png_uint_32 PNGAPI -png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr, - png_timep *mod_time) +png_uint_32 +png_get_tIME(const png_struct *png_ptr, png_info *info_ptr, + png_time **mod_time) { png_debug1(1, "in %s retrieval function", "tIME"); @@ -1051,24 +1190,25 @@ png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr, (info_ptr->valid & PNG_INFO_tIME) != 0 && mod_time != NULL) { *mod_time = &(info_ptr->mod_time); - return (PNG_INFO_tIME); + return PNG_INFO_tIME; } - return (0); + return 0; } #endif #ifdef PNG_tRNS_SUPPORTED -png_uint_32 PNGAPI -png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr, - png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color) +png_uint_32 +png_get_tRNS(const png_struct *png_ptr, png_info *info_ptr, + png_byte **trans_alpha, int *num_trans, png_color_16 **trans_color) { png_uint_32 retval = 0; + + png_debug1(1, "in %s retrieval function", "tRNS"); + if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0) { - png_debug1(1, "in %s retrieval function", "tRNS"); - if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { if (trans_alpha != NULL) @@ -1100,14 +1240,14 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr, } } - return (retval); + return retval; } #endif #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED -int PNGAPI -png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr, - png_unknown_chunkpp unknowns) +int +png_get_unknown_chunks(const png_struct *png_ptr, png_info *info_ptr, + png_unknown_chunk **unknowns) { if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL) { @@ -1115,28 +1255,28 @@ png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr, return info_ptr->unknown_chunks_num; } - return (0); + return 0; } #endif #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -png_byte PNGAPI -png_get_rgb_to_gray_status (png_const_structrp png_ptr) +png_byte +png_get_rgb_to_gray_status(const png_struct *png_ptr) { return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0); } #endif #ifdef PNG_USER_CHUNKS_SUPPORTED -png_voidp PNGAPI -png_get_user_chunk_ptr(png_const_structrp png_ptr) +void * +png_get_user_chunk_ptr(const png_struct *png_ptr) { return (png_ptr ? png_ptr->user_chunk_ptr : NULL); } #endif -png_size_t PNGAPI -png_get_compression_buffer_size(png_const_structrp png_ptr) +size_t +png_get_compression_buffer_size(const png_struct *png_ptr) { if (png_ptr == NULL) return 0; @@ -1161,28 +1301,28 @@ png_get_compression_buffer_size(png_const_structrp png_ptr) #ifdef PNG_SET_USER_LIMITS_SUPPORTED /* These functions were added to libpng 1.2.6 and were enabled * by default in libpng-1.4.0 */ -png_uint_32 PNGAPI -png_get_user_width_max (png_const_structrp png_ptr) +png_uint_32 +png_get_user_width_max(const png_struct *png_ptr) { return (png_ptr ? png_ptr->user_width_max : 0); } -png_uint_32 PNGAPI -png_get_user_height_max (png_const_structrp png_ptr) +png_uint_32 +png_get_user_height_max(const png_struct *png_ptr) { return (png_ptr ? png_ptr->user_height_max : 0); } /* This function was added to libpng 1.4.0 */ -png_uint_32 PNGAPI -png_get_chunk_cache_max (png_const_structrp png_ptr) +png_uint_32 +png_get_chunk_cache_max(const png_struct *png_ptr) { return (png_ptr ? png_ptr->user_chunk_cache_max : 0); } /* This function was added to libpng 1.4.1 */ -png_alloc_size_t PNGAPI -png_get_chunk_malloc_max (png_const_structrp png_ptr) +png_alloc_size_t +png_get_chunk_malloc_max(const png_struct *png_ptr) { return (png_ptr ? png_ptr->user_chunk_malloc_max : 0); } @@ -1190,14 +1330,14 @@ png_get_chunk_malloc_max (png_const_structrp png_ptr) /* These functions were added to libpng 1.4.0 */ #ifdef PNG_IO_STATE_SUPPORTED -png_uint_32 PNGAPI -png_get_io_state (png_const_structrp png_ptr) +png_uint_32 +png_get_io_state(const png_struct *png_ptr) { return png_ptr->io_state; } -png_uint_32 PNGAPI -png_get_io_chunk_type (png_const_structrp png_ptr) +png_uint_32 +png_get_io_chunk_type(const png_struct *png_ptr) { return png_ptr->chunk_name; } @@ -1205,177 +1345,177 @@ png_get_io_chunk_type (png_const_structrp png_ptr) #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED # ifdef PNG_GET_PALETTE_MAX_SUPPORTED -int PNGAPI -png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr) +int +png_get_palette_max(const png_struct *png_ptr, const png_info *info_ptr) { if (png_ptr != NULL && info_ptr != NULL) return png_ptr->num_palette_max; - return (-1); + return -1; } # endif #endif #ifdef PNG_APNG_SUPPORTED png_uint_32 PNGAPI -png_get_acTL(png_structp png_ptr, png_infop info_ptr, +png_get_acTL(png_struct *png_ptr, png_info *info_ptr, png_uint_32 *num_frames, png_uint_32 *num_plays) { - png_debug1(1, "in %s retrieval function", "acTL"); + png_debug1(1, "in %s retrieval function", "acTL"); - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_acTL) != 0 && - num_frames != NULL && num_plays != NULL) - { - *num_frames = info_ptr->num_frames; - *num_plays = info_ptr->num_plays; - return (1); - } + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_acTL) && + num_frames != NULL && num_plays != NULL) + { + *num_frames = info_ptr->num_frames; + *num_plays = info_ptr->num_plays; + return 1; + } - return (0); + return 0; } png_uint_32 PNGAPI -png_get_num_frames(png_structp png_ptr, png_infop info_ptr) +png_get_num_frames(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_get_num_frames()"); + png_debug(1, "in png_get_num_frames"); - if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->num_frames); - return (0); + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->num_frames; + return 0; } png_uint_32 PNGAPI -png_get_num_plays(png_structp png_ptr, png_infop info_ptr) +png_get_num_plays(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_get_num_plays()"); + png_debug(1, "in png_get_num_plays"); - if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->num_plays); - return (0); + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->num_plays; + return 0; } png_uint_32 PNGAPI -png_get_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, - png_uint_32 *width, png_uint_32 *height, - png_uint_32 *x_offset, png_uint_32 *y_offset, - png_uint_16 *delay_num, png_uint_16 *delay_den, - png_byte *dispose_op, png_byte *blend_op) +png_get_next_frame_fcTL(png_struct *png_ptr, png_info *info_ptr, + png_uint_32 *width, png_uint_32 *height, + png_uint_32 *x_offset, png_uint_32 *y_offset, + png_uint_16 *delay_num, png_uint_16 *delay_den, + png_byte *dispose_op, png_byte *blend_op) { - png_debug1(1, "in %s retrieval function", "fcTL"); + png_debug1(1, "in %s retrieval function", "fcTL"); - if (png_ptr != NULL && info_ptr != NULL && - (info_ptr->valid & PNG_INFO_fcTL) != 0 && - width != NULL && height != NULL && - x_offset != NULL && y_offset != NULL && - delay_num != NULL && delay_den != NULL && - dispose_op != NULL && blend_op != NULL) - { - *width = info_ptr->next_frame_width; - *height = info_ptr->next_frame_height; - *x_offset = info_ptr->next_frame_x_offset; - *y_offset = info_ptr->next_frame_y_offset; - *delay_num = info_ptr->next_frame_delay_num; - *delay_den = info_ptr->next_frame_delay_den; - *dispose_op = info_ptr->next_frame_dispose_op; - *blend_op = info_ptr->next_frame_blend_op; - return (1); - } + if (png_ptr != NULL && info_ptr != NULL && + (info_ptr->valid & PNG_INFO_fcTL) && + width != NULL && height != NULL && + x_offset != NULL && y_offset != NULL && + delay_num != NULL && delay_den != NULL && + dispose_op != NULL && blend_op != NULL) + { + *width = info_ptr->next_frame_width; + *height = info_ptr->next_frame_height; + *x_offset = info_ptr->next_frame_x_offset; + *y_offset = info_ptr->next_frame_y_offset; + *delay_num = info_ptr->next_frame_delay_num; + *delay_den = info_ptr->next_frame_delay_den; + *dispose_op = info_ptr->next_frame_dispose_op; + *blend_op = info_ptr->next_frame_blend_op; + return 1; + } - return (0); + return 0; } png_uint_32 PNGAPI -png_get_next_frame_width(png_structp png_ptr, png_infop info_ptr) +png_get_next_frame_width(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_get_next_frame_width()"); + png_debug(1, "in png_get_next_frame_width"); - if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->next_frame_width); - return (0); + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->next_frame_width; + return 0; } png_uint_32 PNGAPI -png_get_next_frame_height(png_structp png_ptr, png_infop info_ptr) +png_get_next_frame_height(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_get_next_frame_height()"); + png_debug(1, "in png_get_next_frame_height"); - if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->next_frame_height); - return (0); + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->next_frame_height; + return 0; } png_uint_32 PNGAPI -png_get_next_frame_x_offset(png_structp png_ptr, png_infop info_ptr) +png_get_next_frame_x_offset(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_get_next_frame_x_offset()"); + png_debug(1, "in png_get_next_frame_x_offset"); - if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->next_frame_x_offset); - return (0); + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->next_frame_x_offset; + return 0; } png_uint_32 PNGAPI -png_get_next_frame_y_offset(png_structp png_ptr, png_infop info_ptr) +png_get_next_frame_y_offset(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_get_next_frame_y_offset()"); + png_debug(1, "in png_get_next_frame_y_offset"); - if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->next_frame_y_offset); - return (0); + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->next_frame_y_offset; + return 0; } png_uint_16 PNGAPI -png_get_next_frame_delay_num(png_structp png_ptr, png_infop info_ptr) +png_get_next_frame_delay_num(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_get_next_frame_delay_num()"); + png_debug(1, "in png_get_next_frame_delay_num"); - if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->next_frame_delay_num); - return (0); + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->next_frame_delay_num; + return 0; } png_uint_16 PNGAPI -png_get_next_frame_delay_den(png_structp png_ptr, png_infop info_ptr) +png_get_next_frame_delay_den(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_get_next_frame_delay_den()"); + png_debug(1, "in png_get_next_frame_delay_den"); - if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->next_frame_delay_den); - return (0); + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->next_frame_delay_den; + return 0; } png_byte PNGAPI -png_get_next_frame_dispose_op(png_structp png_ptr, png_infop info_ptr) +png_get_next_frame_dispose_op(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_get_next_frame_dispose_op()"); + png_debug(1, "in png_get_next_frame_dispose_op"); - if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->next_frame_dispose_op); - return (0); + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->next_frame_dispose_op; + return 0; } png_byte PNGAPI -png_get_next_frame_blend_op(png_structp png_ptr, png_infop info_ptr) +png_get_next_frame_blend_op(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_get_next_frame_blend_op()"); + png_debug(1, "in png_get_next_frame_blend_op"); - if (png_ptr != NULL && info_ptr != NULL) - return (info_ptr->next_frame_blend_op); - return (0); + if (png_ptr != NULL && info_ptr != NULL) + return info_ptr->next_frame_blend_op; + return 0; } png_byte PNGAPI -png_get_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr) +png_get_first_frame_is_hidden(png_struct *png_ptr, png_info *info_ptr) { - png_debug(1, "in png_first_frame_is_hidden()"); + png_debug(1, "in png_first_frame_is_hidden"); - if (png_ptr != NULL) - return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN); + if (png_ptr != NULL) + return (png_byte)(png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN); - PNG_UNUSED(info_ptr) + PNG_UNUSED(info_ptr) - return 0; + return 0; } -#endif /* APNG */ +#endif /* PNG_APNG_SUPPORTED */ #endif /* READ || WRITE */ diff --git a/media/libpng/pnginfo.h b/media/libpng/pnginfo.h index 4b52a11b55..1a14081011 100644 --- a/media/libpng/pnginfo.h +++ b/media/libpng/pnginfo.h @@ -1,53 +1,29 @@ - -/* pnginfo.h - header file for PNG reference library +/* pnginfo.h - internal structures for libpng * - * Last changed in libpng 1.6.1 [March 28, 2013] - * Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2025 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2013,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ - /* png_info is a structure that holds the information in a PNG file so - * that the application can find out the characteristics of the image. - * If you are reading the file, this structure will tell you what is - * in the PNG file. If you are writing the file, fill in the information - * you want to put into the PNG file, using png_set_*() functions, then - * call png_write_info(). - * - * The names chosen should be very close to the PNG specification, so - * consult that document for information about the meaning of each field. - * - * With libpng < 0.95, it was only possible to directly set and read the - * the values in the png_info_struct, which meant that the contents and - * order of the values had to remain fixed. With libpng 0.95 and later, - * however, there are now functions that abstract the contents of - * png_info_struct from the application, so this makes it easier to use - * libpng with dynamic libraries, and even makes it possible to use - * libraries that don't have all of the libpng ancillary chunk-handing - * functionality. In libpng-1.5.0 this was moved into a separate private - * file that is not visible to applications. +#ifndef PNGPRIV_H +# error This file must not be included by applications; please include +#endif + +/* INTERNAL, PRIVATE definition of a PNG. * - * The following members may have allocated storage attached that should be - * cleaned up before the structure is discarded: palette, trans, text, - * pcal_purpose, pcal_units, pcal_params, hist, iccp_name, iccp_profile, - * splt_palettes, scal_unit, row_pointers, and unknowns. By default, these - * are automatically freed when the info structure is deallocated, if they were - * allocated internally by libpng. This behavior can be changed by means - * of the png_data_freer() function. + * png_info is a modifiable description of a PNG datastream. The fields inside + * this structure are accessed through png_get_() functions and modified + * using png_set_() functions. * - * More allocation details: all the chunk-reading functions that - * change these members go through the corresponding png_set_* - * functions. A function to clear these members is available: see - * png_free_data(). The png_set_* functions do not depend on being - * able to point info structure members to any of the storage they are - * passed (they make their own copies), EXCEPT that the png_set_text - * functions use the same storage passed to them in the text_ptr or - * itxt_ptr structure argument, and the png_set_rows and png_set_unknowns - * functions do not make their own copies. + * Some functions in libpng do directly access members of png_info. However, + * this should be avoided. png_struct objects contain members which hold + * caches, sometimes optimised, of the values from png_info objects, and + * png_info is not passed to the functions which read and write image data. */ #ifndef PNGINFO_H #define PNGINFO_H @@ -55,11 +31,11 @@ struct png_info_def { /* The following are necessary for every PNG file */ - 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 valid; /* valid chunk data (see PNG_INFO_ below) */ - png_size_t rowbytes; /* bytes needed to hold an untransformed row */ - png_colorp palette; /* array of color values (valid & PNG_INFO_PLTE) */ + 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 valid; /* valid chunk data (see PNG_INFO_ below) */ + size_t rowbytes; /* bytes needed to hold an untransformed row */ + png_color *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_trans; /* number of transparent palette color (tRNS) */ png_byte bit_depth; /* 1, 2, 4, 8, or 16 bits/channel (from IHDR) */ @@ -87,27 +63,39 @@ struct png_info_def * and initialize the appropriate fields below. */ -#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) - /* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are - * defined. When COLORSPACE is switched on all the colorspace-defining - * chunks should be enabled, when GAMMA is switched on all the gamma-defining - * chunks should be enabled. If this is not done it becomes possible to read - * inconsistent PNG files and assign a probably incorrect interpretation to - * the information. (In other words, by carefully choosing which chunks to - * recognize the system configuration can select an interpretation for PNG - * files containing ambiguous data and this will result in inconsistent - * behavior between different libpng builds!) - */ - png_colorspace colorspace; +#ifdef PNG_cICP_SUPPORTED + /* cICP chunk data */ + png_byte cicp_colour_primaries; + png_byte cicp_transfer_function; + png_byte cicp_matrix_coefficients; + png_byte cicp_video_full_range_flag; #endif #ifdef PNG_iCCP_SUPPORTED /* iCCP chunk data. */ - png_charp iccp_name; /* profile name */ - png_bytep iccp_profile; /* International Color Consortium profile data */ + char *iccp_name; /* profile name */ + png_byte *iccp_profile; /* International Color Consortium profile data */ png_uint_32 iccp_proflen; /* ICC profile data length */ #endif +#ifdef PNG_cLLI_SUPPORTED + png_uint_32 maxCLL; /* cd/m2 (nits) * 10,000 */ + png_uint_32 maxFALL; +#endif + +#ifdef PNG_mDCV_SUPPORTED + png_uint_16 mastering_red_x; /* CIE (xy) x * 50,000 */ + png_uint_16 mastering_red_y; + png_uint_16 mastering_green_x; + png_uint_16 mastering_green_y; + png_uint_16 mastering_blue_x; + png_uint_16 mastering_blue_y; + png_uint_16 mastering_white_x; + png_uint_16 mastering_white_y; + png_uint_32 mastering_maxDL; /* cd/m2 (nits) * 10,000 */ + png_uint_32 mastering_minDL; +#endif + #ifdef PNG_TEXT_SUPPORTED /* The tEXt, and zTXt chunks contain human-readable textual data in * uncompressed, compressed, and optionally compressed forms, respectively. @@ -119,7 +107,7 @@ struct png_info_def */ int num_text; /* number of comments read or comments to write */ int max_text; /* current size of text array */ - png_textp text; /* array of comments read or comments to write */ + png_text *text; /* array of comments read or comments to write */ #endif /* TEXT */ #ifdef PNG_tIME_SUPPORTED @@ -150,7 +138,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * single color specified that should be treated as fully transparent. * Data is valid if (valid & PNG_INFO_tRNS) is non-zero. */ - png_bytep trans_alpha; /* alpha values for paletted image */ + png_byte *trans_alpha; /* alpha values for paletted image */ png_color_16 trans_color; /* transparent color for non-palette image */ #endif @@ -185,6 +173,11 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) png_byte phys_unit_type; /* resolution type (see PNG_RESOLUTION_ below) */ #endif +#ifdef PNG_eXIf_SUPPORTED + png_uint_32 num_exif; /* Added at libpng-1.6.31 */ + png_byte *exif; +#endif + #ifdef PNG_hIST_SUPPORTED /* The hIST chunk contains the relative frequency or importance of the * various palette entries, so that a viewer can intelligently select a @@ -192,7 +185,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * values in the range [0,65535]. Data valid if (valid & PNG_INFO_hIST) * is non-zero. */ - png_uint_16p hist; + png_uint_16 *hist; #endif #ifdef PNG_pCAL_SUPPORTED @@ -207,11 +200,11 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) * implemented, and for a description of the ASCII parameter strings. * Data values are valid if (valid & PNG_INFO_pCAL) non-zero. */ - png_charp pcal_purpose; /* pCAL chunk description string */ + char *pcal_purpose; /* pCAL chunk description string */ png_int_32 pcal_X0; /* minimum value */ png_int_32 pcal_X1; /* maximum value */ - png_charp pcal_units; /* Latin-1 string giving physical units */ - png_charpp pcal_params; /* ASCII strings containing parameter values */ + char *pcal_units; /* Latin-1 string giving physical units */ + char **pcal_params; /* ASCII strings containing parameter values */ png_byte pcal_type; /* equation type (see PNG_EQUATION_ below) */ png_byte pcal_nparams; /* number of parameters given in pcal_params */ #endif @@ -221,7 +214,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED /* Storage for unknown chunks that the library doesn't recognize. */ - png_unknown_chunkp unknown_chunks; + png_unknown_chunk *unknown_chunks; /* The type of this field is limited by the type of * png_struct::user_chunk_cache_max, else overflow can occur. @@ -231,7 +224,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) #ifdef PNG_sPLT_SUPPORTED /* Data on sPLT chunks (there may be more than one). */ - png_sPLT_tp splt_palettes; + png_sPLT_t *splt_palettes; int splt_palettes_num; /* Match type returned by png_get API */ #endif @@ -239,20 +232,32 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) /* The sCAL chunk describes the actual physical dimensions of the * subject matter of the graphic. The chunk contains a unit specification * 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 * non-zero. */ png_byte scal_unit; /* unit of physical scale */ - png_charp scal_s_width; /* string containing height */ - png_charp scal_s_height; /* string containing width */ + char *scal_s_width; /* string containing height */ + char *scal_s_height; /* string containing width */ #endif #ifdef PNG_INFO_IMAGE_SUPPORTED /* Memory has been allocated if (valid & PNG_ALLOCATED_INFO_ROWS) non-zero */ /* Data valid if (valid & PNG_INFO_IDAT) non-zero */ - png_bytepp row_pointers; /* the image bits */ + png_byte **row_pointers; /* the image bits */ +#endif + +#ifdef PNG_cHRM_SUPPORTED + png_xy cHRM; +#endif + +#ifdef PNG_gAMA_SUPPORTED + png_fixed_point gamma; +#endif + +#ifdef PNG_sRGB_SUPPORTED + int rendering_intent; #endif #ifdef PNG_APNG_SUPPORTED @@ -267,6 +272,5 @@ defined(PNG_READ_BACKGROUND_SUPPORTED) png_byte next_frame_dispose_op; png_byte next_frame_blend_op; #endif - }; #endif /* PNGINFO_H */ diff --git a/media/libpng/pnglibconf.h.prebuilt b/media/libpng/pnglibconf.h.prebuilt new file mode 100644 index 0000000000..a932652411 --- /dev/null +++ b/media/libpng/pnglibconf.h.prebuilt @@ -0,0 +1,224 @@ +/* pnglibconf.h - library build configuration */ + +/* libpng version 1.8.0.git */ + +/* Copyright (c) 2018-2026 Cosmin Truta */ +/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ + +/* This code is released under the libpng license. */ +/* For conditions of distribution and use, see the disclaimer */ +/* and license in png.h */ + +/* pnglibconf.h */ +/* Machine generated file: DO NOT EDIT */ +/* Derived from: scripts/pnglibconf/pnglibconf.dfa */ +#ifndef PNGLCONF_H +#define PNGLCONF_H +/* options */ +#define PNG_16BIT_SUPPORTED +#define PNG_APNG_SUPPORTED +#define PNG_BENIGN_ERRORS_SUPPORTED +#define PNG_BENIGN_READ_ERRORS_SUPPORTED +/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/ +#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED +#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_COLORSPACE_SUPPORTED +#define PNG_CONSOLE_IO_SUPPORTED +#define PNG_CONVERT_tIME_SUPPORTED +/*#undef PNG_DISABLE_ADLER32_CHECK_SUPPORTED*/ +#define PNG_EASY_ACCESS_SUPPORTED +#define PNG_ERROR_TEXT_SUPPORTED +#define PNG_FIXED_POINT_SUPPORTED +#define PNG_FLOATING_ARITHMETIC_SUPPORTED +#define PNG_FLOATING_POINT_SUPPORTED +#define PNG_FORMAT_AFIRST_SUPPORTED +#define PNG_FORMAT_BGR_SUPPORTED +#define PNG_GAMMA_SUPPORTED +#define PNG_GET_PALETTE_MAX_SUPPORTED +#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED +#define PNG_INCH_CONVERSIONS_SUPPORTED +#define PNG_INFO_IMAGE_SUPPORTED +#define PNG_IO_STATE_SUPPORTED +#define PNG_MNG_FEATURES_SUPPORTED +#define PNG_PROGRESSIVE_READ_SUPPORTED +#define PNG_READ_16BIT_SUPPORTED +#define PNG_READ_ALPHA_MODE_SUPPORTED +#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_READ_APNG_SUPPORTED +#define PNG_READ_BACKGROUND_SUPPORTED +#define PNG_READ_BGR_SUPPORTED +#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_READ_COMPOSITE_NODIV_SUPPORTED +#define PNG_READ_COMPRESSED_TEXT_SUPPORTED +#define PNG_READ_EXPAND_16_SUPPORTED +#define PNG_READ_EXPAND_SUPPORTED +#define PNG_READ_FILLER_SUPPORTED +#define PNG_READ_GAMMA_SUPPORTED +#define PNG_READ_GET_PALETTE_MAX_SUPPORTED +#define PNG_READ_GRAY_TO_RGB_SUPPORTED +#define PNG_READ_INTERLACING_SUPPORTED +#define PNG_READ_INT_FUNCTIONS_SUPPORTED +#define PNG_READ_INVERT_ALPHA_SUPPORTED +#define PNG_READ_INVERT_SUPPORTED +#define PNG_READ_OPT_PLTE_SUPPORTED +#define PNG_READ_PACKSWAP_SUPPORTED +#define PNG_READ_PACK_SUPPORTED +#define PNG_READ_QUANTIZE_SUPPORTED +#define PNG_READ_RGB_TO_GRAY_SUPPORTED +#define PNG_READ_SCALE_16_TO_8_SUPPORTED +#define PNG_READ_SHIFT_SUPPORTED +#define PNG_READ_STRIP_16_TO_8_SUPPORTED +#define PNG_READ_STRIP_ALPHA_SUPPORTED +#define PNG_READ_SUPPORTED +#define PNG_READ_SWAP_ALPHA_SUPPORTED +#define PNG_READ_SWAP_SUPPORTED +#define PNG_READ_TEXT_SUPPORTED +#define PNG_READ_TRANSFORMS_SUPPORTED +#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_READ_USER_CHUNKS_SUPPORTED +#define PNG_READ_USER_TRANSFORM_SUPPORTED +#define PNG_READ_bKGD_SUPPORTED +#define PNG_READ_cHRM_SUPPORTED +#define PNG_READ_cICP_SUPPORTED +#define PNG_READ_cLLI_SUPPORTED +#define PNG_READ_eXIf_SUPPORTED +#define PNG_READ_gAMA_SUPPORTED +#define PNG_READ_hIST_SUPPORTED +#define PNG_READ_iCCP_SUPPORTED +#define PNG_READ_iTXt_SUPPORTED +#define PNG_READ_mDCV_SUPPORTED +#define PNG_READ_oFFs_SUPPORTED +#define PNG_READ_pCAL_SUPPORTED +#define PNG_READ_pHYs_SUPPORTED +#define PNG_READ_sBIT_SUPPORTED +#define PNG_READ_sCAL_SUPPORTED +#define PNG_READ_sPLT_SUPPORTED +#define PNG_READ_sRGB_SUPPORTED +#define PNG_READ_tEXt_SUPPORTED +#define PNG_READ_tIME_SUPPORTED +#define PNG_READ_tRNS_SUPPORTED +#define PNG_READ_zTXt_SUPPORTED +#define PNG_SAVE_INT_32_SUPPORTED +#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SEQUENTIAL_READ_SUPPORTED +#define PNG_SETJMP_SUPPORTED +#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_SET_USER_LIMITS_SUPPORTED +#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED +#define PNG_SIMPLIFIED_READ_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED +#define PNG_SIMPLIFIED_WRITE_SUPPORTED +#define PNG_STDIO_SUPPORTED +#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_TARGET_SPECIFIC_CODE_SUPPORTED +#define PNG_TEXT_SUPPORTED +#define PNG_TIME_RFC1123_SUPPORTED +#define PNG_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_USER_CHUNKS_SUPPORTED +#define PNG_USER_LIMITS_SUPPORTED +#define PNG_USER_MEM_SUPPORTED +#define PNG_USER_TRANSFORM_INFO_SUPPORTED +#define PNG_USER_TRANSFORM_PTR_SUPPORTED +#define PNG_WARNINGS_SUPPORTED +#define PNG_WRITE_16BIT_SUPPORTED +#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED +#define PNG_WRITE_APNG_SUPPORTED +#define PNG_WRITE_BGR_SUPPORTED +#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED +#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED +#define PNG_WRITE_FILLER_SUPPORTED +#define PNG_WRITE_FILTER_SUPPORTED +#define PNG_WRITE_FLUSH_SUPPORTED +#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED +#define PNG_WRITE_INTERLACING_SUPPORTED +#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED +#define PNG_WRITE_INVERT_ALPHA_SUPPORTED +#define PNG_WRITE_INVERT_SUPPORTED +#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED +#define PNG_WRITE_PACKSWAP_SUPPORTED +#define PNG_WRITE_PACK_SUPPORTED +#define PNG_WRITE_SHIFT_SUPPORTED +#define PNG_WRITE_SUPPORTED +#define PNG_WRITE_SWAP_ALPHA_SUPPORTED +#define PNG_WRITE_SWAP_SUPPORTED +#define PNG_WRITE_TEXT_SUPPORTED +#define PNG_WRITE_TRANSFORMS_SUPPORTED +#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED +#define PNG_WRITE_USER_TRANSFORM_SUPPORTED +#define PNG_WRITE_bKGD_SUPPORTED +#define PNG_WRITE_cHRM_SUPPORTED +#define PNG_WRITE_cICP_SUPPORTED +#define PNG_WRITE_cLLI_SUPPORTED +#define PNG_WRITE_eXIf_SUPPORTED +#define PNG_WRITE_gAMA_SUPPORTED +#define PNG_WRITE_hIST_SUPPORTED +#define PNG_WRITE_iCCP_SUPPORTED +#define PNG_WRITE_iTXt_SUPPORTED +#define PNG_WRITE_mDCV_SUPPORTED +#define PNG_WRITE_oFFs_SUPPORTED +#define PNG_WRITE_pCAL_SUPPORTED +#define PNG_WRITE_pHYs_SUPPORTED +#define PNG_WRITE_sBIT_SUPPORTED +#define PNG_WRITE_sCAL_SUPPORTED +#define PNG_WRITE_sPLT_SUPPORTED +#define PNG_WRITE_sRGB_SUPPORTED +#define PNG_WRITE_tEXt_SUPPORTED +#define PNG_WRITE_tIME_SUPPORTED +#define PNG_WRITE_tRNS_SUPPORTED +#define PNG_WRITE_zTXt_SUPPORTED +#define PNG_bKGD_SUPPORTED +#define PNG_cHRM_SUPPORTED +#define PNG_cICP_SUPPORTED +#define PNG_cLLI_SUPPORTED +#define PNG_eXIf_SUPPORTED +#define PNG_gAMA_SUPPORTED +#define PNG_hIST_SUPPORTED +#define PNG_iCCP_SUPPORTED +#define PNG_iTXt_SUPPORTED +#define PNG_mDCV_SUPPORTED +#define PNG_oFFs_SUPPORTED +#define PNG_pCAL_SUPPORTED +#define PNG_pHYs_SUPPORTED +#define PNG_sBIT_SUPPORTED +#define PNG_sCAL_SUPPORTED +#define PNG_sPLT_SUPPORTED +#define PNG_sRGB_SUPPORTED +#define PNG_tEXt_SUPPORTED +#define PNG_tIME_SUPPORTED +#define PNG_tRNS_SUPPORTED +#define PNG_zTXt_SUPPORTED +/* end of options */ +/* settings */ +#define PNG_API_RULE 0 +#define PNG_DEFAULT_READ_MACROS 1 +#define PNG_GAMMA_THRESHOLD_FIXED 5000 +#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE +#define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern +#define PNG_MAX_GAMMA_8 11 +#define PNG_QUANTIZE_BLUE_BITS 5 +#define PNG_QUANTIZE_GREEN_BITS 5 +#define PNG_QUANTIZE_RED_BITS 5 +#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1) +#define PNG_TEXT_Z_DEFAULT_STRATEGY 0 +#define PNG_USER_CHUNK_CACHE_MAX 1000 +#define PNG_USER_CHUNK_MALLOC_MAX 8000000 +#define PNG_USER_HEIGHT_MAX 1000000 +#define PNG_USER_WIDTH_MAX 1000000 +#define PNG_ZBUF_SIZE 8192 +#define PNG_ZLIB_VERNUM 0 /* unknown */ +#define PNG_Z_DEFAULT_COMPRESSION (-1) +#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0 +#define PNG_Z_DEFAULT_STRATEGY 1 +#define PNG_sCAL_PRECISION 5 +#define PNG_sRGB_PROFILE_CHECKS 2 +/* end of settings */ +#endif /* PNGLCONF_H */ diff --git a/media/libpng/pngmem.c b/media/libpng/pngmem.c index ff3ef7e88c..f42dcdc283 100644 --- a/media/libpng/pngmem.c +++ b/media/libpng/pngmem.c @@ -1,10 +1,9 @@ - /* pngmem.c - stub functions for memory allocation * - * Last changed in libpng 1.6.26 [October 20, 2016] + * Copyright (c) 2018-2025 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -22,7 +21,7 @@ #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) /* Free a png_struct */ void /* PRIVATE */ -png_destroy_png_struct(png_structrp png_ptr) +png_destroy_png_struct(png_struct *png_ptr) { if (png_ptr != NULL) { @@ -46,10 +45,11 @@ png_destroy_png_struct(png_structrp png_ptr) * need to allocate exactly 64K, so whatever you call here must * have the ability to do that. */ -PNG_FUNCTION(png_voidp,PNGAPI -png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +PNG_FUNCTION(void *, +png_calloc,(const png_struct *png_ptr, png_alloc_size_t size), + PNG_ALLOCATED) { - png_voidp ret; + void *ret; ret = png_malloc(png_ptr, size); @@ -64,8 +64,8 @@ png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) * Checking and error handling must happen outside this routine; it returns NULL * if the allocation cannot be done (for any reason.) */ -PNG_FUNCTION(png_voidp /* PRIVATE */, -png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), +PNG_FUNCTION(void * /* PRIVATE */, +png_malloc_base,(const png_struct *png_ptr, png_alloc_size_t size), PNG_ALLOCATED) { /* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS @@ -73,30 +73,29 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), * to implement a user memory handler. This checks to be sure it isn't * called with big numbers. */ -#ifndef PNG_USER_MEM_SUPPORTED - PNG_UNUSED(png_ptr) -#endif +# ifdef PNG_MAX_MALLOC_64K + /* This is support for legacy systems which had segmented addressing + * limiting the maximum allocation size to 65536. It takes precedence + * over PNG_SIZE_MAX which is set to 65535 on true 16-bit systems. + * + * TODO: libpng-1.8: finally remove both cases. + */ + if (size > 65536U) return NULL; +# endif - /* Some compilers complain that this is always true. However, it - * can be false when integer overflow happens. + /* This is checked too because the system malloc call below takes a (size_t). */ - if (size > 0 && size <= PNG_SIZE_MAX -# ifdef PNG_MAX_MALLOC_64K - && size <= 65536U -# endif - ) - { -#ifdef PNG_USER_MEM_SUPPORTED - if (png_ptr != NULL && png_ptr->malloc_fn != NULL) - return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size); + if (size > PNG_SIZE_MAX) return NULL; - else -#endif - return malloc((size_t)size); /* checked for truncation above */ - } +# ifdef PNG_USER_MEM_SUPPORTED + if (png_ptr != NULL && png_ptr->malloc_fn != NULL) + return png_ptr->malloc_fn(png_constcast(png_struct *,png_ptr), size); +# else + PNG_UNUSED(png_ptr) +# endif - else - return NULL; + /* Use the system malloc */ + return malloc((size_t)/*SAFE*/size); /* checked for truncation above */ } #if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\ @@ -105,8 +104,8 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), * that arises because of the checks in png_realloc_array that are repeated in * png_malloc_array. */ -static png_voidp -png_malloc_array_checked(png_const_structrp png_ptr, int nelements, +static void * +png_malloc_array_checked(const png_struct *png_ptr, int nelements, size_t element_size) { png_alloc_size_t req = (png_alloc_size_t)nelements; /* known to be > 0 */ @@ -118,9 +117,10 @@ png_malloc_array_checked(png_const_structrp png_ptr, int nelements, return NULL; } -PNG_FUNCTION(png_voidp /* PRIVATE */, -png_malloc_array,(png_const_structrp png_ptr, int nelements, - size_t element_size),PNG_ALLOCATED) +PNG_FUNCTION(void * /* PRIVATE */, +png_malloc_array,(const png_struct *png_ptr, int nelements, + size_t element_size), + PNG_ALLOCATED) { if (nelements <= 0 || element_size == 0) png_error(png_ptr, "internal error: array alloc"); @@ -128,9 +128,10 @@ png_malloc_array,(png_const_structrp png_ptr, int nelements, return png_malloc_array_checked(png_ptr, nelements, element_size); } -PNG_FUNCTION(png_voidp /* PRIVATE */, -png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, - int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED) +PNG_FUNCTION(void * /* PRIVATE */, +png_realloc_array,(const png_struct *png_ptr, const void *old_array, + int old_elements, int add_elements, size_t element_size), + PNG_ALLOCATED) { /* These are internal errors: */ if (add_elements <= 0 || element_size == 0 || old_elements < 0 || @@ -142,7 +143,7 @@ png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, */ if (add_elements <= INT_MAX - old_elements) { - png_voidp new_array = png_malloc_array_checked(png_ptr, + void *new_array = png_malloc_array_checked(png_ptr, old_elements+add_elements, element_size); if (new_array != NULL) @@ -168,10 +169,11 @@ png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array, * png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate * function png_malloc_default is also provided. */ -PNG_FUNCTION(png_voidp,PNGAPI -png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) +PNG_FUNCTION(void *, +png_malloc,(const png_struct *png_ptr, png_alloc_size_t size), + PNG_ALLOCATED) { - png_voidp ret; + void *ret; if (png_ptr == NULL) return NULL; @@ -185,11 +187,11 @@ png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) } #ifdef PNG_USER_MEM_SUPPORTED -PNG_FUNCTION(png_voidp,PNGAPI -png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size), +PNG_FUNCTION(void *, +png_malloc_default,(const png_struct *png_ptr, png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED) { - png_voidp ret; + void *ret; if (png_ptr == NULL) return NULL; @@ -208,13 +210,13 @@ png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size), * function will issue a png_warning and return NULL instead of issuing a * png_error, if it fails to allocate the requested memory. */ -PNG_FUNCTION(png_voidp,PNGAPI -png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size), +PNG_FUNCTION(void *, +png_malloc_warn,(const png_struct *png_ptr, png_alloc_size_t size), PNG_ALLOCATED) { if (png_ptr != NULL) { - png_voidp ret = png_malloc_base(png_ptr, size); + void *ret = png_malloc_base(png_ptr, size); if (ret != NULL) return ret; @@ -228,22 +230,23 @@ png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size), /* Free a pointer allocated by png_malloc(). If ptr is NULL, return * without taking any action. */ -void PNGAPI -png_free(png_const_structrp png_ptr, png_voidp ptr) +void +png_free(const png_struct *png_ptr, void *ptr) { if (png_ptr == NULL || ptr == NULL) return; #ifdef PNG_USER_MEM_SUPPORTED if (png_ptr->free_fn != NULL) - png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr); + png_ptr->free_fn(png_constcast(png_struct *,png_ptr), ptr); else png_free_default(png_ptr, ptr); } -PNG_FUNCTION(void,PNGAPI -png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED) +PNG_FUNCTION(void, +png_free_default,(const png_struct *png_ptr, void *ptr), + PNG_DEPRECATED) { if (png_ptr == NULL || ptr == NULL) return; @@ -256,9 +259,9 @@ png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED) /* This function is called when the application wants to use another method * of allocating and freeing memory. */ -void PNGAPI -png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr - malloc_fn, png_free_ptr free_fn) +void +png_set_mem_fn(png_struct *png_ptr, void *mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn) { if (png_ptr != NULL) { @@ -272,8 +275,8 @@ png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr * functions. The application should free any memory associated with this * pointer before png_write_destroy and png_read_destroy are called. */ -png_voidp PNGAPI -png_get_mem_ptr(png_const_structrp png_ptr) +void * +png_get_mem_ptr(const png_struct *png_ptr) { if (png_ptr == NULL) return NULL; diff --git a/media/libpng/pngnow.png b/media/libpng/pngnow.png new file mode 100644 index 0000000000..82793ebddb Binary files /dev/null and b/media/libpng/pngnow.png differ diff --git a/media/libpng/pngpread.c b/media/libpng/pngpread.c index a61ad92890..978559adeb 100644 --- a/media/libpng/pngpread.c +++ b/media/libpng/pngpread.c @@ -1,10 +1,9 @@ - /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -32,9 +31,24 @@ if (png_ptr->push_length + 4 > png_ptr->buffer_size) \ if (png_ptr->buffer_size < N) \ { png_push_save_buffer(png_ptr); return; } -void PNGAPI -png_process_data(png_structrp png_ptr, png_inforp info_ptr, - png_bytep buffer, png_size_t buffer_size) +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */ + +/* Start of interlace block */ +static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; +/* Offset to next interlace block */ +static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +/* Start of interlace block in the y direction */ +static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; +/* Offset to next interlace block in the y direction */ +static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + +/* TODO: Move these arrays to a common utility module to avoid duplication. */ +#endif + +void +png_process_data(png_struct *png_ptr, png_info *info_ptr, + png_byte *buffer, size_t buffer_size) { if (png_ptr == NULL || info_ptr == NULL) return; @@ -47,8 +61,8 @@ png_process_data(png_structrp png_ptr, png_inforp info_ptr, } } -png_size_t PNGAPI -png_process_data_pause(png_structrp png_ptr, int save) +size_t +png_process_data_pause(png_struct *png_ptr, int save) { if (png_ptr != NULL) { @@ -60,7 +74,7 @@ png_process_data_pause(png_structrp png_ptr, int save) else { /* 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; /* So subtract the saved buffer size, unless all the data @@ -74,8 +88,8 @@ png_process_data_pause(png_structrp png_ptr, int save) return 0; } -png_uint_32 PNGAPI -png_process_data_skip(png_structrp png_ptr) +png_uint_32 +png_process_data_skip(png_struct *png_ptr) { /* TODO: Deprecate and remove this API. * Somewhere the implementation of this seems to have been lost, @@ -91,7 +105,7 @@ png_process_data_skip(png_structrp png_ptr) * doing before we ran out of data... */ void /* PRIVATE */ -png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) +png_process_some_data(png_struct *png_ptr, png_info *info_ptr) { if (png_ptr == NULL) return; @@ -131,10 +145,10 @@ png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) * routine. */ void /* PRIVATE */ -png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) +png_push_read_sig(png_struct *png_ptr, png_info *info_ptr) { - png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ - num_to_check = 8 - num_checked; + size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */ + size_t num_to_check = 8 - num_checked; if (png_ptr->buffer_size < num_to_check) { @@ -145,10 +159,10 @@ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) num_to_check); png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); - if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) + if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0) { if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0) png_error(png_ptr, "Not a PNG file"); else @@ -164,7 +178,7 @@ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) } void /* PRIVATE */ -png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) +png_push_read_chunk(png_struct *png_ptr, png_info *info_ptr) { png_uint_32 chunk_name; #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED @@ -179,16 +193,8 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) */ if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0) { - png_byte chunk_length[4]; - png_byte chunk_tag[4]; - PNG_PUSH_SAVE_BUFFER_IF_LT(8) - png_push_fill_buffer(png_ptr, chunk_length, 4); - png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); - png_reset_crc(png_ptr); - png_crc_read(png_ptr, chunk_tag, 4); - png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag); - png_check_chunk_name(png_ptr, png_ptr->chunk_name); + png_ptr->push_length = png_read_chunk_header(png_ptr); png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; } @@ -200,51 +206,73 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) { if (chunk_name == png_IDAT) { - /* Discard trailing IDATs for the first frame */ - if ((png_ptr->mode & PNG_HAVE_fcTL) != 0 || - png_ptr->num_frames_read > 1) - png_error(png_ptr, "out of place IDAT"); + /* Discard trailing IDATs for the first frame. */ + if (png_ptr->mode & PNG_HAVE_fcTL || png_ptr->num_frames_read > 1) + png_error(png_ptr, "Misplaced IDAT in APNG stream"); + + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } - PNG_PUSH_SAVE_BUFFER_IF_FULL png_crc_finish(png_ptr, png_ptr->push_length); png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + return; } - else if (chunk_name == png_fdAT) { - PNG_PUSH_SAVE_BUFFER_IF_LT(4) - png_ensure_sequence_number(png_ptr, 4); - - if ((png_ptr->mode & PNG_HAVE_fcTL) == 0) + if (!(png_ptr->mode & PNG_HAVE_fcTL)) { - /* Discard trailing fdATs for frames other than the first */ + /* Discard trailing fdATs for frames other than the first. */ if (png_ptr->num_frames_read < 2) - png_error(png_ptr, "out of place fdAT"); + png_error(png_ptr, "Misplaced fdAT in APNG stream"); - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_crc_finish(png_ptr, png_ptr->push_length); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + + png_ensure_sequence_number(png_ptr, png_ptr->push_length); + png_crc_finish(png_ptr, png_ptr->push_length - 4); png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + return; } else { - /* frame data follows */ + /* Frame data follows. */ + if (png_ptr->buffer_size < 4) + { + png_push_save_buffer(png_ptr); + return; + } + + png_ensure_sequence_number(png_ptr, png_ptr->push_length); png_ptr->idat_size = png_ptr->push_length - 4; png_ptr->mode |= PNG_HAVE_IDAT; png_ptr->process_mode = PNG_READ_IDAT_MODE; + + return; } } else if (chunk_name == png_fcTL) { - PNG_PUSH_SAVE_BUFFER_IF_FULL + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_read_reset(png_ptr); png_ptr->mode &= ~PNG_HAVE_fcTL; png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); - if ((png_ptr->mode & PNG_HAVE_fcTL) == 0) - png_error(png_ptr, "missing required fcTL chunk"); + if (!(png_ptr->mode & PNG_HAVE_fcTL)) + png_error(png_ptr, "Missing required fcTL chunk in APNG stream"); png_read_reinit(png_ptr, info_ptr); png_progressive_read_reset(png_ptr); @@ -253,29 +281,26 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) (*(png_ptr->frame_info_fn))(png_ptr, png_ptr->num_frames_read); png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; - } - else if (chunk_name == png_IEND) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_warning(png_ptr, "Number of actual frames fewer than expected"); - png_crc_finish(png_ptr, png_ptr->push_length); - png_ptr->process_mode = PNG_READ_DONE_MODE; - png_push_have_end(png_ptr, info_ptr); + return; } else { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_warning(png_ptr, "Skipped (ignored) a chunk " - "between APNG chunks"); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_warning(png_ptr, "Ignoring unexpected chunk in APNG sequence"); png_crc_finish(png_ptr, png_ptr->push_length); png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + return; } return; } -#endif /* READ_APNG */ +#endif /* PNG_READ_APNG_SUPPORTED */ if (chunk_name == png_IDAT) { @@ -306,19 +331,27 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) png_benign_error(png_ptr, "Too many IDATs found"); } + else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) + { + /* These flags must be set consistently for all non-IDAT chunks, + * including the unknown chunks. + */ + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT | PNG_AFTER_IDAT; + } + if (chunk_name == png_IHDR) { if (png_ptr->push_length != 13) png_error(png_ptr, "Invalid IHDR length"); PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); + png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length); } else if (chunk_name == png_IEND) { PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); + png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length); png_ptr->process_mode = PNG_READ_DONE_MODE; png_push_have_end(png_ptr, info_ptr); @@ -335,12 +368,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) } #endif - else if (chunk_name == png_PLTE) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); - } - else if (chunk_name == png_IDAT) { #ifdef PNG_READ_APNG_SUPPORTED @@ -356,170 +383,44 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) return; } -#ifdef PNG_READ_gAMA_SUPPORTED - else if (png_ptr->chunk_name == png_gAMA) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_sBIT_SUPPORTED - else if (png_ptr->chunk_name == png_sBIT) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_cHRM_SUPPORTED - else if (png_ptr->chunk_name == png_cHRM) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_sRGB_SUPPORTED - else if (chunk_name == png_sRGB) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_iCCP_SUPPORTED - else if (png_ptr->chunk_name == png_iCCP) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_sPLT_SUPPORTED - else if (chunk_name == png_sPLT) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_tRNS_SUPPORTED - else if (chunk_name == png_tRNS) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_bKGD_SUPPORTED - else if (chunk_name == png_bKGD) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_hIST_SUPPORTED - else if (chunk_name == png_hIST) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_pHYs_SUPPORTED - else if (chunk_name == png_pHYs) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_oFFs_SUPPORTED - else if (chunk_name == png_oFFs) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); - } -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED - else if (chunk_name == png_pCAL) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_sCAL_SUPPORTED - else if (chunk_name == png_sCAL) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_tIME_SUPPORTED - else if (chunk_name == png_tIME) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_tEXt_SUPPORTED - else if (chunk_name == png_tEXt) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_zTXt_SUPPORTED - else if (chunk_name == png_zTXt) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); - } - -#endif -#ifdef PNG_READ_iTXt_SUPPORTED - else if (chunk_name == png_iTXt) - { - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); - } -#endif - #ifdef PNG_READ_APNG_SUPPORTED else if (chunk_name == png_acTL) { - PNG_PUSH_SAVE_BUFFER_IF_FULL + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_acTL(png_ptr, info_ptr, png_ptr->push_length); } else if (chunk_name == png_fcTL) { - PNG_PUSH_SAVE_BUFFER_IF_FULL + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_handle_fcTL(png_ptr, info_ptr, png_ptr->push_length); } -#endif /* READ_APNG */ +#endif /* PNG_READ_APNG_SUPPORTED */ + else { PNG_PUSH_SAVE_BUFFER_IF_FULL - png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, - PNG_HANDLE_CHUNK_AS_DEFAULT); + png_handle_chunk(png_ptr, info_ptr, png_ptr->push_length); } png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; } -void PNGCBAPI -png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) +void +png_push_fill_buffer(png_struct *png_ptr, png_byte *buffer, size_t length) { - png_bytep ptr; + png_byte *ptr; if (png_ptr == NULL) return; @@ -527,7 +428,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) ptr = buffer; if (png_ptr->save_buffer_size != 0) { - png_size_t save_size; + size_t save_size; if (length < png_ptr->save_buffer_size) save_size = length; @@ -544,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) { - png_size_t save_size; + size_t save_size; if (length < png_ptr->current_buffer_size) save_size = length; @@ -560,15 +461,15 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) } void /* PRIVATE */ -png_push_save_buffer(png_structrp png_ptr) +png_push_save_buffer(png_struct *png_ptr) { if (png_ptr->save_buffer_size != 0) { if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) { - png_size_t i, istop; - png_bytep sp; - png_bytep dp; + size_t i, istop; + png_byte *sp; + png_byte *dp; istop = png_ptr->save_buffer_size; for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; @@ -581,8 +482,8 @@ png_push_save_buffer(png_structrp png_ptr) if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > png_ptr->save_buffer_max) { - png_size_t new_max; - png_bytep old_buffer; + size_t new_max; + png_byte *old_buffer; if (png_ptr->save_buffer_size > PNG_SIZE_MAX - (png_ptr->current_buffer_size + 256)) @@ -592,8 +493,8 @@ png_push_save_buffer(png_structrp png_ptr) new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; old_buffer = png_ptr->save_buffer; - png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, - (png_size_t)new_max); + png_ptr->save_buffer = (png_byte *)png_malloc_warn(png_ptr, + (size_t)new_max); if (png_ptr->save_buffer == NULL) { @@ -620,8 +521,8 @@ png_push_save_buffer(png_structrp png_ptr) } void /* PRIVATE */ -png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) +png_push_restore_buffer(png_struct *png_ptr, png_byte *buffer, + size_t buffer_length) { png_ptr->current_buffer = buffer; png_ptr->current_buffer_size = buffer_length; @@ -630,7 +531,7 @@ png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer, } void /* PRIVATE */ -png_push_read_IDAT(png_structrp png_ptr) +png_push_read_IDAT(png_struct *png_ptr) { if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0) { @@ -653,25 +554,28 @@ png_push_read_IDAT(png_structrp png_ptr) #ifdef PNG_READ_APNG_SUPPORTED if (png_ptr->chunk_name != png_fdAT && png_ptr->num_frames_read > 0) { - if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) != 0) - { - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - if (png_ptr->frame_end_fn != NULL) - (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read); - png_ptr->num_frames_read++; - return; - } - else - { - if (png_ptr->chunk_name == png_IEND) - png_error(png_ptr, "Not enough image data"); - PNG_PUSH_SAVE_BUFFER_IF_FULL - png_warning(png_ptr, "Skipping (ignoring) a chunk between " - "APNG chunks"); - png_crc_finish(png_ptr, png_ptr->push_length); - png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; - return; - } + if (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) + { + png_ptr->process_mode = PNG_READ_CHUNK_MODE; + if (png_ptr->frame_end_fn != NULL) + (*(png_ptr->frame_end_fn))(png_ptr, png_ptr->num_frames_read); + png_ptr->num_frames_read++; + return; + } + else + { + if (png_ptr->chunk_name == png_IEND) + png_error(png_ptr, "Not enough image data"); + if (png_ptr->push_length + 4 > png_ptr->buffer_size) + { + png_push_save_buffer(png_ptr); + return; + } + png_warning(png_ptr, "Ignoring unexpected chunk in APNG sequence"); + png_crc_finish(png_ptr, png_ptr->push_length); + png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; + return; + } } else #endif @@ -700,7 +604,7 @@ png_push_read_IDAT(png_structrp png_ptr) #ifdef PNG_READ_APNG_SUPPORTED if (png_ptr->num_frames_read > 0) { - png_ensure_sequence_number(png_ptr, 4); + png_ensure_sequence_number(png_ptr, png_ptr->push_length); png_ptr->idat_size -= 4; } #endif @@ -708,7 +612,7 @@ png_push_read_IDAT(png_structrp png_ptr) 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; /* We want the smaller of 'idat_size' and 'current_buffer_size', but they @@ -718,7 +622,7 @@ png_push_read_IDAT(png_structrp png_ptr) * will break on either 16-bit or 64-bit platforms. */ if (idat_size < save_size) - save_size = (png_size_t)idat_size; + save_size = (size_t)idat_size; else idat_size = (png_uint_32)save_size; @@ -735,7 +639,7 @@ png_push_read_IDAT(png_structrp png_ptr) 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; /* We want the smaller of 'idat_size' and 'current_buffer_size', but they @@ -744,7 +648,7 @@ png_push_read_IDAT(png_structrp png_ptr) * larger - this cannot overflow. */ if (idat_size < save_size) - save_size = (png_size_t)idat_size; + save_size = (size_t)idat_size; else idat_size = (png_uint_32)save_size; @@ -770,17 +674,16 @@ png_push_read_IDAT(png_structrp png_ptr) } void /* PRIVATE */ -png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, - png_size_t buffer_length) +png_process_IDAT_data(png_struct *png_ptr, png_byte *buffer, + size_t buffer_length) { /* The caller checks for a non-zero buffer length. */ if (!(buffer_length > 0) || buffer == NULL) png_error(png_ptr, "No IDAT data (internal error)"); #ifdef PNG_READ_APNG_SUPPORTED - /* If the app is not APNG-aware, decode only the first frame */ - if ((png_ptr->apng_flags & PNG_APNG_APP) == 0 && - png_ptr->num_frames_read > 0) + /* If the app is not APNG-aware, decode only the first frame. */ + if (!(png_ptr->apng_flags & PNG_APNG_APP) && png_ptr->num_frames_read > 0) { png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED; return; @@ -824,7 +727,7 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, * change the current behavior (see comments in inflate.c * for why this doesn't happen at present with zlib 1.2.5). */ - ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH); + ret = png_zlib_inflate(png_ptr, Z_SYNC_FLUSH); /* Check for any failure before proceeding. */ if (ret != Z_OK && ret != Z_STREAM_END) @@ -892,7 +795,7 @@ png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer, } void /* PRIVATE */ -png_push_process_row(png_structrp png_ptr) +png_push_process_row(png_struct *png_ptr) { /* 1.5.6: row_info moved out of png_struct to a local here. */ png_row_info row_info; @@ -1122,29 +1025,8 @@ png_push_process_row(png_structrp png_ptr) } void /* PRIVATE */ -png_read_push_finish_row(png_structrp png_ptr) +png_read_push_finish_row(png_struct *png_ptr) { -#ifdef PNG_READ_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_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 - * it, uncomment it here and in png.h - static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; - */ -#endif - png_ptr->row_number++; if (png_ptr->row_number < png_ptr->num_rows) return; @@ -1188,21 +1070,21 @@ png_read_push_finish_row(png_structrp png_ptr) } void /* PRIVATE */ -png_push_have_info(png_structrp png_ptr, png_inforp info_ptr) +png_push_have_info(png_struct *png_ptr, png_info *info_ptr) { if (png_ptr->info_fn != NULL) (*(png_ptr->info_fn))(png_ptr, info_ptr); } void /* PRIVATE */ -png_push_have_end(png_structrp png_ptr, png_inforp info_ptr) +png_push_have_end(png_struct *png_ptr, png_info *info_ptr) { if (png_ptr->end_fn != NULL) (*(png_ptr->end_fn))(png_ptr, info_ptr); } void /* PRIVATE */ -png_push_have_row(png_structrp png_ptr, png_bytep row) +png_push_have_row(png_struct *png_ptr, png_byte *row) { if (png_ptr->row_fn != NULL) (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, @@ -1210,9 +1092,9 @@ png_push_have_row(png_structrp png_ptr, png_bytep row) } #ifdef PNG_READ_INTERLACING_SUPPORTED -void PNGAPI -png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row, - png_const_bytep new_row) +void +png_progressive_combine_row(const png_struct *png_ptr, png_byte *old_row, + const png_byte *new_row) { if (png_ptr == NULL) return; @@ -1226,8 +1108,8 @@ png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row, } #endif /* READ_INTERLACING */ -void PNGAPI -png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr, +void +png_set_progressive_read_fn(png_struct *png_ptr, void *progressive_ptr, png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn) { @@ -1242,10 +1124,10 @@ png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr, } #ifdef PNG_READ_APNG_SUPPORTED -void PNGAPI -png_set_progressive_frame_fn(png_structp png_ptr, - png_progressive_frame_ptr frame_info_fn, - png_progressive_frame_ptr frame_end_fn) +void +png_set_progressive_frame_fn(png_struct *png_ptr, + png_progressive_frame_ptr frame_info_fn, + png_progressive_frame_ptr frame_end_fn) { png_ptr->frame_info_fn = frame_info_fn; png_ptr->frame_end_fn = frame_end_fn; @@ -1253,11 +1135,11 @@ png_set_progressive_frame_fn(png_structp png_ptr, } #endif -png_voidp PNGAPI -png_get_progressive_ptr(png_const_structrp png_ptr) +void * +png_get_progressive_ptr(const png_struct *png_ptr) { if (png_ptr == NULL) - return (NULL); + return NULL; return png_ptr->io_ptr; } diff --git a/media/libpng/pngpriv.h b/media/libpng/pngpriv.h index a3db9e79ba..81471f19a7 100644 --- a/media/libpng/pngpriv.h +++ b/media/libpng/pngpriv.h @@ -1,10 +1,9 @@ - /* pngpriv.h - private declarations for use inside libpng * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2025 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -20,8 +19,20 @@ * they should be well aware of the issues that may arise from doing so. */ + +/* pngpriv.h must be included first in each translation unit inside libpng. + * On the other hand, it must not be included at all, directly or indirectly, + * by any application code that uses the libpng API. + */ #ifndef PNGPRIV_H -#define PNGPRIV_H +# define PNGPRIV_H +#else +# error Duplicate inclusion of pngpriv.h; please check the libpng source files +#endif + +#if defined(PNG_H) || defined(PNGCONF_H) || defined(PNGLCONF_H) +# error This file must not be included by applications; please include +#endif /* Feature Test Macros. The following are defined here to ensure that correctly * implemented libraries reveal the APIs libpng needs to build and hide those @@ -35,7 +46,9 @@ * Windows/Visual Studio) there is no effect; the OS specific tests below are * 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 /* Standard library headers not required by png.h: */ @@ -56,7 +69,6 @@ */ #if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H) # include - /* Pick up the definition of 'restrict' from config.h if it was read: */ # define PNG_RESTRICT restrict #endif @@ -66,12 +78,11 @@ * are not internal definitions may be required. This is handled below just * before png.h is included, but load the configuration now if it is available. */ -#ifndef PNGLCONF_H -# include "pnglibconf.h" -#endif +#include "pnglibconf.h" +#include "pngtarget.h" /* Local renames may change non-exported API functions from png.h */ -#if defined(PNG_PREFIX) && !defined(PNGPREFIX_H) +#ifdef PNG_PREFIX # include "pngprefix.h" #endif @@ -86,167 +97,6 @@ # endif #endif -/* Compile time options. - * ===================== - * In a multi-arch build the compiler may compile the code several times for the - * same object module, producing different binaries for different architectures. - * When this happens configure-time setting of the target host options cannot be - * done and this interferes with the handling of the ARM NEON optimizations, and - * possibly other similar optimizations. Put additional tests here; in general - * this is needed when the same option can be changed at both compile time and - * run time depending on the target OS (i.e. iOS vs Android.) - * - * NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because - * this is not possible with certain compilers (Oracle SUN OS CC), as a result - * it is necessary to ensure that all extern functions that *might* be used - * regardless of $(CFLAGS) get declared in this file. The test on __ARM_NEON__ - * below is one example of this behavior because it is controlled by the - * presence or not of -mfpu=neon on the GCC command line, it is possible to do - * this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely - * do this. - */ -#ifndef PNG_ARM_NEON_OPT - /* ARM NEON optimizations are being controlled by the compiler settings, - * typically the target FPU. If the FPU has been set to NEON (-mfpu=neon - * with GCC) then the compiler will define __ARM_NEON__ and we can rely - * unconditionally on NEON instructions not crashing, otherwise we must - * disable use of NEON instructions. - * - * NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they - * can only be turned on automatically if that is supported too. If - * PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail - * to compile with an appropriate #error if ALIGNED_MEMORY has been turned - * off. - * - * Note that gcc-4.9 defines __ARM_NEON instead of the deprecated - * __ARM_NEON__, so we check both variants. - * - * To disable ARM_NEON optimizations entirely, and skip compiling the - * associated assembler code, pass --enable-arm-neon=no to configure - * or put -DPNG_ARM_NEON_OPT=0 in CPPFLAGS. - */ -# if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && \ - defined(PNG_ALIGNED_MEMORY_SUPPORTED) -# define PNG_ARM_NEON_OPT 2 -# else -# define PNG_ARM_NEON_OPT 0 -# endif -#endif - -#if PNG_ARM_NEON_OPT > 0 - /* NEON optimizations are to be at least considered by libpng, so enable the - * callbacks to do this. - */ -# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon - - /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used - * if possible - if __ARM_NEON__ is set and the compiler version is not known - * to be broken. This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can - * be: - * - * 1 The intrinsics code (the default with __ARM_NEON__) - * 2 The hand coded assembler (the default without __ARM_NEON__) - * - * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however - * this is *NOT* supported and may cease to work even after a minor revision - * to libpng. It *is* valid to do this for testing purposes, e.g. speed - * testing or a new compiler, but the results should be communicated to the - * libpng implementation list for incorporation in the next minor release. - */ -# ifndef PNG_ARM_NEON_IMPLEMENTATION -# if defined(__ARM_NEON__) || defined(__ARM_NEON) -# if defined(__clang__) - /* At present it is unknown by the libpng developers which versions - * of clang support the intrinsics, however some or perhaps all - * versions do not work with the assembler so this may be - * irrelevant, so just use the default (do nothing here.) - */ -# elif defined(__GNUC__) - /* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to - * work, so if this *is* GCC, or G++, look for a version >4.5 - */ -# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) -# define PNG_ARM_NEON_IMPLEMENTATION 2 -# endif /* no GNUC support */ -# endif /* __GNUC__ */ -# else /* !defined __ARM_NEON__ */ - /* The 'intrinsics' code simply won't compile without this -mfpu=neon: - */ -# define PNG_ARM_NEON_IMPLEMENTATION 2 -# endif /* __ARM_NEON__ */ -# endif /* !PNG_ARM_NEON_IMPLEMENTATION */ - -# ifndef PNG_ARM_NEON_IMPLEMENTATION - /* Use the intrinsics code by default. */ -# define PNG_ARM_NEON_IMPLEMENTATION 1 -# endif -#endif /* PNG_ARM_NEON_OPT > 0 */ - -#ifndef PNG_MIPS_MSA_OPT -# if defined(__mips_msa) && (__mips_isa_rev >= 5) && defined(PNG_ALIGNED_MEMORY_SUPPORTED) -# define PNG_MIPS_MSA_OPT 2 -# else -# define PNG_MIPS_MSA_OPT 0 -# endif -#endif - -#ifndef PNG_INTEL_SSE_OPT -# ifdef PNG_INTEL_SSE - /* Only check for SSE if the build configuration has been modified to - * enable SSE optimizations. This means that these optimizations will - * be off by default. See contrib/intel for more details. - */ -# if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \ - defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ - (defined(_M_IX86_FP) && _M_IX86_FP >= 2) -# define PNG_INTEL_SSE_OPT 1 -# endif -# endif -#endif - -#if PNG_INTEL_SSE_OPT > 0 -# ifndef PNG_INTEL_SSE_IMPLEMENTATION -# if defined(__SSE4_1__) || defined(__AVX__) - /* We are not actually using AVX, but checking for AVX is the best - way we can detect SSE4.1 and SSSE3 on MSVC. - */ -# define PNG_INTEL_SSE_IMPLEMENTATION 3 -# elif defined(__SSSE3__) -# define PNG_INTEL_SSE_IMPLEMENTATION 2 -# elif defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \ - (defined(_M_IX86_FP) && _M_IX86_FP >= 2) -# define PNG_INTEL_SSE_IMPLEMENTATION 1 -# else -# define PNG_INTEL_SSE_IMPLEMENTATION 0 -# endif -# endif - -# if PNG_INTEL_SSE_IMPLEMENTATION > 0 -# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_sse2 -# endif -#endif - -#if PNG_MIPS_MSA_OPT > 0 -# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa -# ifndef PNG_MIPS_MSA_IMPLEMENTATION -# if defined(__mips_msa) -# if defined(__clang__) -# elif defined(__GNUC__) -# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 7) -# define PNG_MIPS_MSA_IMPLEMENTATION 2 -# 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 */ - - /* Is this a build of a DLL where compilation of the object modules requires * different preprocessor settings to those required for a simple library? If * so PNG_BUILD_DLL must be set. @@ -327,7 +177,7 @@ #ifndef PNG_INTERNAL_CALLBACK # define PNG_INTERNAL_CALLBACK(type, name, args, attributes)\ - PNG_LINKAGE_CALLBACK PNG_FUNCTION(type, (PNGCBAPI name), args,\ + PNG_LINKAGE_CALLBACK PNG_FUNCTION(type, (name), args,\ PNG_EMPTY attributes) #endif @@ -342,19 +192,19 @@ */ #ifndef PNG_FP_EXPORT # ifndef PNG_FLOATING_POINT_SUPPORTED -# define PNG_FP_EXPORT(ordinal, type, name, args)\ +# define PNG_FP_EXPORT(type, name, args)\ PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY); # ifndef PNG_VERSION_INFO_ONLY typedef struct png_incomplete png_double; - typedef png_double* png_doublep; - typedef const png_double* png_const_doublep; - typedef png_double** png_doublepp; + typedef png_double* double *; /* [Deprecated] */ + typedef const png_double* const double *; /* [Deprecated] */ + typedef png_double** double **; /* [Deprecated] */ # endif # endif #endif #ifndef PNG_FIXED_EXPORT # ifndef PNG_FIXED_POINT_SUPPORTED -# define PNG_FIXED_EXPORT(ordinal, type, name, args)\ +# define PNG_FIXED_EXPORT(type, name, args)\ PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY); # endif #endif @@ -385,8 +235,8 @@ /* SECURITY and SAFETY: * * libpng is built with support for internal limits on image dimensions and - * memory usage. These are documented in scripts/pnglibconf.dfa of the - * source and recorded in the machine generated header file pnglibconf.h. + * memory usage. These are documented in scripts/pnglibconf/pnglibconf.dfa of + * the source and recorded in the machine generated header file pnglibconf.h. */ /* If you are running on a machine where you cannot allocate more @@ -439,6 +289,11 @@ # define png_fixed_error(s1,s2) png_err(s1) #endif +#ifndef PNG_VERSION_INFO_ONLY +/* Other defines specific to compilers can go here. Try to keep + * 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 @@ -453,25 +308,11 @@ static_cast(static_cast(value)) #else # define png_voidcast(type, value) (value) -# define png_constcast(type, value) ((type)(value)) +# define png_constcast(type, value) ((type)(void*)(const void*)(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 - * they get used by the corresponding floating point APIs. This magic - * deals with this: - */ -#ifdef PNG_FIXED_POINT_SUPPORTED -# define PNGFAPI PNGAPI -#else -# define PNGFAPI /* PRIVATE */ -#endif - -#ifndef PNG_VERSION_INFO_ONLY -/* Other defines specific to compilers can go here. Try to keep - * them inside an appropriate ifdef/endif pair for portability. - */ #if defined(PNG_FLOATING_POINT_SUPPORTED) ||\ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) /* png.c requires the following ANSI-C constants if the conversion of @@ -499,9 +340,8 @@ # include #endif -#if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ - defined(_WIN32) || defined(__WIN32__) -# include /* defines _WINDOWS_ macro */ +#if defined(_WIN32) || defined(__WIN32__) || defined(__NT__) +# include #endif #endif /* PNG_VERSION_INFO_ONLY */ @@ -510,24 +350,20 @@ * functions that are passed far data must be model-independent. */ -/* Memory model/platform independent fns */ +/* Platform-independent functions */ #ifndef PNG_ABORT -# ifdef _WINDOWS_ -# define PNG_ABORT() ExitProcess(0) -# else -# define PNG_ABORT() abort() -# endif +# define PNG_ABORT() abort() #endif /* These macros may need to be architecture dependent. */ -#define PNG_ALIGN_NONE 0 /* do not use data alignment */ -#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */ +#define PNG_ALIGN_NONE 0 /* do not use data alignment */ +#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */ #ifdef offsetof -# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */ +# define PNG_ALIGN_OFFSET 2 /* use offsetof to determine alignment */ #else # define PNG_ALIGN_OFFSET -1 /* prevent the use of this */ #endif -#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */ +#define PNG_ALIGN_SIZE 3 /* use sizeof to determine alignment */ #ifndef PNG_ALIGN_TYPE /* Default to using aligned access optimizations and requiring alignment to a @@ -541,26 +377,25 @@ /* This is used because in some compiler implementations non-aligned * structure members are supported, so the offsetof approach below fails. * Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access - * is good for performance. Do not do this unless you have tested the result - * and understand it. + * is good for performance. Do not do this unless you have tested the + * result and understand it. */ -# define png_alignof(type) (sizeof (type)) +# define png_alignof(type) (sizeof(type)) #else # if PNG_ALIGN_TYPE == PNG_ALIGN_OFFSET -# define png_alignof(type) offsetof(struct{char c; type t;}, t) +# define png_alignof(type) offsetof(struct{char c; type t;}, t) # else -# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS -# define png_alignof(type) (1) -# endif - /* Else leave png_alignof undefined to prevent use thereof */ +# if PNG_ALIGN_TYPE == PNG_ALIGN_ALWAYS +# define png_alignof(type) 1 +# endif + /* Else leave png_alignof undefined to prevent use thereof */ # endif #endif -/* This implicitly assumes alignment is always to a power of 2. */ +/* This implicitly assumes alignment is always a multiple of 2. */ #ifdef png_alignof -# define png_isaligned(ptr, type)\ - (((type)((const char*)ptr-(const char*)0) & \ - (type)(png_alignof(type)-1)) == 0) +# define png_isaligned(ptr, type) \ + (((type)(size_t)((const void*)(ptr)) & (type)(png_alignof(type)-1)) == 0) #else # define png_isaligned(ptr, type) 0 #endif @@ -591,7 +426,7 @@ #define PNG_BACKGROUND_IS_GRAY 0x800U #define PNG_HAVE_PNG_SIGNATURE 0x1000U #define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000U /* Have another chunk after IDAT */ - /* 0x4000U (unused) */ +#define PNG_WROTE_eXIf 0x4000U #define PNG_IS_READ_STRUCT 0x8000U /* Else is a write struct */ #ifdef PNG_APNG_SUPPORTED #define PNG_HAVE_acTL 0x10000U @@ -648,13 +483,13 @@ #define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200U #define PNG_FLAG_CRC_CRITICAL_USE 0x0400U #define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800U -#define PNG_FLAG_ASSUME_sRGB 0x1000U /* Added to libpng-1.5.4 */ +/* PNG_FLAG_ASSUME_sRGB unused 0x1000U * Added to libpng-1.5.4 */ #define PNG_FLAG_OPTIMIZE_ALPHA 0x2000U /* Added to libpng-1.5.4 */ #define PNG_FLAG_DETECT_UNINITIALIZED 0x4000U /* Added to libpng-1.5.4 */ /* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000U */ /* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000U */ #define PNG_FLAG_LIBRARY_MISMATCH 0x20000U -#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000U + /* 0x40000U unused */ #define PNG_FLAG_STRIP_ERROR_TEXT 0x80000U #define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000U /* Added to libpng-1.4.0 */ #define PNG_FLAG_APP_WARNINGS_WARN 0x200000U /* Added to libpng-1.6.0 */ @@ -697,8 +532,8 @@ /* Added to libpng-1.2.6 JB */ #define PNG_ROWBYTES(pixel_bits, width) \ ((pixel_bits) >= 8 ? \ - ((png_size_t)(width) * (((png_size_t)(pixel_bits)) >> 3)) : \ - (( ((png_size_t)(width) * ((png_size_t)(pixel_bits))) + 7) >> 3) ) + ((size_t)(width) * (((size_t)(pixel_bits)) >> 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 @@ -759,6 +594,8 @@ #ifdef PNG_FIXED_POINT_MACRO_SUPPORTED #define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\ ((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0)) +#define png_fixed_ITU(png_ptr, fp, s) ((fp) <= 214748 && (fp) >= 0 ?\ + ((png_uint_32)(10000 * (fp))) : (png_fixed_error(png_ptr, s),0)) #endif /* else the corresponding function is defined below, inside the scope of the * cplusplus test. @@ -777,11 +614,31 @@ * * PNG_32b correctly produces a value shifted by up to 24 bits, even on * architectures where (int) is only 16 bits. + * + * 1.6.47: PNG_32b was made into a preprocessor evaluable macro by replacing the + * static_cast with a promoting binary operation using a guaranteed 32-bit + * (minimum) unsigned value. */ -#define PNG_32b(b,s) ((png_uint_32)(b) << (s)) +#define PNG_32b(b,s) (((0xFFFFFFFFU)&(b)) << (s)) #define PNG_U32(b1,b2,b3,b4) \ (PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0)) +/* Chunk name validation. When using these macros all the arguments should be + * constants, otherwise code bloat may well occur. The macros are provided + * primarily for use in #if checks. + * + * PNG_32to8 produces a byte value with the right shift; used to extract the + * byte value from a chunk name. + */ +#define PNG_32to8(cn,s) (((cn) >> (s)) & 0xffU) +#define PNG_CN_VALID_UPPER(b) ((b) >= 65 && (b) <= 90) /* upper-case ASCII */ +#define PNG_CN_VALID_ASCII(b) PNG_CN_VALID_UPPER((b) & ~32U) +#define PNG_CHUNK_NAME_VALID(cn) (\ + PNG_CN_VALID_ASCII(PNG_32to8(cn,24)) && /* critical, !ancillary */\ + PNG_CN_VALID_ASCII(PNG_32to8(cn,16)) && /* public, !privately defined */\ + PNG_CN_VALID_UPPER(PNG_32to8(cn, 8)) && /* VALID, !reserved */\ + PNG_CN_VALID_ASCII(PNG_32to8(cn, 0)) /* data-dependent, !copy ok */) + /* Constants for known chunk types. * * MAINTAINERS: If you need to add a chunk, define the name here. @@ -809,8 +666,14 @@ #define png_IEND PNG_U32( 73, 69, 78, 68) #define png_IHDR PNG_U32( 73, 72, 68, 82) #define png_PLTE PNG_U32( 80, 76, 84, 69) +#define png_acTL PNG_U32( 97, 99, 84, 76) /* PNGv3: APNG */ #define png_bKGD PNG_U32( 98, 75, 71, 68) #define png_cHRM PNG_U32( 99, 72, 82, 77) +#define png_cICP PNG_U32( 99, 73, 67, 80) /* PNGv3 */ +#define png_cLLI PNG_U32( 99, 76, 76, 73) /* PNGv3 */ +#define png_eXIf PNG_U32(101, 88, 73, 102) /* registered July 2017 */ +#define png_fcTL PNG_U32(102, 99, 84, 76) /* PNGv3: APNG */ +#define png_fdAT PNG_U32(102, 100, 65, 84) /* PNGv3: APNG */ #define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */ #define png_gAMA PNG_U32(103, 65, 77, 65) #define png_gIFg PNG_U32(103, 73, 70, 103) @@ -819,6 +682,7 @@ #define png_hIST PNG_U32(104, 73, 83, 84) #define png_iCCP PNG_U32(105, 67, 67, 80) #define png_iTXt PNG_U32(105, 84, 88, 116) +#define png_mDCV PNG_U32(109, 68, 67, 86) /* PNGv3 */ #define png_oFFs PNG_U32(111, 70, 70, 115) #define png_pCAL PNG_U32(112, 67, 65, 76) #define png_pHYs PNG_U32(112, 72, 89, 115) @@ -833,9 +697,6 @@ #define png_zTXt PNG_U32(122, 84, 88, 116) #ifdef PNG_APNG_SUPPORTED -#define png_acTL PNG_U32( 97, 99, 84, 76) -#define png_fcTL PNG_U32(102, 99, 84, 76) -#define png_fdAT PNG_U32(102, 100, 65, 84) /* For png_struct.apng_flags: */ #define PNG_FIRST_FRAME_HIDDEN 0x0001U @@ -869,11 +730,74 @@ #define PNG_CHUNK_RESERVED(c) (1 & ((c) >> 13)) #define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >> 5)) +/* Known chunks. All supported chunks must be listed here. The macro PNG_CHUNK + * contains the four character ASCII name by which the chunk is identified. The + * macro is implemented as required to build tables or switch statements which + * require entries for every known chunk. The macro also contains an index + * value which should be in order (this is checked in png.c). + * + * Notice that "known" does not require "SUPPORTED"; tables should be built in + * such a way that chunks unsupported in a build require no more than the table + * entry (which should be small.) In particular function pointers for + * unsupported chunks should be NULL. + * + * At present these index values are not exported (not part of the public API) + * so can be changed at will. For convenience the names are in lexical sort + * order but with the critical chunks at the start in the order of occurrence in + * a PNG. + * + * PNG_INFO_ values do not exist for every one of these chunk handles; for + * example PNG_INFO_{IDAT,IEND,tEXt,iTXt,zTXt} and possibly other chunks in the + * future. + */ +#define PNG_KNOWN_CHUNKS\ + PNG_CHUNK(IHDR, 0)\ + PNG_CHUNK(PLTE, 1)\ + PNG_CHUNK(IDAT, 2)\ + PNG_CHUNK(IEND, 3)\ + PNG_CHUNK(acTL, 4)\ + PNG_CHUNK(bKGD, 5)\ + PNG_CHUNK(cHRM, 6)\ + PNG_CHUNK(cICP, 7)\ + PNG_CHUNK(cLLI, 8)\ + PNG_CHUNK(eXIf, 9)\ + PNG_CHUNK(fcTL, 10)\ + PNG_CHUNK(fdAT, 11)\ + PNG_CHUNK(gAMA, 12)\ + PNG_CHUNK(hIST, 13)\ + PNG_CHUNK(iCCP, 14)\ + PNG_CHUNK(iTXt, 15)\ + PNG_CHUNK(mDCV, 16)\ + PNG_CHUNK(oFFs, 17)\ + PNG_CHUNK(pCAL, 18)\ + PNG_CHUNK(pHYs, 19)\ + PNG_CHUNK(sBIT, 20)\ + PNG_CHUNK(sCAL, 21)\ + PNG_CHUNK(sPLT, 22)\ + PNG_CHUNK(sRGB, 23)\ + PNG_CHUNK(tEXt, 24)\ + PNG_CHUNK(tIME, 25)\ + PNG_CHUNK(tRNS, 26)\ + PNG_CHUNK(zTXt, 27) + /* Gamma values (new at libpng-1.5.4): */ #define PNG_GAMMA_MAC_OLD 151724 /* Assume '1.8' is really 2.2/1.45! */ #define PNG_GAMMA_MAC_INVERSE 65909 #define PNG_GAMMA_sRGB_INVERSE 45455 +/* gamma sanity check. libpng cannot implement gamma transforms outside a + * certain limit because of its use of 16-bit fixed point intermediate values. + * Gamma values that are too large or too small will zap the 16-bit values all + * to 0 or 65535 resulting in an obvious 'bad' image. + * + * In libpng 1.6.0 the limits were changed from 0.07..3 to 0.01..100 to + * accommodate the optimal 16-bit gamma of 36 and its reciprocal. + * + * These are png_fixed_point integral values: + */ +#define PNG_LIB_GAMMA_MIN 1000 +#define PNG_LIB_GAMMA_MAX 10000000 + /* Almost everything below is C specific; the #defines above can be used in * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot. */ @@ -886,25 +810,18 @@ * must match that used in the build, or we must be using pnglibconf.h.prebuilt: */ #if PNG_ZLIB_VERNUM != 0 && PNG_ZLIB_VERNUM != ZLIB_VERNUM -# error ZLIB_VERNUM != PNG_ZLIB_VERNUM \ - "-I (include path) error: see the notes in pngpriv.h" - /* This means that when pnglibconf.h was built the copy of zlib.h that it - * used is not the same as the one being used here. Because the build of - * libpng makes decisions to use inflateInit2 and inflateReset2 based on the - * zlib version number and because this affects handling of certain broken - * PNG files the -I directives must match. +# error The include path of is incorrect + /* When pnglibconf.h was built, the copy of zlib.h that it used was not the + * same as the one being used here. Considering how libpng makes decisions + * to use the zlib API based on the zlib version number, the -I options must + * match. * - * 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 - * directives must be in CPPFLAGS. + * A possible cause of this mismatch is that you passed an -I option in + * CFLAGS, which is unlikely to work. All the preprocessor options, and all + * the -I options in particular, should be in CPPFLAGS. */ #endif -/* This is used for 16-bit gamma tables -- only the top level pointers are - * const; this could be changed: - */ -typedef const png_uint_16p * png_const_uint_16pp; - /* Added to libpng-1.5.7: sRGB conversion tables */ #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) @@ -937,18 +854,19 @@ extern "C" { * * All of these functions must be declared with PNG_INTERNAL_FUNCTION. */ - /* Zlib support */ #define PNG_UNEXPECTED_ZLIB_RETURN (-7) -PNG_INTERNAL_FUNCTION(void, png_zstream_error,(png_structrp png_ptr, int ret), +PNG_INTERNAL_FUNCTION(void, png_zstream_error, + (png_struct *png_ptr, int ret), PNG_EMPTY); /* Used by the zlib handling functions to ensure that z_stream::msg is always * set before they return. */ #ifdef PNG_WRITE_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr, - png_compression_bufferp *list),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_free_buffer_list, + (png_struct *png_ptr, png_compression_buffer **list), + PNG_EMPTY); /* Free the buffer list used by the compressed write code. */ #endif @@ -956,41 +874,75 @@ PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr, !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \ (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \ defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \ + defined(PNG_mDCV_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \ (defined(PNG_sCAL_SUPPORTED) && \ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)) -PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr, - double fp, png_const_charp text),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(png_fixed_point, png_fixed, + (const png_struct *png_ptr, double fp, const char *text), + PNG_EMPTY); +#endif + +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \ + (defined(PNG_cLLI_SUPPORTED) || defined(PNG_mDCV_SUPPORTED)) +PNG_INTERNAL_FUNCTION(png_uint_32, png_fixed_ITU, + (const png_struct *png_ptr, double fp, const char *text), + PNG_EMPTY); #endif /* Check the user version string for compatibility, returns false if the version * numbers aren't compatible. */ -PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr, - png_const_charp user_png_ver),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_user_version_check, + (png_struct *png_ptr, const char *user_png_ver), + PNG_EMPTY); + +#ifdef PNG_READ_SUPPORTED /* should only be used on read */ +/* Security: read limits on the largest allocations while reading a PNG. This + * avoids very large allocations caused by PNG files with damaged or altered + * chunk 'length' fields. + */ +#ifdef PNG_SET_USER_LIMITS_SUPPORTED /* run-time limit */ +# define png_chunk_max(png_ptr) ((png_ptr)->user_chunk_malloc_max) + +#elif PNG_USER_CHUNK_MALLOC_MAX > 0 /* compile-time limit */ +# define png_chunk_max(png_ptr) ((void)png_ptr, PNG_USER_CHUNK_MALLOC_MAX) + +#elif (defined PNG_MAX_MALLOC_64K) /* legacy system limit */ +# define png_chunk_max(png_ptr) ((void)png_ptr, 65536U) + +#else /* modern system limit SIZE_MAX (C99) */ +# define png_chunk_max(png_ptr) ((void)png_ptr, PNG_SIZE_MAX) +#endif +#endif /* READ */ /* Internal base allocator - no messages, NULL on failure to allocate. This * does, however, call the application provided allocator and that could call * png_error (although that would be a bug in the application implementation.) */ -PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_base,(png_const_structrp png_ptr, - png_alloc_size_t size),PNG_ALLOCATED); +PNG_INTERNAL_FUNCTION(void *, png_malloc_base, + (const png_struct *png_ptr, png_alloc_size_t size), + PNG_ALLOCATED); #if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\ defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) /* Internal array allocator, outputs no error or warning messages on failure, * just returns NULL. */ -PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_array,(png_const_structrp png_ptr, - int nelements, size_t element_size),PNG_ALLOCATED); +PNG_INTERNAL_FUNCTION(void *, png_malloc_array, + (const png_struct *png_ptr, int nelements, size_t element_size), + PNG_ALLOCATED); /* The same but an existing array is extended by add_elements. This function * also memsets the new elements to 0 and copies the old elements. The old * array is not freed or altered. */ -PNG_INTERNAL_FUNCTION(png_voidp,png_realloc_array,(png_const_structrp png_ptr, - png_const_voidp array, int old_elements, int add_elements, - size_t element_size),PNG_ALLOCATED); +PNG_INTERNAL_FUNCTION(void *, png_realloc_array, + (const png_struct *png_ptr, + const void *array, int old_elements, int add_elements, + size_t element_size), + PNG_ALLOCATED); #endif /* text, sPLT or unknown chunks */ /* Magic to create a struct when there is no struct to call the user supplied @@ -999,87 +951,105 @@ PNG_INTERNAL_FUNCTION(png_voidp,png_realloc_array,(png_const_structrp png_ptr, * restriction so libpng has to assume that the 'free' handler, at least, might * call png_error. */ -PNG_INTERNAL_FUNCTION(png_structp,png_create_png_struct, - (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn, - png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn, - png_free_ptr free_fn),PNG_ALLOCATED); +PNG_INTERNAL_FUNCTION(png_struct *, png_create_png_struct, + (const char *user_png_ver, + void *error_ptr, png_error_ptr error_fn, png_error_ptr warn_fn, + void *mem_ptr, png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED); /* Free memory from internal libpng struct */ -PNG_INTERNAL_FUNCTION(void,png_destroy_png_struct,(png_structrp png_ptr), +PNG_INTERNAL_FUNCTION(void, png_destroy_png_struct, + (png_struct *png_ptr), PNG_EMPTY); /* Free an allocated jmp_buf (always succeeds) */ -PNG_INTERNAL_FUNCTION(void,png_free_jmpbuf,(png_structrp png_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_free_jmpbuf, + (png_struct *png_ptr), + PNG_EMPTY); -/* Function to allocate memory for zlib. PNGAPI is disallowed. */ -PNG_INTERNAL_FUNCTION(voidpf,png_zalloc,(voidpf png_ptr, uInt items, uInt size), +/* Function to allocate memory for zlib. */ +PNG_INTERNAL_FUNCTION(voidpf, png_zalloc, + (voidpf png_ptr, uInt items, uInt size), PNG_ALLOCATED); -/* Function to free memory for zlib. PNGAPI is disallowed. */ -PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY); - -/* Next four functions are used internally as callbacks. PNGCBAPI is required - * but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to - * PNGCBAPI at 1.5.0 - */ +/* Function to free memory for zlib. */ +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_bytep data, png_size_t length),PNG_EMPTY); +/* Internal callback. */ +PNG_INTERNAL_FUNCTION(void, png_default_read_data, + (png_struct *png_ptr, png_byte *data, size_t length), + PNG_EMPTY); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr, - png_bytep buffer, png_size_t length),PNG_EMPTY); +/* Internal callback. */ +PNG_INTERNAL_FUNCTION(void, png_push_fill_buffer, + (png_struct *png_ptr, png_byte *buffer, size_t length), + PNG_EMPTY); #endif -PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr, - png_bytep data, png_size_t length),PNG_EMPTY); +/* Internal callback. */ +PNG_INTERNAL_FUNCTION(void, png_default_write_data, + (png_struct *png_ptr, png_byte *data, size_t length), + PNG_EMPTY); #ifdef PNG_WRITE_FLUSH_SUPPORTED # ifdef PNG_STDIO_SUPPORTED -PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_flush,(png_structp png_ptr), +/* Internal callback. */ +PNG_INTERNAL_FUNCTION(void, png_default_flush, + (png_struct *png_ptr), PNG_EMPTY); # endif #endif /* Reset the CRC variable */ -PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_reset_crc, + (png_struct *png_ptr), + PNG_EMPTY); /* Write the "data" buffer to whatever output you are using */ -PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr, - png_const_bytep data, png_size_t length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_data, + (png_struct *png_ptr, const png_byte *data, size_t length), + PNG_EMPTY); /* Read and check the PNG file signature */ -PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_read_sig, + (png_struct *png_ptr, png_info *info_ptr), + PNG_EMPTY); /* Read the chunk header (length + type name) */ -PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr), +PNG_INTERNAL_FUNCTION(png_uint_32, png_read_chunk_header, + (png_struct *png_ptr), PNG_EMPTY); /* 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_size_t length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_read_data, + (png_struct *png_ptr, png_byte *data, size_t length), + PNG_EMPTY); /* Read bytes into buf, and update png_ptr->crc */ -PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf, - png_uint_32 length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_crc_read, + (png_struct *png_ptr, png_byte *buf, png_uint_32 length), + PNG_EMPTY); /* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ -PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr, - png_uint_32 skip),PNG_EMPTY); - -/* Read the CRC from the file and compare it to the libpng calculated CRC */ -PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_crc_finish, + (png_struct *png_ptr, png_uint_32 skip), + PNG_EMPTY); /* Calculate the CRC over a section of data. Note that we are only * passing a maximum of 64K on systems that have this as a memory limit, * since this is the maximum buffer size we can specify. */ -PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr, - png_const_bytep ptr, png_size_t length),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_calculate_crc, + (png_struct *png_ptr, const png_byte *ptr, size_t length), + PNG_EMPTY); #ifdef PNG_WRITE_FLUSH_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_flush, + (png_struct *png_ptr), + PNG_EMPTY); #endif /* Write various chunks */ @@ -1087,126 +1057,193 @@ PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); /* Write the IHDR chunk, and update the png_struct with the necessary * information. */ -PNG_INTERNAL_FUNCTION(void,png_write_IHDR,(png_structrp png_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, - int compression_method, int filter_method, int interlace_method),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_IHDR, + (png_struct *png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, + int compression_method, int filter_method, int interlace_method), + PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_write_PLTE,(png_structrp png_ptr, - png_const_colorp palette, png_uint_32 num_pal),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_PLTE, + (png_struct *png_ptr, + const png_color *palette, png_uint_32 num_pal), + PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_compress_IDAT,(png_structrp png_ptr, - png_const_bytep row_data, png_alloc_size_t row_data_length, int flush), +PNG_INTERNAL_FUNCTION(void, png_compress_IDAT, + (png_struct *png_ptr, + const png_byte *row_data, png_alloc_size_t row_data_length, int flush), PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_write_IEND,(png_structrp png_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_IEND, + (png_struct *png_ptr), + PNG_EMPTY); #ifdef PNG_WRITE_gAMA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_gAMA_fixed,(png_structrp png_ptr, - png_fixed_point file_gamma),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_gAMA_fixed, + (png_struct *png_ptr, png_fixed_point file_gamma), + PNG_EMPTY); #endif #ifdef PNG_WRITE_sBIT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_sBIT,(png_structrp png_ptr, - png_const_color_8p sbit, int color_type),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_sBIT, + (png_struct *png_ptr, const png_color_8 *sbit, int color_type), + PNG_EMPTY); #endif #ifdef PNG_WRITE_cHRM_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr, - const png_xy *xy), PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_cHRM_fixed, + (png_struct *png_ptr, const png_xy *xy), + PNG_EMPTY); /* The xy value must have been previously validated */ #endif +#ifdef PNG_WRITE_cICP_SUPPORTED +PNG_INTERNAL_FUNCTION(void, png_write_cICP, + (png_struct *png_ptr, + png_byte colour_primaries, png_byte transfer_function, + png_byte matrix_coefficients, png_byte video_full_range_flag), + PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_cLLI_SUPPORTED +PNG_INTERNAL_FUNCTION(void, png_write_cLLI_fixed, + (png_struct *png_ptr, png_uint_32 maxCLL, png_uint_32 maxFALL), + PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_mDCV_SUPPORTED +PNG_INTERNAL_FUNCTION(void, png_write_mDCV_fixed, + (png_struct *png_ptr, + png_uint_16 red_x, png_uint_16 red_y, + png_uint_16 green_x, png_uint_16 green_y, + png_uint_16 blue_x, png_uint_16 blue_y, + png_uint_16 white_x, png_uint_16 white_y, + png_uint_32 maxDL, png_uint_32 minDL), + PNG_EMPTY); +#endif + #ifdef PNG_WRITE_sRGB_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr, - int intent),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_sRGB, + (png_struct *png_ptr, int intent), + PNG_EMPTY); +#endif + +#ifdef PNG_WRITE_eXIf_SUPPORTED +PNG_INTERNAL_FUNCTION(void, png_write_eXIf, + (png_struct *png_ptr, png_byte *exif, int num_exif), + PNG_EMPTY); #endif #ifdef PNG_WRITE_iCCP_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr, - png_const_charp name, png_const_bytep profile), PNG_EMPTY); - /* The profile must have been previously validated for correctness, the - * length comes from the first four bytes. Only the base, deflate, - * compression is supported. +PNG_INTERNAL_FUNCTION(void, png_write_iCCP, + (png_struct *png_ptr, + const char *name, const png_byte *profile, png_uint_32 proflen), + PNG_EMPTY); + /* Writes a previously 'set' profile. The profile argument is **not** + * compressed. */ #endif #ifdef PNG_WRITE_sPLT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_sPLT,(png_structrp png_ptr, - png_const_sPLT_tp palette),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_sPLT, + (png_struct *png_ptr, const png_sPLT_t *palette), + PNG_EMPTY); #endif #ifdef PNG_WRITE_tRNS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_tRNS,(png_structrp png_ptr, - png_const_bytep trans, png_const_color_16p values, int number, - int color_type),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_tRNS, + (png_struct *png_ptr, + const png_byte *trans, const png_color_16 *values, int number, + int color_type), + PNG_EMPTY); #endif #ifdef PNG_WRITE_bKGD_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_bKGD,(png_structrp png_ptr, - png_const_color_16p values, int color_type),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_bKGD, + (png_struct *png_ptr, const png_color_16 *values, int color_type), + PNG_EMPTY); #endif #ifdef PNG_WRITE_hIST_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr, - png_const_uint_16p hist, int num_hist),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_hIST, + (png_struct *png_ptr, const png_uint_16 *hist, int num_hist), + PNG_EMPTY); #endif /* Chunks that have keywords */ #ifdef PNG_WRITE_tEXt_SUPPORTED -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_INTERNAL_FUNCTION(void, png_write_tEXt, + (png_struct *png_ptr, + const char *key, const char *text, size_t text_len), + PNG_EMPTY); #endif #ifdef PNG_WRITE_zTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_zTXt,(png_structrp png_ptr, png_const_charp - key, png_const_charp text, int compression),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_zTXt, + (png_struct *png_ptr, + const char *key, const char *text, int compression), + PNG_EMPTY); #endif #ifdef PNG_WRITE_iTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,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_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_iTXt, + (png_struct *png_ptr, + int compression, const char *key, const char *lang, + const char *lang_key, const char *text), + PNG_EMPTY); #endif #ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */ -PNG_INTERNAL_FUNCTION(int,png_set_text_2,(png_const_structrp png_ptr, - png_inforp info_ptr, png_const_textp text_ptr, int num_text),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_set_text_2, + (const png_struct *png_ptr, + png_info *info_ptr, const png_text *text_ptr, int num_text), + PNG_EMPTY); #endif #ifdef PNG_WRITE_oFFs_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_oFFs,(png_structrp png_ptr, - png_int_32 x_offset, png_int_32 y_offset, int unit_type),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_oFFs, + (png_struct *png_ptr, + png_int_32 x_offset, png_int_32 y_offset, int unit_type), + PNG_EMPTY); #endif #ifdef PNG_WRITE_pCAL_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_pCAL,(png_structrp png_ptr, - png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams, - png_const_charp units, png_charpp params),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_pCAL, + (png_struct *png_ptr, + char *purpose, png_int_32 X0, png_int_32 X1, + int type, int nparams, const char *units, char **params), + PNG_EMPTY); #endif #ifdef PNG_WRITE_pHYs_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_pHYs,(png_structrp png_ptr, +PNG_INTERNAL_FUNCTION(void, png_write_pHYs, + (png_struct *png_ptr, png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, - int unit_type),PNG_EMPTY); + int unit_type), + PNG_EMPTY); #endif #ifdef PNG_WRITE_tIME_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_tIME,(png_structrp png_ptr, - png_const_timep mod_time),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_tIME, + (png_struct *png_ptr, const png_time *mod_time), + PNG_EMPTY); #endif #ifdef PNG_WRITE_sCAL_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_sCAL_s,(png_structrp png_ptr, - int unit, png_const_charp width, png_const_charp height),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_sCAL_s, + (png_struct *png_ptr, + int unit, const char *width, const char *height), + PNG_EMPTY); #endif /* Called when finished processing a row of data */ -PNG_INTERNAL_FUNCTION(void,png_write_finish_row,(png_structrp png_ptr), - PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_finish_row, + (png_struct *png_ptr), + PNG_EMPTY); /* Internal use only. Called before first row of data */ -PNG_INTERNAL_FUNCTION(void,png_write_start_row,(png_structrp png_ptr), - PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_start_row, + (png_struct *png_ptr), + PNG_EMPTY); /* Combine a row of data, dealing with alpha, etc. if requested. 'row' is an * array of png_ptr->width pixels. If the image is not interlaced or this @@ -1234,8 +1271,9 @@ PNG_INTERNAL_FUNCTION(void,png_write_start_row,(png_structrp png_ptr), #ifndef PNG_USE_COMPILE_TIME_MASKS # define PNG_USE_COMPILE_TIME_MASKS 1 #endif -PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr, - png_bytep row, int display),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_combine_row, + (const png_struct *png_ptr, png_byte *row, int display), + PNG_EMPTY); #ifdef PNG_READ_INTERLACING_SUPPORTED /* Expand an interlaced row: the 'row_info' describes the pass data that has @@ -1244,255 +1282,186 @@ PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr, * the pixels are *replicated* to the intervening space. This is essential for * the correct operation of png_combine_row, above. */ -PNG_INTERNAL_FUNCTION(void,png_do_read_interlace,(png_row_infop row_info, - png_bytep row, int pass, png_uint_32 transformations),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_do_read_interlace, + (png_row_info *row_info, + png_byte *row, int pass, png_uint_32 transformations), + PNG_EMPTY); #endif /* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */ #ifdef PNG_WRITE_INTERLACING_SUPPORTED /* Grab pixels out of a row for an interlaced pass */ -PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info, - png_bytep row, int pass),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_do_write_interlace, + (png_row_info *row_info, png_byte *row, int pass), + PNG_EMPTY); #endif /* Unfilter a row: check the filter value before calling this, there is no point * calling it for PNG_FILTER_VALUE_NONE. */ -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); - -#if PNG_ARM_NEON_OPT > 0 -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_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop - row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY); -#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_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 +PNG_INTERNAL_FUNCTION(void, png_read_filter_row, + (png_struct *pp, png_row_info *row_info, + png_byte *row, const png_byte *prev_row, int filter), + PNG_EMPTY); + +#ifdef PNG_TARGET_CODE_IMPLEMENTATION +/* png_struct::target_state contains a cache of these flags and updates + * it as required during read. The hardware implementation may also do + * this, for example if it determines that hardware optimization is not + * available for this image. + */ +#define png_target_filters 1 /* MASK: hardware support for filters */ +#define png_target_expand_palette 2 /* MASK: hardware support for palettes */ + +PNG_INTERNAL_FUNCTION(void, png_target_init, + (png_struct *), + PNG_EMPTY); + /* Initialize png_struct::target_state if required. */ + +PNG_INTERNAL_FUNCTION(void, png_target_free_data, + (png_struct *), + PNG_EMPTY); + /* Free any data allocated in the png_struct::target_data. + */ + +PNG_INTERNAL_FUNCTION(void, png_target_init_filter_functions, + (png_struct *png_ptr, unsigned int bpp), + PNG_EMPTY); + /* The filter function initializer that selects the specific hardware + * implementation. Called once before the first row needs to be defiltered. + */ + +/* Handlers for specific transforms (currently only 'expand_palette'). These + * are implemented in pngsimd.c to call the actual SIMD implementation if + * required. + * + * The handlers return "false" if nothing was done and the C code will then be + * called. The implementations must do everything or nothing. + */ +PNG_INTERNAL_FUNCTION(int, png_target_do_expand_palette, + (png_struct *, png_row_info *), + PNG_EMPTY); + /* Expand the palette and return true or do nothing and return false. */ +#endif /* TARGET_CODE */ /* Choose the best filter to use and filter the row data */ -PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr, - png_row_infop row_info),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_find_filter, + (png_struct *png_ptr, png_row_info *row_info), + PNG_EMPTY); #ifdef PNG_SEQUENTIAL_READ_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr, - png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_read_IDAT_data, + (png_struct *png_ptr, png_byte *output, png_alloc_size_t avail_out), + PNG_EMPTY); /* Read 'avail_out' bytes of data from the IDAT stream. If the output buffer * is NULL the function checks, instead, for the end of the stream. In this * case a benign error will be issued if the stream end is not found or if * extra data has to be consumed. */ -PNG_INTERNAL_FUNCTION(void,png_read_finish_IDAT,(png_structrp png_ptr), +PNG_INTERNAL_FUNCTION(void, png_read_finish_IDAT, + (png_struct *png_ptr), PNG_EMPTY); /* This cleans up when the IDAT LZ stream does not end when the last image * byte is read; there is still some pending input. */ -PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr), +PNG_INTERNAL_FUNCTION(void, png_read_finish_row, + (png_struct *png_ptr), PNG_EMPTY); /* Finish a row while reading, dealing with interlacing passes, etc. */ #endif /* SEQUENTIAL_READ */ /* 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_struct *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 */ +PNG_INTERNAL_FUNCTION(int, png_zlib_inflate, + (png_struct *png_ptr, int flush), + PNG_EMPTY); #ifdef PNG_READ_TRANSFORMS_SUPPORTED /* Optional call to update the users info structure */ -PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_read_transform_info, + (png_struct *png_ptr, png_info *info_ptr), + PNG_EMPTY); #endif /* Shared transform functions, defined in pngtran.c */ #if defined(PNG_WRITE_FILLER_SUPPORTED) || \ defined(PNG_READ_STRIP_ALPHA_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_strip_channel,(png_row_infop row_info, - png_bytep row, int at_start),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_do_strip_channel, + (png_row_info *row_info, png_byte *row, int at_start), + PNG_EMPTY); #endif #ifdef PNG_16BIT_SUPPORTED #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_swap,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_do_swap, + (png_row_info *row_info, png_byte *row), + PNG_EMPTY); #endif #endif #if defined(PNG_READ_PACKSWAP_SUPPORTED) || \ defined(PNG_WRITE_PACKSWAP_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_packswap,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_do_packswap, + (png_row_info *row_info, png_byte *row), + PNG_EMPTY); #endif #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_invert,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_do_invert, + (png_row_info *row_info, png_byte *row), + PNG_EMPTY); #endif #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info, - png_bytep row),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_do_bgr, + (png_row_info *row_info, png_byte *row), + PNG_EMPTY); #endif /* The following decodes the appropriate chunks, and does error correction, * then calls the appropriate callback for the chunk if it is valid. */ - -/* Decode the IHDR chunk */ -PNG_INTERNAL_FUNCTION(void,png_handle_IHDR,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_handle_PLTE,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_handle_IEND,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); - -#ifdef PNG_READ_bKGD_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_bKGD,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_cHRM_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_gAMA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_hIST_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_hIST,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_iCCP_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_iCCP,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif /* READ_iCCP */ - -#ifdef PNG_READ_iTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_iTXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_oFFs_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_oFFs,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_pCAL,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_pHYs_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_pHYs,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_sBIT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_sBIT,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_sCAL_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_sCAL,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_sPLT_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_sPLT,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif /* READ_sPLT */ - -#ifdef PNG_READ_sRGB_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_sRGB,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_tEXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_tEXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_tIME_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_tIME,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_tRNS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_tRNS,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -#endif - -PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr, - png_uint_32 chunk_name),PNG_EMPTY); - -PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY); +typedef enum +{ + /* Result of a call to png_handle_chunk made to handle the current chunk + * png_struct::chunk_name on read. Always informational, either the stream + * is read for the next chunk or the routine will call png_error. + * + * NOTE: order is important internally. handled_saved and above are regarded + * as handling the chunk. + */ + handled_error = 0, /* bad crc or known and bad format or too long */ + handled_discarded, /* not saved in the unknown chunk list */ + handled_saved, /* saved in the unknown chunk list */ + handled_ok /* known, supported and handled without error */ +} png_handle_result_code; + +PNG_INTERNAL_FUNCTION(png_handle_result_code, png_handle_unknown, + (png_struct *png_ptr, png_info *info_ptr, png_uint_32 length, int keep), + PNG_EMPTY); /* This is the function that gets called for unknown chunks. The 'keep' * argument is either non-zero for a known chunk that has been set to be * handled as unknown or zero for an unknown chunk. By default the function * just skips the chunk or errors out if it is critical. */ +PNG_INTERNAL_FUNCTION(png_handle_result_code, png_handle_chunk, + (png_struct *png_ptr, png_info *info_ptr, png_uint_32 length), + PNG_EMPTY); + /* This handles the current chunk png_ptr->chunk_name with unread + * data[length] and returns one of the above result codes. + */ + #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) -PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling, - (png_const_structrp png_ptr, png_uint_32 chunk_name),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_chunk_unknown_handling, + (const png_struct *png_ptr, png_uint_32 chunk_name), + PNG_EMPTY); /* Exactly as the API png_handle_as_unknown() except that the argument is a * 32-bit chunk name, not a string. */ @@ -1500,231 +1469,197 @@ PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling, /* Handle the transformations for reading and writing */ #ifdef PNG_READ_TRANSFORMS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_read_transformations,(png_structrp png_ptr, - png_row_infop row_info),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_do_read_transformations, + (png_struct *png_ptr, png_row_info *row_info), + PNG_EMPTY); #endif #ifdef PNG_WRITE_TRANSFORMS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_do_write_transformations,(png_structrp png_ptr, - png_row_infop row_info),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_do_write_transformations, + (png_struct *png_ptr, png_row_info *row_info), + PNG_EMPTY); #endif #ifdef PNG_READ_TRANSFORMS_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_init_read_transformations,(png_structrp png_ptr), - PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_init_read_transformations, + (png_struct *png_ptr), + PNG_EMPTY); #endif #ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_push_read_chunk,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_sig,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -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_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr, - png_bytep buffer, png_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_process_IDAT_data,(png_structrp png_ptr, - png_bytep buffer, png_size_t buffer_length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr), - PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_have_row,(png_structrp png_ptr, - png_bytep row),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_end,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_push_finish_row,(png_structrp png_ptr), - PNG_EMPTY); -# ifdef PNG_READ_tEXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_push_handle_tEXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_tEXt,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -# endif -# ifdef PNG_READ_zTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_push_handle_zTXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_zTXt,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -# endif -# ifdef PNG_READ_iTXt_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_push_handle_iTXt,(png_structrp png_ptr, - png_inforp info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_read_iTXt,(png_structrp png_ptr, - png_inforp info_ptr),PNG_EMPTY); -# endif - +PNG_INTERNAL_FUNCTION(void, png_push_read_chunk, + (png_struct *png_ptr, png_info *info_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_push_read_sig, + (png_struct *png_ptr, png_info *info_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_push_check_crc, + (png_struct *png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_push_save_buffer, + (png_struct *png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_push_restore_buffer, + (png_struct *png_ptr, png_byte *buffer, size_t buffer_length), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_push_read_IDAT, + (png_struct *png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_process_IDAT_data, + (png_struct *png_ptr, png_byte *buffer, size_t buffer_length), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_push_process_row, + (png_struct *png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_push_have_info, + (png_struct *png_ptr, png_info *info_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_push_have_end, + (png_struct *png_ptr, png_info *info_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_push_have_row, + (png_struct *png_ptr, png_byte *row), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_push_read_end, + (png_struct *png_ptr, png_info *info_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_process_some_data, + (png_struct *png_ptr, png_info *info_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_read_push_finish_row, + (png_struct *png_ptr), + PNG_EMPTY); #endif /* PROGRESSIVE_READ */ #ifdef PNG_APNG_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_ensure_fcTL_is_valid,(png_structp png_ptr, - png_uint_32 width, png_uint_32 height, - png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, - png_byte dispose_op, png_byte blend_op),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_ensure_fcTL_is_valid, + (png_struct *png_ptr, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op), + PNG_EMPTY); #ifdef PNG_READ_APNG_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_handle_acTL,(png_structp png_ptr, - png_infop info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_handle_fcTL,(png_structp png_ptr, - png_infop info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_handle_fdAT,(png_structp png_ptr, - png_infop info_ptr, png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_have_info,(png_structp png_ptr, - png_infop info_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_ensure_sequence_number,(png_structp png_ptr, - png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_reset,(png_structp png_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_read_reinit,(png_structp png_ptr, - png_infop info_ptr),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_handle_acTL, + (png_struct *png_ptr, png_info *info_ptr, png_uint_32 length), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_handle_fcTL, + (png_struct *png_ptr, png_info *info_ptr, png_uint_32 length), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_handle_fdAT, + (png_struct *png_ptr, png_info *info_ptr, png_uint_32 length), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_have_info, + (png_struct *png_ptr, png_info *info_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_ensure_sequence_number, + (png_struct *png_ptr, png_uint_32 length), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_read_reset, + (png_struct *png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_read_reinit, + (png_struct *png_ptr, png_info *info_ptr), + PNG_EMPTY); #ifdef PNG_PROGRESSIVE_READ_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_progressive_read_reset,(png_structp png_ptr), +PNG_INTERNAL_FUNCTION(void, png_progressive_read_reset, + (png_struct *png_ptr), PNG_EMPTY); -#endif /* PROGRESSIVE_READ */ -#endif /* READ_APNG */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ +#endif /* PNG_READ_APNG_SUPPORTED */ #ifdef PNG_WRITE_APNG_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_write_acTL,(png_structp png_ptr, - png_uint_32 num_frames, png_uint_32 num_plays),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_write_fcTL,(png_structp png_ptr, - png_uint_32 width, png_uint_32 height, - png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, - png_byte dispose_op, png_byte blend_op),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_write_fdAT,(png_structp png_ptr, - png_const_bytep data, png_size_t length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_write_reset,(png_structp png_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_write_reinit,(png_structp png_ptr, - png_infop info_ptr, png_uint_32 width, png_uint_32 height),PNG_EMPTY); -#endif /* WRITE_APNG */ -#endif /* APNG */ - -/* Added at libpng version 1.6.0 */ -#ifdef PNG_GAMMA_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_fixed_point gAMA), PNG_EMPTY); - /* Set the colorspace gamma with a value provided by the application or by - * the gAMA chunk on read. The value will override anything set by an ICC - * profile. - */ - -PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr, - png_inforp info_ptr), PNG_EMPTY); - /* Synchronize the info 'valid' flags with the colorspace */ - -PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr, - png_inforp info_ptr), PNG_EMPTY); - /* Copy the png_struct colorspace to the info_struct and call the above to - * synchronize the flags. Checks for NULL info_ptr and does nothing. - */ -#endif - -/* Added at libpng version 1.4.0 */ -#ifdef PNG_COLORSPACE_SUPPORTED -/* These internal functions are for maintaining the colorspace structure within - * a png_info or png_struct (or, indeed, both). - */ -PNG_INTERNAL_FUNCTION(int,png_colorspace_set_chromaticities, - (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_xy *xy, - int preferred), PNG_EMPTY); - -PNG_INTERNAL_FUNCTION(int,png_colorspace_set_endpoints, - (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_XYZ *XYZ, - int preferred), PNG_EMPTY); - -#ifdef PNG_sRGB_SUPPORTED -PNG_INTERNAL_FUNCTION(int,png_colorspace_set_sRGB,(png_const_structrp png_ptr, - png_colorspacerp colorspace, int intent), PNG_EMPTY); - /* This does set the colorspace gAMA and cHRM values too, but doesn't set the - * flags to write them, if it returns false there was a problem and an error - * message has already been output (but the colorspace may still need to be - * synced to record the invalid flag). - */ -#endif /* sRGB */ - -#ifdef PNG_iCCP_SUPPORTED -PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_charp name, - png_uint_32 profile_length, png_const_bytep profile, int color_type), +PNG_INTERNAL_FUNCTION(void, png_write_acTL, + (png_struct *png_ptr, png_uint_32 num_frames, png_uint_32 num_plays), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_fcTL, + (png_struct *png_ptr, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op), PNG_EMPTY); - /* The 'name' is used for information only */ +PNG_INTERNAL_FUNCTION(void, png_write_fdAT, + (png_struct *png_ptr, const png_byte *data, png_size_t length), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_reset, + (png_struct *png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_write_reinit, + (png_struct *png_ptr, png_info *info_ptr, + png_uint_32 width, png_uint_32 height), + PNG_EMPTY); +#endif /* PNG_WRITE_APNG_SUPPORTED */ +#endif /* PNG_APNG_SUPPORTED */ +#ifdef PNG_iCCP_SUPPORTED /* 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_colorspacerp colorspace, png_const_charp name, - png_uint_32 profile_length), PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_icc_check_length, + (const png_struct *png_ptr, + const char *name, png_uint_32 profile_length), + PNG_EMPTY); #endif /* READ_iCCP */ -PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_charp name, - png_uint_32 profile_length, - png_const_bytep profile /* first 132 bytes only */, int color_type), - PNG_EMPTY); -PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr, - png_colorspacerp colorspace, png_const_charp name, - png_uint_32 profile_length, - png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY); -#ifdef PNG_sRGB_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_icc_set_sRGB,( - png_const_structrp png_ptr, png_colorspacerp colorspace, - png_const_bytep profile, uLong adler), PNG_EMPTY); - /* 'adler' is the Adler32 checksum of the uncompressed profile data. It may - * be zero to indicate that it is not available. It is used, if provided, - * as a fast check on the profile when checking to see if it is sRGB. - */ -#endif +PNG_INTERNAL_FUNCTION(int, png_icc_check_header, + (const png_struct *png_ptr, + const char *name, png_uint_32 profile_length, + const png_byte *profile /* first 132 bytes only */, int color_type), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_icc_check_tag_table, + (const png_struct *png_ptr, + const char *name, png_uint_32 profile_length, + const png_byte *profile /* header plus whole tag table */), + PNG_EMPTY); #endif /* iCCP */ #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -PNG_INTERNAL_FUNCTION(void,png_colorspace_set_rgb_coefficients, - (png_structrp png_ptr), PNG_EMPTY); - /* Set the rgb_to_gray coefficients from the colorspace Y values */ +PNG_INTERNAL_FUNCTION(void, png_set_rgb_coefficients, + (png_struct *png_ptr), + PNG_EMPTY); + /* Set the rgb_to_gray coefficients from the cHRM Y values (if unset) */ #endif /* READ_RGB_TO_GRAY */ -#endif /* COLORSPACE */ /* Added at libpng version 1.4.0 */ -PNG_INTERNAL_FUNCTION(void,png_check_IHDR,(png_const_structrp png_ptr, - png_uint_32 width, png_uint_32 height, int bit_depth, - int color_type, int interlace_type, int compression_type, - int filter_type),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_check_IHDR, + (const png_struct *png_ptr, + png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, + int interlace_type, int compression_type, int filter_type), + PNG_EMPTY); /* Added at libpng version 1.5.10 */ #if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \ defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_do_check_palette_indexes, - (png_structrp png_ptr, png_row_infop row_info),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_do_check_palette_indexes, + (png_struct *png_ptr, png_row_info *row_info), + PNG_EMPTY); #endif #if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED) -PNG_INTERNAL_FUNCTION(void,png_fixed_error,(png_const_structrp png_ptr, - png_const_charp name),PNG_NORETURN); +PNG_INTERNAL_FUNCTION(void, png_fixed_error, + (const png_struct *png_ptr, const char *name), + PNG_NORETURN); #endif /* Puts 'string' into 'buffer' at buffer[pos], taking care never to overwrite * the end. Always leaves the buffer nul terminated. Never errors out (and * there is no error code.) */ -PNG_INTERNAL_FUNCTION(size_t,png_safecat,(png_charp buffer, size_t bufsize, - size_t pos, png_const_charp string),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(size_t, png_safecat, + (char *buffer, size_t bufsize, size_t pos, const char *string), + PNG_EMPTY); /* Various internal functions to handle formatted warning messages, currently * only implemented for warnings. */ #if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_TIME_RFC1123_SUPPORTED) /* Utility to dump an unsigned value into a buffer, given a start pointer and - * and end pointer (which should point just *beyond* the end of the buffer!) + * an end pointer (which should point just *beyond* the end of the buffer!). * Returns the pointer to the start of the formatted string. This utility only * does unsigned values. */ -PNG_INTERNAL_FUNCTION(png_charp,png_format_number,(png_const_charp start, - png_charp end, int format, png_alloc_size_t number),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(char *, png_format_number, + (const char *start, char *end, int format, png_alloc_size_t number), + PNG_EMPTY); /* Convenience macro that takes an array: */ #define PNG_FORMAT_NUMBER(buffer,format,number) \ @@ -1756,23 +1691,26 @@ PNG_INTERNAL_FUNCTION(png_charp,png_format_number,(png_const_charp start, typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][ PNG_WARNING_PARAMETER_SIZE]; -PNG_INTERNAL_FUNCTION(void,png_warning_parameter,(png_warning_parameters p, - int number, png_const_charp string),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_warning_parameter, + (png_warning_parameters p, int number, const char *string), + PNG_EMPTY); /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters, * including the trailing '\0'. */ -PNG_INTERNAL_FUNCTION(void,png_warning_parameter_unsigned, +PNG_INTERNAL_FUNCTION(void, png_warning_parameter_unsigned, (png_warning_parameters p, int number, int format, png_alloc_size_t value), PNG_EMPTY); /* Use png_alloc_size_t because it is an unsigned type as big as any we * need to output. Use the following for a signed value. */ -PNG_INTERNAL_FUNCTION(void,png_warning_parameter_signed, +PNG_INTERNAL_FUNCTION(void, png_warning_parameter_signed, (png_warning_parameters p, int number, int format, png_int_32 value), PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_formatted_warning,(png_const_structrp png_ptr, - png_warning_parameters p, png_const_charp message),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_formatted_warning, + (const png_struct *png_ptr, + png_warning_parameters p, const char *message), + PNG_EMPTY); /* 'message' follows the X/Open approach of using @1, @2 to insert * parameters previously supplied using the above functions. Errors in * specifying the parameters will simply result in garbage substitutions. @@ -1794,14 +1732,16 @@ PNG_INTERNAL_FUNCTION(void,png_formatted_warning,(png_const_structrp png_ptr, * If benign errors aren't supported they end up as the corresponding base call * (png_warning or png_error.) */ -PNG_INTERNAL_FUNCTION(void,png_app_warning,(png_const_structrp png_ptr, - png_const_charp message),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_app_warning, + (const png_struct *png_ptr, const char *message), + PNG_EMPTY); /* The application provided invalid parameters to an API function or called * an API function at the wrong time, libpng can completely recover. */ -PNG_INTERNAL_FUNCTION(void,png_app_error,(png_const_structrp png_ptr, - png_const_charp message),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_app_error, + (const png_struct *png_ptr, const char *message), + PNG_EMPTY); /* As above but libpng will ignore the call, or attempt some other partial * recovery from the error. */ @@ -1810,8 +1750,9 @@ PNG_INTERNAL_FUNCTION(void,png_app_error,(png_const_structrp png_ptr, # define png_app_error(pp,s) png_error(pp,s) #endif -PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr, - png_const_charp message, int error),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_chunk_report, + (const png_struct *png_ptr, const char *message, int error), + PNG_EMPTY); /* Report a recoverable issue in chunk data. On read this is used to report * a problem found while reading a particular chunk and the * png_chunk_benign_error or png_chunk_warning function is used as @@ -1837,14 +1778,17 @@ PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr, #define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/) #ifdef PNG_FLOATING_POINT_SUPPORTED -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_INTERNAL_FUNCTION(void, png_ascii_from_fp, + (const png_struct *png_ptr, + char *ascii, size_t size, double fp, unsigned int precision), PNG_EMPTY); #endif /* FLOATING_POINT */ #ifdef PNG_FIXED_POINT_SUPPORTED -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_INTERNAL_FUNCTION(void, png_ascii_from_fixed, + (const png_struct *png_ptr, + char *ascii, size_t size, png_fixed_point fp), + PNG_EMPTY); #endif /* FIXED_POINT */ #endif /* sCAL */ @@ -1854,7 +1798,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, * not valid it will be the index of a character in the supposed number. * * The format of a number is defined in the PNG extensions specification - * and this API is strictly conformant to that spec, not anyone elses! + * and this API is strictly conformant to that spec, not anyone else's! * * The format as a regular expression is: * @@ -1901,7 +1845,7 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, */ #define PNG_FP_INVALID 512 /* Available for callers as a distinct value */ -/* Result codes for the parser (boolean - true meants ok, false means +/* Result codes for the parser (boolean - true means ok, false means * not ok yet.) */ #define PNG_FP_MAYBE 0 /* The number may be valid in the future */ @@ -1936,8 +1880,9 @@ PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr, * that omits the last character (i.e. set the size to the index of * the problem character.) This has not been tested within libpng. */ -PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, - png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_check_fp_number, + (const char *string, size_t size, int *statep, size_t *whereami), + PNG_EMPTY); /* 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 @@ -1945,52 +1890,61 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string, * it was valid (otherwise it returns 0.) This can be used for testing * for negative or zero values using the sticky flag. */ -PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string, - png_size_t size),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_check_fp_string, + (const char *string, size_t size), + PNG_EMPTY); #endif /* pCAL || sCAL */ -#if defined(PNG_GAMMA_SUPPORTED) ||\ - defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) +#if defined(PNG_READ_GAMMA_SUPPORTED) ||\ + defined(PNG_COLORSPACE_SUPPORTED) ||\ + defined(PNG_INCH_CONVERSIONS_SUPPORTED) ||\ + defined(PNG_READ_pHYs_SUPPORTED) /* Added at libpng version 1.5.0 */ /* This is a utility to provide a*times/div (rounded) and indicate * if there is an overflow. The result is a boolean - false (0) * for overflow, true (1) if no overflow, in which case *res * holds the result. */ -PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a, - png_int_32 multiplied_by, png_int_32 divided_by),PNG_EMPTY); -#endif - -#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) -/* Same deal, but issue a warning on overflow and return 0. */ -PNG_INTERNAL_FUNCTION(png_fixed_point,png_muldiv_warn, - (png_const_structrp png_ptr, png_fixed_point a, png_int_32 multiplied_by, - png_int_32 divided_by),PNG_EMPTY); -#endif +PNG_INTERNAL_FUNCTION(int, png_muldiv, + (png_fixed_point *res, png_fixed_point a, + png_int_32 multiplied_by, png_int_32 divided_by), + PNG_EMPTY); -#ifdef PNG_GAMMA_SUPPORTED /* Calculate a reciprocal - used for gamma values. This returns * 0 if the argument is 0 in order to maintain an undefined value; * there are no warnings. */ -PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a), +PNG_INTERNAL_FUNCTION(png_fixed_point, png_reciprocal, + (png_fixed_point a), PNG_EMPTY); +#endif #ifdef PNG_READ_GAMMA_SUPPORTED /* The same but gives a reciprocal of the product of two fixed point * values. Accuracy is suitable for gamma calculations but this is * not exact - use png_muldiv for that. Only required at present on read. */ -PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a, - png_fixed_point b),PNG_EMPTY); -#endif +PNG_INTERNAL_FUNCTION(png_fixed_point, png_reciprocal2, + (png_fixed_point a, png_fixed_point b), + PNG_EMPTY); /* Return true if the gamma value is significantly different from 1.0 */ -PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value), +PNG_INTERNAL_FUNCTION(int, png_gamma_significant, + (png_fixed_point gamma_value), + PNG_EMPTY); + +/* PNGv3: 'resolve' the file gamma according to the new PNGv3 rules for colour + * space information. + * + * NOTE: this uses precisely those chunks that libpng supports. For example it + * doesn't use iCCP and it can only use cICP for known and manageable + * transforms. For this reason a gamma specified by png_set_gamma always takes + * precedence. + */ +PNG_INTERNAL_FUNCTION(png_fixed_point, png_resolve_file_gamma, + (const png_struct *png_ptr), PNG_EMPTY); -#endif -#ifdef PNG_READ_GAMMA_SUPPORTED /* Internal fixed point gamma correction. These APIs are called as * required to convert single values - they don't need to be fast, * they are not used when processing image pixel values. @@ -1998,34 +1952,59 @@ PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value), * While the input is an 'unsigned' value it must actually be the * correct bit value - 0..255 or 0..65535 as required. */ -PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_correct,(png_structrp png_ptr, - unsigned int value, png_fixed_point gamma_value),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_16bit_correct,(unsigned int value, - png_fixed_point gamma_value),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(png_byte,png_gamma_8bit_correct,(unsigned int value, - png_fixed_point gamma_value),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr), +PNG_INTERNAL_FUNCTION(png_uint_16, png_gamma_correct, + (png_struct *png_ptr, unsigned int value, png_fixed_point gamma_value), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(png_uint_16, png_gamma_16bit_correct, + (unsigned int value, png_fixed_point gamma_value), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(png_byte, png_gamma_8bit_correct, + (unsigned int value, png_fixed_point gamma_value), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_destroy_gamma_table, + (png_struct *png_ptr), + PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_build_gamma_table, + (png_struct *png_ptr, int bit_depth), + PNG_EMPTY); +#endif /* READ_GAMMA */ + +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED +/* Set the RGB coefficients if not already set by png_set_rgb_to_gray */ +PNG_INTERNAL_FUNCTION(void, png_set_rgb_coefficients, + (png_struct *png_ptr), + PNG_EMPTY); +#endif + +#if defined(PNG_cHRM_SUPPORTED) || defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) +PNG_INTERNAL_FUNCTION(int, png_XYZ_from_xy, + (png_XYZ *XYZ, const png_xy *xy), + PNG_EMPTY); +#endif /* cHRM || READ_RGB_TO_GRAY */ + +#ifdef PNG_COLORSPACE_SUPPORTED +PNG_INTERNAL_FUNCTION(int, png_xy_from_XYZ, + (png_xy *xy, const png_XYZ *XYZ), PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr, - int bit_depth),PNG_EMPTY); #endif /* SIMPLIFIED READ/WRITE SUPPORT */ #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ - defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + /* The internal structure that png_image::opaque points to. */ -typedef struct png_control +struct png_control_def { - png_structp png_ptr; - png_infop info_ptr; - png_voidp error_buf; /* Always a jmp_buf at present. */ + png_struct *png_ptr; + png_info *info_ptr; + void *error_buf; /* Currently this can only be jmp_buf */ - png_const_bytep memory; /* Memory buffer. */ - png_size_t size; /* Size of the memory buffer. */ + const png_byte *memory; /* Memory buffer */ + size_t size; /* Size of the memory buffer */ unsigned int for_write :1; /* Otherwise it is a read structure */ unsigned int owned_file :1; /* We own the file in io_ptr */ -} png_control; +}; /* Return the pointer to the jmp_buf from a png_control: necessary because C * does not reveal the type of the elements of jmp_buf. @@ -2040,64 +2019,41 @@ typedef struct png_control * errors that might occur. Returns true on success, false on failure (either * of the function or as a result of a png_error.) */ -PNG_INTERNAL_CALLBACK(void,png_safe_error,(png_structp png_ptr, - png_const_charp error_message),PNG_NORETURN); +PNG_INTERNAL_CALLBACK(void, png_safe_error, + (png_struct *png_ptr, const char *error_message), + PNG_NORETURN); #ifdef PNG_WARNINGS_SUPPORTED -PNG_INTERNAL_CALLBACK(void,png_safe_warning,(png_structp png_ptr, - png_const_charp warning_message),PNG_EMPTY); +PNG_INTERNAL_CALLBACK(void, png_safe_warning, + (png_struct *png_ptr, const char *warning_message), + PNG_EMPTY); #else # define png_safe_warning 0/*dummy argument*/ #endif -PNG_INTERNAL_FUNCTION(int,png_safe_execute,(png_imagep image, - int (*function)(png_voidp), png_voidp arg),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_safe_execute, + (png_image *image, int (*function)(void *), void *arg), + PNG_EMPTY); /* Utility to log an error; this also cleans up the png_image; the function * always returns 0 (false). */ -PNG_INTERNAL_FUNCTION(int,png_image_error,(png_imagep image, - png_const_charp error_message),PNG_EMPTY); +PNG_INTERNAL_FUNCTION(int, png_image_error, + (png_image *image, const char *error_message), + PNG_EMPTY); #ifndef PNG_SIMPLIFIED_READ_SUPPORTED /* png_image_free is used by the write code but not exported */ -PNG_INTERNAL_FUNCTION(void, png_image_free, (png_imagep image), PNG_EMPTY); +PNG_INTERNAL_FUNCTION(void, png_image_free, + (png_image *image), + PNG_EMPTY); #endif /* !SIMPLIFIED_READ */ #endif /* SIMPLIFIED READ/WRITE */ -/* These are initialization functions for hardware specific PNG filter - * optimizations; list these here then select the appropriate one at compile - * time using the macro PNG_FILTER_OPTIMIZATIONS. If the macro is not defined - * the generic code is used. - */ -#ifdef PNG_FILTER_OPTIMIZATIONS -PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr, - unsigned int bpp), PNG_EMPTY); - /* Just declare the optimization that will be used */ -#else - /* List *all* the possible optimizations here - this branch is required if - * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in - * 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_structp png_ptr, unsigned int bpp), PNG_EMPTY); -#endif - -#if PNG_MIPS_MSA_OPT > 0 -PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa, - (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); -#endif - -# if PNG_INTEL_SSE_IMPLEMENTATION > 0 -PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2, - (png_structp png_ptr, unsigned int bpp), PNG_EMPTY); -# endif -#endif - -PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, - png_const_charp key, png_bytep new_key), PNG_EMPTY); +PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, + (png_struct *png_ptr, const char *key, png_byte *new_key), + PNG_EMPTY); /* Maintainer: Put new private prototypes here ^ */ @@ -2108,4 +2064,3 @@ PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr, #endif #endif /* PNG_VERSION_INFO_ONLY */ -#endif /* PNGPRIV_H */ diff --git a/media/libpng/pngread.c b/media/libpng/pngread.c index 0fac203dfd..f76e44cc44 100644 --- a/media/libpng/pngread.c +++ b/media/libpng/pngread.c @@ -1,10 +1,9 @@ - /* pngread.c - read a PNG file * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -22,12 +21,13 @@ #ifdef PNG_READ_SUPPORTED /* Create a PNG structure for reading, and allocate any memory needed. */ -PNG_FUNCTION(png_structp,PNGAPI -png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) +PNG_FUNCTION(png_struct *, +png_create_read_struct,(const char *user_png_ver, void *error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED) { #ifndef PNG_USER_MEM_SUPPORTED - png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + png_struct *png_ptr = png_create_png_struct(user_png_ver, error_ptr, error_fn, warn_fn, NULL, NULL, NULL); #else return png_create_read_struct_2(user_png_ver, error_ptr, error_fn, @@ -37,12 +37,13 @@ png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, /* Alternate create PNG structure for reading, and allocate any memory * needed. */ -PNG_FUNCTION(png_structp,PNGAPI -png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +PNG_FUNCTION(png_struct *, +png_create_read_struct_2,(const char *user_png_ver, void *error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, void *mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED) { - png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + png_struct *png_ptr = png_create_png_struct(user_png_ver, error_ptr, error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); #endif /* USER_MEM */ @@ -68,6 +69,15 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, # endif # endif +# ifdef PNG_TARGET_CODE_IMPLEMENTATION /* target specific code */ + /* Current support is read-only so this happens here, not in the + * general creation. It could easily be moved. + */ + png_target_init(png_ptr); + if (png_ptr->target_state != 0U) + png_set_option(png_ptr, PNG_TARGET_SPECIFIC_CODE, 1); +# endif + /* TODO: delay this, it can be done in png_init_io (if the app doesn't * do it itself) avoiding setting the default function if it is not * required. @@ -88,8 +98,8 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, * here. The application can then have access to the signature bytes we * read if it is determined that this isn't a valid PNG file. */ -void PNGAPI -png_read_info(png_structrp png_ptr, png_inforp info_ptr) +void +png_read_info(png_struct *png_ptr, png_info *info_ptr) { #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED int keep; @@ -132,14 +142,11 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) png_ptr->mode |= PNG_AFTER_IDAT; } - /* This should be a binary subdivision search or a hash for - * matching the chunk name rather than a linear search. - */ if (chunk_name == png_IHDR) - png_handle_IHDR(png_ptr, info_ptr, length); + png_handle_chunk(png_ptr, info_ptr, length); else if (chunk_name == png_IEND) - png_handle_IEND(png_ptr, info_ptr, length); + png_handle_chunk(png_ptr, info_ptr, length); #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) @@ -156,8 +163,6 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) } } #endif - else if (chunk_name == png_PLTE) - png_handle_PLTE(png_ptr, info_ptr, length); else if (chunk_name == png_IDAT) { @@ -168,91 +173,6 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) break; } -#ifdef PNG_READ_bKGD_SUPPORTED - else if (chunk_name == png_bKGD) - png_handle_bKGD(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_cHRM_SUPPORTED - else if (chunk_name == png_cHRM) - png_handle_cHRM(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_gAMA_SUPPORTED - else if (chunk_name == png_gAMA) - png_handle_gAMA(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_hIST_SUPPORTED - else if (chunk_name == png_hIST) - png_handle_hIST(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_oFFs_SUPPORTED - else if (chunk_name == png_oFFs) - png_handle_oFFs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED - else if (chunk_name == png_pCAL) - png_handle_pCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sCAL_SUPPORTED - else if (chunk_name == png_sCAL) - png_handle_sCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pHYs_SUPPORTED - else if (chunk_name == png_pHYs) - png_handle_pHYs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sBIT_SUPPORTED - else if (chunk_name == png_sBIT) - png_handle_sBIT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sRGB_SUPPORTED - else if (chunk_name == png_sRGB) - png_handle_sRGB(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iCCP_SUPPORTED - else if (chunk_name == png_iCCP) - png_handle_iCCP(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sPLT_SUPPORTED - else if (chunk_name == png_sPLT) - png_handle_sPLT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tEXt_SUPPORTED - else if (chunk_name == png_tEXt) - png_handle_tEXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tIME_SUPPORTED - else if (chunk_name == png_tIME) - png_handle_tIME(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tRNS_SUPPORTED - else if (chunk_name == png_tRNS) - png_handle_tRNS(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED - else if (chunk_name == png_zTXt) - png_handle_zTXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iTXt_SUPPORTED - else if (chunk_name == png_iTXt) - png_handle_iTXt(png_ptr, info_ptr, length); -#endif - #ifdef PNG_READ_APNG_SUPPORTED else if (chunk_name == png_acTL) png_handle_acTL(png_ptr, info_ptr, length); @@ -265,81 +185,79 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr) #endif else - png_handle_unknown(png_ptr, info_ptr, length, - PNG_HANDLE_CHUNK_AS_DEFAULT); + png_handle_chunk(png_ptr, info_ptr, length); } } #endif /* SEQUENTIAL_READ */ #ifdef PNG_READ_APNG_SUPPORTED void PNGAPI -png_read_frame_head(png_structp png_ptr, png_infop info_ptr) +png_read_frame_head(png_struct *png_ptr, png_info *info_ptr) { - png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */ - - png_debug(0, "Reading frame head"); - - if ((png_ptr->mode & PNG_HAVE_acTL) == 0) - png_error(png_ptr, "attempt to png_read_frame_head() but " - "no acTL present"); - - /* do nothing for the main IDAT */ - if (png_ptr->num_frames_read == 0) - return; - - png_read_reset(png_ptr); - png_ptr->flags &= ~PNG_FLAG_ROW_INIT; - png_ptr->mode &= ~PNG_HAVE_fcTL; - - have_chunk_after_DAT = 0; - for (;;) - { - png_uint_32 length = png_read_chunk_header(png_ptr); - - if (png_ptr->chunk_name == png_IDAT) - { - /* discard trailing IDATs for the first frame */ - if (have_chunk_after_DAT != 0 || png_ptr->num_frames_read > 1) - png_error(png_ptr, "png_read_frame_head(): out of place IDAT"); - png_crc_finish(png_ptr, length); - } - - else if (png_ptr->chunk_name == png_fcTL) - { - png_handle_fcTL(png_ptr, info_ptr, length); - have_chunk_after_DAT = 1; - } - - else if (png_ptr->chunk_name == png_fdAT) - { - png_ensure_sequence_number(png_ptr, length); - - /* discard trailing fdATs for frames other than the first */ - if (have_chunk_after_DAT == 0 && png_ptr->num_frames_read > 1) - png_crc_finish(png_ptr, length - 4); - else if(png_ptr->mode & PNG_HAVE_fcTL) - { - png_ptr->idat_size = length - 4; - png_ptr->mode |= PNG_HAVE_IDAT; + png_byte have_chunk_after_DAT; /* after IDAT or after fdAT */ - break; - } - else - png_error(png_ptr, "png_read_frame_head(): out of place fdAT"); - } - else - { - png_warning(png_ptr, "Skipped (ignored) a chunk " - "between APNG chunks"); - png_crc_finish(png_ptr, length); - } - } + png_debug(1, "Reading frame head"); + + if (!(png_ptr->mode & PNG_HAVE_acTL)) + png_error(png_ptr, "Cannot read APNG frame: missing acTL"); + + /* Do nothing for the main IDAT. */ + if (png_ptr->num_frames_read == 0) + return; + + png_read_reset(png_ptr); + png_ptr->flags &= ~PNG_FLAG_ROW_INIT; + png_ptr->mode &= ~PNG_HAVE_fcTL; + + have_chunk_after_DAT = 0; + for (;;) + { + png_uint_32 length = png_read_chunk_header(png_ptr); + + if (png_ptr->chunk_name == png_IDAT) + { + /* Discard trailing IDATs for the first frame. */ + if (have_chunk_after_DAT || png_ptr->num_frames_read > 1) + png_error(png_ptr, "Misplaced IDAT in APNG stream"); + png_crc_finish(png_ptr, length); + } + else if (png_ptr->chunk_name == png_fcTL) + { + png_handle_fcTL(png_ptr, info_ptr, length); + have_chunk_after_DAT = 1; + } + else if (png_ptr->chunk_name == png_fdAT) + { + png_ensure_sequence_number(png_ptr, length); + + /* Discard trailing fdATs for all frames except the first. */ + if (!have_chunk_after_DAT && png_ptr->num_frames_read > 1) + { + png_crc_finish(png_ptr, length - 4); + } + else if (png_ptr->mode & PNG_HAVE_fcTL) + { + png_ptr->idat_size = length - 4; + png_ptr->mode |= PNG_HAVE_IDAT; + break; + } + else + { + png_error(png_ptr, "Misplaced fdAT in APNG stream"); + } + } + else + { + png_warning(png_ptr, "Ignoring unexpected chunk in APNG sequence"); + png_crc_finish(png_ptr, length); + } + } } -#endif /* READ_APNG */ +#endif /* PNG_READ_APNG_SUPPORTED */ /* Optional call to update the users info_ptr structure */ -void PNGAPI -png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) +void +png_read_update_info(png_struct *png_ptr, png_info *info_ptr) { png_debug(1, "in png_read_update_info"); @@ -369,8 +287,8 @@ png_read_update_info(png_structrp png_ptr, png_inforp info_ptr) * the user to obtain a gamma-corrected palette, for example. * If the user doesn't call this, we will do it ourselves. */ -void PNGAPI -png_start_read_image(png_structrp png_ptr) +void +png_start_read_image(png_struct *png_ptr) { png_debug(1, "in png_start_read_image"); @@ -393,7 +311,7 @@ png_start_read_image(png_structrp png_ptr) * NOTE: this is apparently only supported in the 'sequential' reader. */ static void -png_do_read_intrapixel(png_row_infop row_info, png_bytep row) +png_do_read_intrapixel(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_read_intrapixel"); @@ -405,7 +323,7 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { - png_bytep rp; + png_byte *rp; png_uint_32 i; if (row_info->color_type == PNG_COLOR_TYPE_RGB) @@ -425,7 +343,7 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row) } else if (row_info->bit_depth == 16) { - png_bytep rp; + png_byte *rp; png_uint_32 i; if (row_info->color_type == PNG_COLOR_TYPE_RGB) @@ -454,8 +372,8 @@ png_do_read_intrapixel(png_row_infop row_info, png_bytep row) } #endif /* MNG_FEATURES */ -void PNGAPI -png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) +void +png_read_row(png_struct *png_ptr, png_byte *row, png_byte *dsp_row) { png_row_info row_info; @@ -614,6 +532,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"); /* 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); if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) @@ -642,7 +561,11 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) #endif #ifdef PNG_READ_TRANSFORMS_SUPPORTED - if (png_ptr->transformations) + if (png_ptr->transformations +# ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED + || png_ptr->num_palette_max >= 0 +# endif + ) png_do_read_transformations(png_ptr, &row_info); #endif @@ -686,7 +609,6 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) if (png_ptr->read_row_fn != NULL) (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); - } #endif /* SEQUENTIAL_READ */ @@ -715,13 +637,13 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) * [*] png_handle_alpha() does not exist yet, as of this version of libpng */ -void PNGAPI -png_read_rows(png_structrp png_ptr, png_bytepp row, - png_bytepp display_row, png_uint_32 num_rows) +void +png_read_rows(png_struct *png_ptr, png_byte **row, + png_byte **display_row, png_uint_32 num_rows) { png_uint_32 i; - png_bytepp rp; - png_bytepp dp; + png_byte **rp; + png_byte **dp; png_debug(1, "in png_read_rows"); @@ -733,8 +655,8 @@ png_read_rows(png_structrp png_ptr, png_bytepp row, if (rp != NULL && dp != NULL) for (i = 0; i < num_rows; i++) { - png_bytep rptr = *rp++; - png_bytep dptr = *dp++; + png_byte *rptr = *rp++; + png_byte *dptr = *dp++; png_read_row(png_ptr, rptr, dptr); } @@ -742,7 +664,7 @@ png_read_rows(png_structrp png_ptr, png_bytepp row, else if (rp != NULL) for (i = 0; i < num_rows; i++) { - png_bytep rptr = *rp; + png_byte *rptr = *rp; png_read_row(png_ptr, rptr, NULL); rp++; } @@ -750,7 +672,7 @@ png_read_rows(png_structrp png_ptr, png_bytepp row, else if (dp != NULL) for (i = 0; i < num_rows; i++) { - png_bytep dptr = *dp; + png_byte *dptr = *dp; png_read_row(png_ptr, NULL, dptr); dp++; } @@ -770,12 +692,12 @@ png_read_rows(png_structrp png_ptr, png_bytepp row, * * [*] png_handle_alpha() does not exist yet, as of this version of libpng */ -void PNGAPI -png_read_image(png_structrp png_ptr, png_bytepp image) +void +png_read_image(png_struct *png_ptr, png_byte **image) { png_uint_32 i, image_height; int pass, j; - png_bytepp rp; + png_byte **rp; png_debug(1, "in png_read_image"); @@ -836,8 +758,8 @@ png_read_image(png_structrp png_ptr, png_bytepp image) * file, will verify the end is accurate, and will read any comments * or time information at the end of the file, if info is not NULL. */ -void PNGAPI -png_read_end(png_structrp png_ptr, png_inforp info_ptr) +void +png_read_end(png_struct *png_ptr, png_info *info_ptr) { #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED int keep; @@ -857,9 +779,9 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) png_read_finish_IDAT(png_ptr); #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED - /* Report invalid palette index; added at libng-1.5.10 */ + /* Report invalid palette index; added at libpng-1.5.10 */ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - png_ptr->num_palette_max > png_ptr->num_palette) + png_ptr->num_palette_max >= png_ptr->num_palette) png_benign_error(png_ptr, "Read palette index exceeding num_palette"); #endif @@ -869,13 +791,18 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) png_uint_32 chunk_name = png_ptr->chunk_name; if (chunk_name != png_IDAT) - png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; + { + /* These flags must be set consistently for all non-IDAT chunks, + * including the unknown chunks. + */ + png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT | PNG_AFTER_IDAT; + } if (chunk_name == png_IEND) - png_handle_IEND(png_ptr, info_ptr, length); + png_handle_chunk(png_ptr, info_ptr, length); else if (chunk_name == png_IHDR) - png_handle_IHDR(png_ptr, info_ptr, length); + png_handle_chunk(png_ptr, info_ptr, length); else if (info_ptr == NULL) png_crc_finish(png_ptr, length); @@ -909,104 +836,16 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr) png_crc_finish(png_ptr, length); } - else if (chunk_name == png_PLTE) - png_handle_PLTE(png_ptr, info_ptr, length); - -#ifdef PNG_READ_bKGD_SUPPORTED - else if (chunk_name == png_bKGD) - png_handle_bKGD(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_cHRM_SUPPORTED - else if (chunk_name == png_cHRM) - png_handle_cHRM(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_gAMA_SUPPORTED - else if (chunk_name == png_gAMA) - png_handle_gAMA(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_hIST_SUPPORTED - else if (chunk_name == png_hIST) - png_handle_hIST(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_oFFs_SUPPORTED - else if (chunk_name == png_oFFs) - png_handle_oFFs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pCAL_SUPPORTED - else if (chunk_name == png_pCAL) - png_handle_pCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sCAL_SUPPORTED - else if (chunk_name == png_sCAL) - png_handle_sCAL(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_pHYs_SUPPORTED - else if (chunk_name == png_pHYs) - png_handle_pHYs(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sBIT_SUPPORTED - else if (chunk_name == png_sBIT) - png_handle_sBIT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sRGB_SUPPORTED - else if (chunk_name == png_sRGB) - png_handle_sRGB(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iCCP_SUPPORTED - else if (chunk_name == png_iCCP) - png_handle_iCCP(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_sPLT_SUPPORTED - else if (chunk_name == png_sPLT) - png_handle_sPLT(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tEXt_SUPPORTED - else if (chunk_name == png_tEXt) - png_handle_tEXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tIME_SUPPORTED - else if (chunk_name == png_tIME) - png_handle_tIME(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_tRNS_SUPPORTED - else if (chunk_name == png_tRNS) - png_handle_tRNS(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_zTXt_SUPPORTED - else if (chunk_name == png_zTXt) - png_handle_zTXt(png_ptr, info_ptr, length); -#endif - -#ifdef PNG_READ_iTXt_SUPPORTED - else if (chunk_name == png_iTXt) - png_handle_iTXt(png_ptr, info_ptr, length); -#endif else - png_handle_unknown(png_ptr, info_ptr, length, - PNG_HANDLE_CHUNK_AS_DEFAULT); + png_handle_chunk(png_ptr, info_ptr, length); } while ((png_ptr->mode & PNG_HAVE_IEND) == 0); } #endif /* SEQUENTIAL_READ */ /* Free all memory used in the read struct */ static void -png_read_destroy(png_structrp png_ptr) +png_read_destroy(png_struct *png_ptr) { png_debug(1, "in png_read_destroy"); @@ -1028,21 +867,19 @@ png_read_destroy(png_structrp png_ptr) png_ptr->quantize_index = NULL; #endif - if ((png_ptr->free_me & PNG_FREE_PLTE) != 0) - { - png_zfree(png_ptr, png_ptr->palette); - png_ptr->palette = NULL; - } - png_ptr->free_me &= ~PNG_FREE_PLTE; + /* png_ptr->palette is always independently allocated (not aliased + * with info_ptr->palette), so free it unconditionally. + */ + png_free(png_ptr, png_ptr->palette); + png_ptr->palette = NULL; #if defined(PNG_tRNS_SUPPORTED) || \ defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - if ((png_ptr->free_me & PNG_FREE_TRNS) != 0) - { - png_free(png_ptr, png_ptr->trans_alpha); - png_ptr->trans_alpha = NULL; - } - png_ptr->free_me &= ~PNG_FREE_TRNS; + /* png_ptr->trans_alpha is always independently allocated (not aliased + * with info_ptr->trans_alpha), so free it unconditionally. + */ + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->trans_alpha = NULL; #endif inflateEnd(&png_ptr->zstream); @@ -1063,6 +900,12 @@ png_read_destroy(png_structrp png_ptr) png_ptr->chunk_list = NULL; #endif +#ifdef PNG_TARGET_STORES_DATA + if (png_ptr->target_data != NULL) + png_target_free_data(png_ptr); + png_ptr->target_data = NULL; +#endif + /* 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 * destruction of the png_struct itself. @@ -1070,11 +913,11 @@ png_read_destroy(png_structrp png_ptr) } /* Free all memory used by the read */ -void PNGAPI -png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, - png_infopp end_info_ptr_ptr) +void +png_destroy_read_struct(png_struct **png_ptr_ptr, png_info **info_ptr_ptr, + png_info **end_info_ptr_ptr) { - png_structrp png_ptr = NULL; + png_struct *png_ptr = NULL; png_debug(1, "in png_destroy_read_struct"); @@ -1096,8 +939,8 @@ png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, png_destroy_png_struct(png_ptr); } -void PNGAPI -png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn) +void +png_set_read_status_fn(png_struct *png_ptr, png_read_status_ptr read_row_fn) { if (png_ptr == NULL) return; @@ -1108,10 +951,12 @@ png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn) #ifdef PNG_SEQUENTIAL_READ_SUPPORTED #ifdef PNG_INFO_IMAGE_SUPPORTED -void PNGAPI -png_read_png(png_structrp png_ptr, png_inforp info_ptr, - int transforms, voidp params) +void +png_read_png(png_struct *png_ptr, png_info *info_ptr, + int transforms, void *params) { + png_debug(1, "in png_read_png"); + if (png_ptr == NULL || info_ptr == NULL) return; @@ -1119,7 +964,7 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, * PNG file before the first IDAT (image data chunk). */ png_read_info(png_ptr, info_ptr); - if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep))) + if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_byte *))) png_error(png_ptr, "Image is too high to process with png_read_png()"); /* -------------- image transformations start here ------------------- */ @@ -1288,8 +1133,8 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, { png_uint_32 iptr; - info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr, - info_ptr->height * (sizeof (png_bytep)))); + info_ptr->row_pointers = png_voidcast(png_byte **, png_malloc(png_ptr, + info_ptr->height * (sizeof (png_byte *)))); for (iptr=0; iptrheight; iptr++) info_ptr->row_pointers[iptr] = NULL; @@ -1297,7 +1142,7 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, info_ptr->free_me |= PNG_FREE_ROWS; for (iptr = 0; iptr < info_ptr->height; iptr++) - info_ptr->row_pointers[iptr] = png_voidcast(png_bytep, + info_ptr->row_pointers[iptr] = png_voidcast(png_byte *, png_malloc(png_ptr, info_ptr->rowbytes)); } @@ -1345,19 +1190,20 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, typedef struct { - /* Arguments: */ - png_imagep image; - png_voidp buffer; + /* Arguments */ + png_image *image; + void *buffer; png_int_32 row_stride; - png_voidp colormap; - png_const_colorp background; - /* Local variables: */ - png_voidp local_row; - png_voidp first_row; - ptrdiff_t row_bytes; /* step between rows */ - int file_encoding; /* E_ values above */ - png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */ - int colormap_processing; /* PNG_CMAP_ values above */ + void *colormap; + const png_color *background; + + /* Instance variables */ + void *local_row; + void *first_row; + ptrdiff_t row_step; /* step between rows */ + int file_encoding; /* E_ values above */ + png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */ + int colormap_processing; /* PNG_CMAP_ values above */ } png_image_read_control; /* Do all the *safe* initialization - 'safe' means that png_error won't be @@ -1366,11 +1212,11 @@ typedef struct * instead so that control is returned safely back to this routine. */ static int -png_image_read_init(png_imagep image) +png_image_read_init(png_image *image) { if (image->opaque == NULL) { - png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image, + png_struct *png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image, png_safe_error, png_safe_warning); /* And set the rest of the structure to NULL to ensure that the various @@ -1381,11 +1227,11 @@ png_image_read_init(png_imagep image) if (png_ptr != NULL) { - png_infop info_ptr = png_create_info_struct(png_ptr); + png_info *info_ptr = png_create_info_struct(png_ptr); if (info_ptr != NULL) { - png_controlp control = png_voidcast(png_controlp, + png_control *control = png_voidcast(png_control *, png_malloc_warn(png_ptr, (sizeof *control))); if (control != NULL) @@ -1415,7 +1261,7 @@ png_image_read_init(png_imagep image) /* Utility to find the base format of a PNG file from a png_struct. */ static png_uint_32 -png_image_format(png_structrp png_ptr) +png_image_format(png_struct *png_ptr) { png_uint_32 format = 0; @@ -1442,6 +1288,31 @@ png_image_format(png_structrp png_ptr) return format; } +static int +chromaticities_match_sRGB(const png_xy *xy) +{ +# define sRGB_TOLERANCE 1000 + static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */ + { + /* color x y */ + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000, + /* white */ 31270, 32900 + }; + + if (PNG_OUT_OF_RANGE(xy->whitex, sRGB_xy.whitex,sRGB_TOLERANCE) || + PNG_OUT_OF_RANGE(xy->whitey, sRGB_xy.whitey,sRGB_TOLERANCE) || + PNG_OUT_OF_RANGE(xy->redx, sRGB_xy.redx, sRGB_TOLERANCE) || + PNG_OUT_OF_RANGE(xy->redy, sRGB_xy.redy, sRGB_TOLERANCE) || + PNG_OUT_OF_RANGE(xy->greenx, sRGB_xy.greenx,sRGB_TOLERANCE) || + PNG_OUT_OF_RANGE(xy->greeny, sRGB_xy.greeny,sRGB_TOLERANCE) || + PNG_OUT_OF_RANGE(xy->bluex, sRGB_xy.bluex, sRGB_TOLERANCE) || + PNG_OUT_OF_RANGE(xy->bluey, sRGB_xy.bluey, sRGB_TOLERANCE)) + return 0; + return 1; +} + /* Is the given gamma significantly different from sRGB? The test is the same * one used in pngrtran.c when deciding whether to do gamma correction. The * arithmetic optimizes the division by using the fact that the inverse of the @@ -1450,16 +1321,11 @@ png_image_format(png_structrp png_ptr) static int png_gamma_not_sRGB(png_fixed_point g) { - if (g < PNG_FP_1) - { - /* An uninitialized gamma is assumed to be sRGB for the simplified API. */ - if (g == 0) - return 0; + /* 1.6.47: use the same sanity checks as used in pngrtran.c */ + if (g < PNG_LIB_GAMMA_MIN || g > PNG_LIB_GAMMA_MAX) + return 0; /* Includes the uninitialized value 0 */ - return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */); - } - - return 1; + return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */); } /* Do the main body of a 'png_image_begin_read' function; read the PNG file @@ -1467,11 +1333,38 @@ png_gamma_not_sRGB(png_fixed_point g) * unlike the init routine above. */ static int -png_image_read_header(png_voidp argument) +png_image_is_not_sRGB(const png_struct *png_ptr) +{ + /* Does the colorspace **not** match sRGB? The flag is only set if the + * answer can be determined reliably. + * + * png_struct::chromaticities always exists since the simplified API + * requires rgb-to-gray. The mDCV, cICP and cHRM chunks may all set it to + * a non-sRGB value, so it needs to be checked but **only** if one of + * those chunks occurred in the file. + */ + /* Highest priority: check to be safe. */ + if (png_has_chunk(png_ptr, cICP) || png_has_chunk(png_ptr, mDCV)) + return !chromaticities_match_sRGB(&png_ptr->chromaticities); + + /* If the image is marked as sRGB then it is... */ + if (png_has_chunk(png_ptr, sRGB)) + return 0; + + /* Last stop: cHRM, must check: */ + if (png_has_chunk(png_ptr, cHRM)) + return !chromaticities_match_sRGB(&png_ptr->chromaticities); + + /* Else default to sRGB */ + return 0; +} + +static int +png_image_read_header(void *argument) { - png_imagep image = png_voidcast(png_imagep, argument); - png_structrp png_ptr = image->opaque->png_ptr; - png_inforp info_ptr = image->opaque->info_ptr; + png_image *image = png_voidcast(png_image *, argument); + png_struct *png_ptr = image->opaque->png_ptr; + png_info *info_ptr = image->opaque->info_ptr; #ifdef PNG_BENIGN_ERRORS_SUPPORTED png_set_benign_errors(png_ptr, 1/*warn*/); @@ -1487,17 +1380,13 @@ png_image_read_header(png_voidp argument) image->format = format; -#ifdef PNG_COLORSPACE_SUPPORTED - /* Does the colorspace match sRGB? If there is no color endpoint - * (colorant) information assume yes, otherwise require the - * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set. If the - * colorspace has been determined to be invalid ignore it. + /* Greyscale images don't (typically) have colour space information and + * using it is pretty much impossible, so use sRGB for grayscale (it + * doesn't matter r==g==b so the transform is irrelevant.) */ - if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags - & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB| - PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS)) + if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && + png_image_is_not_sRGB(png_ptr)) image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB; -#endif } /* We need the maximum number of entries regardless of the format the @@ -1531,8 +1420,8 @@ png_image_read_header(png_voidp argument) } #ifdef PNG_STDIO_SUPPORTED -int PNGAPI -png_image_begin_read_from_stdio(png_imagep image, FILE* file) +int +png_image_begin_read_from_stdio(png_image *image, FILE *file) { if (image != NULL && image->version == PNG_IMAGE_VERSION) { @@ -1561,8 +1450,8 @@ png_image_begin_read_from_stdio(png_imagep image, FILE* file) return 0; } -int PNGAPI -png_image_begin_read_from_file(png_imagep image, const char *file_name) +int +png_image_begin_read_from_file(png_image *image, const char *file_name) { if (image != NULL && image->version == PNG_IMAGE_VERSION) { @@ -1600,19 +1489,19 @@ png_image_begin_read_from_file(png_imagep image, const char *file_name) } #endif /* STDIO */ -static void PNGCBAPI -png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) +static void +png_image_memory_read(png_struct *png_ptr, png_byte *out, size_t need) { if (png_ptr != NULL) { - png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr); + png_image *image = png_voidcast(png_image *, png_ptr->io_ptr); if (image != NULL) { - png_controlp cp = image->opaque; + png_control *cp = image->opaque; if (cp != NULL) { - png_const_bytep memory = cp->memory; - png_size_t size = cp->size; + const png_byte *memory = cp->memory; + size_t size = cp->size; if (memory != NULL && size >= need) { @@ -1630,8 +1519,8 @@ 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, - png_const_voidp memory, png_size_t size) +int png_image_begin_read_from_memory(png_image *image, + const void *memory, size_t size) { if (image != NULL && image->version == PNG_IMAGE_VERSION) { @@ -1643,7 +1532,7 @@ int PNGAPI png_image_begin_read_from_memory(png_imagep image, * store it into io_ptr. Again do this in-place to avoid calling a * libpng function that requires error handling. */ - image->opaque->memory = png_voidcast(png_const_bytep, memory); + image->opaque->memory = png_voidcast(const png_byte *, memory); image->opaque->size = size; image->opaque->png_ptr->io_ptr = image; image->opaque->png_ptr->read_data_fn = png_image_memory_read; @@ -1669,7 +1558,7 @@ int PNGAPI png_image_begin_read_from_memory(png_imagep image, */ #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED static void -png_image_skip_unused_chunks(png_structrp png_ptr) +png_image_skip_unused_chunks(png_struct *png_ptr) { /* Prepare the reader to ignore all recognized chunks whose data will not * be used, i.e., all chunks recognized by libpng except for those @@ -1685,21 +1574,18 @@ png_image_skip_unused_chunks(png_structrp png_ptr) * potential vulnerability to security problems in the unused chunks. * * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored - * too. This allows the simplified API to be compiled without iCCP support, - * however if the support is there the chunk is still checked to detect - * errors (which are unfortunately quite common.) + * too. This allows the simplified API to be compiled without iCCP support. */ { - static PNG_CONST png_byte chunks_to_process[] = { + static const png_byte chunks_to_process[] = { 98, 75, 71, 68, '\0', /* bKGD */ 99, 72, 82, 77, '\0', /* cHRM */ + 99, 73, 67, 80, '\0', /* cICP */ 103, 65, 77, 65, '\0', /* gAMA */ -# ifdef PNG_READ_iCCP_SUPPORTED - 105, 67, 67, 80, '\0', /* iCCP */ -# endif + 109, 68, 67, 86, '\0', /* mDCV */ 115, 66, 73, 84, '\0', /* sBIT */ 115, 82, 71, 66, '\0', /* sRGB */ - }; + }; /* Ignore unknown chunks and all other chunks except for the * IHDR, PLTE, tRNS, IDAT, and IEND chunks. @@ -1728,7 +1614,15 @@ png_image_skip_unused_chunks(png_structrp png_ptr) static void set_file_encoding(png_image_read_control *display) { - png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma; + png_struct *png_ptr = display->image->opaque->png_ptr; + png_fixed_point g = png_resolve_file_gamma(png_ptr); + + /* PNGv3: the result may be 0 however the 'default_gamma' should have been + * set before this is called so zero is an error: + */ + if (g == 0) + png_error(png_ptr, "internal: default gamma not set"); + if (png_gamma_significant(g) != 0) { if (png_gamma_not_sRGB(g) != 0) @@ -1826,10 +1720,10 @@ png_create_colormap_entry(png_image_read_control *display, png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, png_uint_32 alpha, int encoding) { - png_imagep image = display->image; - const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ? + png_image *image = display->image; + int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ? 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); if (ip > 255) @@ -1938,20 +1832,20 @@ png_create_colormap_entry(png_image_read_control *display, /* Store the value. */ { # 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; # else # define afirst 0 # endif # 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 # define bgr 0 # endif if (output_encoding == P_LINEAR) { - png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap); + png_uint_16 *entry = png_voidcast(png_uint_16 *, display->colormap); entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); @@ -1963,7 +1857,7 @@ png_create_colormap_entry(png_image_read_control *display, { case 4: entry[afirst ? 0 : 3] = (png_uint_16)alpha; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 3: if (alpha < 65535) @@ -1985,7 +1879,7 @@ png_create_colormap_entry(png_image_read_control *display, case 2: entry[1 ^ afirst] = (png_uint_16)alpha; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: if (alpha < 65535) @@ -2006,7 +1900,7 @@ png_create_colormap_entry(png_image_read_control *display, else /* output encoding is P_sRGB */ { - png_bytep entry = png_voidcast(png_bytep, display->colormap); + png_byte *entry = png_voidcast(png_byte *, display->colormap); entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); @@ -2014,6 +1908,7 @@ png_create_colormap_entry(png_image_read_control *display, { case 4: entry[afirst ? 0 : 3] = (png_byte)alpha; + /* FALLTHROUGH */ case 3: entry[afirst + (2 ^ bgr)] = (png_byte)blue; entry[afirst + 1] = (png_byte)green; @@ -2022,6 +1917,7 @@ png_create_colormap_entry(png_image_read_control *display, case 2: entry[1 ^ afirst] = (png_byte)alpha; + /* FALLTHROUGH */ case 1: entry[afirst] = (png_byte)green; break; @@ -2148,15 +2044,15 @@ make_rgb_colormap(png_image_read_control *display) ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b))) static int -png_image_read_colormap(png_voidp argument) +png_image_read_colormap(void *argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, argument); - const png_imagep image = display->image; + png_image *image = display->image; - const png_structrp png_ptr = image->opaque->png_ptr; - const png_uint_32 output_format = image->format; - const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ? + png_struct *png_ptr = image->opaque->png_ptr; + png_uint_32 output_format = image->format; + int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ? P_LINEAR : P_sRGB; unsigned int cmap_entries; @@ -2214,24 +2110,18 @@ png_image_read_colormap(png_voidp argument) /* Default the input file gamma if required - this is necessary because * libpng assumes that if no gamma information is present the data is in the * output format, but the simplified API deduces the gamma from the input - * format. + * format. The 'default' gamma value is also set by png_set_alpha_mode, but + * this is happening before any such call, so: + * + * TODO: should be an internal API and all this code should be copied into a + * single common gamma+colorspace file. */ - if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0) - { - /* Do this directly, not using the png_colorspace functions, to ensure - * that it happens even if the colorspace is invalid (though probably if - * it is the setting will be ignored) Note that the same thing can be - * achieved at the application interface with png_set_gAMA. - */ - if (png_ptr->bit_depth == 16 && - (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) - png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR; + if (png_ptr->bit_depth == 16 && + (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) + png_ptr->default_gamma = PNG_GAMMA_LINEAR; - else - png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE; - - png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; - } + else + png_ptr->default_gamma = PNG_GAMMA_sRGB_INVERSE; /* Decide what to do based on the PNG color type of the input data. The * utility function png_create_colormap_entry deals with most aspects of the @@ -2609,6 +2499,8 @@ png_image_read_colormap(png_voidp argument) else { + const png_fixed_point gamma = png_resolve_file_gamma(png_ptr); + /* Either the input or the output has no alpha channel, so there * will be no non-opaque pixels in the color-map; it will just be * grayscale. @@ -2623,10 +2515,13 @@ png_image_read_colormap(png_voidp argument) * this case and doing it in the palette; this will result in * duplicate palette entries, but that's better than the * alternative of double gamma correction. + * + * NOTE: PNGv3: check the resolved result of all the potentially + * different colour space chunks. */ if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || png_ptr->num_trans > 0) && - png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0) + png_gamma_not_sRGB(gamma) != 0) { cmap_entries = (unsigned int)make_gray_file_colormap(display); data_encoding = P_FILE; @@ -2658,8 +2553,8 @@ png_image_read_colormap(png_voidp argument) if (output_encoding == P_sRGB) gray = png_sRGB_table[gray]; /* now P_LINEAR */ - gray = PNG_DIV257(png_gamma_16bit_correct(gray, - png_ptr->colorspace.gamma)); /* now P_FILE */ + gray = PNG_DIV257(png_gamma_16bit_correct(gray, gamma)); + /* now P_FILE */ /* And make sure the corresponding palette entry contains * exactly the required sRGB value. @@ -2786,7 +2681,7 @@ png_image_read_colormap(png_voidp argument) { r = back_r; g = back_g; - b = back_g; + b = back_b; } /* Compare the newly-created color-map entry with the one the @@ -2794,9 +2689,9 @@ png_image_read_colormap(png_voidp argument) * match, add the new one and set this as the background * index. */ - if (memcmp((png_const_bytep)display->colormap + + if (memcmp((const png_byte *)display->colormap + sample_size * cmap_entries, - (png_const_bytep)display->colormap + + (const png_byte *)display->colormap + sample_size * PNG_RGB_INDEX(r,g,b), sample_size) != 0) { @@ -2867,9 +2762,9 @@ png_image_read_colormap(png_voidp argument) */ { unsigned int num_trans = png_ptr->num_trans; - png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; - png_const_colorp colormap = png_ptr->palette; - const int do_background = trans != NULL && + const png_byte *trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; + const png_color *colormap = png_ptr->palette; + int do_background = trans != NULL && (output_format & PNG_FORMAT_FLAG_ALPHA) == 0; unsigned int i; @@ -2941,7 +2836,7 @@ png_image_read_colormap(png_voidp argument) case P_sRGB: /* Change to 8-bit sRGB */ png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); - /* FALL THROUGH */ + /* FALLTHROUGH */ case P_FILE: if (png_ptr->bit_depth > 8) @@ -3002,12 +2897,12 @@ png_image_read_colormap(png_voidp argument) /* The final part of the color-map read called from png_image_finish_read. */ static int -png_image_read_and_map(png_voidp argument) +png_image_read_and_map(void *argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; + png_image *image = display->image; + png_struct *png_ptr = image->opaque->png_ptr; int passes; /* Called when the libpng data must be transformed into the color-mapped @@ -3029,17 +2924,17 @@ png_image_read_and_map(png_voidp argument) } { - png_uint_32 height = image->height; - png_uint_32 width = image->width; - int proc = display->colormap_processing; - png_bytep first_row = png_voidcast(png_bytep, display->first_row); - ptrdiff_t step_row = display->row_bytes; + png_uint_32 height = image->height; + png_uint_32 width = image->width; + int proc = display->colormap_processing; + png_byte *first_row = png_voidcast(png_byte *, display->first_row); + ptrdiff_t row_step = display->row_step; int pass; for (pass = 0; pass < passes; ++pass) { - unsigned int startx, stepx, stepy; - png_uint_32 y; + unsigned int startx, stepx, stepy; + png_uint_32 y; if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) { @@ -3062,11 +2957,11 @@ png_image_read_and_map(png_voidp argument) for (; ylocal_row); - png_bytep outrow = first_row + y * step_row; - png_const_bytep end_row = outrow + width; + png_byte *inrow = png_voidcast(png_byte *, display->local_row); + png_byte *outrow = first_row + y * row_step; + png_byte *row_end = outrow + width; - /* Read read the libpng data into the temporary buffer. */ + /* Read the libpng data into the temporary buffer. */ png_read_row(png_ptr, inrow, NULL); /* Now process the row according to the processing option, note @@ -3077,7 +2972,7 @@ png_image_read_and_map(png_voidp argument) switch (proc) { case PNG_CMAP_GA: - for (; outrow < end_row; outrow += stepx) + for (; outrow < row_end; outrow += stepx) { /* The data is always in the PNG order */ unsigned int gray = *inrow++; @@ -3106,7 +3001,7 @@ png_image_read_and_map(png_voidp argument) break; case PNG_CMAP_TRANS: - for (; outrow < end_row; outrow += stepx) + for (; outrow < row_end; outrow += stepx) { png_byte gray = *inrow++; png_byte alpha = *inrow++; @@ -3123,7 +3018,7 @@ png_image_read_and_map(png_voidp argument) break; case PNG_CMAP_RGB: - for (; outrow < end_row; outrow += stepx) + for (; outrow < row_end; outrow += stepx) { *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]); inrow += 3; @@ -3131,7 +3026,7 @@ png_image_read_and_map(png_voidp argument) break; case PNG_CMAP_RGB_ALPHA: - for (; outrow < end_row; outrow += stepx) + for (; outrow < row_end; outrow += stepx) { unsigned int alpha = inrow[3]; @@ -3168,10 +3063,10 @@ png_image_read_and_map(png_voidp argument) */ if (inrow[0] & 0x80) back_i += 9; /* red */ if (inrow[0] & 0x40) back_i += 9; - if (inrow[0] & 0x80) back_i += 3; /* green */ - if (inrow[0] & 0x40) back_i += 3; - if (inrow[0] & 0x80) back_i += 1; /* blue */ - if (inrow[0] & 0x40) back_i += 1; + if (inrow[1] & 0x80) back_i += 3; /* green */ + if (inrow[1] & 0x40) back_i += 3; + if (inrow[2] & 0x80) back_i += 1; /* blue */ + if (inrow[2] & 0x40) back_i += 1; *outrow = (png_byte)back_i; } @@ -3191,14 +3086,14 @@ png_image_read_and_map(png_voidp argument) } static int -png_image_read_colormapped(png_voidp argument) +png_image_read_colormapped(void *argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, argument); - png_imagep image = display->image; - png_controlp control = image->opaque; - png_structrp png_ptr = control->png_ptr; - png_inforp info_ptr = control->info_ptr; + png_image *image = display->image; + png_control *control = image->opaque; + png_struct *png_ptr = control->png_ptr; + png_info *info_ptr = control->info_ptr; int passes = 0; /* As a flag */ @@ -3259,8 +3154,7 @@ png_image_read_colormapped(png_voidp argument) image->colormap_entries == 244 /* 216 + 1 + 27 */) break; - /* goto bad_output; */ - /* FALL THROUGH */ + goto bad_output; default: bad_output: @@ -3272,27 +3166,27 @@ png_image_read_colormapped(png_voidp argument) * size libpng requires and call the relevant processing routine safely. */ { - png_voidp first_row = display->buffer; - ptrdiff_t row_bytes = display->row_stride; + void *first_row = display->buffer; + ptrdiff_t row_step = display->row_stride; - /* The following expression is designed to work correctly whether it gives - * a signed or an unsigned result. + /* The following adjustment is to ensure that calculations are correct, + * regardless whether row_step is positive or negative. */ - if (row_bytes < 0) + if (row_step < 0) { char *ptr = png_voidcast(char*, first_row); - ptr += (image->height-1) * (-row_bytes); - first_row = png_voidcast(png_voidp, ptr); + ptr += (image->height-1) * (-row_step); + first_row = png_voidcast(void *, ptr); } display->first_row = first_row; - display->row_bytes = row_bytes; + display->row_step = row_step; } if (passes == 0) { int result; - png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + void *row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); display->local_row = row; result = png_safe_execute(image, png_image_read_and_map, display); @@ -3304,17 +3198,17 @@ png_image_read_colormapped(png_voidp argument) else { - png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes; + ptrdiff_t row_step = display->row_step; while (--passes >= 0) { - png_uint_32 y = image->height; - png_bytep row = png_voidcast(png_bytep, display->first_row); + png_uint_32 y = image->height; + png_byte *row = png_voidcast(png_byte *, display->first_row); for (; y > 0; --y) { png_read_row(png_ptr, row, NULL); - row += row_bytes; + row += row_step; } } @@ -3322,14 +3216,69 @@ png_image_read_colormapped(png_voidp argument) } } +/* Row reading for interlaced 16-to-8 bit depth conversion with local buffer. */ +static int +png_image_read_direct_scaled(void *argument) +{ + png_image_read_control *display = png_voidcast(png_image_read_control*, + argument); + png_image *image = display->image; + png_struct *png_ptr = image->opaque->png_ptr; + png_info *info_ptr = image->opaque->info_ptr; + png_byte *local_row = png_voidcast(png_byte *, display->local_row); + png_byte *first_row = png_voidcast(png_byte *, display->first_row); + ptrdiff_t row_step = display->row_step; + size_t row_bytes = png_get_rowbytes(png_ptr, info_ptr); + int passes; + + /* Handle interlacing. */ + switch (png_ptr->interlaced) + { + case PNG_INTERLACE_NONE: + passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + passes = PNG_INTERLACE_ADAM7_PASSES; + break; + + default: + png_error(png_ptr, "unknown interlace type"); + } + + /* Read each pass using local_row as intermediate buffer. */ + while (--passes >= 0) + { + png_uint_32 y = image->height; + png_byte *output_row = first_row; + + for (; y > 0; --y) + { + /* Read into local_row (gets transformed 8-bit data). */ + png_read_row(png_ptr, local_row, NULL); + + /* Copy from local_row to user buffer. + * Use row_bytes (i.e. the actual size in bytes of the row data) for + * copying into output_row. Use row_step for advancing output_row, + * to respect the caller's stride for padding or negative (bottom-up) + * layouts. + */ + memcpy(output_row, local_row, row_bytes); + output_row += row_step; + } + } + + return 1; +} + /* Just the row reading part of png_image_read. */ static int -png_image_read_composite(png_voidp argument) +png_image_read_composite(void *argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; + png_image *image = display->image; + png_struct *png_ptr = image->opaque->png_ptr; int passes; switch (png_ptr->interlaced) @@ -3347,17 +3296,18 @@ png_image_read_composite(png_voidp argument) } { - png_uint_32 height = image->height; - png_uint_32 width = image->width; - ptrdiff_t step_row = display->row_bytes; + png_uint_32 height = image->height; + png_uint_32 width = image->width; + ptrdiff_t row_step = display->row_step; unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; + int optimize_alpha = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; int pass; for (pass = 0; pass < passes; ++pass) { - unsigned int startx, stepx, stepy; - png_uint_32 y; + unsigned int startx, stepx, stepy; + png_uint_32 y; if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) { @@ -3381,20 +3331,20 @@ png_image_read_composite(png_voidp argument) for (; ylocal_row); - png_bytep outrow; - png_const_bytep end_row; + png_byte *inrow = png_voidcast(png_byte *, display->local_row); + png_byte *outrow; + png_byte *row_end; /* Read the row, which is packed: */ png_read_row(png_ptr, inrow, NULL); - outrow = png_voidcast(png_bytep, display->first_row); - outrow += y * step_row; - end_row = outrow + width * channels; + outrow = png_voidcast(png_byte *, display->first_row); + outrow += y * row_step; + row_end = outrow + width * channels; /* Now do the composition on each pixel in this row. */ outrow += startx; - for (; outrow < end_row; outrow += stepx) + for (; outrow < row_end; outrow += stepx) { png_byte alpha = inrow[channels]; @@ -3408,20 +3358,44 @@ png_image_read_composite(png_voidp argument) if (alpha < 255) /* else just use component */ { - /* This is PNG_OPTIMIZED_ALPHA, the component value - * is a linear 8-bit value. Combine this with the - * current outrow[c] value which is sRGB encoded. - * Arithmetic here is 16-bits to preserve the output - * values correctly. - */ - component *= 257*255; /* =65535 */ - component += (255-alpha)*png_sRGB_table[outrow[c]]; + if (optimize_alpha != 0) + { + /* This is PNG_OPTIMIZED_ALPHA, the component value + * is a linear 8-bit value. Combine this with the + * current outrow[c] value which is sRGB encoded. + * Arithmetic here is 16-bits to preserve the output + * values correctly. + */ + component *= 257*255; /* =65535 */ + component += (255-alpha)*png_sRGB_table[outrow[c]]; - /* So 'component' is scaled by 255*65535 and is - * therefore appropriate for the sRGB to linear - * conversion table. - */ - component = PNG_sRGB_FROM_LINEAR(component); + /* Clamp to the valid range to defend against + * unforeseen cases where the data might be sRGB + * instead of linear premultiplied. + * (Belt-and-suspenders for CVE-2025-66293.) + */ + if (component > 255*65535) + component = 255*65535; + + /* So 'component' is scaled by 255*65535 and is + * therefore appropriate for the sRGB-to-linear + * conversion table. + */ + component = PNG_sRGB_FROM_LINEAR(component); + } + else + { + /* Compositing was already done on the palette + * entries. The data is sRGB premultiplied on black. + * Composite with the background in sRGB space. + * This is not gamma-correct, but matches what was + * done to the palette. + */ + png_uint_32 background = outrow[c]; + component += ((255-alpha) * background + 127) / 255; + if (component > 255) + component = 255; + } } outrow[c] = (png_byte)component; @@ -3451,13 +3425,13 @@ png_image_read_composite(png_voidp argument) * row and handles the removal or pre-multiplication of the alpha channel. */ static int -png_image_read_background(png_voidp argument) +png_image_read_background(void *argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; - png_inforp info_ptr = image->opaque->info_ptr; + png_image *image = display->image; + png_struct *png_ptr = image->opaque->png_ptr; + png_info *info_ptr = image->opaque->info_ptr; png_uint_32 height = image->height; png_uint_32 width = image->width; int pass, passes; @@ -3509,14 +3483,13 @@ png_image_read_background(png_voidp argument) * Unlike the code above ALPHA_OPTIMIZED has *not* been done. */ { - png_bytep first_row = png_voidcast(png_bytep, display->first_row); - ptrdiff_t step_row = display->row_bytes; + png_byte *first_row = png_voidcast(png_byte *, display->first_row); + ptrdiff_t row_step = display->row_step; for (pass = 0; pass < passes; ++pass) { - png_bytep row = png_voidcast(png_bytep, display->first_row); - unsigned int startx, stepx, stepy; - png_uint_32 y; + unsigned int startx, stepx, stepy; + png_uint_32 y; if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) { @@ -3541,17 +3514,17 @@ png_image_read_background(png_voidp argument) { for (; ylocal_row); - png_bytep outrow = first_row + y * step_row; - png_const_bytep end_row = outrow + width; + png_byte *outrow = first_row + y * row_step; + png_byte *row_end = outrow + width; /* Read the row, which is packed: */ png_read_row(png_ptr, inrow, NULL); /* Now do the composition on each pixel in this row. */ outrow += startx; - for (; outrow < end_row; outrow += stepx) + for (; outrow < row_end; outrow += stepx) { png_byte alpha = inrow[1]; @@ -3586,17 +3559,17 @@ png_image_read_background(png_voidp argument) for (; ylocal_row); - png_bytep outrow = first_row + y * step_row; - png_const_bytep end_row = outrow + width; + png_byte *outrow = first_row + y * row_step; + png_byte *row_end = outrow + width; /* Read the row, which is packed: */ png_read_row(png_ptr, inrow, NULL); /* Now do the composition on each pixel in this row. */ outrow += startx; - for (; outrow < end_row; outrow += stepx) + for (; outrow < row_end; outrow += stepx) { png_byte alpha = inrow[1]; @@ -3619,8 +3592,6 @@ png_image_read_background(png_voidp argument) inrow += 2; /* gray and alpha channel */ } - - row += display->row_bytes; } } } @@ -3633,12 +3604,12 @@ png_image_read_background(png_voidp argument) * handles the alpha-first option. */ { - png_uint_16p first_row = png_voidcast(png_uint_16p, + png_uint_16 *first_row = png_voidcast(png_uint_16 *, display->first_row); /* The division by two is safe because the caller passed in a - * stride which was multiplied by 2 (below) to get row_bytes. + * stride which was multiplied by 2 (below) to get row_step. */ - ptrdiff_t step_row = display->row_bytes / 2; + ptrdiff_t row_step = display->row_step / 2; unsigned int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; unsigned int outchannels = 1U+preserve_alpha; @@ -3652,8 +3623,8 @@ png_image_read_background(png_voidp argument) for (pass = 0; pass < passes; ++pass) { - unsigned int startx, stepx, stepy; - png_uint_32 y; + unsigned int startx, stepx, stepy; + png_uint_32 y; /* The 'x' start and step are adjusted to output components here. */ @@ -3679,19 +3650,19 @@ png_image_read_background(png_voidp argument) for (; ylocal_row), NULL); - inrow = png_voidcast(png_const_uint_16p, display->local_row); + inrow = png_voidcast(const png_uint_16 *, display->local_row); /* Now do the pre-multiplication on each pixel in this row. */ outrow += startx; - for (; outrow < end_row; outrow += stepx) + for (; outrow < row_end; outrow += stepx) { png_uint_32 component = inrow[0]; png_uint_16 alpha = inrow[1]; @@ -3731,18 +3702,19 @@ png_image_read_background(png_voidp argument) /* The guts of png_image_finish_read as a png_safe_execute callback. */ static int -png_image_read_direct(png_voidp argument) +png_image_read_direct(void *argument) { png_image_read_control *display = png_voidcast(png_image_read_control*, argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; - png_inforp info_ptr = image->opaque->info_ptr; + png_image *image = display->image; + png_struct *png_ptr = image->opaque->png_ptr; + png_info *info_ptr = image->opaque->info_ptr; png_uint_32 format = image->format; int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; int do_local_compose = 0; int do_local_background = 0; /* to avoid double gamma correction bug */ + int do_local_scale = 0; /* for interlaced 16-to-8 bit conversion */ int passes = 0; /* Add transforms to ensure the correct output format is produced then check @@ -3794,6 +3766,12 @@ png_image_read_direct(png_voidp argument) /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise. */ { + /* This is safe but should no longer be necessary as + * png_ptr->default_gamma should have been set after the + * info-before-IDAT was read in png_image_read_header. + * + * TODO: 1.8: remove this and see what happens. + */ png_fixed_point input_gamma_default; if ((base_format & PNG_FORMAT_FLAG_LINEAR) != 0 && @@ -3828,6 +3806,12 @@ png_image_read_direct(png_voidp argument) 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 * correction; this is part of the work-round for the libpng bug * described above. @@ -3843,8 +3827,9 @@ png_image_read_direct(png_voidp argument) * yet; it's set below. png_struct::gamma, however, is set to the * final value. */ - if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma, - PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0) + if (png_muldiv(>est, output_gamma, + png_resolve_file_gamma(png_ptr), PNG_FP_1) != 0 && + png_gamma_significant(gtest) == 0) do_local_background = 0; else if (mode == PNG_ALPHA_STANDARD) @@ -3863,8 +3848,16 @@ png_image_read_direct(png_voidp argument) png_set_expand_16(png_ptr); else /* 8-bit output */ + { png_set_scale_16(png_ptr); + /* For interlaced images, use local_row buffer to avoid overflow + * in png_combine_row() which writes using IHDR bit-depth. + */ + if (png_ptr->interlaced != 0) + do_local_scale = 1; + } + change &= ~PNG_FORMAT_FLAG_LINEAR; } @@ -4008,9 +4001,9 @@ png_image_read_direct(png_voidp argument) */ if (linear != 0) { - PNG_CONST png_uint_16 le = 0x0001; + png_uint_16 le = 0x0001; - if ((*(png_const_bytep) & le) != 0) + if ((*(const png_byte *) & le) != 0) png_set_swap(png_ptr); } @@ -4053,6 +4046,10 @@ png_image_read_direct(png_voidp argument) else if (do_local_compose != 0) /* internal error */ 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) info_format |= PNG_FORMAT_FLAG_LINEAR; @@ -4090,30 +4087,30 @@ png_image_read_direct(png_voidp argument) * display acts as a flag. */ { - png_voidp first_row = display->buffer; - ptrdiff_t row_bytes = display->row_stride; + void *first_row = display->buffer; + ptrdiff_t row_step = display->row_stride; if (linear != 0) - row_bytes *= 2; + row_step *= 2; - /* The following expression is designed to work correctly whether it gives - * a signed or an unsigned result. + /* The following adjustment is to ensure that calculations are correct, + * regardless whether row_step is positive or negative. */ - if (row_bytes < 0) + if (row_step < 0) { char *ptr = png_voidcast(char*, first_row); - ptr += (image->height-1) * (-row_bytes); - first_row = png_voidcast(png_voidp, ptr); + ptr += (image->height - 1) * (-row_step); + first_row = png_voidcast(void *, ptr); } display->first_row = first_row; - display->row_bytes = row_bytes; + display->row_step = row_step; } if (do_local_compose != 0) { int result; - png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + void *row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); display->local_row = row; result = png_safe_execute(image, png_image_read_composite, display); @@ -4126,7 +4123,7 @@ png_image_read_direct(png_voidp argument) else if (do_local_background == 2) { int result; - png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + void *row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); display->local_row = row; result = png_safe_execute(image, png_image_read_background, display); @@ -4136,19 +4133,37 @@ png_image_read_direct(png_voidp argument) return result; } + else if (do_local_scale != 0) + { + /* For interlaced 16-to-8 conversion, use an intermediate row buffer + * to avoid buffer overflows in png_combine_row. The local_row is sized + * for the transformed (8-bit) output, preventing the overflow that would + * occur if png_combine_row wrote 16-bit data directly to the user buffer. + */ + int result; + void *row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); + + display->local_row = row; + result = png_safe_execute(image, png_image_read_direct_scaled, display); + display->local_row = NULL; + png_free(png_ptr, row); + + return result; + } + else { - png_alloc_size_t row_bytes = (png_alloc_size_t)display->row_bytes; + ptrdiff_t row_step = display->row_step; while (--passes >= 0) { - png_uint_32 y = image->height; - png_bytep row = png_voidcast(png_bytep, display->first_row); + png_uint_32 y = image->height; + png_byte *row = png_voidcast(png_byte *, display->first_row); for (; y > 0; --y) { png_read_row(png_ptr, row, NULL); - row += row_bytes; + row += row_step; } } @@ -4156,8 +4171,8 @@ png_image_read_direct(png_voidp argument) } } -int PNGAPI -png_image_finish_read(png_imagep image, png_const_colorp background, +int +png_image_finish_read(png_image *image, const png_color *background, void *buffer, png_int_32 row_stride, void *colormap) { if (image != NULL && image->version == PNG_IMAGE_VERSION) @@ -4166,7 +4181,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background, * original PNG format because it may not occur in the output PNG format * and libpng deals with the issues of reading the original. */ - const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); + 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 @@ -4177,13 +4192,13 @@ png_image_finish_read(png_imagep image, png_const_colorp background, if (image->width <= 0x7fffffffU/channels) /* no overflow */ { png_uint_32 check; - const png_uint_32 png_row_stride = image->width * channels; + png_uint_32 png_row_stride = image->width * channels; if (row_stride == 0) row_stride = (png_int_32)/*SAFE*/png_row_stride; if (row_stride < 0) - check = (png_uint_32)(-row_stride); + check = -(png_uint_32)row_stride; else check = (png_uint_32)row_stride; @@ -4208,7 +4223,7 @@ png_image_finish_read(png_imagep image, png_const_colorp background, * * 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 - * accomodated on 64-bit systems. + * accommodated on 64-bit systems. */ if (image->height <= 0xffffffffU/PNG_IMAGE_PIXEL_COMPONENT_SIZE(image->format)/check) diff --git a/media/libpng/pngrio.c b/media/libpng/pngrio.c index 7e26e855ca..05ed9be3c6 100644 --- a/media/libpng/pngrio.c +++ b/media/libpng/pngrio.c @@ -1,10 +1,9 @@ - /* pngrio.c - functions for data input * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2025 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -29,7 +28,7 @@ * to read more than 64K on a 16-bit machine. */ void /* PRIVATE */ -png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) +png_read_data(png_struct *png_ptr, png_byte *data, size_t length) { png_debug1(4, "reading %d bytes", (int)length); @@ -46,18 +45,18 @@ png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) * read_data function and use it at run time with png_set_read_fn(), rather * than changing the library. */ -void PNGCBAPI -png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) +void +png_default_read_data(png_struct *png_ptr, png_byte *data, size_t length) { - png_size_t check; + size_t check; if (png_ptr == NULL) 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. */ - check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr)); + check = fread(data, 1, length, png_voidcast(FILE *, png_ptr->io_ptr)); if (check != length) png_error(png_ptr, "Read Error"); @@ -83,8 +82,8 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length) * May be NULL, in which case libpng's default function will * be used. */ -void PNGAPI -png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr, +void +png_set_read_fn(png_struct *png_ptr, void *io_ptr, png_rw_ptr read_data_fn) { if (png_ptr == NULL) diff --git a/media/libpng/pngrtran.c b/media/libpng/pngrtran.c index 0b4f4f9068..25a333fe8a 100644 --- a/media/libpng/pngrtran.c +++ b/media/libpng/pngrtran.c @@ -1,10 +1,9 @@ - /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -21,8 +20,8 @@ #ifdef PNG_READ_SUPPORTED /* Set the action on getting a CRC error for an ancillary or critical chunk. */ -void PNGAPI -png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action) +void +png_set_crc_action(png_struct *png_ptr, int crit_action, int ancil_action) { png_debug(1, "in png_set_crc_action"); @@ -49,6 +48,7 @@ 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 */ png_warning(png_ptr, "Can't discard critical data on CRC error"); + /* FALLTHROUGH */ case PNG_CRC_ERROR_QUIT: /* Error/quit */ case PNG_CRC_DEFAULT: @@ -95,7 +95,7 @@ png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action) * check too. */ static int -png_rtran_ok(png_structrp png_ptr, int need_IHDR) +png_rtran_ok(png_struct *png_ptr, int need_IHDR) { if (png_ptr != NULL) { @@ -121,9 +121,9 @@ png_rtran_ok(png_structrp png_ptr, int need_IHDR) #ifdef PNG_READ_BACKGROUND_SUPPORTED /* Handle alpha and tRNS via a background color */ -void PNGFAPI -png_set_background_fixed(png_structrp png_ptr, - png_const_color_16p background_color, int background_gamma_code, +void +png_set_background_fixed(png_struct *png_ptr, + const png_color_16 *background_color, int background_gamma_code, int need_expand, png_fixed_point background_gamma) { png_debug(1, "in png_set_background_fixed"); @@ -151,9 +151,9 @@ png_set_background_fixed(png_structrp png_ptr, } # ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_background(png_structrp png_ptr, - png_const_color_16p background_color, int background_gamma_code, +void +png_set_background(png_struct *png_ptr, + const png_color_16 *background_color, int background_gamma_code, int need_expand, double background_gamma) { png_set_background_fixed(png_ptr, background_color, background_gamma_code, @@ -167,8 +167,8 @@ png_set_background(png_structrp png_ptr, * TRANSFORM and API behavior to be somewhat consistent, and it's simpler. */ #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED -void PNGAPI -png_set_scale_16(png_structrp png_ptr) +void +png_set_scale_16(png_struct *png_ptr) { png_debug(1, "in png_set_scale_16"); @@ -181,8 +181,8 @@ png_set_scale_16(png_structrp png_ptr) #ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED /* Chop 16-bit depth files to 8-bit depth */ -void PNGAPI -png_set_strip_16(png_structrp png_ptr) +void +png_set_strip_16(png_struct *png_ptr) { png_debug(1, "in png_set_strip_16"); @@ -194,8 +194,8 @@ png_set_strip_16(png_structrp png_ptr) #endif #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED -void PNGAPI -png_set_strip_alpha(png_structrp png_ptr) +void +png_set_strip_alpha(png_struct *png_ptr) { png_debug(1, "in png_set_strip_alpha"); @@ -207,9 +207,59 @@ png_set_strip_alpha(png_structrp png_ptr) #endif #if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED) +/* PNGv3 conformance: this private API exists to resolve the now mandatory error + * resolution when multiple conflicting sources of gamma or colour space + * information are available. + * + * Terminology (assuming power law, "gamma", encodings): + * "screen" gamma: a power law imposed by the output device when digital + * samples are converted to visible light output. The EOTF - voltage to + * luminance on output. + * + * "file" gamma: a power law used to encode luminance levels from the input + * data (the scene or the mastering display system) into digital voltages. + * The OETF - luminance to voltage on input. + * + * gamma "correction": a power law matching the **inverse** of the overall + * transfer function from input luminance levels to output levels. The + * **inverse** of the OOTF; the correction "corrects" for the OOTF by aiming + * to make the overall OOTF (including the correction) linear. + * + * It is important to understand this terminology because the defined terms are + * scattered throughout the libpng code and it is very easy to end up with the + * inverse of the power law required. + * + * Variable and struct::member names: + * file_gamma OETF how the PNG data was encoded + * + * screen_gamma EOTF how the screen will decode digital levels + * + * -- not used -- OOTF the net effect OETF x EOTF + * gamma_correction the inverse of OOTF to make the result linear + * + * All versions of libpng require a call to "png_set_gamma" to establish the + * "screen" gamma, the power law representing the EOTF. png_set_gamma may also + * set or default the "file" gamma; the OETF. gamma_correction is calculated + * internally. + * + * The earliest libpng versions required file_gamma to be supplied to set_gamma. + * Later versions started allowing png_set_gamma and, later, png_set_alpha_mode, + * to cause defaulting from the file data. + * + * PNGv3 mandated a particular form for this defaulting, one that is compatible + * with what libpng did except that if libpng detected inconsistencies it marked + * all the chunks as "invalid". PNGv3 effectively invalidates this prior code. + * + * Behaviour implemented below: + * translate_gamma_flags(gamma, is_screen) + * The libpng-1.6 API for the gamma parameters to libpng APIs + * (png_set_gamma and png_set_alpha_mode at present). This allows the + * 'gamma' value to be passed as a png_fixed_point number or as one of a + * set of integral values for specific "well known" examples of transfer + * functions. This is compatible with PNGv3. + */ static png_fixed_point -translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma, - int is_screen) +translate_gamma_flags(png_fixed_point output_gamma, int is_screen) { /* Check for flag values. The main reason for having the old Mac value as a * flag is that it is pretty near impossible to work out what the correct @@ -219,14 +269,6 @@ translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma, if (output_gamma == PNG_DEFAULT_sRGB || output_gamma == PNG_FP_1 / PNG_DEFAULT_sRGB) { - /* If there is no sRGB support this just sets the gamma to the standard - * sRGB value. (This is a side effect of using this function!) - */ -# ifdef PNG_READ_sRGB_SUPPORTED - png_ptr->flags |= PNG_FLAG_ASSUME_sRGB; -# else - PNG_UNUSED(png_ptr) -# endif if (is_screen != 0) output_gamma = PNG_GAMMA_sRGB; else @@ -247,7 +289,7 @@ translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma, # ifdef PNG_FLOATING_POINT_SUPPORTED static png_fixed_point -convert_gamma_value(png_structrp png_ptr, double output_gamma) +convert_gamma_value(png_struct *png_ptr, double output_gamma) { /* The following silently ignores cases where fixed point (times 100,000) * gamma values are passed to the floating point API. This is safe and it @@ -268,39 +310,63 @@ convert_gamma_value(png_structrp png_ptr, double output_gamma) return (png_fixed_point)output_gamma; } # endif + +static int +unsupported_gamma(png_struct *png_ptr, png_fixed_point gamma, int warn) +{ + /* Validate a gamma value to ensure it is in a reasonable range. The value + * is expected to be 1 or greater, but this range test allows for some + * viewing correction values. The intent is to weed out the API users + * who might use the inverse of the gamma value accidentally! + * + * 1.6.47: apply the test in png_set_gamma as well but only warn and return + * false if it fires. + * + * TODO: 1.8: make this an app_error in png_set_gamma as well. + */ + if (gamma < PNG_LIB_GAMMA_MIN || gamma > PNG_LIB_GAMMA_MAX) + { +# define msg "gamma out of supported range" + if (warn) + png_app_warning(png_ptr, msg); + else + png_app_error(png_ptr, msg); + return 1; +# undef msg + } + + return 0; +} #endif /* READ_ALPHA_MODE || READ_GAMMA */ #ifdef PNG_READ_ALPHA_MODE_SUPPORTED -void PNGFAPI -png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, +void +png_set_alpha_mode_fixed(png_struct *png_ptr, int mode, png_fixed_point output_gamma) { - int compose = 0; png_fixed_point file_gamma; + int compose = 0; - png_debug(1, "in png_set_alpha_mode"); + png_debug(1, "in png_set_alpha_mode_fixed"); if (png_rtran_ok(png_ptr, 0) == 0) return; - output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/); - - /* Validate the value to ensure it is in a reasonable range. The value - * is expected to be 1 or greater, but this range test allows for some - * viewing correction values. The intent is to weed out users of this API - * who use the inverse of the gamma value accidentally! Since some of these - * values are reasonable this may have to be changed: - * - * 1.6.x: changed from 0.07..3 to 0.01..100 (to accomodate the optimal 16-bit - * gamma of 36, and its reciprocal.) - */ - if (output_gamma < 1000 || output_gamma > 10000000) - png_error(png_ptr, "output gamma out of expected range"); + output_gamma = translate_gamma_flags(output_gamma, 1/*screen*/); + if (unsupported_gamma(png_ptr, output_gamma, 0/*error*/)) + return; /* The default file gamma is the inverse of the output gamma; the output - * gamma may be changed below so get the file value first: + * gamma may be changed below so get the file value first. The default_gamma + * is set here and from the simplified API (which uses a different algorithm) + * so don't overwrite a set value: */ - file_gamma = png_reciprocal(output_gamma); + file_gamma = png_ptr->default_gamma; + if (file_gamma == 0) + { + file_gamma = png_reciprocal(output_gamma); + png_ptr->default_gamma = file_gamma; + } /* There are really 8 possibilities here, composed of any combination * of: @@ -351,17 +417,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, png_error(png_ptr, "invalid alpha mode"); } - /* Only set the default gamma if the file gamma has not been set (this has - * the side effect that the gamma in a second call to png_set_alpha_mode will - * be ignored.) - */ - if (png_ptr->colorspace.gamma == 0) - { - png_ptr->colorspace.gamma = file_gamma; - png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; - } - - /* But always set the output gamma: */ + /* Set the screen gamma values: */ png_ptr->screen_gamma = output_gamma; /* Finally, if pre-multiplying, set the background fields to achieve the @@ -371,7 +427,7 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, { /* And obtain alpha pre-multiplication by composing on black: */ memset(&png_ptr->background, 0, (sizeof png_ptr->background)); - png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */ + png_ptr->background_gamma = file_gamma; /* just in case */ png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE; png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND; @@ -384,8 +440,8 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode, } # ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma) +void +png_set_alpha_mode(png_struct *png_ptr, int mode, double output_gamma) { png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr, output_gamma)); @@ -409,12 +465,10 @@ typedef struct png_dsort_struct png_byte left; png_byte right; } png_dsort; -typedef png_dsort * png_dsortp; -typedef png_dsort * * png_dsortpp; -void PNGAPI -png_set_quantize(png_structrp png_ptr, png_colorp palette, - int num_palette, int maximum_colors, png_const_uint_16p histogram, +void +png_set_quantize(png_struct *png_ptr, png_color *palette, + int num_palette, int maximum_colors, const png_uint_16 *histogram, int full_quantize) { png_debug(1, "in png_set_quantize"); @@ -422,15 +476,28 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, if (png_rtran_ok(png_ptr, 0) == 0) return; + if (palette == NULL) + return; + png_ptr->transformations |= PNG_QUANTIZE; if (full_quantize == 0) { int i; - png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); - for (i = 0; i < num_palette; i++) + /* Initialize the array to index colors. + * + * Ensure quantize_index can fit 256 elements (PNG_MAX_PALETTE_LENGTH) + * rather than num_palette elements. This is to prevent buffer overflows + * caused by malformed PNG files with out-of-range palette indices. + * + * Be careful to avoid leaking memory. Applications are allowed to call + * this function more than once per png_struct. + */ + png_free(png_ptr, png_ptr->quantize_index); + png_ptr->quantize_index = (png_byte *)png_malloc(png_ptr, + PNG_MAX_PALETTE_LENGTH); + for (i = 0; i < PNG_MAX_PALETTE_LENGTH; i++) png_ptr->quantize_index[i] = (png_byte)i; } @@ -442,15 +509,14 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, * Perhaps not the best solution, but good enough. */ - int i; - - /* Initialize an array to sort colors */ - png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); + png_byte *quantize_sort; + int i, j; - /* Initialize the quantize_sort array */ + /* Initialize the local array to sort colors. */ + quantize_sort = (png_byte *)png_malloc(png_ptr, + (png_alloc_size_t)num_palette); for (i = 0; i < num_palette; i++) - png_ptr->quantize_sort[i] = (png_byte)i; + quantize_sort[i] = (png_byte)i; /* Find the least used palette entries by starting a * bubble sort, and running it until we have sorted @@ -462,19 +528,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, for (i = num_palette - 1; i >= maximum_colors; i--) { int done; /* To stop early if the list is pre-sorted */ - int j; done = 1; for (j = 0; j < i; j++) { - if (histogram[png_ptr->quantize_sort[j]] - < histogram[png_ptr->quantize_sort[j + 1]]) + if (histogram[quantize_sort[j]] + < histogram[quantize_sort[j + 1]]) { png_byte t; - t = png_ptr->quantize_sort[j]; - png_ptr->quantize_sort[j] = png_ptr->quantize_sort[j + 1]; - png_ptr->quantize_sort[j + 1] = t; + t = quantize_sort[j]; + quantize_sort[j] = quantize_sort[j + 1]; + quantize_sort[j + 1] = t; done = 0; } } @@ -486,18 +551,18 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, /* Swap the palette around, and set up a table, if necessary */ if (full_quantize != 0) { - int j = num_palette; + j = num_palette; /* Put all the useful colors within the max, but don't * move the others. */ for (i = 0; i < maximum_colors; i++) { - if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + if ((int)quantize_sort[i] >= maximum_colors) { do j--; - while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + while ((int)quantize_sort[j] >= maximum_colors); palette[i] = palette[j]; } @@ -505,7 +570,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, } else { - int j = num_palette; + j = num_palette; /* Move all the used colors inside the max limit, and * develop a translation table. @@ -513,13 +578,13 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, for (i = 0; i < maximum_colors; i++) { /* Only move the colors we need to */ - if ((int)png_ptr->quantize_sort[i] >= maximum_colors) + if ((int)quantize_sort[i] >= maximum_colors) { png_color tmp_color; do j--; - while ((int)png_ptr->quantize_sort[j] >= maximum_colors); + while ((int)quantize_sort[j] >= maximum_colors); tmp_color = palette[j]; palette[j] = palette[i]; @@ -557,8 +622,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, } } } - png_free(png_ptr, png_ptr->quantize_sort); - png_ptr->quantize_sort = NULL; + png_free(png_ptr, quantize_sort); } else { @@ -573,16 +637,16 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, int i; int max_d; int num_new_palette; - png_dsortp t; - png_dsortpp hash; + png_dsort *t; + png_dsort **hash; t = NULL; /* Initialize palette index arrays */ - png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); - png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((png_uint_32)num_palette * (sizeof (png_byte)))); + png_ptr->index_to_palette = (png_byte *)png_malloc(png_ptr, + (png_alloc_size_t)num_palette); + png_ptr->palette_to_index = (png_byte *)png_malloc(png_ptr, + (png_alloc_size_t)num_palette); /* Initialize the sort array */ for (i = 0; i < num_palette; i++) @@ -591,8 +655,8 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, png_ptr->palette_to_index[i] = (png_byte)i; } - hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 * - (sizeof (png_dsortp)))); + hash = (png_dsort **)png_calloc(png_ptr, (png_alloc_size_t)(769 * + (sizeof (png_dsort *)))); num_new_palette = num_palette; @@ -621,15 +685,15 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, if (d <= max_d) { - t = (png_dsortp)png_malloc_warn(png_ptr, - (png_uint_32)(sizeof (png_dsort))); + t = (png_dsort *)png_malloc_warn(png_ptr, + (png_alloc_size_t)(sizeof (png_dsort))); if (t == NULL) break; t->next = hash[d]; - t->left = (png_byte)i; - t->right = (png_byte)j; + t->left = png_ptr->palette_to_index[i]; + t->right = png_ptr->palette_to_index[j]; hash[d] = t; } } @@ -642,7 +706,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, { if (hash[i] != NULL) { - png_dsortp p; + png_dsort *p; for (p = hash[i]; p; p = p->next) { @@ -709,7 +773,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, { if (hash[i] != NULL) { - png_dsortp p = hash[i]; + png_dsort *p = hash[i]; while (p) { t = p->next; @@ -731,28 +795,33 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, } if (png_ptr->palette == NULL) { - png_ptr->palette = palette; + /* Allocate an owned copy rather than aliasing the caller's pointer, + * so that png_read_destroy can free png_ptr->palette unconditionally. + */ + png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); + memcpy(png_ptr->palette, palette, (unsigned int)num_palette * + (sizeof (png_color))); } png_ptr->num_palette = (png_uint_16)num_palette; if (full_quantize != 0) { int i; - png_bytep distance; + png_byte *distance; int total_bits = PNG_QUANTIZE_RED_BITS + PNG_QUANTIZE_GREEN_BITS + PNG_QUANTIZE_BLUE_BITS; int num_red = (1 << PNG_QUANTIZE_RED_BITS); int num_green = (1 << PNG_QUANTIZE_GREEN_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_uint_32)(num_entries * (sizeof (png_byte)))); + png_ptr->palette_lookup = (png_byte *)png_calloc(png_ptr, + (png_alloc_size_t)(num_entries)); - distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries * - (sizeof (png_byte)))); + distance = (png_byte *)png_malloc(png_ptr, (png_alloc_size_t)num_entries); - memset(distance, 0xff, num_entries * (sizeof (png_byte))); + memset(distance, 0xff, num_entries); for (i = 0; i < num_palette; i++) { @@ -800,8 +869,8 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette, #endif /* READ_QUANTIZE */ #ifdef PNG_READ_GAMMA_SUPPORTED -void PNGFAPI -png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma, +void +png_set_gamma_fixed(png_struct *png_ptr, png_fixed_point scrn_gamma, png_fixed_point file_gamma) { png_debug(1, "in png_set_gamma_fixed"); @@ -810,8 +879,8 @@ png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma, return; /* New in libpng-1.5.4 - reserve particular negative values as flags. */ - scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/); - file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/); + scrn_gamma = translate_gamma_flags(scrn_gamma, 1/*screen*/); + file_gamma = translate_gamma_flags(file_gamma, 0/*file*/); /* Checking the gamma values for being >0 was added in 1.5.4 along with the * premultiplied alpha support; this actually hides an undocumented feature @@ -825,23 +894,25 @@ png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma, * libpng-1.6.0. */ if (file_gamma <= 0) - png_error(png_ptr, "invalid file gamma in png_set_gamma"); - + png_app_error(png_ptr, "invalid file gamma in png_set_gamma"); if (scrn_gamma <= 0) - png_error(png_ptr, "invalid screen gamma in png_set_gamma"); + png_app_error(png_ptr, "invalid screen gamma in png_set_gamma"); + + if (unsupported_gamma(png_ptr, file_gamma, 1/*warn*/) || + unsupported_gamma(png_ptr, scrn_gamma, 1/*warn*/)) + return; - /* Set the gamma values unconditionally - this overrides the value in the PNG - * file if a gAMA chunk was present. png_set_alpha_mode provides a - * different, easier, way to default the file gamma. + /* 1.6.47: png_struct::file_gamma and png_struct::screen_gamma are now only + * written by this API. This removes dependencies on the order of API calls + * and allows the complex gamma checks to be delayed until needed. */ - png_ptr->colorspace.gamma = file_gamma; - png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; + png_ptr->file_gamma = file_gamma; png_ptr->screen_gamma = scrn_gamma; } # ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma) +void +png_set_gamma(png_struct *png_ptr, double scrn_gamma, double file_gamma) { png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma), convert_gamma_value(png_ptr, file_gamma)); @@ -854,8 +925,8 @@ png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma) * less than 8-bit depth to 8-bit depth, and expand tRNS chunks * to alpha channels. */ -void PNGAPI -png_set_expand(png_structrp png_ptr) +void +png_set_expand(png_struct *png_ptr) { png_debug(1, "in png_set_expand"); @@ -884,8 +955,8 @@ png_set_expand(png_structrp png_ptr) */ /* Expand paletted images to RGB. */ -void PNGAPI -png_set_palette_to_rgb(png_structrp png_ptr) +void +png_set_palette_to_rgb(png_struct *png_ptr) { png_debug(1, "in png_set_palette_to_rgb"); @@ -896,8 +967,8 @@ png_set_palette_to_rgb(png_structrp png_ptr) } /* Expand grayscale images of less than 8-bit depth to 8 bits. */ -void PNGAPI -png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr) +void +png_set_expand_gray_1_2_4_to_8(png_struct *png_ptr) { png_debug(1, "in png_set_expand_gray_1_2_4_to_8"); @@ -908,8 +979,8 @@ png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr) } /* Expand tRNS chunks to alpha channels. */ -void PNGAPI -png_set_tRNS_to_alpha(png_structrp png_ptr) +void +png_set_tRNS_to_alpha(png_struct *png_ptr) { png_debug(1, "in png_set_tRNS_to_alpha"); @@ -924,8 +995,8 @@ png_set_tRNS_to_alpha(png_structrp png_ptr) /* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise * it may not work correctly.) */ -void PNGAPI -png_set_expand_16(png_structrp png_ptr) +void +png_set_expand_16(png_struct *png_ptr) { png_debug(1, "in png_set_expand_16"); @@ -937,8 +1008,8 @@ png_set_expand_16(png_structrp png_ptr) #endif #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED -void PNGAPI -png_set_gray_to_rgb(png_structrp png_ptr) +void +png_set_gray_to_rgb(png_struct *png_ptr) { png_debug(1, "in png_set_gray_to_rgb"); @@ -952,11 +1023,11 @@ png_set_gray_to_rgb(png_structrp png_ptr) #endif #ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED -void PNGFAPI -png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, +void +png_set_rgb_to_gray_fixed(png_struct *png_ptr, int error_action, png_fixed_point red, png_fixed_point green) { - png_debug(1, "in png_set_rgb_to_gray"); + png_debug(1, "in png_set_rgb_to_gray_fixed"); /* Need the IHDR here because of the check on color_type below. */ /* TODO: fix this */ @@ -1013,26 +1084,9 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, png_ptr->rgb_to_gray_coefficients_set = 1; } - else - { - if (red >= 0 && green >= 0) - png_app_warning(png_ptr, - "ignoring out of range rgb_to_gray coefficients"); - - /* Use the defaults, from the cHRM chunk if set, else the historical - * values which are close to the sRGB/HDTV/ITU-Rec 709 values. See - * png_do_rgb_to_gray for more discussion of the values. In this case - * the coefficients are not marked as 'set' and are not overwritten if - * something has already provided a default. - */ - if (png_ptr->rgb_to_gray_red_coeff == 0 && - png_ptr->rgb_to_gray_green_coeff == 0) - { - png_ptr->rgb_to_gray_red_coeff = 6968; - png_ptr->rgb_to_gray_green_coeff = 23434; - /* png_ptr->rgb_to_gray_blue_coeff = 2366; */ - } - } + else if (red >= 0 && green >= 0) + png_app_warning(png_ptr, + "ignoring out of range rgb_to_gray coefficients"); } } @@ -1041,8 +1095,8 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, * for example, to convert a 24 bpp RGB image into an 8 bpp grayscale image. */ -void PNGAPI -png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red, +void +png_set_rgb_to_gray(png_struct *png_ptr, int error_action, double red, double green) { png_set_rgb_to_gray_fixed(png_ptr, error_action, @@ -1055,9 +1109,9 @@ png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red, #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) -void PNGAPI -png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr - read_user_transform_fn) +void +png_set_read_user_transform_fn(png_struct *png_ptr, + png_user_transform_ptr read_user_transform_fn) { png_debug(1, "in png_set_read_user_transform_fn"); @@ -1100,7 +1154,7 @@ png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma) * extracted from 'png_init_read_transformations'. */ static void /* PRIVATE */ -png_init_palette_transformations(png_structrp png_ptr) +png_init_palette_transformations(png_struct *png_ptr) { /* Called to handle the (input) palette case. In png_do_read_transformations * the first step is to expand the palette if requested, so this code must @@ -1168,20 +1222,20 @@ png_init_palette_transformations(png_structrp png_ptr) png_ptr->palette[png_ptr->background.index].blue; #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED - if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0) - { - if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0) - { - /* Invert the alpha channel (in tRNS) unless the pixels are - * going to be expanded, in which case leave it for later - */ - int i, istop = png_ptr->num_trans; - - for (i=0; itrans_alpha[i] = (png_byte)(255 - - png_ptr->trans_alpha[i]); - } - } + if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0) + { + if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0) + { + /* Invert the alpha channel (in tRNS) unless the pixels are + * going to be expanded, in which case leave it for later + */ + int i, istop = png_ptr->num_trans; + + for (i = 0; i < istop; i++) + png_ptr->trans_alpha[i] = + (png_byte)(255 - png_ptr->trans_alpha[i]); + } + } #endif /* READ_INVERT_ALPHA */ } } /* background expand and (therefore) no alpha association. */ @@ -1189,7 +1243,7 @@ png_init_palette_transformations(png_structrp png_ptr) } static void /* PRIVATE */ -png_init_rgb_transformations(png_structrp png_ptr) +png_init_rgb_transformations(png_struct *png_ptr) { /* Added to libpng-1.5.4: check the color type to determine whether there * is any alpha or transparency in the image and simply cancel the @@ -1253,7 +1307,7 @@ png_init_rgb_transformations(png_structrp png_ptr) default: case 8: - /* FALL THROUGH (Already 8 bits) */ + /* FALLTHROUGH */ /* (Already 8 bits) */ case 16: /* Already a full 16 bits */ @@ -1273,8 +1327,82 @@ png_init_rgb_transformations(png_structrp png_ptr) #endif /* READ_EXPAND && READ_BACKGROUND */ } +#ifdef PNG_READ_GAMMA_SUPPORTED +png_fixed_point /* PRIVATE */ +png_resolve_file_gamma(const png_struct *png_ptr) +{ + png_fixed_point file_gamma; + + /* The file gamma is determined by these precedence rules, in this order + * (i.e. use the first value found): + * + * png_set_gamma; png_struct::file_gammma if not zero, then: + * png_struct::chunk_gamma if not 0 (determined the PNGv3 rules), then: + * png_set_gamma; 1/png_struct::screen_gamma if not zero + * + * 0 (i.e. do no gamma handling) + */ + file_gamma = png_ptr->file_gamma; + if (file_gamma != 0) + return file_gamma; + + file_gamma = png_ptr->chunk_gamma; + if (file_gamma != 0) + return file_gamma; + + file_gamma = png_ptr->default_gamma; + if (file_gamma != 0) + return file_gamma; + + /* If png_reciprocal overflows, it returns 0, indicating to the caller that + * there is no usable file gamma. (The checks added to png_set_gamma and + * png_set_alpha_mode should prevent a screen_gamma which would overflow.) + */ + if (png_ptr->screen_gamma != 0) + file_gamma = png_reciprocal(png_ptr->screen_gamma); + + return file_gamma; +} + +static int +png_init_gamma_values(png_struct *png_ptr) +{ + /* The following temporary indicates if overall gamma correction is + * required. + */ + int gamma_correction = 0; + png_fixed_point file_gamma, screen_gamma; + + /* Resolve the file_gamma. See above: if png_ptr::screen_gamma is set + * file_gamma will always be set here: + */ + file_gamma = png_resolve_file_gamma(png_ptr); + screen_gamma = png_ptr->screen_gamma; + + if (file_gamma > 0) /* file has been set */ + { + if (screen_gamma > 0) /* screen set too */ + gamma_correction = png_gamma_threshold(file_gamma, screen_gamma); + + else + /* Assume the output matches the input; a long time default behavior + * of libpng, although the standard has nothing to say about this. + */ + screen_gamma = png_reciprocal(file_gamma); + } + + else /* both unset, prevent corrections: */ + file_gamma = screen_gamma = PNG_FP_1; + + png_ptr->file_gamma = file_gamma; + png_ptr->screen_gamma = screen_gamma; + return gamma_correction; + +} +#endif /* READ_GAMMA */ + void /* PRIVATE */ -png_init_read_transformations(png_structrp png_ptr) +png_init_read_transformations(png_struct *png_ptr) { png_debug(1, "in png_init_read_transformations"); @@ -1292,59 +1420,22 @@ png_init_read_transformations(png_structrp png_ptr) * the test needs to be performed later - here. In addition prior to 1.5.4 * the tests were repeated for the PALETTE color type here - this is no * longer necessary (and doesn't seem to have been necessary before.) + * + * PNGv3: the new mandatory precedence/priority rules for colour space chunks + * are handled here (by calling the above function). + * + * Turn the gamma transformation on or off as appropriate. Notice that + * PNG_GAMMA just refers to the file->screen correction. Alpha composition + * may independently cause gamma correction because it needs linear data + * (e.g. if the file has a gAMA chunk but the screen gamma hasn't been + * specified.) In any case this flag may get turned off in the code + * immediately below if the transform can be handled outside the row loop. */ - { - /* The following temporary indicates if overall gamma correction is - * required. - */ - int gamma_correction = 0; - - if (png_ptr->colorspace.gamma != 0) /* has been set */ - { - if (png_ptr->screen_gamma != 0) /* screen set too */ - gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma, - png_ptr->screen_gamma); - - else - /* Assume the output matches the input; a long time default behavior - * of libpng, although the standard has nothing to say about this. - */ - png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma); - } - - else if (png_ptr->screen_gamma != 0) - /* The converse - assume the file matches the screen, note that this - * perhaps undesireable default can (from 1.5.4) be changed by calling - * png_set_alpha_mode (even if the alpha handling mode isn't required - * or isn't changed from the default.) - */ - png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma); + if (png_init_gamma_values(png_ptr) != 0) + png_ptr->transformations |= PNG_GAMMA; - else /* neither are set */ - /* Just in case the following prevents any processing - file and screen - * are both assumed to be linear and there is no way to introduce a - * third gamma value other than png_set_background with 'UNIQUE', and, - * prior to 1.5.4 - */ - png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1; - - /* We have a gamma value now. */ - png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; - - /* Now turn the gamma transformation on or off as appropriate. Notice - * that PNG_GAMMA just refers to the file->screen correction. Alpha - * composition may independently cause gamma correction because it needs - * linear data (e.g. if the file has a gAMA chunk but the screen gamma - * hasn't been specified.) In any case this flag may get turned off in - * the code immediately below if the transform can be handled outside the - * row loop. - */ - if (gamma_correction != 0) - png_ptr->transformations |= PNG_GAMMA; - - else - png_ptr->transformations &= ~PNG_GAMMA; - } + else + png_ptr->transformations &= ~PNG_GAMMA; #endif /* Certain transformations have the effect of preventing other @@ -1416,7 +1507,7 @@ png_init_read_transformations(png_structrp png_ptr) * appropriately. */ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0) - png_colorspace_set_rgb_coefficients(png_ptr); + png_set_rgb_coefficients(png_ptr); #endif #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED @@ -1530,9 +1621,10 @@ png_init_read_transformations(png_structrp png_ptr) } #endif - /* NOTE: below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the - * background support (see the comments in scripts/pnglibconf.dfa), this - * allows pre-multiplication of the alpha channel to be implemented as + /* NOTE: + * Below 'PNG_READ_ALPHA_MODE_SUPPORTED' is presumed to also enable the + * background support; see comments in scripts/pnglibconf/pnglibconf.dfa. + * This allows pre-multiplication of the alpha channel to be implemented as * compositing on black. This is probably sub-optimal and has been done in * 1.5.4 betas simply to enable external critique and testing (i.e. to * implement the new API quickly, without lots of internal changes.) @@ -1559,10 +1651,10 @@ png_init_read_transformations(png_structrp png_ptr) */ if ((png_ptr->transformations & PNG_GAMMA) != 0 || ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 && - (png_gamma_significant(png_ptr->colorspace.gamma) != 0 || + (png_gamma_significant(png_ptr->file_gamma) != 0 || png_gamma_significant(png_ptr->screen_gamma) != 0)) || ((png_ptr->transformations & PNG_COMPOSE) != 0 && - (png_gamma_significant(png_ptr->colorspace.gamma) != 0 || + (png_gamma_significant(png_ptr->file_gamma) != 0 || png_gamma_significant(png_ptr->screen_gamma) != 0 # ifdef PNG_READ_BACKGROUND_SUPPORTED || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE && @@ -1592,7 +1684,7 @@ png_init_read_transformations(png_structrp png_ptr) * entries - see the checking code at the start of this function. */ png_color back, back_1; - png_colorp palette = png_ptr->palette; + png_color *palette = png_ptr->palette; int num_palette = png_ptr->num_palette; int i; if (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_FILE) @@ -1618,8 +1710,8 @@ png_init_read_transformations(png_structrp png_ptr) break; case PNG_BACKGROUND_GAMMA_FILE: - g = png_reciprocal(png_ptr->colorspace.gamma); - gs = png_reciprocal2(png_ptr->colorspace.gamma, + g = png_reciprocal(png_ptr->file_gamma); + gs = png_reciprocal2(png_ptr->file_gamma, png_ptr->screen_gamma); break; @@ -1680,19 +1772,51 @@ png_init_read_transformations(png_structrp png_ptr) } else /* if (png_ptr->trans_alpha[i] != 0xff) */ { - png_byte v, w; + if ((png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0) + { + /* Premultiply only: + * component = round((component * alpha) / 255) + */ + png_uint_32 component; + + component = png_ptr->gamma_to_1[palette[i].red]; + component = + (component * png_ptr->trans_alpha[i] + 128) / 255; + palette[i].red = png_ptr->gamma_from_1[component]; + + component = png_ptr->gamma_to_1[palette[i].green]; + component = + (component * png_ptr->trans_alpha[i] + 128) / 255; + palette[i].green = png_ptr->gamma_from_1[component]; + + component = png_ptr->gamma_to_1[palette[i].blue]; + component = + (component * png_ptr->trans_alpha[i] + 128) / 255; + palette[i].blue = png_ptr->gamma_from_1[component]; + } + else + { + /* Composite with background color: + * component = + * alpha * component + (1 - alpha) * background + */ + png_byte v, w; - v = png_ptr->gamma_to_1[palette[i].red]; - png_composite(w, v, png_ptr->trans_alpha[i], back_1.red); - palette[i].red = png_ptr->gamma_from_1[w]; + v = png_ptr->gamma_to_1[palette[i].red]; + png_composite(w, v, + png_ptr->trans_alpha[i], back_1.red); + palette[i].red = png_ptr->gamma_from_1[w]; - v = png_ptr->gamma_to_1[palette[i].green]; - png_composite(w, v, png_ptr->trans_alpha[i], back_1.green); - palette[i].green = png_ptr->gamma_from_1[w]; + v = png_ptr->gamma_to_1[palette[i].green]; + png_composite(w, v, + png_ptr->trans_alpha[i], back_1.green); + palette[i].green = png_ptr->gamma_from_1[w]; - v = png_ptr->gamma_to_1[palette[i].blue]; - png_composite(w, v, png_ptr->trans_alpha[i], back_1.blue); - palette[i].blue = png_ptr->gamma_from_1[w]; + v = png_ptr->gamma_to_1[palette[i].blue]; + png_composite(w, v, + png_ptr->trans_alpha[i], back_1.blue); + palette[i].blue = png_ptr->gamma_from_1[w]; + } } } else @@ -1710,6 +1834,7 @@ png_init_read_transformations(png_structrp png_ptr) * transformations elsewhere. */ png_ptr->transformations &= ~(PNG_COMPOSE | PNG_GAMMA); + png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA; } /* color_type == PNG_COLOR_TYPE_PALETTE */ /* if (png_ptr->background_gamma_type!=PNG_BACKGROUND_GAMMA_UNKNOWN) */ @@ -1727,8 +1852,8 @@ png_init_read_transformations(png_structrp png_ptr) break; case PNG_BACKGROUND_GAMMA_FILE: - g = png_reciprocal(png_ptr->colorspace.gamma); - gs = png_reciprocal2(png_ptr->colorspace.gamma, + g = png_reciprocal(png_ptr->file_gamma); + gs = png_reciprocal2(png_ptr->file_gamma, png_ptr->screen_gamma); break; @@ -1809,7 +1934,7 @@ png_init_read_transformations(png_structrp png_ptr) #endif ) { - png_colorp palette = png_ptr->palette; + png_color *palette = png_ptr->palette; int num_palette = png_ptr->num_palette; int i; @@ -1840,7 +1965,7 @@ png_init_read_transformations(png_structrp png_ptr) int i; int istop = (int)png_ptr->num_trans; png_color back; - png_colorp palette = png_ptr->palette; + png_color *palette = png_ptr->palette; back.red = (png_byte)png_ptr->background.red; back.green = (png_byte)png_ptr->background.green; @@ -1882,7 +2007,7 @@ png_init_read_transformations(png_structrp png_ptr) 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 * error condition which is silently ignored.) */ @@ -1923,10 +2048,21 @@ png_init_read_transformations(png_structrp png_ptr) * assuming the transformations result in valid PNG data. */ void /* PRIVATE */ -png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr) +png_read_transform_info(png_struct *png_ptr, png_info *info_ptr) { png_debug(1, "in png_read_transform_info"); + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + info_ptr->palette != NULL && png_ptr->palette != NULL) + { + /* Sync info_ptr->palette with png_ptr->palette, which may + * have been modified by png_init_read_transformations + * (e.g. for gamma correction or background compositing). + */ + memcpy(info_ptr->palette, png_ptr->palette, + PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))); + } + #ifdef PNG_READ_EXPAND_SUPPORTED if ((png_ptr->transformations & PNG_EXPAND) != 0) { @@ -1978,11 +2114,11 @@ png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr) * been called before this from png_read_update_info->png_read_start_row * sometimes does the gamma transform and cancels the flag. * - * TODO: this looks wrong; the info_ptr should end up with a gamma equal to - * the screen_gamma value. The following probably results in weirdness if - * the info_ptr is used by the app after the rows have been read. + * TODO: this is confusing. It only changes the result of png_get_gAMA and, + * yes, it does return the value that the transformed data effectively has + * but does any app really understand this? */ - info_ptr->colorspace.gamma = png_ptr->colorspace.gamma; + info_ptr->gamma = png_ptr->file_gamma; #endif if (info_ptr->bit_depth == 16) @@ -2135,7 +2271,7 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED) * png_do_shift() after this. */ static void -png_do_unpack(png_row_infop row_info, png_bytep row) +png_do_unpack(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_unpack"); @@ -2148,8 +2284,8 @@ png_do_unpack(png_row_infop row_info, png_bytep row) { case 1: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 3); - png_bytep dp = row + (png_size_t)row_width - 1; + png_byte *sp = row + (size_t)((row_width - 1) >> 3); + png_byte *dp = row + (size_t)row_width - 1; png_uint_32 shift = 7U - ((row_width + 7U) & 0x07); for (i = 0; i < row_width; i++) { @@ -2172,8 +2308,8 @@ png_do_unpack(png_row_infop row_info, png_bytep row) case 2: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 2); - png_bytep dp = row + (png_size_t)row_width - 1; + png_byte *sp = row + (size_t)((row_width - 1) >> 2); + png_byte *dp = row + (size_t)row_width - 1; png_uint_32 shift = ((3U - ((row_width + 3U) & 0x03)) << 1); for (i = 0; i < row_width; i++) { @@ -2195,8 +2331,8 @@ png_do_unpack(png_row_infop row_info, png_bytep row) case 4: { - png_bytep sp = row + (png_size_t)((row_width - 1) >> 1); - png_bytep dp = row + (png_size_t)row_width - 1; + png_byte *sp = row + (size_t)((row_width - 1) >> 1); + png_byte *dp = row + (size_t)row_width - 1; png_uint_32 shift = ((1U - ((row_width + 1U) & 0x01)) << 2); for (i = 0; i < row_width; i++) { @@ -2221,7 +2357,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row) } row_info->bit_depth = 8; row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_width * row_info->channels; + row_info->rowbytes = (size_t)row_width * row_info->channels; } } #endif @@ -2233,8 +2369,8 @@ png_do_unpack(png_row_infop row_info, png_bytep row) * the values back to 0 through 31. */ static void -png_do_unshift(png_row_infop row_info, png_bytep row, - png_const_color_8p sig_bits) +png_do_unshift(png_row_info *row_info, png_byte *row, + const png_color_8 *sig_bits) { int color_type; @@ -2296,8 +2432,8 @@ png_do_unshift(png_row_infop row_info, png_bytep row, /* Must be 2bpp gray */ /* assert(channels == 1 && shift[0] == 1) */ { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; + png_byte *bp = row; + png_byte *bp_end = bp + row_info->rowbytes; while (bp < bp_end) { @@ -2311,8 +2447,8 @@ png_do_unshift(png_row_infop row_info, png_bytep row, /* Must be 4bpp gray */ /* assert(channels == 1) */ { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; + png_byte *bp = row; + png_byte *bp_end = bp + row_info->rowbytes; int gray_shift = shift[0]; int mask = 0xf >> gray_shift; @@ -2329,8 +2465,8 @@ png_do_unshift(png_row_infop row_info, png_bytep row, case 8: /* Single byte components, G, GA, RGB, RGBA */ { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; + png_byte *bp = row; + png_byte *bp_end = bp + row_info->rowbytes; int channel = 0; while (bp < bp_end) @@ -2347,8 +2483,8 @@ png_do_unshift(png_row_infop row_info, png_bytep row, case 16: /* Double byte components, G, GA, RGB, RGBA */ { - png_bytep bp = row; - png_bytep bp_end = bp + row_info->rowbytes; + png_byte *bp = row; + png_byte *bp_end = bp + row_info->rowbytes; int channel = 0; while (bp < bp_end) @@ -2372,15 +2508,15 @@ png_do_unshift(png_row_infop row_info, png_bytep row, #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED /* Scale rows of bit depth 16 down to 8 accurately */ static void -png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) +png_do_scale_16_to_8(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_scale_16_to_8"); if (row_info->bit_depth == 16) { - png_bytep sp = row; /* source */ - png_bytep dp = row; /* destination */ - png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + png_byte *sp = row; /* source */ + png_byte *dp = row; /* destination */ + png_byte *ep = sp + row_info->rowbytes; /* end+1 */ while (sp < ep) { @@ -2423,7 +2559,7 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) row_info->bit_depth = 8; row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_info->width * row_info->channels; + row_info->rowbytes = (size_t)row_info->width * row_info->channels; } } #endif @@ -2433,15 +2569,15 @@ static void /* Simply discard the low byte. This was the default behavior prior * to libpng-1.5.4. */ -png_do_chop(png_row_infop row_info, png_bytep row) +png_do_chop(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_chop"); if (row_info->bit_depth == 16) { - png_bytep sp = row; /* source */ - png_bytep dp = row; /* destination */ - png_bytep ep = sp + row_info->rowbytes; /* end+1 */ + png_byte *sp = row; /* source */ + png_byte *dp = row; /* destination */ + png_byte *ep = sp + row_info->rowbytes; /* end+1 */ while (sp < ep) { @@ -2451,111 +2587,110 @@ png_do_chop(png_row_infop row_info, png_bytep row) row_info->bit_depth = 8; row_info->pixel_depth = (png_byte)(8 * row_info->channels); - row_info->rowbytes = row_info->width * row_info->channels; + row_info->rowbytes = (size_t)row_info->width * row_info->channels; } } #endif #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED static void -png_do_read_swap_alpha(png_row_infop row_info, png_bytep row) +png_do_read_swap_alpha(png_row_info *row_info, png_byte *row) { + png_uint_32 row_width = row_info->width; + png_debug(1, "in png_do_read_swap_alpha"); + if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - png_uint_32 row_width = row_info->width; - if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) + /* This converts from RGBA to ARGB */ + if (row_info->bit_depth == 8) { - /* This converts from RGBA to ARGB */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; + png_byte *sp = row + row_info->rowbytes; + png_byte *dp = sp; + png_byte save; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; } + } #ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from RRGGBBAA to AARRGGBB */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; + /* This converts from RRGGBBAA to AARRGGBB */ + else + { + png_byte *sp = row + row_info->rowbytes; + png_byte *dp = sp; + png_byte save[2]; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; } -#endif } +#endif + } - else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + { + /* This converts from GA to AG */ + if (row_info->bit_depth == 8) { - /* This converts from GA to AG */ - if (row_info->bit_depth == 8) - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save; - png_uint_32 i; + png_byte *sp = row + row_info->rowbytes; + png_byte *dp = sp; + png_byte save; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save; - } + for (i = 0; i < row_width; i++) + { + save = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save; } + } #ifdef PNG_READ_16BIT_SUPPORTED - /* This converts from GGAA to AAGG */ - else - { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; - png_byte save[2]; - png_uint_32 i; + /* This converts from GGAA to AAGG */ + else + { + png_byte *sp = row + row_info->rowbytes; + png_byte *dp = sp; + png_byte save[2]; + png_uint_32 i; - for (i = 0; i < row_width; i++) - { - save[0] = *(--sp); - save[1] = *(--sp); - *(--dp) = *(--sp); - *(--dp) = *(--sp); - *(--dp) = save[0]; - *(--dp) = save[1]; - } + for (i = 0; i < row_width; i++) + { + save[0] = *(--sp); + save[1] = *(--sp); + *(--dp) = *(--sp); + *(--dp) = *(--sp); + *(--dp) = save[0]; + *(--dp) = save[1]; } -#endif } +#endif } } #endif #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED static void -png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) +png_do_read_invert_alpha(png_row_info *row_info, png_byte *row) { png_uint_32 row_width; png_debug(1, "in png_do_read_invert_alpha"); @@ -2566,8 +2701,8 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This inverts the alpha channel in RGBA */ - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; + png_byte *sp = row + row_info->rowbytes; + png_byte *dp = sp; png_uint_32 i; for (i = 0; i < row_width; i++) @@ -2589,8 +2724,8 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) /* This inverts the alpha channel in RRGGBBAA */ else { - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; + png_byte *sp = row + row_info->rowbytes; + png_byte *dp = sp; png_uint_32 i; for (i = 0; i < row_width; i++) @@ -2618,8 +2753,8 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This inverts the alpha channel in GA */ - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; + png_byte *sp = row + row_info->rowbytes; + png_byte *dp = sp; png_uint_32 i; for (i = 0; i < row_width; i++) @@ -2633,8 +2768,8 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) else { /* This inverts the alpha channel in GGAA */ - png_bytep sp = row + row_info->rowbytes; - png_bytep dp = sp; + png_byte *sp = row + row_info->rowbytes; + png_byte *dp = sp; png_uint_32 i; for (i = 0; i < row_width; i++) @@ -2657,7 +2792,7 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row) #ifdef PNG_READ_FILLER_SUPPORTED /* Add filler channel if we have RGB color */ static void -png_do_read_filler(png_row_infop row_info, png_bytep row, +png_do_read_filler(png_row_info *row_info, png_byte *row, png_uint_32 filler, png_uint_32 flags) { png_uint_32 i; @@ -2678,8 +2813,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from G to GX */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; + png_byte *sp = row + (size_t)row_width; + png_byte *dp = sp + (size_t)row_width; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2688,14 +2823,14 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, *(--dp) = lo_filler; row_info->channels = 2; row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; + row_info->rowbytes = (size_t)row_width * 2; } else { /* This changes the data from G to XG */ - png_bytep sp = row + (png_size_t)row_width; - png_bytep dp = sp + (png_size_t)row_width; + png_byte *sp = row + (size_t)row_width; + png_byte *dp = sp + (size_t)row_width; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2703,7 +2838,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, } row_info->channels = 2; row_info->pixel_depth = 16; - row_info->rowbytes = row_width * 2; + row_info->rowbytes = (size_t)row_width * 2; } } @@ -2713,8 +2848,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from GG to GGXX */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_byte *sp = row + (size_t)row_width * 2; + png_byte *dp = sp + (size_t)row_width * 2; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2726,14 +2861,14 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, *(--dp) = hi_filler; row_info->channels = 2; row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; + row_info->rowbytes = (size_t)row_width * 4; } else { /* This changes the data from GG to XXGG */ - png_bytep sp = row + (png_size_t)row_width * 2; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_byte *sp = row + (size_t)row_width * 2; + png_byte *dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2743,7 +2878,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, } row_info->channels = 2; row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; + row_info->rowbytes = (size_t)row_width * 4; } } #endif @@ -2755,8 +2890,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from RGB to RGBX */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; + png_byte *sp = row + (size_t)row_width * 3; + png_byte *dp = sp + (size_t)row_width; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2767,14 +2902,14 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, *(--dp) = lo_filler; row_info->channels = 4; row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; + row_info->rowbytes = (size_t)row_width * 4; } else { /* This changes the data from RGB to XRGB */ - png_bytep sp = row + (png_size_t)row_width * 3; - png_bytep dp = sp + (png_size_t)row_width; + png_byte *sp = row + (size_t)row_width * 3; + png_byte *dp = sp + (size_t)row_width; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2784,7 +2919,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, } row_info->channels = 4; row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; + row_info->rowbytes = (size_t)row_width * 4; } } @@ -2794,8 +2929,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, if ((flags & PNG_FLAG_FILLER_AFTER) != 0) { /* This changes the data from RRGGBB to RRGGBBXX */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_byte *sp = row + (size_t)row_width * 6; + png_byte *dp = sp + (size_t)row_width * 2; for (i = 1; i < row_width; i++) { *(--dp) = lo_filler; @@ -2811,14 +2946,14 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, *(--dp) = hi_filler; row_info->channels = 4; row_info->pixel_depth = 64; - row_info->rowbytes = row_width * 8; + row_info->rowbytes = (size_t)row_width * 8; } else { /* This changes the data from RRGGBB to XXRRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 6; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_byte *sp = row + (size_t)row_width * 6; + png_byte *dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(--dp) = *(--sp); @@ -2833,7 +2968,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, row_info->channels = 4; row_info->pixel_depth = 64; - row_info->rowbytes = row_width * 8; + row_info->rowbytes = (size_t)row_width * 8; } } #endif @@ -2844,7 +2979,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row, #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED /* Expand grayscale files to RGB, with or without alpha */ static void -png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) +png_do_gray_to_rgb(png_row_info *row_info, png_byte *row) { png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -2859,8 +2994,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This changes G to RGB */ - png_bytep sp = row + (png_size_t)row_width - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_byte *sp = row + (size_t)row_width - 1; + png_byte *dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(dp--) = *sp; @@ -2872,8 +3007,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) else { /* This changes GG to RRGGBB */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; + png_byte *sp = row + (size_t)row_width * 2 - 1; + png_byte *dp = sp + (size_t)row_width * 4; for (i = 0; i < row_width; i++) { *(dp--) = *sp; @@ -2891,8 +3026,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This changes GA to RGBA */ - png_bytep sp = row + (png_size_t)row_width * 2 - 1; - png_bytep dp = sp + (png_size_t)row_width * 2; + png_byte *sp = row + (size_t)row_width * 2 - 1; + png_byte *dp = sp + (size_t)row_width * 2; for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); @@ -2905,8 +3040,8 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row) else { /* This changes GGAA to RRGGBBAA */ - png_bytep sp = row + (png_size_t)row_width * 4 - 1; - png_bytep dp = sp + (png_size_t)row_width * 4; + png_byte *sp = row + (size_t)row_width * 4 - 1; + png_byte *dp = sp + (size_t)row_width * 4; for (i = 0; i < row_width; i++) { *(dp--) = *(sp--); @@ -2934,7 +3069,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 * (THIS LINK IS DEAD June 2008 but * 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 ) * Charles Poynton poynton at poynton.com * @@ -2977,14 +3112,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 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 * calculated to make the sum 32768. This will result in different rounding * to that used above. */ 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_struct *png_ptr, png_row_info *row_info, png_byte *row) { int rgb_error = 0; @@ -2993,12 +3127,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 && (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) { - PNG_CONST 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_CONST png_uint_32 bc = 32768 - rc - gc; - PNG_CONST png_uint_32 row_width = row_info->width; - PNG_CONST int have_alpha = - (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; + png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff; + png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff; + png_uint_32 bc = 32768 - rc - gc; + png_uint_32 row_width = row_info->width; + int have_alpha = (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0; if (row_info->bit_depth == 8) { @@ -3010,8 +3143,8 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) */ if (png_ptr->gamma_from_1 != NULL && png_ptr->gamma_to_1 != NULL) { - png_bytep sp = row; - png_bytep dp = row; + png_byte *sp = row; + png_byte *dp = row; png_uint_32 i; for (i = 0; i < row_width; i++) @@ -3049,8 +3182,8 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) else #endif { - png_bytep sp = row; - png_bytep dp = row; + png_byte *sp = row; + png_byte *dp = row; png_uint_32 i; for (i = 0; i < row_width; i++) @@ -3082,8 +3215,8 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) #ifdef PNG_READ_GAMMA_SUPPORTED if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL) { - png_bytep sp = row; - png_bytep dp = row; + png_byte *sp = row; + png_byte *dp = row; png_uint_32 i; for (i = 0; i < row_width; i++) @@ -3134,8 +3267,8 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) else #endif { - png_bytep sp = row; - png_bytep dp = row; + png_byte *sp = row; + png_byte *dp = row; png_uint_32 i; for (i = 0; i < row_width; i++) @@ -3186,740 +3319,738 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) * at a gamma of 1.0. Paletted files have already been taken care of. */ static void -png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) +png_do_compose(png_row_info *row_info, png_byte *row, png_struct *png_ptr) { #ifdef PNG_READ_GAMMA_SUPPORTED - png_const_bytep gamma_table = png_ptr->gamma_table; - png_const_bytep gamma_from_1 = png_ptr->gamma_from_1; - png_const_bytep gamma_to_1 = png_ptr->gamma_to_1; - png_const_uint_16pp gamma_16 = png_ptr->gamma_16_table; - png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1; - png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1; + const png_byte *gamma_table = png_ptr->gamma_table; + const png_byte *gamma_from_1 = png_ptr->gamma_from_1; + const png_byte *gamma_to_1 = png_ptr->gamma_to_1; + png_uint_16 * const *gamma_16 = png_ptr->gamma_16_table; + png_uint_16 * const *gamma_16_from_1 = png_ptr->gamma_16_from_1; + png_uint_16 * const *gamma_16_to_1 = png_ptr->gamma_16_to_1; int gamma_shift = png_ptr->gamma_shift; int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0; #endif - png_bytep sp; + png_byte *sp; png_uint_32 i; png_uint_32 row_width = row_info->width; int shift; 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: + switch (row_info->bit_depth) { - switch (row_info->bit_depth) + case 1: + { + sp = row; + shift = 7; + for (i = 0; i < row_width; i++) + { + if ((png_uint_16)((*sp >> shift) & 0x01) + == png_ptr->trans_color.gray) + { + unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); + } + + if (shift == 0) + { + shift = 7; + sp++; + } + + else + shift--; + } + break; + } + + case 2: { - case 1: +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_table != NULL) { sp = row; - shift = 7; + shift = 6; for (i = 0; i < row_width; i++) { - if ((png_uint_16)((*sp >> shift) & 0x01) - == png_ptr->trans_color.gray) + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0x7f7f >> (7 - shift)); + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); tmp |= - (unsigned int)(png_ptr->background.gray << shift); + (unsigned int)png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); + } + + else + { + unsigned int p = (*sp >> shift) & 0x03; + unsigned int g = (gamma_table [p | (p << 2) | + (p << 4) | (p << 6)] >> 6) & 0x03; + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= (unsigned int)(g << shift); *sp = (png_byte)(tmp & 0xff); } if (shift == 0) { - shift = 7; + shift = 6; sp++; } else - shift--; + shift -= 2; } - break; } - case 2: + else +#endif { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) + sp = row; + shift = 6; + for (i = 0; i < row_width; i++) { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) + if ((png_uint_16)((*sp >> shift) & 0x03) + == png_ptr->trans_color.gray) { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= - (unsigned int)png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x03; - unsigned int g = (gamma_table [p | (p << 2) | - (p << 4) | (p << 6)] >> 6) & 0x03; - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= (unsigned int)(g << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 6; - sp++; - } - - else - shift -= 2; + unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); + tmp |= + (unsigned int)png_ptr->background.gray << shift; + *sp = (png_byte)(tmp & 0xff); } - } - else -#endif - { - sp = row; - shift = 6; - for (i = 0; i < row_width; i++) + if (shift == 0) { - if ((png_uint_16)((*sp >> shift) & 0x03) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x3f3f >> (6 - shift)); - tmp |= - (unsigned int)png_ptr->background.gray << shift; - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 6; - sp++; - } - - else - shift -= 2; + shift = 6; + sp++; } + + else + shift -= 2; } - break; } + break; + } - case 4: - { + case 4: + { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) + if (gamma_table != NULL) + { + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= - (unsigned int)(png_ptr->background.gray << shift); - *sp = (png_byte)(tmp & 0xff); - } - - else - { - unsigned int p = (*sp >> shift) & 0x0f; - unsigned int g = (gamma_table[p | (p << 4)] >> 4) & - 0x0f; - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= (unsigned int)(g << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 4; - sp++; - } - - else - shift -= 4; + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); } - } - else -#endif - { - sp = row; - shift = 4; - for (i = 0; i < row_width; i++) + else { - if ((png_uint_16)((*sp >> shift) & 0x0f) - == png_ptr->trans_color.gray) - { - unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); - tmp |= - (unsigned int)(png_ptr->background.gray << shift); - *sp = (png_byte)(tmp & 0xff); - } - - if (shift == 0) - { - shift = 4; - sp++; - } - - else - shift -= 4; + unsigned int p = (*sp >> shift) & 0x0f; + unsigned int g = (gamma_table[p | (p << 4)] >> 4) & + 0x0f; + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= (unsigned int)(g << shift); + *sp = (png_byte)(tmp & 0xff); } - } - break; - } - - case 8: - { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_table != NULL) - { - sp = row; - for (i = 0; i < row_width; i++, sp++) - { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; - else - *sp = gamma_table[*sp]; - } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp++) + if (shift == 0) { - if (*sp == png_ptr->trans_color.gray) - *sp = (png_byte)png_ptr->background.gray; + shift = 4; + sp++; } + + else + shift -= 4; } - break; } - case 16: + else +#endif { -#ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL) + sp = row; + shift = 4; + for (i = 0; i < row_width; i++) { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) + if ((png_uint_16)((*sp >> shift) & 0x0f) + == png_ptr->trans_color.gray) { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - - if (v == png_ptr->trans_color.gray) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } - - else - { - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); + tmp |= + (unsigned int)(png_ptr->background.gray << shift); + *sp = (png_byte)(tmp & 0xff); } - } - else -#endif - { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) - { - png_uint_16 v; - - v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (v == png_ptr->trans_color.gray) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray - & 0xff); - } + if (shift == 0) + { + shift = 4; + sp++; } + + else + shift -= 4; } - break; } - - default: - break; + break; } - break; - } - case PNG_COLOR_TYPE_RGB: - { - if (row_info->bit_depth == 8) + case 8: { #ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_table != NULL) { sp = row; - for (i = 0; i < row_width; i++, sp += 3) + for (i = 0; i < row_width; i++, sp++) { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; else - { *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } } } else #endif { sp = row; - for (i = 0; i < row_width; i++, sp += 3) + for (i = 0; i < row_width; i++, sp++) { - if (*sp == png_ptr->trans_color.red && - *(sp + 1) == png_ptr->trans_color.green && - *(sp + 2) == png_ptr->trans_color.blue) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + if (*sp == png_ptr->trans_color.gray) + *sp = (png_byte)png_ptr->background.gray; } } + break; } - else /* if (row_info->bit_depth == 16) */ + + case 16: { #ifdef PNG_READ_GAMMA_SUPPORTED if (gamma_16 != NULL) { sp = row; - for (i = 0; i < row_width; i++, sp += 6) + for (i = 0; i < row_width; i++, sp += 2) { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 v; - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); - - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) + if (v == png_ptr->trans_color.gray) { /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); } else { - png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; *sp = (png_byte)((v >> 8) & 0xff); *(sp + 1) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); - - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); } } } - else #endif { sp = row; - for (i = 0; i < row_width; i++, sp += 6) + for (i = 0; i < row_width; i++, sp += 2) { - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 v; - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); + v = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - if (r == png_ptr->trans_color.red && - g == png_ptr->trans_color.green && - b == png_ptr->trans_color.blue) + if (v == png_ptr->trans_color.gray) { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray + & 0xff); } } } + break; } - break; + + default: + break; } + break; + } - case PNG_COLOR_TYPE_GRAY_ALPHA: + case PNG_COLOR_TYPE_RGB: + { + if (row_info->bit_depth == 8) { - if (row_info->bit_depth == 8) - { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) + if (gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) { - png_uint_16 a = *(sp + 1); + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } - if (a == 0xff) - *sp = gamma_table[*sp]; + else + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } + } + } + else +#endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 3) + { + if (*sp == png_ptr->trans_color.red && + *(sp + 1) == png_ptr->trans_color.green && + *(sp + 2) == png_ptr->trans_color.blue) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } + } + } + } + else /* if (row_info->bit_depth == 16) */ + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_16 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) + { + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.gray; - } + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); - else - { - png_byte v, w; + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.gray); - if (optimize == 0) - w = gamma_from_1[w]; - *sp = w; - } + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + + else + { + png_uint_16 v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); + + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); } } - else + } + + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 6) { - sp = row; - for (i = 0; i < row_width; i++, sp += 2) + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); + + if (r == png_ptr->trans_color.red && + g == png_ptr->trans_color.green && + b == png_ptr->trans_color.blue) { - png_byte a = *(sp + 1); + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } + } + } + } + break; + } - if (a == 0) - *sp = (png_byte)png_ptr->background.gray; + case PNG_COLOR_TYPE_GRAY_ALPHA: + { + if (row_info->bit_depth == 8) + { +#ifdef PNG_READ_GAMMA_SUPPORTED + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_uint_16 a = *(sp + 1); + + if (a == 0xff) + *sp = gamma_table[*sp]; + + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.gray; + } - else if (a < 0xff) - png_composite(*sp, *sp, a, png_ptr->background.gray); + else + { + png_byte v, w; + + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.gray); + if (optimize == 0) + w = gamma_from_1[w]; + *sp = w; } } } - else /* if (png_ptr->bit_depth == 16) */ + else +#endif { + sp = row; + for (i = 0; i < row_width; i++, sp += 2) + { + png_byte a = *(sp + 1); + + if (a == 0) + *sp = (png_byte)png_ptr->background.gray; + + else if (a < 0xff) + png_composite(*sp, *sp, a, png_ptr->background.gray); + } + } + } + else /* if (png_ptr->bit_depth == 16) */ + { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + + if (a == (png_uint_16)0xffff) { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + png_uint_16 v; - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); + } - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } + else + { + png_uint_16 g, v, w; + g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(v, g, a, png_ptr->background_1.gray); + if (optimize != 0) + w = v; else - { - png_uint_16 g, v, w; - - g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(v, g, a, png_ptr->background_1.gray); - if (optimize != 0) - w = v; - else - w = gamma_16_from_1[(v & 0xff) >> - gamma_shift][v >> 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - } + w = gamma_16_from_1[(v & 0xff) >> + gamma_shift][v >> 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); } } - else + } + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); + png_uint_16 a = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.gray >> 8) - & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); - } + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.gray >> 8) + & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff); + } - else if (a < 0xffff) - { - png_uint_16 g, v; + else if (a < 0xffff) + { + png_uint_16 g, v; - g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_composite_16(v, g, a, png_ptr->background.gray); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); - } + g = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_composite_16(v, g, a, png_ptr->background.gray); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); } } } - break; } + break; + } - case PNG_COLOR_TYPE_RGB_ALPHA: + case PNG_COLOR_TYPE_RGB_ALPHA: + { + if (row_info->bit_depth == 8) { - if (row_info->bit_depth == 8) - { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_to_1 != NULL && gamma_from_1 != NULL && - gamma_table != NULL) + if (gamma_to_1 != NULL && gamma_from_1 != NULL && + gamma_table != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); + png_byte a = *(sp + 3); - if (a == 0xff) - { - *sp = gamma_table[*sp]; - *(sp + 1) = gamma_table[*(sp + 1)]; - *(sp + 2) = gamma_table[*(sp + 2)]; - } + if (a == 0xff) + { + *sp = gamma_table[*sp]; + *(sp + 1) = gamma_table[*(sp + 1)]; + *(sp + 2) = gamma_table[*(sp + 2)]; + } - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } - else - { - png_byte v, w; + else + { + png_byte v, w; - v = gamma_to_1[*sp]; - png_composite(w, v, a, png_ptr->background_1.red); - if (optimize == 0) w = gamma_from_1[w]; - *sp = w; + v = gamma_to_1[*sp]; + png_composite(w, v, a, png_ptr->background_1.red); + if (optimize == 0) w = gamma_from_1[w]; + *sp = w; - v = gamma_to_1[*(sp + 1)]; - png_composite(w, v, a, png_ptr->background_1.green); - if (optimize == 0) w = gamma_from_1[w]; - *(sp + 1) = w; + v = gamma_to_1[*(sp + 1)]; + png_composite(w, v, a, png_ptr->background_1.green); + if (optimize == 0) w = gamma_from_1[w]; + *(sp + 1) = w; - v = gamma_to_1[*(sp + 2)]; - png_composite(w, v, a, png_ptr->background_1.blue); - if (optimize == 0) w = gamma_from_1[w]; - *(sp + 2) = w; - } + v = gamma_to_1[*(sp + 2)]; + png_composite(w, v, a, png_ptr->background_1.blue); + if (optimize == 0) w = gamma_from_1[w]; + *(sp + 2) = w; } } - else + } + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 4) { - sp = row; - for (i = 0; i < row_width; i++, sp += 4) - { - png_byte a = *(sp + 3); + png_byte a = *(sp + 3); - if (a == 0) - { - *sp = (png_byte)png_ptr->background.red; - *(sp + 1) = (png_byte)png_ptr->background.green; - *(sp + 2) = (png_byte)png_ptr->background.blue; - } + if (a == 0) + { + *sp = (png_byte)png_ptr->background.red; + *(sp + 1) = (png_byte)png_ptr->background.green; + *(sp + 2) = (png_byte)png_ptr->background.blue; + } - else if (a < 0xff) - { - png_composite(*sp, *sp, a, png_ptr->background.red); + else if (a < 0xff) + { + png_composite(*sp, *sp, a, png_ptr->background.red); - png_composite(*(sp + 1), *(sp + 1), a, - png_ptr->background.green); + png_composite(*(sp + 1), *(sp + 1), a, + png_ptr->background.green); - png_composite(*(sp + 2), *(sp + 2), a, - png_ptr->background.blue); - } + png_composite(*(sp + 2), *(sp + 2), a, + png_ptr->background.blue); } } } - else /* if (row_info->bit_depth == 16) */ - { + } + else /* if (row_info->bit_depth == 16) */ + { #ifdef PNG_READ_GAMMA_SUPPORTED - if (gamma_16 != NULL && gamma_16_from_1 != NULL && - gamma_16_to_1 != NULL) + if (gamma_16 != NULL && gamma_16_from_1 != NULL && + gamma_16_to_1 != NULL) + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); - if (a == (png_uint_16)0xffff) - { - png_uint_16 v; + if (a == (png_uint_16)0xffff) + { + png_uint_16 v; - v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 1) >> gamma_shift][*sp]; + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); + v = gamma_16[*(sp + 3) >> gamma_shift][*(sp + 2)]; + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); - v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } + v = gamma_16[*(sp + 5) >> gamma_shift][*(sp + 4)]; + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); + } - else if (a == 0) - { - /* Background is already in screen gamma */ - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } + else if (a == 0) + { + /* Background is already in screen gamma */ + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } - else - { - png_uint_16 v, w; - - v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; - png_composite_16(w, v, a, png_ptr->background_1.red); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - *sp = (png_byte)((w >> 8) & 0xff); - *(sp + 1) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; - png_composite_16(w, v, a, png_ptr->background_1.green); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 2) = (png_byte)((w >> 8) & 0xff); - *(sp + 3) = (png_byte)(w & 0xff); - - v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; - png_composite_16(w, v, a, png_ptr->background_1.blue); - if (optimize == 0) - w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> - 8]; - - *(sp + 4) = (png_byte)((w >> 8) & 0xff); - *(sp + 5) = (png_byte)(w & 0xff); - } + else + { + png_uint_16 v, w; + + v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp]; + png_composite_16(w, v, a, png_ptr->background_1.red); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + *sp = (png_byte)((w >> 8) & 0xff); + *(sp + 1) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)]; + png_composite_16(w, v, a, png_ptr->background_1.green); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 2) = (png_byte)((w >> 8) & 0xff); + *(sp + 3) = (png_byte)(w & 0xff); + + v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)]; + png_composite_16(w, v, a, png_ptr->background_1.blue); + if (optimize == 0) + w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >> + 8]; + + *(sp + 4) = (png_byte)((w >> 8) & 0xff); + *(sp + 5) = (png_byte)(w & 0xff); } } + } - else + else #endif + { + sp = row; + for (i = 0; i < row_width; i++, sp += 8) { - sp = row; - for (i = 0; i < row_width; i++, sp += 8) - { - png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) - << 8) + (png_uint_16)(*(sp + 7))); + png_uint_16 a = (png_uint_16)(((png_uint_16)(*(sp + 6)) + << 8) + (png_uint_16)(*(sp + 7))); - if (a == 0) - { - *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); - *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); - *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) - & 0xff); - *(sp + 3) = (png_byte)(png_ptr->background.green - & 0xff); - *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) - & 0xff); - *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); - } + if (a == 0) + { + *sp = (png_byte)((png_ptr->background.red >> 8) & 0xff); + *(sp + 1) = (png_byte)(png_ptr->background.red & 0xff); + *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) + & 0xff); + *(sp + 3) = (png_byte)(png_ptr->background.green + & 0xff); + *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) + & 0xff); + *(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff); + } - else if (a < 0xffff) - { - png_uint_16 v; + else if (a < 0xffff) + { + png_uint_16 v; - png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); - png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) - + *(sp + 3)); - png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) - + *(sp + 5)); + png_uint_16 r = (png_uint_16)(((*sp) << 8) + *(sp + 1)); + png_uint_16 g = (png_uint_16)(((*(sp + 2)) << 8) + + *(sp + 3)); + png_uint_16 b = (png_uint_16)(((*(sp + 4)) << 8) + + *(sp + 5)); - png_composite_16(v, r, a, png_ptr->background.red); - *sp = (png_byte)((v >> 8) & 0xff); - *(sp + 1) = (png_byte)(v & 0xff); + png_composite_16(v, r, a, png_ptr->background.red); + *sp = (png_byte)((v >> 8) & 0xff); + *(sp + 1) = (png_byte)(v & 0xff); - png_composite_16(v, g, a, png_ptr->background.green); - *(sp + 2) = (png_byte)((v >> 8) & 0xff); - *(sp + 3) = (png_byte)(v & 0xff); + png_composite_16(v, g, a, png_ptr->background.green); + *(sp + 2) = (png_byte)((v >> 8) & 0xff); + *(sp + 3) = (png_byte)(v & 0xff); - png_composite_16(v, b, a, png_ptr->background.blue); - *(sp + 4) = (png_byte)((v >> 8) & 0xff); - *(sp + 5) = (png_byte)(v & 0xff); - } + png_composite_16(v, b, a, png_ptr->background.blue); + *(sp + 4) = (png_byte)((v >> 8) & 0xff); + *(sp + 5) = (png_byte)(v & 0xff); } } } - break; } - - default: - break; + break; } + + default: + break; } } #endif /* READ_BACKGROUND || READ_ALPHA_MODE */ @@ -3932,13 +4063,13 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) * build_gamma_table(). */ static void -png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr) +png_do_gamma(png_row_info *row_info, png_byte *row, png_struct *png_ptr) { - png_const_bytep gamma_table = png_ptr->gamma_table; - png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table; + const png_byte *gamma_table = png_ptr->gamma_table; + png_uint_16 * const *gamma_16_table = png_ptr->gamma_16_table; int gamma_shift = png_ptr->gamma_shift; - png_bytep sp; + png_byte *sp; png_uint_32 i; png_uint_32 row_width=row_info->width; @@ -4133,7 +4264,7 @@ png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr) * from_1 tables. */ static void -png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) +png_do_encode_alpha(png_row_info *row_info, png_byte *row, png_struct *png_ptr) { png_uint_32 row_width = row_info->width; @@ -4143,12 +4274,11 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) { if (row_info->bit_depth == 8) { - PNG_CONST png_bytep table = png_ptr->gamma_from_1; + png_byte *table = png_ptr->gamma_from_1; if (table != NULL) { - PNG_CONST int step = - (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; + int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 4 : 2; /* The alpha channel is the last component: */ row += step - 1; @@ -4162,13 +4292,12 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) else if (row_info->bit_depth == 16) { - PNG_CONST png_uint_16pp table = png_ptr->gamma_16_from_1; - PNG_CONST int gamma_shift = png_ptr->gamma_shift; + png_uint_16 **table = png_ptr->gamma_16_from_1; + int gamma_shift = png_ptr->gamma_shift; if (table != NULL) { - PNG_CONST int step = - (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; + int step = (row_info->color_type & PNG_COLOR_MASK_COLOR) ? 8 : 4; /* The alpha channel is the last component: */ row += step - 2; @@ -4199,11 +4328,11 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr) * upon whether you supply trans and num_trans. */ static void -png_do_expand_palette(png_row_infop row_info, png_bytep row, - png_const_colorp palette, png_const_bytep trans_alpha, int num_trans) +png_do_expand_palette(png_row_info *row_info, png_byte *row, + const png_color *palette, const png_byte *trans_alpha, int num_trans) { int shift, value; - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width=row_info->width; @@ -4217,8 +4346,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { case 1: { - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 3); + dp = row + (size_t)row_width - 1; shift = 7 - (int)((row_width + 7) & 0x07); for (i = 0; i < row_width; i++) { @@ -4244,8 +4373,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, case 2: { - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 2); + dp = row + (size_t)row_width - 1; shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); for (i = 0; i < row_width; i++) { @@ -4267,8 +4396,8 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, case 4: { - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; + sp = row + (size_t)((row_width - 1) >> 1); + dp = row + (size_t)row_width - 1; shift = (int)((row_width & 0x01) << 2); for (i = 0; i < row_width; i++) { @@ -4301,17 +4430,16 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, { if (num_trans > 0) { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 2) - 1; + sp = row + (size_t)row_width - 1; + dp = row + ((size_t)row_width << 2) - 1; + i = 0; for (i = 0; i < row_width; i++) { if ((int)(*sp) >= num_trans) *dp-- = 0xff; - else *dp-- = trans_alpha[*sp]; - *dp-- = palette[*sp].blue; *dp-- = palette[*sp].green; *dp-- = palette[*sp].red; @@ -4319,16 +4447,15 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, } row_info->bit_depth = 8; row_info->pixel_depth = 32; - row_info->rowbytes = row_width * 4; + row_info->rowbytes = (size_t)row_width * 4; row_info->color_type = 6; row_info->channels = 4; } else { - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width * 3) - 1; - + sp = row + (size_t)row_width - 1; + dp = row + (size_t)row_width * 3 - 1; for (i = 0; i < row_width; i++) { *dp-- = palette[*sp].blue; @@ -4339,7 +4466,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, row_info->bit_depth = 8; row_info->pixel_depth = 24; - row_info->rowbytes = row_width * 3; + row_info->rowbytes = (size_t)row_width * 3; row_info->color_type = 2; row_info->channels = 3; } @@ -4352,205 +4479,140 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row, * expanded transparency value is supplied, an alpha channel is built. */ static void -png_do_expand(png_row_infop row_info, png_bytep row, - png_const_color_16p trans_color) +png_do_expand(png_row_info *row_info, png_byte *row, + const png_color_16 *trans_color) { int shift, value; - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width=row_info->width; 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; - if (row_info->bit_depth < 8) + if (row_info->bit_depth < 8) + { + switch (row_info->bit_depth) { - switch (row_info->bit_depth) + case 1: { - case 1: + gray = (gray & 0x01) * 0xff; + sp = row + (size_t)((row_width - 1) >> 3); + dp = row + (size_t)row_width - 1; + shift = 7 - (int)((row_width + 7) & 0x07); + for (i = 0; i < row_width; i++) { - gray = (gray & 0x01) * 0xff; - sp = row + (png_size_t)((row_width - 1) >> 3); - dp = row + (png_size_t)row_width - 1; - shift = 7 - (int)((row_width + 7) & 0x07); - for (i = 0; i < row_width; i++) - { - if ((*sp >> shift) & 0x01) - *dp = 0xff; - - else - *dp = 0; - - if (shift == 7) - { - shift = 0; - sp--; - } - - else - shift++; + if ((*sp >> shift) & 0x01) + *dp = 0xff; - dp--; - } - break; - } + else + *dp = 0; - case 2: - { - gray = (gray & 0x03) * 0x55; - sp = row + (png_size_t)((row_width - 1) >> 2); - dp = row + (png_size_t)row_width - 1; - shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); - for (i = 0; i < row_width; i++) + if (shift == 7) { - value = (*sp >> shift) & 0x03; - *dp = (png_byte)(value | (value << 2) | (value << 4) | - (value << 6)); - if (shift == 6) - { - shift = 0; - sp--; - } - - else - shift += 2; - - dp--; + shift = 0; + sp--; } - break; - } - - case 4: - { - gray = (gray & 0x0f) * 0x11; - sp = row + (png_size_t)((row_width - 1) >> 1); - dp = row + (png_size_t)row_width - 1; - shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); - for (i = 0; i < row_width; i++) - { - value = (*sp >> shift) & 0x0f; - *dp = (png_byte)(value | (value << 4)); - if (shift == 4) - { - shift = 0; - sp--; - } - else - shift = 4; + else + shift++; - dp--; - } - break; + dp--; } - - default: - break; + break; } - row_info->bit_depth = 8; - row_info->pixel_depth = 8; - row_info->rowbytes = row_width; - } - - if (trans_color != NULL) - { - if (row_info->bit_depth == 8) + case 2: { - gray = gray & 0xff; - sp = row + (png_size_t)row_width - 1; - dp = row + (png_size_t)(row_width << 1) - 1; - + gray = (gray & 0x03) * 0x55; + sp = row + (size_t)((row_width - 1) >> 2); + dp = row + (size_t)row_width - 1; + shift = (int)((3 - ((row_width + 3) & 0x03)) << 1); for (i = 0; i < row_width; i++) { - if ((*sp & 0xffU) == gray) - *dp-- = 0; + value = (*sp >> shift) & 0x03; + *dp = (png_byte)(value | (value << 2) | (value << 4) | + (value << 6)); + if (shift == 6) + { + shift = 0; + sp--; + } else - *dp-- = 0xff; + shift += 2; - *dp-- = *sp--; + dp--; } + break; } - else if (row_info->bit_depth == 16) + case 4: { - unsigned int gray_high = (gray >> 8) & 0xff; - unsigned int gray_low = gray & 0xff; - sp = row + row_info->rowbytes - 1; - dp = row + (row_info->rowbytes << 1) - 1; + gray = (gray & 0x0f) * 0x11; + sp = row + (size_t)((row_width - 1) >> 1); + dp = row + (size_t)row_width - 1; + shift = (int)((1 - ((row_width + 1) & 0x01)) << 2); for (i = 0; i < row_width; i++) { - if ((*(sp - 1) & 0xffU) == gray_high && - (*(sp) & 0xffU) == gray_low) + value = (*sp >> shift) & 0x0f; + *dp = (png_byte)(value | (value << 4)); + if (shift == 4) { - *dp-- = 0; - *dp-- = 0; + shift = 0; + sp--; } else - { - *dp-- = 0xff; - *dp-- = 0xff; - } + shift = 4; - *dp-- = *sp--; - *dp-- = *sp--; + dp--; } + break; } - row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; - row_info->channels = 2; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, - row_width); + default: + break; } + + row_info->bit_depth = 8; + row_info->pixel_depth = 8; + row_info->rowbytes = row_width; } - else if (row_info->color_type == PNG_COLOR_TYPE_RGB && - trans_color != NULL) + + if (trans_color != NULL) { if (row_info->bit_depth == 8) { - png_byte red = (png_byte)(trans_color->red & 0xff); - png_byte green = (png_byte)(trans_color->green & 0xff); - png_byte blue = (png_byte)(trans_color->blue & 0xff); - sp = row + (png_size_t)row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 2) - 1; + gray = gray & 0xff; + sp = row + (size_t)row_width - 1; + dp = row + ((size_t)row_width << 1) - 1; + for (i = 0; i < row_width; i++) { - if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + if ((*sp & 0xffU) == gray) *dp-- = 0; else *dp-- = 0xff; *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; } } + else if (row_info->bit_depth == 16) { - png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); - png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); - png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); - png_byte red_low = (png_byte)(trans_color->red & 0xff); - png_byte green_low = (png_byte)(trans_color->green & 0xff); - png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + unsigned int gray_high = (gray >> 8) & 0xff; + unsigned int gray_low = gray & 0xff; sp = row + row_info->rowbytes - 1; - dp = row + (png_size_t)(row_width << 3) - 1; + dp = row + (row_info->rowbytes << 1) - 1; for (i = 0; i < row_width; i++) { - if (*(sp - 5) == red_high && - *(sp - 4) == red_low && - *(sp - 3) == green_high && - *(sp - 2) == green_low && - *(sp - 1) == blue_high && - *(sp ) == blue_low) + if ((*(sp - 1) & 0xffU) == gray_high && + (*(sp) & 0xffU) == gray_low) { *dp-- = 0; *dp-- = 0; @@ -4564,17 +4626,80 @@ png_do_expand(png_row_infop row_info, png_bytep row, *dp-- = *sp--; *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; - *dp-- = *sp--; } } - row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; - row_info->channels = 4; - row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); - row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); + + row_info->color_type = PNG_COLOR_TYPE_GRAY_ALPHA; + row_info->channels = 2; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 1); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, + row_width); + } + } + else if (row_info->color_type == PNG_COLOR_TYPE_RGB && + trans_color != NULL) + { + if (row_info->bit_depth == 8) + { + png_byte red = (png_byte)(trans_color->red & 0xff); + png_byte green = (png_byte)(trans_color->green & 0xff); + png_byte blue = (png_byte)(trans_color->blue & 0xff); + sp = row + (size_t)row_info->rowbytes - 1; + dp = row + ((size_t)row_width << 2) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 2) == red && *(sp - 1) == green && *(sp) == blue) + *dp-- = 0; + + else + *dp-- = 0xff; + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } + } + else if (row_info->bit_depth == 16) + { + png_byte red_high = (png_byte)((trans_color->red >> 8) & 0xff); + png_byte green_high = (png_byte)((trans_color->green >> 8) & 0xff); + png_byte blue_high = (png_byte)((trans_color->blue >> 8) & 0xff); + png_byte red_low = (png_byte)(trans_color->red & 0xff); + png_byte green_low = (png_byte)(trans_color->green & 0xff); + png_byte blue_low = (png_byte)(trans_color->blue & 0xff); + sp = row + row_info->rowbytes - 1; + dp = row + ((size_t)row_width << 3) - 1; + for (i = 0; i < row_width; i++) + { + if (*(sp - 5) == red_high && + *(sp - 4) == red_low && + *(sp - 3) == green_high && + *(sp - 2) == green_low && + *(sp - 1) == blue_high && + *(sp ) == blue_low) + { + *dp-- = 0; + *dp-- = 0; + } + + else + { + *dp-- = 0xff; + *dp-- = 0xff; + } + + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + *dp-- = *sp--; + } } + row_info->color_type = PNG_COLOR_TYPE_RGB_ALPHA; + row_info->channels = 4; + row_info->pixel_depth = (png_byte)(row_info->bit_depth << 2); + row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_width); } } #endif @@ -4584,7 +4709,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, * whole row to 16 bits. Has no effect otherwise. */ static void -png_do_expand_16(png_row_infop row_info, png_bytep row) +png_do_expand_16(png_row_info *row_info, png_byte *row) { if (row_info->bit_depth == 8 && row_info->color_type != PNG_COLOR_TYPE_PALETTE) @@ -4601,7 +4726,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 *dp = sp + row_info->rowbytes; /* destination, end + 1 */ while (dp > sp) - dp[-2] = dp[-1] = *--sp, dp -= 2; + { + dp[-2] = dp[-1] = *--sp; dp -= 2; + } row_info->rowbytes *= 2; row_info->bit_depth = 16; @@ -4612,10 +4739,10 @@ png_do_expand_16(png_row_infop row_info, png_bytep row) #ifdef PNG_READ_QUANTIZE_SUPPORTED static void -png_do_quantize(png_row_infop row_info, png_bytep row, - png_const_bytep palette_lookup, png_const_bytep quantize_lookup) +png_do_quantize(png_row_info *row_info, png_byte *row, + const png_byte *palette_lookup, const png_byte *quantize_lookup) { - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width=row_info->width; @@ -4709,7 +4836,7 @@ png_do_quantize(png_row_infop row_info, png_bytep row, * decide how it fits in with the other transformations here. */ void /* PRIVATE */ -png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) +png_do_read_transformations(png_struct *png_ptr, png_row_info *row_info) { png_debug(1, "in png_do_read_transformations"); @@ -4743,6 +4870,13 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) { if (row_info->color_type == PNG_COLOR_TYPE_PALETTE) { +#ifdef PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE + /* Do not call 'png_do_expand_palette' if the SIMD implementation + * does it. (Note that this accommodates SIMD implementations which + * might only handle specific cases.) + */ + if (!png_target_do_expand_palette(png_ptr, row_info)) +#endif png_do_expand_palette(row_info, png_ptr->row_buf + 1, png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans); } @@ -4755,8 +4889,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) &(png_ptr->trans_color)); else - png_do_expand(row_info, png_ptr->row_buf + 1, - NULL); + png_do_expand(row_info, png_ptr->row_buf + 1, NULL); } } #endif @@ -4890,13 +5023,8 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) #ifdef PNG_READ_QUANTIZE_SUPPORTED if ((png_ptr->transformations & PNG_QUANTIZE) != 0) - { png_do_quantize(row_info, png_ptr->row_buf + 1, png_ptr->palette_lookup, png_ptr->quantize_index); - - if (row_info->rowbytes == 0) - png_error(png_ptr, "png_do_quantize returned rowbytes=0"); - } #endif /* READ_QUANTIZE */ #ifdef PNG_READ_EXPAND_16_SUPPORTED @@ -4980,7 +5108,7 @@ png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info) (png_ptr, /* png_ptr */ row_info, /* row_info: */ /* 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 bit_depth; bit depth of samples */ /* png_byte channels; number of channels (1-4) */ diff --git a/media/libpng/pngrutil.c b/media/libpng/pngrutil.c index 8537df45d2..6d937c85b4 100644 --- a/media/libpng/pngrutil.c +++ b/media/libpng/pngrutil.c @@ -1,10 +1,9 @@ - /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2025 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -18,54 +17,50 @@ #ifdef PNG_READ_SUPPORTED -png_uint_32 PNGAPI -png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf) -{ - png_uint_32 uval = png_get_uint_32(buf); - - if (uval > PNG_UINT_31_MAX) - png_error(png_ptr, "PNG unsigned integer out of range"); - - return (uval); -} - -#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED) -/* The following is a variation on the above for use with the fixed - * point values used for gAMA and cHRM. Instead of png_error it - * issues a warning and returns (-1) - an invalid value because both - * gAMA and cHRM use *unsigned* integers for fixed point values. +/* The minimum 'zlib' stream is assumed to be just the 2 byte header, 5 bytes + * minimum 'deflate' stream, and the 4 byte checksum. */ -#define PNG_FIXED_ERROR (-1) +#define LZ77Min (2U+5U+4U) + +#ifdef PNG_READ_INTERLACING_SUPPORTED +/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */ + +/* Start of interlace block */ +static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; +/* Offset to next interlace block */ +static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +/* Start of interlace block in the y direction */ +static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; +/* Offset to next interlace block in the y direction */ +static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + +/* TODO: Move these arrays to a common utility module to avoid duplication. */ +#endif -static png_fixed_point /* PRIVATE */ -png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf) +png_uint_32 +png_get_uint_31(const png_struct *png_ptr, const png_byte *buf) { png_uint_32 uval = png_get_uint_32(buf); - if (uval <= PNG_UINT_31_MAX) - return (png_fixed_point)uval; /* known to be in range */ - - /* The caller can turn off the warning by passing NULL. */ - if (png_ptr != NULL) - png_warning(png_ptr, "PNG fixed point integer out of range"); + if (uval > PNG_UINT_31_MAX) + png_error(png_ptr, "PNG unsigned integer out of range"); - return PNG_FIXED_ERROR; + return uval; } -#endif #ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED /* NOTE: the read macros will obscure these definitions, so that if * PNG_USE_READ_MACROS is set the library will not use them internally, * but the APIs will still be available externally. * - * The parentheses around "PNGAPI function_name" in the following three - * functions are necessary because they allow the macros to co-exist with - * these (unused but exported) functions. + * The parentheses around function names in the following three functions + * are necessary, because they allow the macros to co-exist with these + * (unused but exported) functions. */ /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */ -png_uint_32 (PNGAPI -png_get_uint_32)(png_const_bytep buf) +png_uint_32 +(png_get_uint_32)(const png_byte *buf) { png_uint_32 uval = ((png_uint_32)(*(buf )) << 24) + @@ -81,8 +76,8 @@ png_get_uint_32)(png_const_bytep buf) * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore * the following code does a two's complement to native conversion. */ -png_int_32 (PNGAPI -png_get_int_32)(png_const_bytep buf) +png_int_32 +(png_get_int_32)(const png_byte *buf) { png_uint_32 uval = png_get_uint_32(buf); if ((uval & 0x80000000) == 0) /* non-negative */ @@ -99,10 +94,10 @@ png_get_int_32)(png_const_bytep buf) } /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ -png_uint_16 (PNGAPI -png_get_uint_16)(png_const_bytep buf) +png_uint_16 +(png_get_uint_16)(const png_byte *buf) { - /* ANSI-C requires an int value to accomodate at least 16 bits so this + /* ANSI-C requires an int value to accommodate at least 16 bits so this * works and allows the compiler not to worry about possible narrowing * on 32-bit systems. (Pre-ANSI systems did not make integers smaller * than 16 bits either.) @@ -118,9 +113,9 @@ png_get_uint_16)(png_const_bytep buf) /* Read and check the PNG file signature */ void /* PRIVATE */ -png_read_sig(png_structrp png_ptr, png_inforp info_ptr) +png_read_sig(png_struct *png_ptr, png_info *info_ptr) { - png_size_t num_checked, num_to_check; + size_t num_checked, num_to_check; /* Exit if the user application does not expect a signature. */ if (png_ptr->sig_bytes >= 8) @@ -140,7 +135,7 @@ png_read_sig(png_structrp png_ptr, png_inforp info_ptr) if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0) { if (num_checked < 4 && - png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) + png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0) png_error(png_ptr, "Not a PNG file"); else png_error(png_ptr, "PNG file corrupted by ASCII conversion"); @@ -149,37 +144,75 @@ png_read_sig(png_structrp png_ptr, png_inforp info_ptr) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; } +/* This function is called to verify that a chunk name is valid. + * Do this using the bit-whacking approach from contrib/tools/pngfix.c + * + * Copied from libpng 1.7. + */ +static int +check_chunk_name(png_uint_32 name) +{ + png_uint_32 t; + + /* Remove bit 5 from all but the reserved byte; this means + * every 8-bit unit must be in the range 65-90 to be valid. + * So bit 5 must be zero, bit 6 must be set and bit 7 zero. + */ + name &= ~PNG_U32(32,32,0,32); + t = (name & ~0x1f1f1f1fU) ^ 0x40404040U; + + /* Subtract 65 for each 8-bit quantity, this must not + * overflow and each byte must then be in the range 0-25. + */ + name -= PNG_U32(65,65,65,65); + t |= name; + + /* Subtract 26, handling the overflow which should set the + * top three bits of each byte. + */ + name -= PNG_U32(25,25,25,26); + t |= ~name; + + return (t & 0xe0e0e0e0U) == 0U; +} + /* Read the chunk header (length + type name). * Put the type name into png_ptr->chunk_name, and return the length. */ png_uint_32 /* PRIVATE */ -png_read_chunk_header(png_structrp png_ptr) +png_read_chunk_header(png_struct *png_ptr) { png_byte buf[8]; - png_uint_32 length; + png_uint_32 chunk_name, length; #ifdef PNG_IO_STATE_SUPPORTED png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR; #endif - /* Read the length and the chunk name. - * This must be performed in a single I/O call. + /* Read the length and the chunk name. png_struct::chunk_name is immediately + * updated even if they are detectably wrong. This aids error message + * handling by allowing png_chunk_error to be used. */ png_read_data(png_ptr, buf, 8); length = png_get_uint_31(png_ptr, buf); - - /* Put the chunk name into png_ptr->chunk_name. */ - png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4); - - png_debug2(0, "Reading %lx chunk, length = %lu", - (unsigned long)png_ptr->chunk_name, (unsigned long)length); + png_ptr->chunk_name = chunk_name = PNG_CHUNK_FROM_STRING(buf+4); /* Reset the crc and run it over the chunk name. */ png_reset_crc(png_ptr); png_calculate_crc(png_ptr, buf + 4, 4); + png_debug2(0, "Reading chunk typeid = 0x%lx, length = %lu", + (unsigned long)png_ptr->chunk_name, (unsigned long)length); + + /* Sanity check the length (first by <= 0x80) and the chunk name. An error + * here indicates a broken stream and libpng has no recovery from this. + */ + if (buf[0] >= 0x80U) + png_chunk_error(png_ptr, "bad header (invalid length)"); + /* Check to see if chunk name is valid. */ - png_check_chunk_name(png_ptr, png_ptr->chunk_name); + if (!check_chunk_name(chunk_name)) + png_chunk_error(png_ptr, "bad header (invalid type)"); #ifdef PNG_IO_STATE_SUPPORTED png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA; @@ -190,7 +223,7 @@ png_read_chunk_header(png_structrp png_ptr) /* Read data, and (optionally) run it through the CRC. */ void /* PRIVATE */ -png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length) +png_crc_read(png_struct *png_ptr, png_byte *buf, png_uint_32 length) { if (png_ptr == NULL) return; @@ -199,13 +232,85 @@ png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length) png_calculate_crc(png_ptr, buf, length); } +/* Compare the CRC stored in the PNG file with that calculated by libpng from + * the data it has read thus far. + */ +static int +png_crc_error(png_struct *png_ptr, int handle_as_ancillary) +{ + png_byte crc_bytes[4]; + png_uint_32 crc; + int need_crc = 1; + + /* There are four flags two for ancillary and two for critical chunks. The + * default setting of these flags is all zero. + * + * PNG_FLAG_CRC_ANCILLARY_USE + * PNG_FLAG_CRC_ANCILLARY_NOWARN + * USE+NOWARN: no CRC calculation (implemented here), else; + * NOWARN: png_chunk_error on error (implemented in png_crc_finish) + * else: png_chunk_warning on error (implemented in png_crc_finish) + * This is the default. + * + * I.e. NOWARN without USE produces png_chunk_error. The default setting + * where neither are set does the same thing. + * + * PNG_FLAG_CRC_CRITICAL_USE + * PNG_FLAG_CRC_CRITICAL_IGNORE + * IGNORE: no CRC calculation (implemented here), else; + * USE: png_chunk_warning on error (implemented in png_crc_finish) + * else: png_chunk_error on error (implemented in png_crc_finish) + * This is the default. + * + * This arose because of original mis-implementation and has persisted for + * compatibility reasons. + * + * TODO: the flag names are internal so maybe this can be changed to + * something comprehensible. + */ + if (handle_as_ancillary || PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0) + { + if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == + (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) + need_crc = 0; + } + + else /* critical */ + { + if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0) + need_crc = 0; + } + +#ifdef PNG_IO_STATE_SUPPORTED + png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; +#endif + + /* The chunk CRC must be serialized in a single I/O call. */ + png_read_data(png_ptr, crc_bytes, 4); + + if (need_crc != 0) + { + crc = png_get_uint_32(crc_bytes); + return crc != png_ptr->crc; + } + + else + return 0; +} + /* Optionally skip data and then check the CRC. Depending on whether we * are reading an ancillary or critical chunk, and how the program has set * things up, we may calculate the CRC on the data and print a message. * Returns '1' if there was a CRC error, '0' otherwise. + * + * There is one public version which is used in most places and another which + * takes the value for the 'critical' flag to check. This allows PLTE and IEND + * handling code to ignore the CRC error and removes some confusing code + * duplication. */ -int /* PRIVATE */ -png_crc_finish(png_structrp png_ptr, png_uint_32 skip) +static int +png_crc_finish_critical(png_struct *png_ptr, png_uint_32 skip, + int handle_as_ancillary) { /* The size of the local buffer for inflate is a good guess as to a * reasonable size to use for buffering reads from the application. @@ -223,82 +328,59 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip) png_crc_read(png_ptr, tmpbuf, len); } - if (png_crc_error(png_ptr) != 0) + /* If 'handle_as_ancillary' has been requested and this is a critical chunk + * but PNG_FLAG_CRC_CRITICAL_IGNORE was set then png_read_crc did not, in + * fact, calculate the CRC so the ANCILLARY settings should not be used + * instead. + */ + if (handle_as_ancillary && + (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0) + handle_as_ancillary = 0; + + /* TODO: this might be more comprehensible if png_crc_error was inlined here. + */ + if (png_crc_error(png_ptr, handle_as_ancillary) != 0) { - if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0 ? + /* See above for the explanation of how the flags work. */ + if (handle_as_ancillary || PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0 ? (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0 : (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE) != 0) - { png_chunk_warning(png_ptr, "CRC error"); - } else png_chunk_error(png_ptr, "CRC error"); - return (1); + return 1; } - return (0); + return 0; } -/* Compare the CRC stored in the PNG file with that calculated by libpng from - * the data it has read thus far. - */ int /* PRIVATE */ -png_crc_error(png_structrp png_ptr) +png_crc_finish(png_struct *png_ptr, png_uint_32 skip) { - png_byte crc_bytes[4]; - png_uint_32 crc; - int need_crc = 1; - - if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0) - { - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == - (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) - need_crc = 0; - } - - else /* critical */ - { - if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0) - need_crc = 0; - } - -#ifdef PNG_IO_STATE_SUPPORTED - png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC; -#endif - - /* The chunk CRC must be serialized in a single I/O call. */ - png_read_data(png_ptr, crc_bytes, 4); - - if (need_crc != 0) - { - crc = png_get_uint_32(crc_bytes); - return ((int)(crc != png_ptr->crc)); - } - - else - return (0); + return png_crc_finish_critical(png_ptr, skip, 0/*critical handling*/); } #if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\ defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_sCAL_SUPPORTED) ||\ defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) ||\ - defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_SEQUENTIAL_READ_SUPPORTED) + defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_eXIf_SUPPORTED) ||\ + defined(PNG_SEQUENTIAL_READ_SUPPORTED) /* Manage the read buffer; this simply reallocates the buffer if it is not small * enough (or if it is not allocated). The routine returns a pointer to the * buffer; if an error occurs and 'warn' is set the routine returns NULL, else - * it will call png_error (via png_malloc) on failure. (warn == 2 means - * 'silent'). + * it will call png_error on failure. */ -static png_bytep -png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) +static png_byte * +png_read_buffer(png_struct *png_ptr, png_alloc_size_t new_size) { - png_bytep buffer = png_ptr->read_buffer; + png_byte *buffer = png_ptr->read_buffer; + + if (new_size > png_chunk_max(png_ptr)) return NULL; if (buffer != NULL && new_size > png_ptr->read_buffer_size) { - png_ptr->read_buffer = NULL; png_ptr->read_buffer = NULL; png_ptr->read_buffer_size = 0; png_free(png_ptr, buffer); @@ -307,27 +389,21 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) if (buffer == NULL) { - buffer = png_voidcast(png_bytep, png_malloc_base(png_ptr, new_size)); + buffer = png_voidcast(png_byte *, png_malloc_base(png_ptr, new_size)); if (buffer != NULL) { +# ifndef PNG_NO_MEMZERO /* for detecting UIM bugs **only** */ + memset(buffer, 0, new_size); /* just in case */ +# endif png_ptr->read_buffer = buffer; png_ptr->read_buffer_size = new_size; } - - else if (warn < 2) /* else silent */ - { - if (warn != 0) - png_chunk_warning(png_ptr, "insufficient memory to read chunk"); - - else - png_chunk_error(png_ptr, "insufficient memory to read chunk"); - } } return buffer; } -#endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|SEQUENTIAL_READ */ +#endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|eXIf|SEQUENTIAL_READ */ /* png_inflate_claim: claim the zstream for some nefarious purpose that involves * decompression. Returns Z_OK on success, else a zlib error code. It checks @@ -335,7 +411,7 @@ png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn) * chunk apparently owns the stream. Prior to release it does a png_error. */ static int -png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) +png_inflate_claim(png_struct *png_ptr, png_uint_32 owner) { if (png_ptr->zowner != 0) { @@ -360,20 +436,14 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) * be gained by using this when it is known *if* the zlib stream itself does * not record the number; however, this is an illusion: the original writer * of the PNG may have selected a lower window size, and we really must - * follow that because, for systems with with limited capabilities, we + * follow that because, for systems with limited capabilities, we * would otherwise reject the application's attempts to use a smaller window * size (zlib doesn't have an interface to say "this or lower"!). - * - * inflateReset2 was added to zlib 1.2.4; before this the window could not be - * reset, therefore it is necessary to always allocate the maximum window - * size with earlier zlibs just in case later compressed chunks need it. */ { int ret; /* zlib return code */ -#if ZLIB_VERNUM >= 0x1240 int window_bits = 0; -# if defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_MAXIMUM_INFLATE_WINDOW) if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) == PNG_OPTION_ON) { @@ -385,9 +455,6 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) { png_ptr->zstream_start = 1; } -# endif - -#endif /* ZLIB_VERNUM >= 0x1240 */ /* Set this for safety, just in case the previous owner left pointers to * memory allocations. @@ -399,28 +466,20 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0) { -#if ZLIB_VERNUM >= 0x1240 ret = inflateReset2(&png_ptr->zstream, window_bits); -#else - ret = inflateReset(&png_ptr->zstream); -#endif } else { -#if ZLIB_VERNUM >= 0x1240 ret = inflateInit2(&png_ptr->zstream, window_bits); -#else - ret = inflateInit(&png_ptr->zstream); -#endif if (ret == Z_OK) png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; } -#if ZLIB_VERNUM >= 0x1281 - /* Turn off validation of the ADLER32 checksum */ - if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0) +#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED + if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON) + /* Turn off validation of the ADLER32 checksum in IDAT chunks */ ret = inflateValidate(&png_ptr->zstream, 0); #endif @@ -438,7 +497,6 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) #endif } -#if ZLIB_VERNUM >= 0x1240 /* Handle the start of the inflate stream if we called inflateInit2(strm,0); * in this case some zlib versions skip validation of the CINFO field and, in * certain circumstances, libpng may end up displaying an invalid image, in @@ -446,7 +504,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) * 1.5). */ int /* PRIVATE */ -png_zlib_inflate(png_structrp png_ptr, int flush) +png_zlib_inflate(png_struct *png_ptr, int flush) { if (png_ptr->zstream_start && png_ptr->zstream.avail_in > 0) { @@ -461,7 +519,6 @@ png_zlib_inflate(png_structrp png_ptr, int flush) return inflate(&png_ptr->zstream, flush); } -#endif /* Zlib >= 1.2.4 */ #ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED #if defined(PNG_READ_zTXt_SUPPORTED) || defined (PNG_READ_iTXt_SUPPORTED) @@ -477,9 +534,9 @@ png_zlib_inflate(png_structrp png_ptr, int flush) * available output is (output+output_size). */ static int -png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, - /* INPUT: */ png_const_bytep input, png_uint_32p input_size_ptr, - /* OUTPUT: */ png_bytep output, png_alloc_size_t *output_size_ptr) +png_inflate(png_struct *png_ptr, png_uint_32 owner, int finish, + /* INPUT: */ const png_byte *input, png_uint_32 *input_size_ptr, + /* OUTPUT: */ png_byte *output, png_alloc_size_t *output_size_ptr) { if (png_ptr->zowner == owner) /* Else not claimed */ { @@ -496,7 +553,7 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, * a performance advantage, because it reduces the amount of data accessed * at each step and that may give the OS more time to page it in. */ - png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); + png_ptr->zstream.next_in = input; /* avail_in and avail_out are set below from 'size' */ png_ptr->zstream.avail_in = 0; png_ptr->zstream.avail_out = 0; @@ -557,7 +614,7 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, * the previous chunk of input data. Tell zlib if we have reached the * end of the output buffer. */ - ret = PNG_INFLATE(png_ptr, avail_out > 0 ? Z_NO_FLUSH : + ret = png_zlib_inflate(png_ptr, avail_out > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); } while (ret == Z_OK); @@ -589,7 +646,7 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, * pointer, which is not owned by the caller, but this is safe; it's only * used on errors! */ - png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed"); + png_ptr->zstream.msg = "zstream unclaimed"; return Z_STREAM_ERROR; } } @@ -602,7 +659,7 @@ png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish, * trailing part (the malloc area passed in is freed). */ static int -png_decompress_chunk(png_structrp png_ptr, +png_decompress_chunk(png_struct *png_ptr, png_uint_32 chunklength, png_uint_32 prefix_size, png_alloc_size_t *newlength /* must be initialized to the maximum! */, int terminate /*add a '\0' to the end of the uncompressed data*/) @@ -614,16 +671,7 @@ png_decompress_chunk(png_structrp png_ptr, * maybe a '\0' terminator too. We have to assume that 'prefix_size' is * limited only by the maximum chunk size. */ - png_alloc_size_t limit = PNG_SIZE_MAX; - -# ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (png_ptr->user_chunk_malloc_max > 0 && - png_ptr->user_chunk_malloc_max < limit) - limit = png_ptr->user_chunk_malloc_max; -# elif PNG_USER_CHUNK_MALLOC_MAX > 0 - if (PNG_USER_CHUNK_MALLOC_MAX < limit) - limit = PNG_USER_CHUNK_MALLOC_MAX; -# endif + png_alloc_size_t limit = png_chunk_max(png_ptr); if (limit >= prefix_size + (terminate != 0)) { @@ -664,11 +712,13 @@ png_decompress_chunk(png_structrp png_ptr, png_alloc_size_t new_size = *newlength; png_alloc_size_t buffer_size = prefix_size + new_size + (terminate != 0); - png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr, - buffer_size)); + png_byte *text = png_voidcast(png_byte *, + png_malloc_base(png_ptr, buffer_size)); if (text != NULL) { + memset(text, 0, buffer_size); + ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/, png_ptr->read_buffer + prefix_size, &lzsize, text + prefix_size, newlength); @@ -684,7 +734,7 @@ png_decompress_chunk(png_structrp png_ptr, memcpy(text, png_ptr->read_buffer, prefix_size); { - png_bytep old_ptr = png_ptr->read_buffer; + png_byte *old_ptr = png_ptr->read_buffer; png_ptr->read_buffer = text; png_ptr->read_buffer_size = buffer_size; @@ -716,7 +766,7 @@ png_decompress_chunk(png_structrp png_ptr, * the extra space may otherwise be used as a Trojan Horse. */ if (ret == Z_STREAM_END && - chunklength - prefix_size != lzsize) + chunklength - prefix_size != lzsize) png_chunk_benign_error(png_ptr, "extra compressed data"); } @@ -732,9 +782,7 @@ png_decompress_chunk(png_structrp png_ptr, { /* inflateReset failed, store the error message */ png_zstream_error(png_ptr, ret); - - if (ret == Z_STREAM_END) - ret = PNG_UNEXPECTED_ZLIB_RETURN; + ret = PNG_UNEXPECTED_ZLIB_RETURN; } } @@ -766,8 +814,8 @@ png_decompress_chunk(png_structrp png_ptr, * reading from the current chunk as required. */ static int -png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, - png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size, +png_inflate_read(png_struct *png_ptr, png_byte *read_buffer, uInt read_size, + png_uint_32 *chunk_bytes, png_byte *next_out, png_alloc_size_t *out_size, int finish) { if (png_ptr->zowner == png_ptr->chunk_name) @@ -807,7 +855,7 @@ png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, * the available output is produced; this allows reading of truncated * streams. */ - ret = PNG_INFLATE(png_ptr, *chunk_bytes > 0 ? + ret = png_zlib_inflate(png_ptr, *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH)); } while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0)); @@ -822,16 +870,16 @@ png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size, else { - png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed"); + png_ptr->zstream.msg = "zstream unclaimed"; return Z_STREAM_ERROR; } } -#endif +#endif /* READ_iCCP */ +/* CHUNK HANDLING */ /* Read and check the IDHR chunk */ - -void /* PRIVATE */ -png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code +png_handle_IHDR(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { png_byte buf[13]; png_uint_32 width, height; @@ -840,12 +888,7 @@ png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_debug(1, "in png_handle_IHDR"); - if ((png_ptr->mode & PNG_HAVE_IHDR) != 0) - png_chunk_error(png_ptr, "out of place"); - - /* Check the length */ - if (length != 13) - png_chunk_error(png_ptr, "invalid"); + /* Length and position are checked by the caller. */ png_ptr->mode |= PNG_HAVE_IHDR; @@ -904,258 +947,184 @@ png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_debug1(3, "bit_depth = %d", png_ptr->bit_depth); png_debug1(3, "channels = %d", png_ptr->channels); png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes); + + /* Rely on png_set_IHDR to completely validate the data and call png_error if + * it's wrong. + */ png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth, color_type, interlace_type, compression_type, filter_type); + + return handled_ok; + PNG_UNUSED(length) } /* Read and check the palette */ -void /* PRIVATE */ -png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +/* TODO: there are several obvious errors in this code when handling + * out-of-place chunks and there is much over-complexity caused by trying to + * patch up the problems. + */ +static png_handle_result_code +png_handle_PLTE(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { - png_color palette[PNG_MAX_PALETTE_LENGTH]; - int max_palette_length, num, i; -#ifdef PNG_POINTER_INDEXING_SUPPORTED - png_colorp pal_ptr; -#endif + const char *errmsg = NULL; png_debug(1, "in png_handle_PLTE"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - /* Moved to before the 'after IDAT' check below because otherwise duplicate - * PLTE chunks are potentially ignored (the spec says there shall not be more - * than one PLTE, the error is not treated as benign, so this check trumps - * the requirement that PLTE appears before IDAT.) + /* 1.6.47: consistency. This used to be especially treated as a critical + * error even in an image which is not colour mapped, there isn't a good + * justification for treating some errors here one way and others another so + * everything uses the same logic. */ - else if ((png_ptr->mode & PNG_HAVE_PLTE) != 0) - png_chunk_error(png_ptr, "duplicate"); + if ((png_ptr->mode & PNG_HAVE_PLTE) != 0) + errmsg = "duplicate"; else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - { - /* This is benign because the non-benign error happened before, when an - * IDAT was encountered in a color-mapped image with no PLTE. - */ - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } + errmsg = "out of place"; - png_ptr->mode |= PNG_HAVE_PLTE; + else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) + errmsg = "ignored in grayscale PNG"; - if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "ignored in grayscale PNG"); - return; - } + else if (length > 3*PNG_MAX_PALETTE_LENGTH || (length % 3) != 0) + errmsg = "invalid"; -#ifndef PNG_READ_OPT_PLTE_SUPPORTED - if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - { - png_crc_finish(png_ptr, length); - return; - } -#endif + /* This drops PLTE in favour of tRNS or bKGD because both of those chunks + * can have an effect on the rendering of the image whereas PLTE only matters + * in the case of an 8-bit display with a decoder which controls the palette. + * + * The alternative here is to ignore the error and store the palette anyway; + * destroying the tRNS will definitely cause problems. + * + * NOTE: the case of PNG_COLOR_TYPE_PALETTE need not be considered because + * the png_handle_ routines for the three 'after PLTE' chunks tRNS, bKGD and + * hIST all check for a preceding PLTE in these cases. + */ + else if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE && + (png_has_chunk(png_ptr, tRNS) || png_has_chunk(png_ptr, bKGD))) + errmsg = "out of place"; - if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3) + else { - png_crc_finish(png_ptr, length); - - if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE) - png_chunk_benign_error(png_ptr, "invalid"); - - else - png_chunk_error(png_ptr, "invalid"); - - return; - } + /* If the palette has 256 or fewer entries but is too large for the bit + * depth we don't issue an error to preserve the behavior of previous + * libpng versions. We silently truncate the unused extra palette entries + * here. + */ + const unsigned max_palette_length = + (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? + 1U << png_ptr->bit_depth : PNG_MAX_PALETTE_LENGTH; - /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */ - num = (int)length / 3; + /* The cast is safe because 'length' is less than + * 3*PNG_MAX_PALETTE_LENGTH + */ + const unsigned num = (length > 3U*max_palette_length) ? + max_palette_length : (unsigned)length / 3U; - /* If the palette has 256 or fewer entries but is too large for the bit - * depth, we don't issue an error, to preserve the behavior of previous - * libpng versions. We silently truncate the unused extra palette entries - * here. - */ - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - max_palette_length = (1 << png_ptr->bit_depth); - else - max_palette_length = PNG_MAX_PALETTE_LENGTH; + unsigned i, j; + png_byte buf[3*PNG_MAX_PALETTE_LENGTH]; + png_color palette[PNG_MAX_PALETTE_LENGTH]; - if (num > max_palette_length) - num = max_palette_length; + /* Read the chunk into the buffer then read to the end of the chunk. */ + png_crc_read(png_ptr, buf, num*3U); + png_crc_finish_critical(png_ptr, length - 3U*num, + /* Handle as ancillary if PLTE is optional: */ + png_ptr->color_type != PNG_COLOR_TYPE_PALETTE); -#ifdef PNG_POINTER_INDEXING_SUPPORTED - for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) - { - png_byte buf[3]; + for (i = 0U, j = 0U; i < num; i++) + { + palette[i].red = buf[j++]; + palette[i].green = buf[j++]; + palette[i].blue = buf[j++]; + } - png_crc_read(png_ptr, buf, 3); - pal_ptr->red = buf[0]; - pal_ptr->green = buf[1]; - pal_ptr->blue = buf[2]; - } -#else - for (i = 0; i < num; i++) - { - png_byte buf[3]; + /* A valid PLTE chunk has been read */ + png_ptr->mode |= PNG_HAVE_PLTE; - png_crc_read(png_ptr, buf, 3); - /* Don't depend upon png_color being any order */ - palette[i].red = buf[0]; - palette[i].green = buf[1]; - palette[i].blue = buf[2]; + png_set_PLTE(png_ptr, info_ptr, palette, num); + return handled_ok; } -#endif - /* If we actually need the PLTE chunk (ie for a paletted image), we do - * whatever the normal CRC configuration tells us. However, if we - * have an RGB image, the PLTE can be considered ancillary, so - * we will act as though it is. - */ -#ifndef PNG_READ_OPT_PLTE_SUPPORTED + /* Here on error: errmsg is non NULL. */ if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) -#endif { - png_crc_finish(png_ptr, (png_uint_32) (length - (unsigned int)num * 3)); + png_crc_finish(png_ptr, length); + png_chunk_error(png_ptr, errmsg); } -#ifndef PNG_READ_OPT_PLTE_SUPPORTED - else if (png_crc_error(png_ptr) != 0) /* Only if we have a CRC error */ + else /* not critical to this image */ { - /* If we don't want to use the data from an ancillary chunk, - * we have two options: an error abort, or a warning and we - * ignore the data in this chunk (which should be OK, since - * it's considered ancillary for a RGB or RGBA image). - * - * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the - * chunk type to determine whether to check the ancillary or the critical - * flags. - */ - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE) == 0) - { - if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) != 0) - return; - - else - png_chunk_error(png_ptr, "CRC error"); - } - - /* Otherwise, we (optionally) emit a warning and use the chunk. */ - else if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0) - png_chunk_warning(png_ptr, "CRC error"); + png_crc_finish_critical(png_ptr, length, 1/*handle as ancillary*/); + png_chunk_benign_error(png_ptr, errmsg); } -#endif - /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its - * own copy of the palette. This has the side effect that when png_start_row - * is called (this happens after any call to png_read_update_info) the - * info_ptr palette gets changed. This is extremely unexpected and - * confusing. - * - * Fix this by not sharing the palette in this way. - */ - png_set_PLTE(png_ptr, info_ptr, palette, num); - - /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before - * IDAT. Prior to 1.6.0 this was not checked; instead the code merely - * checked the apparent validity of a tRNS chunk inserted before PLTE on a - * palette PNG. 1.6.0 attempts to rigorously follow the standard and - * therefore does a benign error if the erroneous condition is detected *and* - * cancels the tRNS if the benign error returns. The alternative is to - * amend the standard since it would be rather hypocritical of the standards - * maintainers to ignore it. + /* Because PNG_UNUSED(errmsg) does not work if all the uses are compiled out + * (this does happen). */ -#ifdef PNG_READ_tRNS_SUPPORTED - if (png_ptr->num_trans > 0 || - (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0)) - { - /* Cancel this because otherwise it would be used if the transforms - * require it. Don't cancel the 'valid' flag because this would prevent - * detection of duplicate chunks. - */ - png_ptr->num_trans = 0; - - if (info_ptr != NULL) - info_ptr->num_trans = 0; - - png_chunk_benign_error(png_ptr, "tRNS must be after"); - } -#endif - -#ifdef PNG_READ_hIST_SUPPORTED - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0) - png_chunk_benign_error(png_ptr, "hIST must be after"); -#endif - -#ifdef PNG_READ_bKGD_SUPPORTED - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0) - png_chunk_benign_error(png_ptr, "bKGD must be after"); -#endif + return errmsg != NULL ? handled_error : handled_error; } -void /* PRIVATE */ -png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +/* On read the IDAT chunk is always handled specially, even if marked for + * unknown handling (this is allowed), so: + */ +#define png_handle_IDAT NULL + +static png_handle_result_code +png_handle_IEND(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { png_debug(1, "in png_handle_IEND"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0 || - (png_ptr->mode & PNG_HAVE_IDAT) == 0) - png_chunk_error(png_ptr, "out of place"); - png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND); - png_crc_finish(png_ptr, length); - if (length != 0) png_chunk_benign_error(png_ptr, "invalid"); + png_crc_finish_critical(png_ptr, length, 1/*handle as ancillary*/); + + return handled_ok; PNG_UNUSED(info_ptr) } #ifdef PNG_READ_gAMA_SUPPORTED -void /* PRIVATE */ -png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code +png_handle_gAMA(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { - png_fixed_point igamma; + png_uint_32 ugamma; png_byte buf[4]; png_debug(1, "in png_handle_gAMA"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); + png_crc_read(png_ptr, buf, 4); - else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } + if (png_crc_finish(png_ptr, 0) != 0) + return handled_error; - if (length != 4) + ugamma = png_get_uint_32(buf); + + if (ugamma > PNG_UINT_31_MAX) { - png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "invalid"); - return; + return handled_error; } - png_crc_read(png_ptr, buf, 4); - - if (png_crc_finish(png_ptr, 0) != 0) - return; + png_set_gAMA_fixed(png_ptr, info_ptr, (png_fixed_point)/*SAFE*/ugamma); - igamma = png_get_fixed_point(NULL, buf); +#ifdef PNG_READ_GAMMA_SUPPORTED + /* PNGv3: chunk precedence for gamma is cICP, [iCCP], sRGB, gAMA. gAMA is + * at the end of the chain so simply check for an unset value. + */ + if (png_ptr->chunk_gamma == 0) + png_ptr->chunk_gamma = (png_fixed_point)/*SAFE*/ugamma; +#endif /*READ_GAMMA*/ - png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma); - png_colorspace_sync(png_ptr, info_ptr); + return handled_ok; + PNG_UNUSED(length) } +#else +# define png_handle_gAMA NULL #endif #ifdef PNG_READ_sBIT_SUPPORTED -void /* PRIVATE */ -png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_sBIT(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { unsigned int truelen, i; png_byte sample_depth; @@ -1163,54 +1132,37 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_debug(1, "in png_handle_sBIT"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; + truelen = 3; + sample_depth = 8; } - if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) - { - truelen = 3; - sample_depth = 8; - } - - else + else { truelen = png_ptr->channels; sample_depth = png_ptr->bit_depth; } - if (length != truelen || length > 4) + if (length != truelen) { - png_chunk_benign_error(png_ptr, "invalid"); png_crc_finish(png_ptr, length); - return; + png_chunk_benign_error(png_ptr, "bad length"); + return handled_error; } buf[0] = buf[1] = buf[2] = buf[3] = sample_depth; png_crc_read(png_ptr, buf, truelen); if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; for (i=0; i sample_depth) { png_chunk_benign_error(png_ptr, "invalid"); - return; + return handled_error; } } @@ -1222,7 +1174,7 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_ptr->sig_bit.alpha = buf[3]; } - else + else /* grayscale */ { png_ptr->sig_bit.gray = buf[0]; png_ptr->sig_bit.red = buf[0]; @@ -1232,177 +1184,144 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit)); + return handled_ok; } +#else +# define png_handle_sBIT NULL #endif #ifdef PNG_READ_cHRM_SUPPORTED -void /* PRIVATE */ -png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_int_32 +png_get_int_32_checked(const png_byte *buf, int *error) { - png_byte buf[32]; - png_xy xy; + png_uint_32 uval = png_get_uint_32(buf); + if ((uval & 0x80000000) == 0) /* non-negative */ + return (png_int_32)uval; - png_debug(1, "in png_handle_cHRM"); + uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */ + if ((uval & 0x80000000) == 0) /* no overflow */ + return -(png_int_32)uval; - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); + /* This version of png_get_int_32 has a way of returning the error to the + * caller, so: + */ + *error = 1; + return 0; /* Safe */ +} - else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } +static png_handle_result_code /* PRIVATE */ +png_handle_cHRM(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) +{ + int error = 0; + png_xy xy; + png_byte buf[32]; - if (length != 32) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } + png_debug(1, "in png_handle_cHRM"); png_crc_read(png_ptr, buf, 32); if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; + + xy.whitex = png_get_int_32_checked(buf + 0, &error); + xy.whitey = png_get_int_32_checked(buf + 4, &error); + xy.redx = png_get_int_32_checked(buf + 8, &error); + xy.redy = png_get_int_32_checked(buf + 12, &error); + xy.greenx = png_get_int_32_checked(buf + 16, &error); + xy.greeny = png_get_int_32_checked(buf + 20, &error); + xy.bluex = png_get_int_32_checked(buf + 24, &error); + xy.bluey = png_get_int_32_checked(buf + 28, &error); - xy.whitex = png_get_fixed_point(NULL, buf); - xy.whitey = png_get_fixed_point(NULL, buf + 4); - xy.redx = png_get_fixed_point(NULL, buf + 8); - xy.redy = png_get_fixed_point(NULL, buf + 12); - xy.greenx = png_get_fixed_point(NULL, buf + 16); - xy.greeny = png_get_fixed_point(NULL, buf + 20); - xy.bluex = png_get_fixed_point(NULL, buf + 24); - xy.bluey = png_get_fixed_point(NULL, buf + 28); - - if (xy.whitex == PNG_FIXED_ERROR || - xy.whitey == PNG_FIXED_ERROR || - xy.redx == PNG_FIXED_ERROR || - xy.redy == PNG_FIXED_ERROR || - xy.greenx == PNG_FIXED_ERROR || - xy.greeny == PNG_FIXED_ERROR || - xy.bluex == PNG_FIXED_ERROR || - xy.bluey == PNG_FIXED_ERROR) + if (error) { - png_chunk_benign_error(png_ptr, "invalid values"); - return; + png_chunk_benign_error(png_ptr, "invalid"); + return handled_error; } - /* If a colorspace error has already been output skip this chunk */ - if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0) - return; + /* png_set_cHRM may complain about some of the values but this doesn't matter + * because it was a cHRM and it did have vaguely (if, perhaps, ridiculous) + * values. Ridiculosity will be checked if the values are used later. + */ + png_set_cHRM_fixed(png_ptr, info_ptr, xy.whitex, xy.whitey, xy.redx, xy.redy, + xy.greenx, xy.greeny, xy.bluex, xy.bluey); - if ((png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0) - { - png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; - png_colorspace_sync(png_ptr, info_ptr); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } + /* We only use 'chromaticities' for RGB to gray */ +# ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + /* There is no need to check sRGB here, cICP is NYI and iCCP is not + * supported so just check mDCV. + */ + if (!png_has_chunk(png_ptr, mDCV)) + { + png_ptr->chromaticities = xy; + } +# endif /* READ_RGB_TO_GRAY */ - png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; - (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy, - 1/*prefer cHRM values*/); - png_colorspace_sync(png_ptr, info_ptr); + return handled_ok; + PNG_UNUSED(length) } +#else +# define png_handle_cHRM NULL #endif #ifdef PNG_READ_sRGB_SUPPORTED -void /* PRIVATE */ -png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_sRGB(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { png_byte intent; png_debug(1, "in png_handle_sRGB"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - if (length != 1) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - png_crc_read(png_ptr, &intent, 1); if (png_crc_finish(png_ptr, 0) != 0) - return; - - /* If a colorspace error has already been output skip this chunk */ - if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0) - return; + return handled_error; - /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect - * this. + /* This checks the range of the "rendering intent" because it is specified in + * the PNG spec itself; the "reserved" values will result in the chunk not + * being accepted, just as they do with the various "reserved" values in + * IHDR. */ - if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) != 0) + if (intent > 3/*PNGv3 spec*/) { - png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; - png_colorspace_sync(png_ptr, info_ptr); - png_chunk_benign_error(png_ptr, "too many profiles"); - return; + png_chunk_benign_error(png_ptr, "invalid"); + return handled_error; } - (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent); - png_colorspace_sync(png_ptr, info_ptr); + png_set_sRGB(png_ptr, info_ptr, intent); + /* NOTE: png_struct::chromaticities is not set here because the RGB to gray + * coefficients are known without a need for the chromaticities. + */ + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* PNGv3: chunk precedence for gamma is cICP, [iCCP], sRGB, gAMA. iCCP is + * not supported by libpng so the only requirement is to check for cICP + * setting the gamma (this is NYI, but this check is safe.) + */ + if (!png_has_chunk(png_ptr, cICP) || png_ptr->chunk_gamma == 0) + png_ptr->chunk_gamma = PNG_GAMMA_sRGB_INVERSE; +#endif /*READ_GAMMA*/ + + return handled_ok; + PNG_UNUSED(length) } +#else +# define png_handle_sRGB NULL #endif /* READ_sRGB */ #ifdef PNG_READ_iCCP_SUPPORTED -void /* PRIVATE */ -png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_iCCP(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) /* Note: this does not properly handle profiles that are > 64K under DOS */ { - png_const_charp errmsg = NULL; /* error message output, or no error */ + const char *errmsg = NULL; /* error message output, or no error */ int finished = 0; /* crc checked */ png_debug(1, "in png_handle_iCCP"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - /* Consistent with all the above colorspace handling an obviously *invalid* - * chunk is just ignored, so does not invalidate the color space. An - * alternative is to set the 'invalid' flags at the start of this routine - * and only clear them in they were not set before and all the tests pass. - * The minimum 'deflate' stream is assumed to be just the 2 byte header and - * 4 byte checksum. The keyword must be at least one character and there is - * a terminator (0) byte and the compression method. + /* PNGv3: allow PNG files with both sRGB and iCCP because the PNG spec only + * ever said that there "should" be only one, not "shall" and the PNGv3 + * colour chunk precedence rules give a handling for this case anyway. */ - if (length < 9) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "too short"); - return; - } - - /* If a colorspace error has already been output skip this chunk */ - if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0) - { - png_crc_finish(png_ptr, length); - return; - } - - /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect - * this. - */ - if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0) { uInt read_length, keyword_length; char keyword[81]; @@ -1412,11 +1331,18 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) */ read_length = 81; /* maximum */ if (read_length > length) - read_length = (uInt)length; + read_length = (uInt)/*SAFE*/length; - png_crc_read(png_ptr, (png_bytep)keyword, read_length); + png_crc_read(png_ptr, (png_byte *)keyword, read_length); length -= read_length; + if (length < LZ77Min) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "too short"); + return handled_error; + } + keyword_length = 0; while (keyword_length < 80 && keyword_length < read_length && keyword[keyword_length] != 0) @@ -1435,7 +1361,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK) { - Byte profile_header[132]; + Byte profile_header[132]={0}; Byte local_buffer[PNG_INFLATE_BUF_SIZE]; png_alloc_size_t size = (sizeof profile_header); @@ -1449,28 +1375,26 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { /* We have the ICC profile header; do the basic header checks. */ - const png_uint_32 profile_length = - png_get_uint_32(profile_header); + png_uint_32 profile_length = png_get_uint_32(profile_header); - if (png_icc_check_length(png_ptr, &png_ptr->colorspace, - keyword, profile_length) != 0) + if (png_icc_check_length(png_ptr, keyword, profile_length) != + 0) { /* The length is apparently ok, so we can check the 132 * byte header. */ - if (png_icc_check_header(png_ptr, &png_ptr->colorspace, - keyword, profile_length, profile_header, - png_ptr->color_type) != 0) + if (png_icc_check_header(png_ptr, keyword, profile_length, + profile_header, png_ptr->color_type) != 0) { /* Now read the tag table; a variable size buffer is * needed at this point, allocate one for the whole * profile. The header check has already validated - * that none of these stuff will overflow. + * that none of this stuff will overflow. */ - const png_uint_32 tag_count = png_get_uint_32( - profile_header+128); - png_bytep profile = png_read_buffer(png_ptr, - profile_length, 2/*silent*/); + png_uint_32 tag_count = + png_get_uint_32(profile_header + 128); + png_byte *profile = png_read_buffer(png_ptr, + profile_length); if (profile != NULL) { @@ -1489,8 +1413,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (size == 0) { if (png_icc_check_tag_table(png_ptr, - &png_ptr->colorspace, keyword, profile_length, - profile) != 0) + keyword, profile_length, profile) != 0) { /* The profile has been validated for basic * security issues, so read the whole thing in. @@ -1522,13 +1445,6 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_crc_finish(png_ptr, length); finished = 1; -# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0 - /* Check for a match against sRGB */ - png_icc_set_sRGB(png_ptr, - &png_ptr->colorspace, profile, - png_ptr->zstream.adler); -# endif - /* Steal the profile for info_ptr. */ if (info_ptr != NULL) { @@ -1551,11 +1467,7 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } else - { - png_ptr->colorspace.flags |= - PNG_COLORSPACE_INVALID; errmsg = "out of memory"; - } } /* else the profile remains in the read @@ -1563,28 +1475,17 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) * chunks. */ - if (info_ptr != NULL) - png_colorspace_sync(png_ptr, info_ptr); - if (errmsg == NULL) { png_ptr->zowner = 0; - return; + return handled_ok; } } - - else if (size > 0) - errmsg = "truncated"; - -#ifndef __COVERITY__ - else + if (errmsg == NULL) errmsg = png_ptr->zstream.msg; -#endif } - /* else png_icc_check_tag_table output an error */ } - else /* profile truncated */ errmsg = png_ptr->zstream.msg; } @@ -1618,33 +1519,33 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) errmsg = "bad keyword"; } - else - errmsg = "too many profiles"; - /* Failure: the reason is in 'errmsg' */ if (finished == 0) png_crc_finish(png_ptr, length); - png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID; - png_colorspace_sync(png_ptr, info_ptr); if (errmsg != NULL) /* else already output */ png_chunk_benign_error(png_ptr, errmsg); + + return handled_error; } +#else +# define png_handle_iCCP NULL #endif /* READ_iCCP */ #ifdef PNG_READ_sPLT_SUPPORTED -void /* PRIVATE */ -png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_sPLT(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) /* Note: this does not properly handle chunks that are > 64K under DOS */ { - png_bytep entry_start, buffer; + png_byte *buffer; + png_byte *entry_start; png_sPLT_t new_palette; - png_sPLT_entryp pp; + png_sPLT_entry *pp; png_uint_32 data_length; int entry_size, i; png_uint_32 skip = 0; png_uint_32 dl; - png_size_t max_dl; + size_t max_dl; png_debug(1, "in png_handle_sPLT"); @@ -1654,43 +1555,24 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); - return; + return handled_error; } if (--png_ptr->user_chunk_cache_max == 1) { png_warning(png_ptr, "No space in chunk cache for sPLT"); png_crc_finish(png_ptr, length); - return; + return handled_error; } } #endif - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - -#ifdef PNG_MAX_MALLOC_64K - if (length > 65535U) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "too large to fit in memory"); - return; - } -#endif - - buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); + buffer = png_read_buffer(png_ptr, length+1); if (buffer == NULL) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "out of memory"); - return; + return handled_error; } @@ -1701,7 +1583,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_crc_read(png_ptr, buffer, length); if (png_crc_finish(png_ptr, skip) != 0) - return; + return handled_error; buffer[length] = 0; @@ -1714,7 +1596,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (length < 2U || entry_start > buffer + (length - 2U)) { png_warning(png_ptr, "malformed sPLT chunk"); - return; + return handled_error; } new_palette.depth = *entry_start++; @@ -1728,7 +1610,7 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if ((data_length % (unsigned int)entry_size) != 0) { png_warning(png_ptr, "sPLT chunk has bad length"); - return; + return handled_error; } dl = (png_uint_32)(data_length / (unsigned int)entry_size); @@ -1737,21 +1619,20 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (dl > max_dl) { png_warning(png_ptr, "sPLT chunk too long"); - return; + return handled_error; } new_palette.nentries = (png_int_32)(data_length / (unsigned int)entry_size); - new_palette.entries = (png_sPLT_entryp)png_malloc_warn(png_ptr, + new_palette.entries = (png_sPLT_entry *)png_malloc_warn(png_ptr, (png_alloc_size_t) new_palette.nentries * (sizeof (png_sPLT_entry))); if (new_palette.entries == NULL) { png_warning(png_ptr, "sPLT chunk requires too much memory"); - return; + return handled_error; } -#ifdef PNG_POINTER_INDEXING_SUPPORTED for (i = 0; i < new_palette.nentries; i++) { pp = new_palette.entries + i; @@ -1774,66 +1655,27 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) pp->frequency = png_get_uint_16(entry_start); entry_start += 2; } -#else - pp = new_palette.entries; - - for (i = 0; i < new_palette.nentries; i++) - { - - if (new_palette.depth == 8) - { - pp[i].red = *entry_start++; - pp[i].green = *entry_start++; - pp[i].blue = *entry_start++; - pp[i].alpha = *entry_start++; - } - - else - { - pp[i].red = png_get_uint_16(entry_start); entry_start += 2; - pp[i].green = png_get_uint_16(entry_start); entry_start += 2; - pp[i].blue = png_get_uint_16(entry_start); entry_start += 2; - pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2; - } - - pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2; - } -#endif /* Discard all chunk data except the name and stash that */ - new_palette.name = (png_charp)buffer; + new_palette.name = (char *)buffer; png_set_sPLT(png_ptr, info_ptr, &new_palette, 1); png_free(png_ptr, new_palette.entries); + return handled_ok; } +#else +# define png_handle_sPLT NULL #endif /* READ_sPLT */ #ifdef PNG_READ_tRNS_SUPPORTED -void /* PRIVATE */ -png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_tRNS(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { png_byte readbuf[PNG_MAX_PALETTE_LENGTH]; png_debug(1, "in png_handle_tRNS"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY) { png_byte buf[2]; @@ -1842,7 +1684,7 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "invalid"); - return; + return handled_error; } png_crc_read(png_ptr, buf, 2); @@ -1858,7 +1700,7 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "invalid"); - return; + return handled_error; } png_crc_read(png_ptr, buf, length); @@ -1872,10 +1714,9 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { if ((png_ptr->mode & PNG_HAVE_PLTE) == 0) { - /* TODO: is this actually an error in the ISO spec? */ png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "out of place"); - return; + return handled_error; } if (length > (unsigned int) png_ptr->num_palette || @@ -1884,7 +1725,7 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "invalid"); - return; + return handled_error; } png_crc_read(png_ptr, readbuf, length); @@ -1895,27 +1736,26 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "invalid with alpha channel"); - return; + return handled_error; } if (png_crc_finish(png_ptr, 0) != 0) { png_ptr->num_trans = 0; - return; + return handled_error; } - /* TODO: this is a horrible side effect in the palette case because the - * png_struct ends up with a pointer to the tRNS buffer owned by the - * png_info. Fix this. - */ png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans, &(png_ptr->trans_color)); + return handled_ok; } +#else +# define png_handle_tRNS NULL #endif #ifdef PNG_READ_bKGD_SUPPORTED -void /* PRIVATE */ -png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_bKGD(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { unsigned int truelen; png_byte buf[6]; @@ -1923,27 +1763,17 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_debug(1, "in png_handle_bKGD"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 || - (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && - (png_ptr->mode & PNG_HAVE_PLTE) == 0)) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0) + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } + if ((png_ptr->mode & PNG_HAVE_PLTE) == 0) + { + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, "out of place"); + return handled_error; + } - if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) truelen = 1; + } else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) truelen = 6; @@ -1955,13 +1785,13 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "invalid"); - return; + return handled_error; } png_crc_read(png_ptr, buf, truelen); if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; /* We convert the index value into RGB components so that we can allow * arbitrary RGB values for background when we have transparency, and @@ -1977,7 +1807,7 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (buf[0] >= info_ptr->num_palette) { png_chunk_benign_error(png_ptr, "invalid index"); - return; + return handled_error; } background.red = (png_uint_16)png_ptr->palette[buf[0]].red; @@ -1993,6 +1823,15 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) /* GRAY */ { + if (png_ptr->bit_depth <= 8) + { + if (buf[0] != 0 || buf[1] >= (unsigned int)(1 << png_ptr->bit_depth)) + { + png_chunk_benign_error(png_ptr, "invalid gray level"); + return handled_error; + } + } + background.index = 0; background.red = background.green = @@ -2002,6 +1841,15 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else { + if (png_ptr->bit_depth <= 8) + { + if (buf[0] != 0 || buf[2] != 0 || buf[4] != 0) + { + png_chunk_benign_error(png_ptr, "invalid color"); + return handled_error; + } + } + background.index = 0; background.red = png_get_uint_16(buf); background.green = png_get_uint_16(buf + 2); @@ -2010,44 +1858,196 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } png_set_bKGD(png_ptr, info_ptr, &background); + return handled_ok; } +#else +# define png_handle_bKGD NULL #endif -#ifdef PNG_READ_hIST_SUPPORTED -void /* PRIVATE */ -png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +#ifdef PNG_READ_cICP_SUPPORTED +static png_handle_result_code /* PRIVATE */ +png_handle_cICP(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { - unsigned int num, i; - png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + png_byte buf[4]; - png_debug(1, "in png_handle_hIST"); + png_debug(1, "in png_handle_cICP"); + + png_crc_read(png_ptr, buf, 4); + + if (png_crc_finish(png_ptr, 0) != 0) + return handled_error; + + png_set_cICP(png_ptr, info_ptr, buf[0], buf[1], buf[2], buf[3]); + + /* We only use 'chromaticities' for RGB to gray */ +# ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + if (!png_has_chunk(png_ptr, mDCV)) + { + /* TODO: png_ptr->chromaticities = chromaticities; */ + } +# endif /* READ_RGB_TO_GRAY */ + +#ifdef PNG_READ_GAMMA_SUPPORTED + /* PNGv3: chunk precedence for gamma is cICP, [iCCP], sRGB, gAMA. cICP is + * at the head so simply set the gamma if it can be determined. If not + * chunk_gamma remains unchanged; sRGB and gAMA handling check it for + * being zero. + */ + /* TODO: set png_struct::chunk_gamma when possible */ +#endif /*READ_GAMMA*/ + + return handled_ok; + PNG_UNUSED(length) +} +#else +# define png_handle_cICP NULL +#endif + +#ifdef PNG_READ_cLLI_SUPPORTED +static png_handle_result_code /* PRIVATE */ +png_handle_cLLI(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) +{ + png_byte buf[8]; + + png_debug(1, "in png_handle_cLLI"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); + png_crc_read(png_ptr, buf, 8); - else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 || - (png_ptr->mode & PNG_HAVE_PLTE) == 0) + if (png_crc_finish(png_ptr, 0) != 0) + return handled_error; + + /* The error checking happens here, this puts it in just one place: */ + png_set_cLLI_fixed(png_ptr, info_ptr, png_get_uint_32(buf), + png_get_uint_32(buf+4)); + return handled_ok; + PNG_UNUSED(length) +} +#else +# define png_handle_cLLI NULL +#endif + +#ifdef PNG_READ_mDCV_SUPPORTED +static png_handle_result_code /* PRIVATE */ +png_handle_mDCV(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) +{ + png_xy chromaticities; + png_byte buf[24]; + + png_debug(1, "in png_handle_mDCV"); + + png_crc_read(png_ptr, buf, 24); + + if (png_crc_finish(png_ptr, 0) != 0) + return handled_error; + + /* The error checking happens here, this puts it in just one place. The + * odd /50000 scaling factor makes it more difficult but the (x.y) values are + * only two bytes so a <<1 is safe. + * + * WARNING: the PNG specification defines the cHRM chunk to **start** with + * the white point (x,y). The W3C PNG v3 specification puts the white point + * **after* R,G,B. The x,y values in mDCV are also scaled by 50,000 and + * stored in just two bytes, whereas those in cHRM are scaled by 100,000 and + * stored in four bytes. This is very, very confusing. These APIs remove + * the confusion by copying the existing, well established, API. + */ + chromaticities.redx = png_get_uint_16(buf+ 0U) << 1; /* red x */ + chromaticities.redy = png_get_uint_16(buf+ 2U) << 1; /* red y */ + chromaticities.greenx = png_get_uint_16(buf+ 4U) << 1; /* green x */ + chromaticities.greeny = png_get_uint_16(buf+ 6U) << 1; /* green y */ + chromaticities.bluex = png_get_uint_16(buf+ 8U) << 1; /* blue x */ + chromaticities.bluey = png_get_uint_16(buf+10U) << 1; /* blue y */ + chromaticities.whitex = png_get_uint_16(buf+12U) << 1; /* white x */ + chromaticities.whitey = png_get_uint_16(buf+14U) << 1; /* white y */ + + png_set_mDCV_fixed(png_ptr, info_ptr, + chromaticities.whitex, chromaticities.whitey, + chromaticities.redx, chromaticities.redy, + chromaticities.greenx, chromaticities.greeny, + chromaticities.bluex, chromaticities.bluey, + png_get_uint_32(buf+16U), /* peak luminance */ + png_get_uint_32(buf+20U));/* minimum perceivable luminance */ + + /* We only use 'chromaticities' for RGB to gray */ +# ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_ptr->chromaticities = chromaticities; +# endif /* READ_RGB_TO_GRAY */ + + return handled_ok; + PNG_UNUSED(length) +} +#else +# define png_handle_mDCV NULL +#endif + +#ifdef PNG_READ_eXIf_SUPPORTED +static png_handle_result_code /* PRIVATE */ +png_handle_eXIf(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) +{ + png_byte *buffer = NULL; + + png_debug(1, "in png_handle_eXIf"); + + buffer = png_read_buffer(png_ptr, length); + + if (buffer == NULL) { png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; + png_chunk_benign_error(png_ptr, "out of memory"); + return handled_error; } - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0) + png_crc_read(png_ptr, buffer, length); + + if (png_crc_finish(png_ptr, 0) != 0) + return handled_error; + + /* PNGv3: the code used to check the byte order mark at the start for MM or + * II, however PNGv3 states that the first 4 bytes should be checked. + * The caller ensures that there are four bytes available. + */ { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; + png_uint_32 header = png_get_uint_32(buffer); + + /* These numbers are copied from the PNGv3 spec: */ + if (header != 0x49492A00 && header != 0x4D4D002A) + { + png_chunk_benign_error(png_ptr, "invalid"); + return handled_error; + } } - num = length / 2 ; + png_set_eXIf_1(png_ptr, info_ptr, length, buffer); + return handled_ok; +} +#else +# define png_handle_eXIf NULL +#endif + +#ifdef PNG_READ_hIST_SUPPORTED +static png_handle_result_code /* PRIVATE */ +png_handle_hIST(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) +{ + unsigned int num, i; + png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH]; + + png_debug(1, "in png_handle_hIST"); - if (num != (unsigned int) png_ptr->num_palette || - num > (unsigned int) PNG_MAX_PALETTE_LENGTH) + /* This cast is safe because the chunk definition limits the length to a + * maximum of 1024 bytes. + * + * TODO: maybe use png_uint_32 anyway, not unsigned int, to reduce the + * casts. + */ + num = (unsigned int)length / 2 ; + + if (length != num * 2 || + num != (unsigned int)png_ptr->num_palette || + num > (unsigned int)PNG_MAX_PALETTE_LENGTH) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "invalid"); - return; + return handled_error; } for (i = 0; i < num; i++) @@ -2059,15 +2059,18 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) } if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; png_set_hIST(png_ptr, info_ptr, readbuf); + return handled_ok; } +#else +# define png_handle_hIST NULL #endif #ifdef PNG_READ_pHYs_SUPPORTED -void /* PRIVATE */ -png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_pHYs(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { png_byte buf[9]; png_uint_32 res_x, res_y; @@ -2075,45 +2078,25 @@ png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_debug(1, "in png_handle_pHYs"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - if (length != 9) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - png_crc_read(png_ptr, buf, 9); if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; res_x = png_get_uint_32(buf); res_y = png_get_uint_32(buf + 4); unit_type = buf[8]; png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type); + return handled_ok; + PNG_UNUSED(length) } +#else +# define png_handle_pHYs NULL #endif #ifdef PNG_READ_oFFs_SUPPORTED -void /* PRIVATE */ -png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_oFFs(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { png_byte buf[9]; png_int_32 offset_x, offset_y; @@ -2121,88 +2104,54 @@ png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_debug(1, "in png_handle_oFFs"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - if (length != 9) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - png_crc_read(png_ptr, buf, 9); if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; offset_x = png_get_int_32(buf); offset_y = png_get_int_32(buf + 4); unit_type = buf[8]; png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type); + return handled_ok; + PNG_UNUSED(length) } +#else +# define png_handle_oFFs NULL #endif #ifdef PNG_READ_pCAL_SUPPORTED /* Read the pCAL chunk (described in the PNG Extensions document) */ -void /* PRIVATE */ -png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_pCAL(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { + png_byte *buffer; + png_byte *buf; + png_byte *endptr; png_int_32 X0, X1; - png_byte type, nparams; - png_bytep buffer, buf, units, endptr; - png_charpp params; + png_byte type; + png_byte nparams; + png_byte *units; + char **params; int i; png_debug(1, "in png_handle_pCAL"); - - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)", length + 1); - buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); + buffer = png_read_buffer(png_ptr, length+1); if (buffer == NULL) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "out of memory"); - return; + return handled_error; } png_crc_read(png_ptr, buffer, length); if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; buffer[length] = 0; /* Null terminate the last string */ @@ -2218,12 +2167,12 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (endptr - buf <= 12) { png_chunk_benign_error(png_ptr, "invalid"); - return; + return handled_error; } png_debug(3, "Reading pCAL X0, X1, type, nparams, and units"); - X0 = png_get_int_32((png_bytep)buf+1); - X1 = png_get_int_32((png_bytep)buf+5); + X0 = png_get_int_32((png_byte *)buf+1); + X1 = png_get_int_32((png_byte *)buf+5); type = buf[9]; nparams = buf[10]; units = buf + 11; @@ -2238,7 +2187,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) (type == PNG_EQUATION_HYPERBOLIC && nparams != 4)) { png_chunk_benign_error(png_ptr, "invalid parameter count"); - return; + return handled_error; } else if (type >= PNG_EQUATION_LAST) @@ -2251,13 +2200,13 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_debug(3, "Allocating pCAL parameters array"); - params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, - nparams * (sizeof (png_charp)))); + params = png_voidcast(char **, png_malloc_warn(png_ptr, + nparams * (sizeof (char *)))); if (params == NULL) { png_chunk_benign_error(png_ptr, "out of memory"); - return; + return handled_error; } /* Get pointers to the start of each parameter string. */ @@ -2267,7 +2216,7 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_debug1(3, "Reading pCAL parameter %d", i); - for (params[i] = (png_charp)buf; buf <= endptr && *buf != 0; buf++) + for (params[i] = (char *)buf; buf <= endptr && *buf != 0; buf++) /* Empty loop to move past each parameter string */ ; /* Make sure we haven't run out of data yet */ @@ -2275,76 +2224,59 @@ png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_free(png_ptr, params); png_chunk_benign_error(png_ptr, "invalid data"); - return; + return handled_error; } } - png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams, - (png_charp)units, params); + png_set_pCAL(png_ptr, info_ptr, (char *)buffer, X0, X1, type, nparams, + (char *)units, params); + /* TODO: BUG: png_set_pCAL calls png_chunk_report which, in this case, calls + * png_benign_error and that can error out. + * + * png_read_buffer needs to be allocated with space for both nparams and the + * parameter strings. Not hard to do. + */ png_free(png_ptr, params); + return handled_ok; } +#else +# define png_handle_pCAL NULL #endif #ifdef PNG_READ_sCAL_SUPPORTED /* Read the sCAL chunk */ -void /* PRIVATE */ -png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_sCAL(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { - png_bytep buffer; - png_size_t i; + png_byte *buffer; + size_t i; int state; png_debug(1, "in png_handle_sCAL"); - - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "out of place"); - return; - } - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - - /* Need unit type, width, \0, height: minimum 4 bytes */ - else if (length < 4) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)", length + 1); - buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/); + buffer = png_read_buffer(png_ptr, length+1); if (buffer == NULL) { - png_chunk_benign_error(png_ptr, "out of memory"); png_crc_finish(png_ptr, length); - return; + png_chunk_benign_error(png_ptr, "out of memory"); + return handled_error; } png_crc_read(png_ptr, buffer, length); buffer[length] = 0; /* Null terminate the last string */ if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; /* Validate the unit. */ if (buffer[0] != 1 && buffer[0] != 2) { png_chunk_benign_error(png_ptr, "invalid unit"); - return; + return handled_error; } /* Validate the ASCII numbers, need two ASCII numbers separated by @@ -2353,7 +2285,7 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) i = 1; state = 0; - if (png_check_fp_number((png_const_charp)buffer, length, &state, &i) == 0 || + if (png_check_fp_number((const char *)buffer, length, &state, &i) == 0 || i >= length || buffer[i++] != 0) png_chunk_benign_error(png_ptr, "bad width format"); @@ -2362,10 +2294,10 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else { - png_size_t heighti = i; + size_t heighti = i; state = 0; - if (png_check_fp_number((png_const_charp)buffer, length, + if (png_check_fp_number((const char *)buffer, length, &state, &i) == 0 || i != length) png_chunk_benign_error(png_ptr, "bad height format"); @@ -2373,46 +2305,40 @@ png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) png_chunk_benign_error(png_ptr, "non-positive height"); else + { /* This is the (only) success case. */ png_set_sCAL_s(png_ptr, info_ptr, buffer[0], - (png_charp)buffer+1, (png_charp)buffer+heighti); + (char *)buffer+1, (char *)buffer+heighti); + return handled_ok; + } } + + return handled_error; } +#else +# define png_handle_sCAL NULL #endif #ifdef PNG_READ_tIME_SUPPORTED -void /* PRIVATE */ -png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_tIME(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { png_byte buf[7]; png_time mod_time; png_debug(1, "in png_handle_tIME"); - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) != 0) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "duplicate"); - return; - } - + /* TODO: what is this doing here? It should be happened in pngread.c and + * pngpread.c, although it could be moved to png_handle_chunk below and + * thereby avoid some code duplication. + */ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) png_ptr->mode |= PNG_AFTER_IDAT; - if (length != 7) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "invalid"); - return; - } - png_crc_read(png_ptr, buf, 7); if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; mod_time.second = buf[6]; mod_time.minute = buf[5]; @@ -2422,18 +2348,22 @@ png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) mod_time.year = png_get_uint_16(buf); png_set_tIME(png_ptr, info_ptr, &mod_time); + return handled_ok; + PNG_UNUSED(length) } +#else +# define png_handle_tIME NULL #endif #ifdef PNG_READ_tEXt_SUPPORTED /* Note: this does not properly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_tEXt(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { - png_text text_info; - png_bytep buffer; - png_charp key; - png_charp text; + png_text text_info; + png_byte *buffer; + char *key; + char *text; png_uint_32 skip = 0; png_debug(1, "in png_handle_tEXt"); @@ -2444,47 +2374,33 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); - return; + return handled_error; } if (--png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "no space in chunk cache"); - return; + return handled_error; } } #endif - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - png_ptr->mode |= PNG_AFTER_IDAT; - -#ifdef PNG_MAX_MALLOC_64K - if (length > 65535U) - { - png_crc_finish(png_ptr, length); - png_chunk_benign_error(png_ptr, "too large to fit in memory"); - return; - } -#endif - - buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/); + buffer = png_read_buffer(png_ptr, length+1); if (buffer == NULL) { + png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "out of memory"); - return; + return handled_error; } png_crc_read(png_ptr, buffer, length); if (png_crc_finish(png_ptr, skip) != 0) - return; + return handled_error; - key = (png_charp)buffer; + key = (char *)buffer; key[length] = 0; for (text = key; *text; text++) @@ -2501,19 +2417,24 @@ png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) text_info.text = text; text_info.text_length = strlen(text); - if (png_set_text_2(png_ptr, info_ptr, &text_info, 1) != 0) - png_warning(png_ptr, "Insufficient memory to process text chunk"); + if (png_set_text_2(png_ptr, info_ptr, &text_info, 1) == 0) + return handled_ok; + + png_chunk_benign_error(png_ptr, "out of memory"); + return handled_error; } +#else +# define png_handle_tEXt NULL #endif #ifdef PNG_READ_zTXt_SUPPORTED /* Note: this does not correctly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_zTXt(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { - png_const_charp errmsg = NULL; - png_bytep buffer; - png_uint_32 keyword_length; + const char *errmsg = NULL; + png_byte *buffer; + png_uint_32 keyword_length; png_debug(1, "in png_handle_zTXt"); @@ -2523,37 +2444,35 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); - return; + return handled_error; } if (--png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "no space in chunk cache"); - return; + return handled_error; } } #endif - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - png_ptr->mode |= PNG_AFTER_IDAT; - - buffer = png_read_buffer(png_ptr, length, 2/*silent*/); + /* Note, "length" is sufficient here; we won't be adding + * a null terminator later. The limit check in png_handle_chunk should be + * sufficient. + */ + buffer = png_read_buffer(png_ptr, length); if (buffer == NULL) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "out of memory"); - return; + return handled_error; } png_crc_read(png_ptr, buffer, length); if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; /* TODO: also check that the keyword contents match the spec! */ for (keyword_length = 0; @@ -2587,41 +2506,50 @@ png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_text text; - /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except - * for the extra compression type byte and the fact that it isn't - * necessarily '\0' terminated. - */ - buffer = png_ptr->read_buffer; - buffer[uncompressed_length+(keyword_length+2)] = 0; - - text.compression = PNG_TEXT_COMPRESSION_zTXt; - text.key = (png_charp)buffer; - text.text = (png_charp)(buffer + keyword_length+2); - text.text_length = uncompressed_length; - text.itxt_length = 0; - text.lang = NULL; - text.lang_key = NULL; - - if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0) - errmsg = "insufficient memory"; + if (png_ptr->read_buffer == NULL) + errmsg="Read failure in png_handle_zTXt"; + else + { + /* It worked; png_ptr->read_buffer now looks like a tEXt chunk + * except for the extra compression type byte and the fact that + * it isn't necessarily '\0' terminated. + */ + buffer = png_ptr->read_buffer; + buffer[uncompressed_length+(keyword_length+2)] = 0; + + text.compression = PNG_TEXT_COMPRESSION_zTXt; + text.key = (char *)buffer; + text.text = (char *)(buffer + keyword_length+2); + text.text_length = uncompressed_length; + text.itxt_length = 0; + text.lang = NULL; + text.lang_key = NULL; + + if (png_set_text_2(png_ptr, info_ptr, &text, 1) == 0) + return handled_ok; + + errmsg = "out of memory"; + } } else errmsg = png_ptr->zstream.msg; } - if (errmsg != NULL) - png_chunk_benign_error(png_ptr, errmsg); + png_chunk_benign_error(png_ptr, errmsg); + return handled_error; } +#else +# define png_handle_zTXt NULL #endif #ifdef PNG_READ_iTXt_SUPPORTED /* Note: this does not correctly handle chunks that are > 64K under DOS */ -void /* PRIVATE */ -png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) +static png_handle_result_code /* PRIVATE */ +png_handle_iTXt(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { - png_const_charp errmsg = NULL; - png_bytep buffer; + const char *errmsg = NULL; + png_byte *buffer; png_uint_32 prefix_length; png_debug(1, "in png_handle_iTXt"); @@ -2632,37 +2560,31 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); - return; + return handled_error; } if (--png_ptr->user_chunk_cache_max == 1) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "no space in chunk cache"); - return; + return handled_error; } } #endif - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - png_chunk_error(png_ptr, "missing IHDR"); - - if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - png_ptr->mode |= PNG_AFTER_IDAT; - - buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/); + buffer = png_read_buffer(png_ptr, length+1); if (buffer == NULL) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "out of memory"); - return; + return handled_error; } png_crc_read(png_ptr, buffer, length); if (png_crc_finish(png_ptr, 0) != 0) - return; + return handled_error; /* First the keyword. */ for (prefix_length=0; @@ -2745,15 +2667,17 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) else text.compression = PNG_ITXT_COMPRESSION_zTXt; - text.key = (png_charp)buffer; - text.lang = (png_charp)buffer + language_offset; - text.lang_key = (png_charp)buffer + translated_keyword_offset; - text.text = (png_charp)buffer + prefix_length; + text.key = (char *)buffer; + text.lang = (char *)buffer + language_offset; + text.lang_key = (char *)buffer + translated_keyword_offset; + text.text = (char *)buffer + prefix_length; text.text_length = 0; text.itxt_length = uncompressed_length; - if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0) - errmsg = "insufficient memory"; + if (png_set_text_2(png_ptr, info_ptr, &text, 1) == 0) + return handled_ok; + + errmsg = "out of memory"; } } @@ -2762,189 +2686,196 @@ png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (errmsg != NULL) png_chunk_benign_error(png_ptr, errmsg); + return handled_error; } +#else +# define png_handle_iTXt NULL #endif #ifdef PNG_READ_APNG_SUPPORTED void /* PRIVATE */ -png_handle_acTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +png_handle_acTL(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { - png_byte data[8]; - png_uint_32 num_frames; - png_uint_32 num_plays; - png_uint_32 didSet; - - png_debug(1, "in png_handle_acTL"); - - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - { - png_error(png_ptr, "Missing IHDR before acTL"); - } - else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - { - png_warning(png_ptr, "Invalid acTL after IDAT skipped"); - png_crc_finish(png_ptr, length); - return; - } - else if ((png_ptr->mode & PNG_HAVE_acTL) != 0) - { - png_warning(png_ptr, "Duplicate acTL skipped"); - png_crc_finish(png_ptr, length); - return; - } - else if (length != 8) - { - png_warning(png_ptr, "acTL with invalid length skipped"); - png_crc_finish(png_ptr, length); - return; - } - - png_crc_read(png_ptr, data, 8); - png_crc_finish(png_ptr, 0); - - num_frames = png_get_uint_31(png_ptr, data); - num_plays = png_get_uint_31(png_ptr, data + 4); - - /* the set function will do error checking on num_frames */ - didSet = png_set_acTL(png_ptr, info_ptr, num_frames, num_plays); - if (didSet != 0) - png_ptr->mode |= PNG_HAVE_acTL; + png_byte data[8]; + png_uint_32 num_frames; + png_uint_32 num_plays; + + png_debug(1, "in png_handle_acTL"); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + { + png_error(png_ptr, "Missing IHDR before acTL"); + } + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + png_warning(png_ptr, "Ignoring misplaced acTL after IDAT"); + png_crc_finish(png_ptr, length); + return; + } + else if (png_ptr->mode & PNG_HAVE_acTL) + { + png_warning(png_ptr, "Ignoring duplicate acTL"); + png_crc_finish(png_ptr, length); + return; + } + else if (length != 8) + { + png_warning(png_ptr, "Ignoring acTL with incorrect length"); + png_crc_finish(png_ptr, length); + return; + } + + png_crc_read(png_ptr, data, 8); + png_crc_finish(png_ptr, 0); + + num_frames = png_get_uint_31(png_ptr, data); + num_plays = png_get_uint_31(png_ptr, data + 4); + + /* The set function will do error checking on num_frames. */ + if (png_set_acTL(png_ptr, info_ptr, num_frames, num_plays)) + png_ptr->mode |= PNG_HAVE_acTL; } void /* PRIVATE */ -png_handle_fcTL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +png_handle_fcTL(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { - png_byte data[22]; - png_uint_32 width; - png_uint_32 height; - png_uint_32 x_offset; - png_uint_32 y_offset; - png_uint_16 delay_num; - png_uint_16 delay_den; - png_byte dispose_op; - png_byte blend_op; - - png_debug(1, "in png_handle_fcTL"); - - png_ensure_sequence_number(png_ptr, length); - - if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) - { - png_error(png_ptr, "Missing IHDR before fcTL"); - } - else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) - { - /* for any frames other then the first this message may be misleading, - * but correct. PNG_HAVE_IDAT is unset before the frame head is read - * i can't think of a better message */ - png_warning(png_ptr, "Invalid fcTL after IDAT skipped"); - png_crc_finish(png_ptr, length-4); - return; - } - else if ((png_ptr->mode & PNG_HAVE_fcTL) != 0) - { - png_warning(png_ptr, "Duplicate fcTL within one frame skipped"); - png_crc_finish(png_ptr, length-4); - return; - } - else if (length != 26) - { - png_warning(png_ptr, "fcTL with invalid length skipped"); - png_crc_finish(png_ptr, length-4); - return; - } - - png_crc_read(png_ptr, data, 22); - png_crc_finish(png_ptr, 0); - - width = png_get_uint_31(png_ptr, data); - height = png_get_uint_31(png_ptr, data + 4); - x_offset = png_get_uint_31(png_ptr, data + 8); - y_offset = png_get_uint_31(png_ptr, data + 12); - delay_num = png_get_uint_16(data + 16); - delay_den = png_get_uint_16(data + 18); - dispose_op = data[20]; - blend_op = data[21]; - - if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0)) - { - png_warning(png_ptr, "fcTL for the first frame must have zero offset"); - return; - } - - if (info_ptr != NULL) - { - if (png_ptr->num_frames_read == 0 && - (width != info_ptr->width || height != info_ptr->height)) - { - png_warning(png_ptr, "size in first frame's fcTL must match " - "the size in IHDR"); - return; - } + png_byte data[22]; + png_uint_32 width; + png_uint_32 height; + png_uint_32 x_offset; + png_uint_32 y_offset; + png_uint_16 delay_num; + png_uint_16 delay_den; + png_byte dispose_op; + png_byte blend_op; + + png_debug(1, "in png_handle_fcTL"); + + png_ensure_sequence_number(png_ptr, length); + + if (!(png_ptr->mode & PNG_HAVE_IHDR)) + { + png_error(png_ptr, "Missing IHDR before fcTL"); + } + else if (png_ptr->mode & PNG_HAVE_IDAT) + { + /* For any frames other then the first this message may be misleading, + * but correct. PNG_HAVE_IDAT is unset before the frame head is read. + * I can't think of a better message. + */ + png_warning(png_ptr, "Ignoring invalid fcTL after IDAT"); + png_crc_finish(png_ptr, length-4); + return; + } + else if (png_ptr->mode & PNG_HAVE_fcTL) + { + png_warning(png_ptr, "Ignoring duplicate fcTL within one frame"); + png_crc_finish(png_ptr, length-4); + return; + } + else if (length != 26) + { + png_warning(png_ptr, "Ignoring fcTL with incorrect length"); + png_crc_finish(png_ptr, length-4); + return; + } + + png_crc_read(png_ptr, data, 22); + png_crc_finish(png_ptr, 0); + + width = png_get_uint_31(png_ptr, data); + height = png_get_uint_31(png_ptr, data + 4); + x_offset = png_get_uint_31(png_ptr, data + 8); + y_offset = png_get_uint_31(png_ptr, data + 12); + delay_num = png_get_uint_16(data + 16); + delay_den = png_get_uint_16(data + 18); + dispose_op = data[20]; + blend_op = data[21]; + + if (png_ptr->num_frames_read == 0 && (x_offset != 0 || y_offset != 0)) + { + png_warning(png_ptr, "Ignoring leading fcTL with non-zero frame offset"); + return; + } - /* The set function will do more error checking */ - png_set_next_frame_fcTL(png_ptr, info_ptr, width, height, - x_offset, y_offset, delay_num, delay_den, - dispose_op, blend_op); + if (info_ptr != NULL) + { + if (png_ptr->num_frames_read == 0 && + (width != info_ptr->width || height != info_ptr->height)) + { + png_warning(png_ptr, + "Ignoring leading fcTL with incorrect frame size"); + return; + } - png_read_reinit(png_ptr, info_ptr); + /* The set function will do more error checking. */ + png_set_next_frame_fcTL(png_ptr, info_ptr, width, height, + x_offset, y_offset, delay_num, delay_den, + dispose_op, blend_op); - png_ptr->mode |= PNG_HAVE_fcTL; - } + png_read_reinit(png_ptr, info_ptr); + + png_ptr->mode |= PNG_HAVE_fcTL; + } } void /* PRIVATE */ -png_have_info(png_structp png_ptr, png_infop info_ptr) +png_have_info(png_struct *png_ptr, png_info *info_ptr) { - if ((info_ptr->valid & PNG_INFO_acTL) != 0 && - (info_ptr->valid & PNG_INFO_fcTL) == 0) - { - png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; - info_ptr->num_frames++; - } + if ((info_ptr->valid & PNG_INFO_acTL) && !(info_ptr->valid & PNG_INFO_fcTL)) + { + png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; + info_ptr->num_frames++; + } } void /* PRIVATE */ -png_handle_fdAT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length) +png_handle_fdAT(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) { - png_ensure_sequence_number(png_ptr, length); - - /* This function is only called from png_read_end(), png_read_info(), - * and png_push_read_chunk() which means that: - * - the user doesn't want to read this frame - * - or this is an out-of-place fdAT - * in either case it is safe to ignore the chunk with a warning */ - png_warning(png_ptr, "ignoring fdAT chunk"); - png_crc_finish(png_ptr, length - 4); - PNG_UNUSED(info_ptr) + png_ensure_sequence_number(png_ptr, length); + + /* This function is called only from png_read_end(), png_read_info(), + * and png_push_read_chunk(). This means one of the following: + * - The user doesn't want to read this frame. + * - This is an out-of-place fdAT. + * In either case, it is safe to ignore the chunk with a warning. + */ + png_warning(png_ptr, "Ignoring fdAT chunk"); + png_crc_finish(png_ptr, length - 4); + PNG_UNUSED(info_ptr) } void /* PRIVATE */ -png_ensure_sequence_number(png_structp png_ptr, png_uint_32 length) +png_ensure_sequence_number(png_struct *png_ptr, png_uint_32 length) { - png_byte data[4]; - png_uint_32 sequence_number; + png_byte data[4]; + png_uint_32 sequence_number; - if (length < 4) - png_error(png_ptr, "invalid fcTL or fdAT chunk found"); + if (length < 4) + { + /* TODO: Write a more precise message. */ + png_error(png_ptr, "Invalid fcTL or fdAT chunk"); + } - png_crc_read(png_ptr, data, 4); - sequence_number = png_get_uint_31(png_ptr, data); + png_crc_read(png_ptr, data, 4); + sequence_number = png_get_uint_31(png_ptr, data); - if (sequence_number != png_ptr->next_seq_num) - png_error(png_ptr, "fcTL or fdAT chunk with out-of-order sequence " - "number found"); + if (sequence_number != png_ptr->next_seq_num) + { + /* TODO: Write a more precise message. */ + png_error(png_ptr, "Out-of-order sequence number in fcTL or fdAT"); + } - png_ptr->next_seq_num++; + png_ptr->next_seq_num++; } -#endif /* READ_APNG */ +#endif /* PNG_READ_APNG_SUPPORTED */ #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED /* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */ static int -png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) +png_cache_unknown_chunk(png_struct *png_ptr, png_uint_32 length) { - png_alloc_size_t limit = PNG_SIZE_MAX; + const png_alloc_size_t limit = png_chunk_max(png_ptr); if (png_ptr->unknown_chunk.data != NULL) { @@ -2952,21 +2883,11 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) png_ptr->unknown_chunk.data = NULL; } -# ifdef PNG_SET_USER_LIMITS_SUPPORTED - if (png_ptr->user_chunk_malloc_max > 0 && - png_ptr->user_chunk_malloc_max < limit) - limit = png_ptr->user_chunk_malloc_max; - -# elif PNG_USER_CHUNK_MALLOC_MAX > 0 - if (PNG_USER_CHUNK_MALLOC_MAX < limit) - limit = PNG_USER_CHUNK_MALLOC_MAX; -# endif - if (length <= limit) { PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name); /* The following is safe because of the PNG_SIZE_MAX init above */ - png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/; + png_ptr->unknown_chunk.size = (size_t)length/*SAFE*/; /* 'mode' is a flag array, only the bottom four bits matter here */ png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/; @@ -2976,7 +2897,7 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) else { /* Do a 'warn' here - it is handled below. */ - png_ptr->unknown_chunk.data = png_voidcast(png_bytep, + png_ptr->unknown_chunk.data = png_voidcast(png_byte *, png_malloc_warn(png_ptr, length)); } } @@ -3000,11 +2921,11 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) #endif /* READ_UNKNOWN_CHUNKS */ /* Handle an unknown, or known but disabled, chunk */ -void /* PRIVATE */ -png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, +png_handle_result_code /*PRIVATE*/ +png_handle_unknown(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length, int keep) { - int handled = 0; /* the chunk was handled */ + png_handle_result_code handled = handled_discarded; /* the default */ png_debug(1, "in png_handle_unknown"); @@ -3051,7 +2972,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, * error at this point unless it is to be saved. * positive: The chunk was handled, libpng will ignore/discard it. */ - if (ret < 0) + if (ret < 0) /* handled_error */ png_chunk_error(png_ptr, "error in user chunk"); else if (ret == 0) @@ -3085,7 +3006,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, else /* chunk was handled */ { - handled = 1; + handled = handled_ok; /* Critical chunks can be safely discarded at this point. */ keep = PNG_HANDLE_CHUNK_NEVER; } @@ -3153,7 +3074,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, case 2: png_ptr->user_chunk_cache_max = 1; png_chunk_benign_error(png_ptr, "no space in chunk cache"); - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: /* NOTE: prior to 1.6.0 this case resulted in an unknown critical * chunk being skipped, now there will be a hard error below. @@ -3162,7 +3083,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, default: /* not at limit */ --(png_ptr->user_chunk_cache_max); - /* FALL THROUGH */ + /* FALLTHROUGH */ case 0: /* no limit */ # endif /* USER_LIMITS */ /* Here when the limit isn't reached or when limits are compiled @@ -3170,7 +3091,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, */ png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); - handled = 1; + handled = handled_saved; # ifdef PNG_USER_LIMITS_SUPPORTED break; } @@ -3196,38 +3117,267 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, #endif /* !READ_UNKNOWN_CHUNKS */ /* Check for unhandled critical chunks */ - if (handled == 0 && PNG_CHUNK_CRITICAL(png_ptr->chunk_name)) + if (handled < handled_saved && PNG_CHUNK_CRITICAL(png_ptr->chunk_name)) png_chunk_error(png_ptr, "unhandled critical chunk"); + + return handled; } -/* This function is called to verify that a chunk name is valid. - * This function can't have the "critical chunk check" incorporated - * into it, since in the future we will need to be able to call user - * functions to handle unknown critical chunks after we check that - * the chunk name itself is valid. +/* APNG handling: the minimal implementation of APNG handling in libpng 1.6 + * requires that those significant applications which already handle APNG not + * get hosed. To do this ensure the code here will have to ensure than APNG + * data by default (at least in 1.6) gets stored in the unknown chunk list. + * Maybe this can be relaxed in a few years but at present it's just the only + * safe way. + * + * ATM just cause unknown handling for all three chunks: */ +#define png_handle_acTL NULL +#define png_handle_fcTL NULL +#define png_handle_fdAT NULL -/* Bit hacking: the test for an invalid byte in the 4 byte chunk name is: +/* + * 1.6.47: This is the new table driven interface to all the chunk handling. + * + * The table describes the PNG standard rules for **reading** known chunks - + * every chunk which has an entry in PNG_KNOWN_CHUNKS. The table contains an + * entry for each PNG_INDEX_cHNK describing the rules. * - * ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97)) + * In this initial version the only information in the entry is the + * png_handle_cHNK function for the chunk in question. When chunk support is + * compiled out the entry will be NULL. */ +static const struct +{ + png_handle_result_code (*handler)( + png_struct *, png_info *, png_uint_32 length); + /* A chunk-specific 'handler', NULL if the chunk is not supported in this + * build. + */ -void /* PRIVATE */ -png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name) + /* Crushing these values helps on modern 32-bit architectures because the + * pointer and the following bit fields both end up requiring 32 bits. + * Typically this will halve the table size. On 64-bit architectures the + * table entries will typically be 8 bytes. + */ + png_uint_32 max_length :12; /* Length min, max in bytes */ + png_uint_32 min_length :8; + /* Length errors on critical chunks have special handling to preserve the + * existing behaviour in libpng 1.6. Ancillary chunks are checked below + * and produce a 'benign' error. + */ + png_uint_32 pos_before :4; /* PNG_HAVE_ values chunk must precede */ + png_uint_32 pos_after :4; /* PNG_HAVE_ values chunk must follow */ + /* NOTE: PLTE, tRNS and bKGD require special handling which depends on + * the colour type of the base image. + */ + png_uint_32 multiple :1; /* Multiple occurrences permitted */ + /* This is enabled for PLTE because PLTE may, in practice, be optional */ +} +read_chunks[PNG_INDEX_unknown] = { - int i; + /* Definitions as above but done indirectly by #define so that + * PNG_KNOWN_CHUNKS can be used safely to build the table in order. + * + * Each CDcHNK definition lists the values for the parameters **after** + * the first, 'handler', function. 'handler' is NULL when the chunk has no + * compiled in support. + */ +# define NoCheck 0x801U /* Do not check the maximum length */ +# define Limit 0x802U /* Limit to png_chunk_max bytes */ +# define LKMin 3U+LZ77Min /* Minimum length of keyword+LZ77 */ + +#define hIHDR PNG_HAVE_IHDR +#define hPLTE PNG_HAVE_PLTE +#define hIDAT PNG_HAVE_IDAT + /* For the two chunks, tRNS and bKGD which can occur in PNGs without a PLTE + * but must occur after the PLTE use this and put the check in the handler + * routine for colour mapped images were PLTE is required. Also put a check + * in PLTE for other image types to drop the PLTE if tRNS or bKGD have been + * seen. + */ +#define hCOL (PNG_HAVE_PLTE|PNG_HAVE_IDAT) + /* Used for the decoding chunks which must be before PLTE. */ +#define aIDAT PNG_AFTER_IDAT + + /* Chunks from W3C PNG v3: */ + /* cHNK max_len, min, before, after, multiple */ +# define CDIHDR 13U, 13U, hIHDR, 0, 0 +# define CDPLTE NoCheck, 0U, 0, hIHDR, 1 + /* PLTE errors are only critical for colour-map images, consequently the + * handler does all the checks. + */ +# define CDIDAT NoCheck, 0U, aIDAT, hIHDR, 1 +# define CDIEND NoCheck, 0U, 0, aIDAT, 0 + /* Historically data was allowed in IEND */ +# define CDtRNS 256U, 0U, hIDAT, hIHDR, 0 +# define CDcHRM 32U, 32U, hCOL, hIHDR, 0 +# define CDgAMA 4U, 4U, hCOL, hIHDR, 0 +# define CDiCCP NoCheck, LKMin, hCOL, hIHDR, 0 +# define CDsBIT 4U, 1U, hCOL, hIHDR, 0 +# define CDsRGB 1U, 1U, hCOL, hIHDR, 0 +# define CDcICP 4U, 4U, hCOL, hIHDR, 0 +# define CDmDCV 24U, 24U, hCOL, hIHDR, 0 +# define CDeXIf Limit, 4U, 0, hIHDR, 0 +# define CDcLLI 8U, 8U, hCOL, hIHDR, 0 +# define CDtEXt NoCheck, 2U, 0, hIHDR, 1 + /* Allocates 'length+1'; checked in the handler */ +# define CDzTXt Limit, LKMin, 0, hIHDR, 1 +# define CDiTXt NoCheck, 6U, 0, hIHDR, 1 + /* Allocates 'length+1'; checked in the handler */ +# define CDbKGD 6U, 1U, hIDAT, hIHDR, 0 +# define CDhIST 1024U, 0U, hPLTE, hIHDR, 0 +# define CDpHYs 9U, 9U, hIDAT, hIHDR, 0 +# define CDsPLT NoCheck, 3U, hIDAT, hIHDR, 1 + /* Allocates 'length+1'; checked in the handler */ +# define CDtIME 7U, 7U, 0, hIHDR, 0 +# define CDacTL 8U, 8U, hIDAT, hIHDR, 0 +# define CDfcTL 25U, 26U, 0, hIHDR, 1 +# define CDfdAT Limit, 4U, hIDAT, hIHDR, 1 + /* Supported chunks from PNG extensions 1.5.0, NYI so limit */ +# define CDoFFs 9U, 9U, hIDAT, hIHDR, 0 +# define CDpCAL NoCheck, 14U, hIDAT, hIHDR, 0 + /* Allocates 'length+1'; checked in the handler */ +# define CDsCAL Limit, 4U, hIDAT, hIHDR, 0 + /* Allocates 'length+1'; checked in the handler */ + +# define PNG_CHUNK(cHNK, index) { png_handle_ ## cHNK, CD ## cHNK }, + PNG_KNOWN_CHUNKS +# undef PNG_CHUNK +}; + + +static png_index +png_chunk_index_from_name(png_uint_32 chunk_name) +{ + /* For chunk png_cHNK return PNG_INDEX_cHNK. Return PNG_INDEX_unknown if + * chunk_name is not known. Notice that in a particular build "known" does + * not necessarily mean "supported", although the inverse applies. + */ + switch (chunk_name) + { +# define PNG_CHUNK(cHNK, index)\ + case png_ ## cHNK: return PNG_INDEX_ ## cHNK; /* == index */ + + PNG_KNOWN_CHUNKS - png_debug(1, "in png_check_chunk_name"); +# undef PNG_CHUNK - for (i=1; i<=4; ++i) + default: return PNG_INDEX_unknown; + } +} + +png_handle_result_code /*PRIVATE*/ +png_handle_chunk(png_struct *png_ptr, png_info *info_ptr, png_uint_32 length) +{ + /* CSE: these things don't change, these autos are just to save typing and + * make the code more clear. + */ + const png_uint_32 chunk_name = png_ptr->chunk_name; + const png_index chunk_index = png_chunk_index_from_name(chunk_name); + + png_handle_result_code handled = handled_error; + const char *errmsg = NULL; + + /* Is this a known chunk? If not there are no checks performed here; + * png_handle_unknown does the correct checks. This means that the values + * for known but unsupported chunks in the above table are not used here + * however the chunks_seen fields in png_struct are still set. + */ + if (chunk_index == PNG_INDEX_unknown || + read_chunks[chunk_index].handler == NULL) + { + handled = png_handle_unknown( + png_ptr, info_ptr, length, PNG_HANDLE_CHUNK_AS_DEFAULT); + } + + /* First check the position. The first check is historical; the stream must + * start with IHDR and anything else causes libpng to give up immediately. + */ + else if (chunk_index != PNG_INDEX_IHDR && + (png_ptr->mode & PNG_HAVE_IHDR) == 0) + png_chunk_error(png_ptr, "missing IHDR"); /* NORETURN */ + + /* Before all the pos_before chunks, after all the pos_after chunks. */ + else if (((png_ptr->mode & read_chunks[chunk_index].pos_before) != 0) || + ((png_ptr->mode & read_chunks[chunk_index].pos_after) != + read_chunks[chunk_index].pos_after)) + { + errmsg = "out of place"; + } + + /* Now check for duplicates: duplicated critical chunks also produce a + * full error. + */ + else if (read_chunks[chunk_index].multiple == 0 && + png_file_has_chunk(png_ptr, chunk_index)) + { + errmsg = "duplicate"; + } + + else if (length < read_chunks[chunk_index].min_length) + errmsg = "too short"; + else { - int c = chunk_name & 0xff; + /* NOTE: apart from IHDR the critical chunks (PLTE, IDAT and IEND) are set + * up above not to do any length checks. + * + * The png_chunk_max check ensures that the variable length chunks are + * always checked at this point for being within the system allocation + * limits. + */ + unsigned max_length = read_chunks[chunk_index].max_length; + + switch (max_length) + { + case Limit: + /* png_read_chunk_header has already png_error'ed chunks with a + * length exceeding the 31-bit PNG limit, so just check the memory + * limit: + */ + if (length <= png_chunk_max(png_ptr)) + goto MeetsLimit; + + errmsg = "length exceeds libpng limit"; + break; + + default: + if (length <= max_length) + goto MeetsLimit; + + errmsg = "too long"; + break; - if (c < 65 || c > 122 || (c > 90 && c < 97)) - png_chunk_error(png_ptr, "invalid chunk type"); + case NoCheck: + MeetsLimit: + handled = read_chunks[chunk_index].handler( + png_ptr, info_ptr, length); + break; + } + } + + /* If there was an error or the chunk was simply skipped it is not counted as + * 'seen'. + */ + if (errmsg != NULL) + { + if (PNG_CHUNK_CRITICAL(chunk_name)) /* stop immediately */ + png_chunk_error(png_ptr, errmsg); + else /* ancillary chunk */ + { + /* The chunk data is skipped: */ + png_crc_finish(png_ptr, length); + png_chunk_benign_error(png_ptr, errmsg); + } + } - chunk_name >>= 8; + else if (handled >= handled_saved) + { + if (chunk_index != PNG_INDEX_unknown) + png_file_add_chunk(png_ptr, chunk_index); } + + return handled; } /* Combines the row recently read in with the existing pixels in the row. This @@ -3238,13 +3388,13 @@ png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name) * 'display' is false only those pixels present in the pass are filled in. */ void /* PRIVATE */ -png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) +png_combine_row(const png_struct *png_ptr, png_byte *dp, int display) { unsigned int pixel_depth = png_ptr->transformed_pixel_depth; - png_const_bytep sp = png_ptr->row_buf + 1; + const png_byte *sp = png_ptr->row_buf + 1; png_alloc_size_t row_width = png_ptr->width; unsigned int pass = png_ptr->pass; - png_bytep end_ptr = 0; + png_byte *end_ptr = NULL; png_byte end_byte = 0; unsigned int end_mask; @@ -3403,7 +3553,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) /* Hence the pre-compiled masks indexed by PACKSWAP (or not), depth and * then pass: */ - static PNG_CONST png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = + static const png_uint_32 row_mask[2/*PACKSWAP*/][3/*depth*/][6] = { /* Little-endian byte masks for PACKSWAP */ { S_MASKS(1,0), S_MASKS(2,0), S_MASKS(4,0) }, @@ -3414,7 +3564,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) /* display_mask has only three entries for the odd passes, so index by * pass>>1. */ - static PNG_CONST png_uint_32 display_mask[2][3][3] = + static const png_uint_32 display_mask[2][3][3] = { /* Little-endian byte masks for PACKSWAP */ { B_MASKS(1,0), B_MASKS(2,0), B_MASKS(4,0) }, @@ -3555,7 +3705,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) */ do { - dp[0] = sp[0], dp[1] = sp[1]; + dp[0] = sp[0]; dp[1] = sp[1]; if (row_width <= bytes_to_jump) return; @@ -3576,7 +3726,7 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) */ for (;;) { - dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2]; + dp[0] = sp[0]; dp[1] = sp[1]; dp[2] = sp[2]; if (row_width <= bytes_to_jump) return; @@ -3607,9 +3757,9 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) bytes_to_copy % (sizeof (png_uint_32)) == 0 && bytes_to_jump % (sizeof (png_uint_32)) == 0) { - png_uint_32p dp32 = png_aligncast(png_uint_32p,dp); - png_const_uint_32p sp32 = png_aligncastconst( - png_const_uint_32p, sp); + png_uint_32 *dp32 = png_aligncast(png_uint_32 *,dp); + const png_uint_32 *sp32 = png_aligncastconst( + const png_uint_32 *, sp); size_t skip = (bytes_to_jump-bytes_to_copy) / (sizeof (png_uint_32)); @@ -3636,8 +3786,8 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) * There will be 1-3 bytes left to copy, so don't try the * 16-bit loop below. */ - dp = (png_bytep)dp32; - sp = (png_const_bytep)sp32; + dp = (png_byte *)dp32; + sp = (const png_byte *)sp32; do *dp++ = *sp++; while (--row_width > 0); @@ -3649,9 +3799,9 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) */ else { - png_uint_16p dp16 = png_aligncast(png_uint_16p, dp); - png_const_uint_16p sp16 = png_aligncastconst( - png_const_uint_16p, sp); + png_uint_16 *dp16 = png_aligncast(png_uint_16 *, dp); + const png_uint_16 *sp16 = png_aligncastconst( + const png_uint_16 *, sp); size_t skip = (bytes_to_jump-bytes_to_copy) / (sizeof (png_uint_16)); @@ -3675,8 +3825,8 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) while (bytes_to_copy <= row_width); /* End of row - 1 byte left, bytes_to_copy > row_width: */ - dp = (png_bytep)dp16; - sp = (png_const_bytep)sp16; + dp = (png_byte *)dp16; + sp = (const png_byte *)sp16; do *dp++ = *sp++; while (--row_width > 0); @@ -3722,13 +3872,9 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) #ifdef PNG_READ_INTERLACING_SUPPORTED void /* PRIVATE */ -png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, +png_do_read_interlace(png_row_info *row_info, png_byte *row, int pass, png_uint_32 transformations /* Because these may affect the byte layout */) { - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - /* Offset to next interlace block */ - static PNG_CONST unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - png_debug(1, "in png_do_read_interlace"); if (row != NULL && row_info != NULL) { @@ -3740,8 +3886,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, { case 1: { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 3); + png_byte *sp = row + (size_t)((row_info->width - 1) >> 3); + png_byte *dp = row + (size_t)((final_width - 1) >> 3); unsigned int sshift, dshift; unsigned int s_start, s_end; int s_inc; @@ -3803,8 +3949,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, case 2: { - png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2); - png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2); + png_byte *sp = row + (png_uint_32)((row_info->width - 1) >> 2); + png_byte *dp = row + (png_uint_32)((final_width - 1) >> 2); unsigned int sshift, dshift; unsigned int s_start, s_end; int s_inc; @@ -3867,8 +4013,8 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, case 4: { - png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1); - png_bytep dp = row + (png_size_t)((final_width - 1) >> 1); + png_byte *sp = row + (size_t)((row_info->width - 1) >> 1); + png_byte *dp = row + (size_t)((final_width - 1) >> 1); unsigned int sshift, dshift; unsigned int s_start, s_end; int s_inc; @@ -3930,12 +4076,12 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, default: { - png_size_t pixel_bytes = (row_info->pixel_depth >> 3); + size_t pixel_bytes = (row_info->pixel_depth >> 3); - png_bytep sp = row + (png_size_t)(row_info->width - 1) + png_byte *sp = row + (size_t)(row_info->width - 1) * pixel_bytes; - png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes; + png_byte *dp = row + (size_t)(final_width - 1) * pixel_bytes; int jstop = (int)png_pass_inc[pass]; png_uint_32 i; @@ -3969,13 +4115,13 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass, #endif /* READ_INTERLACING */ static void -png_read_filter_row_sub(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) +png_read_filter_row_sub(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_size_t i; - png_size_t istop = row_info->rowbytes; + size_t i; + size_t istop = row_info->rowbytes; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp = row + bpp; + png_byte *rp = row + bpp; PNG_UNUSED(prev_row) @@ -3987,13 +4133,13 @@ png_read_filter_row_sub(png_row_infop row_info, png_bytep row, } static void -png_read_filter_row_up(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) +png_read_filter_row_up(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_size_t i; - png_size_t istop = row_info->rowbytes; - png_bytep rp = row; - png_const_bytep pp = prev_row; + size_t i; + size_t istop = row_info->rowbytes; + png_byte *rp = row; + const png_byte *pp = prev_row; for (i = 0; i < istop; i++) { @@ -4003,14 +4149,14 @@ png_read_filter_row_up(png_row_infop row_info, png_bytep row, } static void -png_read_filter_row_avg(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) +png_read_filter_row_avg(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_size_t i; - png_bytep rp = row; - png_const_bytep pp = prev_row; + size_t i; + png_byte *rp = row; + const png_byte *pp = prev_row; unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_size_t istop = row_info->rowbytes - bpp; + size_t istop = row_info->rowbytes - bpp; for (i = 0; i < bpp; i++) { @@ -4030,10 +4176,10 @@ png_read_filter_row_avg(png_row_infop row_info, png_bytep row, } static void -png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) +png_read_filter_row_paeth_1byte_pixel(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { - png_bytep rp_end = row + row_info->rowbytes; + png_byte *rp_end = row + row_info->rowbytes; int a, c; /* First pixel/byte */ @@ -4065,7 +4211,10 @@ png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, /* Find the best predictor, the least of pa, pb, pc favoring the earlier * ones in the case of a tie. */ - if (pb < pa) pa = pb, a = b; + if (pb < pa) + { + pa = pb; a = b; + } if (pc < pa) a = c; /* Calculate the current pixel in a, and move the previous row pixel to c @@ -4078,11 +4227,11 @@ png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, } static void -png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, - png_const_bytep prev_row) +png_read_filter_row_paeth_multibyte_pixel(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) { unsigned int bpp = (row_info->pixel_depth + 7) >> 3; - png_bytep rp_end = row + bpp; + png_byte *rp_end = row + bpp; /* Process the first pixel in the row completely (this is the same as 'up' * because there is only one candidate predictor for the first row). @@ -4117,7 +4266,10 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, pc = (p + pc) < 0 ? -(p + pc) : p + pc; #endif - if (pb < pa) pa = pb, a = b; + if (pb < pa) + { + pa = pb; a = b; + } if (pc < pa) a = c; a += *row; @@ -4126,7 +4278,7 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, } static void -png_init_filter_functions(png_structrp pp) +png_init_filter_functions(png_struct *pp) /* This function is called once for every PNG image (except for PNG images * that only use PNG_FILTER_VALUE_NONE for all rows) to set the * implementations required to reverse the filtering of PNG rows. Reversing @@ -4149,27 +4301,15 @@ png_init_filter_functions(png_structrp pp) pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth_multibyte_pixel; -#ifdef PNG_FILTER_OPTIMIZATIONS - /* To use this define PNG_FILTER_OPTIMIZATIONS as the name of a function to - * call to install hardware optimizations for the above functions; simply - * replace whatever elements of the pp->read_filter[] array with a hardware - * specific (or, for that matter, generic) optimization. - * - * To see an example of this examine what configure.ac does when - * --enable-arm-neon is specified on the command line. - */ - PNG_FILTER_OPTIMIZATIONS(pp, bpp); -#endif +# ifdef PNG_TARGET_IMPLEMENTS_FILTERS + png_target_init_filter_functions(pp, bpp); +# endif } void /* PRIVATE */ -png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row, - png_const_bytep prev_row, int filter) +png_read_filter_row(png_struct *pp, png_row_info *row_info, png_byte *row, + const png_byte *prev_row, int filter) { - /* OPTIMIZATION: DO NOT MODIFY THIS FUNCTION, instead #define - * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic - * implementations. See png_init_filter_functions above. - */ if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST) { if (pp->read_filter[0] == NULL) @@ -4181,7 +4321,7 @@ png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row, #ifdef PNG_SEQUENTIAL_READ_SUPPORTED void /* PRIVATE */ -png_read_IDAT_data(png_structrp png_ptr, png_bytep output, +png_read_IDAT_data(png_struct *png_ptr, png_byte *output, png_alloc_size_t avail_out) { /* Loop reading IDATs and decompressing the result into output[avail_out] */ @@ -4199,8 +4339,7 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, if (png_ptr->zstream.avail_in == 0) { uInt avail_in; - png_bytep buffer; - + png_byte *buffer; #ifdef PNG_READ_APNG_SUPPORTED png_uint_32 bytes_to_skip = 0; @@ -4221,8 +4360,8 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, png_error(png_ptr, "Not enough image data"); if (png_ptr->chunk_name != png_fdAT) { - png_warning(png_ptr, "Skipped (ignored) a chunk " - "between APNG chunks"); + png_warning(png_ptr, + "Ignoring unexpected chunk in APNG sequence"); bytes_to_skip = png_ptr->idat_size; continue; } @@ -4244,10 +4383,12 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, if (png_ptr->chunk_name != png_IDAT) png_error(png_ptr, "Not enough image data"); } -#endif /* READ_APNG */ - +#endif /* PNG_READ_APNG_SUPPORTED */ avail_in = png_ptr->IDAT_read_size; + if (avail_in > png_chunk_max(png_ptr)) + avail_in = (uInt)/*SAFE*/png_chunk_max(png_ptr); + if (avail_in > png_ptr->idat_size) avail_in = (uInt)png_ptr->idat_size; @@ -4255,8 +4396,13 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, * to minimize memory usage by causing lots of re-allocs, but * realistically doing IDAT_read_size re-allocs is not likely to be a * big problem. + * + * An error here corresponds to the system being out of memory. */ - buffer = png_read_buffer(png_ptr, avail_in, 0/*error*/); + buffer = png_read_buffer(png_ptr, avail_in); + + if (buffer == NULL) + png_chunk_error(png_ptr, "out of memory"); png_crc_read(png_ptr, buffer, avail_in); png_ptr->idat_size -= avail_in; @@ -4290,7 +4436,7 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, * * TODO: deal more elegantly with truncated IDAT lists. */ - ret = PNG_INFLATE(png_ptr, Z_NO_FLUSH); + ret = png_zlib_inflate(png_ptr, Z_NO_FLUSH); /* Take the unconsumed output back. */ if (output != NULL) @@ -4322,15 +4468,7 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, png_zstream_error(png_ptr, ret); if (output != NULL) - { - if(!strncmp(png_ptr->zstream.msg,"incorrect data check",20)) - { - png_chunk_benign_error(png_ptr, "ADLER32 checksum mismatch"); - continue; - } - else - png_chunk_error(png_ptr, png_ptr->zstream.msg); - } + png_chunk_error(png_ptr, png_ptr->zstream.msg); else /* checking */ { @@ -4354,7 +4492,7 @@ png_read_IDAT_data(png_structrp png_ptr, png_bytep output, } void /* PRIVATE */ -png_read_finish_IDAT(png_structrp png_ptr) +png_read_finish_IDAT(png_struct *png_ptr) { /* We don't need any more data and the stream should have ended, however the * LZ end code may actually not have been processed. In this case we must @@ -4402,22 +4540,8 @@ png_read_finish_IDAT(png_structrp png_ptr) } void /* PRIVATE */ -png_read_finish_row(png_structrp png_ptr) +png_read_finish_row(png_struct *png_ptr) { - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* 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}; - png_debug(1, "in png_read_finish_row"); png_ptr->row_number++; if (png_ptr->row_number < png_ptr->num_rows) @@ -4467,24 +4591,10 @@ png_read_finish_row(png_structrp png_ptr) #endif /* SEQUENTIAL_READ */ void /* PRIVATE */ -png_read_start_row(png_structrp png_ptr) +png_read_start_row(png_struct *png_ptr) { - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* 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}; - unsigned int max_pixel_depth; - png_size_t row_bytes; + size_t row_bytes; png_debug(1, "in png_read_start_row"); @@ -4682,15 +4792,15 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) png_free(png_ptr, png_ptr->big_prev_row); if (png_ptr->interlaced != 0) - png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, + png_ptr->big_row_buf = (png_byte *)png_calloc(png_ptr, row_bytes + 48); else - png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + png_ptr->big_row_buf = (png_byte *)png_malloc(png_ptr, row_bytes + 48); - png_ptr->big_prev_row = (png_bytep)png_malloc(png_ptr, row_bytes + 48); + png_ptr->big_prev_row = (png_byte *)png_malloc(png_ptr, row_bytes + 48); -#ifdef PNG_ALIGNED_MEMORY_SUPPORTED +#if PNG_TARGET_ROW_ALIGNMENT > 1 /* Use 16-byte aligned memory for row_buf with at least 16 bytes * of padding before and after row_buf; treat prev_row similarly. * NOTE: the alignment is to the start of the pixels, one beyond the start @@ -4699,15 +4809,14 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) * opposite effect of that intended. */ { - png_bytep temp = png_ptr->big_row_buf + 32; - int extra = (int)((temp - (png_bytep)0) & 0x0f); + png_byte *temp = png_ptr->big_row_buf + 32; + size_t extra = (size_t)temp & 0x0f; png_ptr->row_buf = temp - extra - 1/*filter byte*/; temp = png_ptr->big_prev_row + 32; - extra = (int)((temp - (png_bytep)0) & 0x0f); + extra = (size_t)temp & 0x0f; png_ptr->prev_row = temp - extra - 1/*filter byte*/; } - #else /* Use 31 bytes of padding before and 17 bytes after row_buf. */ png_ptr->row_buf = png_ptr->big_row_buf + 31; @@ -4740,7 +4849,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) */ if (png_ptr->read_buffer != NULL) { - png_bytep buffer = png_ptr->read_buffer; + png_byte *buffer = png_ptr->read_buffer; png_ptr->read_buffer_size = 0; png_ptr->read_buffer = NULL; @@ -4759,78 +4868,69 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) } #ifdef PNG_READ_APNG_SUPPORTED -/* This function is to be called after the main IDAT set has been read and - * before a new IDAT is read. It resets some parts of png_ptr - * to make them usable by the read functions again */ +/* This function should be called after the main IDAT sequence has been read + * and before a new fdAT is about to be read. It resets some parts of png_ptr + * to make them usable by the read functions again. + */ void /* PRIVATE */ -png_read_reset(png_structp png_ptr) +png_read_reset(png_struct *png_ptr) { - png_ptr->mode &= ~PNG_HAVE_IDAT; - png_ptr->mode &= ~PNG_AFTER_IDAT; - png_ptr->row_number = 0; - png_ptr->pass = 0; + png_ptr->mode &= ~PNG_HAVE_IDAT; + png_ptr->mode &= ~PNG_AFTER_IDAT; + png_ptr->row_number = 0; + png_ptr->pass = 0; } void /* PRIVATE */ -png_read_reinit(png_structp png_ptr, png_infop info_ptr) +png_read_reinit(png_struct *png_ptr, png_info *info_ptr) { - png_ptr->width = info_ptr->next_frame_width; - png_ptr->height = info_ptr->next_frame_height; - png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); - png_ptr->info_rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, - png_ptr->width); - if (png_ptr->prev_row != NULL) - memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); + png_ptr->width = info_ptr->next_frame_width; + png_ptr->height = info_ptr->next_frame_height; + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width); + if (png_ptr->info_rowbytes != 0) + png_ptr->info_rowbytes = info_ptr->rowbytes = + PNG_ROWBYTES(info_ptr->pixel_depth, png_ptr->width); + if (png_ptr->prev_row) + memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1); } #ifdef PNG_PROGRESSIVE_READ_SUPPORTED -/* same as png_read_reset() but for the progressive reader */ +/* Same as png_read_reset(), but for the progressive reader. */ void /* PRIVATE */ -png_progressive_read_reset(png_structp png_ptr) +png_progressive_read_reset(png_struct *png_ptr) { #ifdef PNG_READ_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; - - /* Offset to next interlace block in the y direction */ - static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; - - if (png_ptr->interlaced != 0) - { - if ((png_ptr->transformations & PNG_INTERLACE) == 0) - png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - - png_pass_ystart[0]) / png_pass_yinc[0]; - else - png_ptr->num_rows = png_ptr->height; - - png_ptr->iwidth = (png_ptr->width + - png_pass_inc[png_ptr->pass] - 1 - - png_pass_start[png_ptr->pass]) / - png_pass_inc[png_ptr->pass]; - } - else -#endif /* READ_INTERLACING */ - { - png_ptr->num_rows = png_ptr->height; - png_ptr->iwidth = png_ptr->width; - } - png_ptr->flags &= ~PNG_FLAG_ZSTREAM_ENDED; - if (inflateReset(&(png_ptr->zstream)) != Z_OK) - png_error(png_ptr, "inflateReset failed"); - png_ptr->zstream.avail_in = 0; - png_ptr->zstream.next_in = 0; - png_ptr->zstream.next_out = png_ptr->row_buf; - png_ptr->zstream.avail_out = (uInt)PNG_ROWBYTES(png_ptr->pixel_depth, - png_ptr->iwidth) + 1; + /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ + + if (png_ptr->interlaced) + { + if (!(png_ptr->transformations & PNG_INTERLACE)) + png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - + png_pass_ystart[0]) / + png_pass_yinc[0]; + else + png_ptr->num_rows = png_ptr->height; + + png_ptr->iwidth = (png_ptr->width + + png_pass_inc[png_ptr->pass] - 1 - + png_pass_start[png_ptr->pass]) / + png_pass_inc[png_ptr->pass]; + } + else +#endif /* PNG_READ_INTERLACING_SUPPORTED */ + { + png_ptr->num_rows = png_ptr->height; + png_ptr->iwidth = png_ptr->width; + } + png_ptr->flags &= ~PNG_FLAG_ZSTREAM_ENDED; + if (inflateReset(&(png_ptr->zstream)) != Z_OK) + png_error(png_ptr, "inflateReset failed"); + png_ptr->zstream.avail_in = 0; + png_ptr->zstream.next_in = 0; + png_ptr->zstream.next_out = png_ptr->row_buf; + png_ptr->zstream.avail_out = + (uInt)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; } -#endif /* PROGRESSIVE_READ */ -#endif /* READ_APNG */ +#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ +#endif /* PNG_READ_APNG_SUPPORTED */ #endif /* READ */ diff --git a/media/libpng/pngset.c b/media/libpng/pngset.c index baec0a68e0..773a2f82c0 100644 --- a/media/libpng/pngset.c +++ b/media/libpng/pngset.c @@ -1,10 +1,9 @@ - /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -21,9 +20,9 @@ #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) #ifdef PNG_bKGD_SUPPORTED -void PNGAPI -png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_color_16p background) +void +png_set_bKGD(const png_struct *png_ptr, png_info *info_ptr, + const png_color_16 *background) { png_debug1(1, "in %s storage function", "bKGD"); @@ -36,37 +35,31 @@ png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr, #endif #ifdef PNG_cHRM_SUPPORTED -void PNGFAPI -png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr, +void +png_set_cHRM_fixed(const png_struct *png_ptr, png_info *info_ptr, png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, png_fixed_point blue_y) { - png_xy xy; - png_debug1(1, "in %s storage function", "cHRM fixed"); if (png_ptr == NULL || info_ptr == NULL) return; - xy.redx = red_x; - xy.redy = red_y; - xy.greenx = green_x; - xy.greeny = green_y; - xy.bluex = blue_x; - xy.bluey = blue_y; - xy.whitex = white_x; - xy.whitey = white_y; - - if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy, - 2/* override with app values*/) != 0) - info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; + info_ptr->cHRM.redx = red_x; + info_ptr->cHRM.redy = red_y; + info_ptr->cHRM.greenx = green_x; + info_ptr->cHRM.greeny = green_y; + info_ptr->cHRM.bluex = blue_x; + info_ptr->cHRM.bluey = blue_y; + info_ptr->cHRM.whitex = white_x; + info_ptr->cHRM.whitey = white_y; - png_colorspace_sync_info(png_ptr, info_ptr); + info_ptr->valid |= PNG_INFO_cHRM; } -void PNGFAPI -png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr, +void +png_set_cHRM_XYZ_fixed(const png_struct *png_ptr, png_info *info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y, png_fixed_point int_red_Z, png_fixed_point int_green_X, png_fixed_point int_green_Y, png_fixed_point int_green_Z, @@ -74,6 +67,7 @@ png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr, png_fixed_point int_blue_Z) { png_XYZ XYZ; + png_xy xy; png_debug1(1, "in %s storage function", "cHRM XYZ fixed"); @@ -90,16 +84,19 @@ png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr, XYZ.blue_Y = int_blue_Y; XYZ.blue_Z = int_blue_Z; - if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace, - &XYZ, 2) != 0) - info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM; + if (png_xy_from_XYZ(&xy, &XYZ) == 0) + { + info_ptr->cHRM = xy; + info_ptr->valid |= PNG_INFO_cHRM; + } - png_colorspace_sync_info(png_ptr, info_ptr); + else + png_app_error(png_ptr, "invalid cHRM XYZ"); } # ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, +void +png_set_cHRM(const png_struct *png_ptr, png_info *info_ptr, double white_x, double white_y, double red_x, double red_y, double green_x, double green_y, double blue_x, double blue_y) { @@ -114,8 +111,8 @@ png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, png_fixed(png_ptr, blue_y, "cHRM Blue Y")); } -void PNGAPI -png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, +void +png_set_cHRM_XYZ(const png_struct *png_ptr, png_info *info_ptr, double red_X, double red_Y, double red_Z, double green_X, double green_Y, double green_Z, double blue_X, double blue_Y, double blue_Z) { @@ -134,9 +131,225 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, #endif /* cHRM */ +#ifdef PNG_cICP_SUPPORTED +void +png_set_cICP(const png_struct *png_ptr, png_info *info_ptr, + png_byte colour_primaries, png_byte transfer_function, + png_byte matrix_coefficients, png_byte video_full_range_flag) +{ + png_debug1(1, "in %s storage function", "cICP"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + info_ptr->cicp_colour_primaries = colour_primaries; + info_ptr->cicp_transfer_function = transfer_function; + info_ptr->cicp_matrix_coefficients = matrix_coefficients; + info_ptr->cicp_video_full_range_flag = video_full_range_flag; + + if (info_ptr->cicp_matrix_coefficients != 0) + { + png_warning(png_ptr, "Invalid cICP matrix coefficients"); + return; + } + + info_ptr->valid |= PNG_INFO_cICP; +} +#endif /* cICP */ + +#ifdef PNG_cLLI_SUPPORTED +void +png_set_cLLI_fixed(const png_struct *png_ptr, png_info *info_ptr, + /* The values below are in cd/m2 (nits) and are scaled by 10,000; not + * 100,000 as in the case of png_fixed_point. + */ + png_uint_32 maxCLL, png_uint_32 maxFALL) +{ + png_debug1(1, "in %s storage function", "cLLI"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Check the light level range: */ + if (maxCLL > 0x7FFFFFFFU || maxFALL > 0x7FFFFFFFU) + { + /* The limit is 200kcd/m2; somewhat bright but not inconceivable because + * human vision is said to run up to 100Mcd/m2. The sun is about 2Gcd/m2. + * + * The reference sRGB monitor is 80cd/m2 and the limit of PQ encoding is + * 2kcd/m2. + */ + png_chunk_report(png_ptr, "cLLI light level exceeds PNG limit", + PNG_CHUNK_WRITE_ERROR); + return; + } + + info_ptr->maxCLL = maxCLL; + info_ptr->maxFALL = maxFALL; + info_ptr->valid |= PNG_INFO_cLLI; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void +png_set_cLLI(const png_struct *png_ptr, png_info *info_ptr, + double maxCLL, double maxFALL) +{ + png_set_cLLI_fixed(png_ptr, info_ptr, + png_fixed_ITU(png_ptr, maxCLL, "png_set_cLLI(maxCLL)"), + png_fixed_ITU(png_ptr, maxFALL, "png_set_cLLI(maxFALL)")); +} +# endif /* FLOATING_POINT */ +#endif /* cLLI */ + +#ifdef PNG_mDCV_SUPPORTED +static png_uint_16 +png_ITU_fixed_16(int *error, png_fixed_point v) +{ + /* Return a safe uint16_t value scaled according to the ITU H273 rules for + * 16-bit display chromaticities. Functions like the corresponding + * png_fixed() internal function with regard to errors: it's an error on + * write, a chunk_benign_error on read: See the definition of + * png_chunk_report in pngpriv.h. + */ + v /= 2; /* rounds to 0 in C: avoids insignificant arithmetic errors */ + if (v > 65535 || v < 0) + { + *error = 1; + return 0; + } + + return (png_uint_16)/*SAFE*/v; +} + +void +png_set_mDCV_fixed(const png_struct *png_ptr, png_info *info_ptr, + png_fixed_point white_x, png_fixed_point white_y, + png_fixed_point red_x, png_fixed_point red_y, + png_fixed_point green_x, png_fixed_point green_y, + png_fixed_point blue_x, png_fixed_point blue_y, + png_uint_32 maxDL, + png_uint_32 minDL) +{ + png_uint_16 rx, ry, gx, gy, bx, by, wx, wy; + int error; + + png_debug1(1, "in %s storage function", "mDCV"); + + if (png_ptr == NULL || info_ptr == NULL) + return; + + /* Check the input values to ensure they are in the expected range: */ + error = 0; + rx = png_ITU_fixed_16(&error, red_x); + ry = png_ITU_fixed_16(&error, red_y); + gx = png_ITU_fixed_16(&error, green_x); + gy = png_ITU_fixed_16(&error, green_y); + bx = png_ITU_fixed_16(&error, blue_x); + by = png_ITU_fixed_16(&error, blue_y); + wx = png_ITU_fixed_16(&error, white_x); + wy = png_ITU_fixed_16(&error, white_y); + + if (error) + { + png_chunk_report(png_ptr, + "mDCV chromaticities outside representable range", + PNG_CHUNK_WRITE_ERROR); + return; + } + + /* Check the light level range: */ + if (maxDL > 0x7FFFFFFFU || minDL > 0x7FFFFFFFU) + { + /* The limit is 200kcd/m2; somewhat bright but not inconceivable because + * human vision is said to run up to 100Mcd/m2. The sun is about 2Gcd/m2. + * + * The reference sRGB monitor is 80cd/m2 and the limit of PQ encoding is + * 2kcd/m2. + */ + png_chunk_report(png_ptr, "mDCV display light level exceeds PNG limit", + PNG_CHUNK_WRITE_ERROR); + return; + } + + /* All values are safe, the settings are accepted. + * + * IMPLEMENTATION NOTE: in practice the values can be checked and assigned + * but the result is confusing if a writing app calls png_set_mDCV more than + * once, the second time with an invalid value. This approach is more + * obviously correct at the cost of typing and a very slight machine + * overhead. + */ + info_ptr->mastering_red_x = rx; + info_ptr->mastering_red_y = ry; + info_ptr->mastering_green_x = gx; + info_ptr->mastering_green_y = gy; + info_ptr->mastering_blue_x = bx; + info_ptr->mastering_blue_y = by; + info_ptr->mastering_white_x = wx; + info_ptr->mastering_white_y = wy; + info_ptr->mastering_maxDL = maxDL; + info_ptr->mastering_minDL = minDL; + info_ptr->valid |= PNG_INFO_mDCV; +} + +# ifdef PNG_FLOATING_POINT_SUPPORTED +void +png_set_mDCV(const png_struct *png_ptr, png_info *info_ptr, + double white_x, double white_y, double red_x, double red_y, double green_x, + double green_y, double blue_x, double blue_y, + double maxDL, double minDL) +{ + png_set_mDCV_fixed(png_ptr, info_ptr, + png_fixed(png_ptr, white_x, "png_set_mDCV(white(x))"), + png_fixed(png_ptr, white_y, "png_set_mDCV(white(y))"), + png_fixed(png_ptr, red_x, "png_set_mDCV(red(x))"), + png_fixed(png_ptr, red_y, "png_set_mDCV(red(y))"), + png_fixed(png_ptr, green_x, "png_set_mDCV(green(x))"), + png_fixed(png_ptr, green_y, "png_set_mDCV(green(y))"), + png_fixed(png_ptr, blue_x, "png_set_mDCV(blue(x))"), + png_fixed(png_ptr, blue_y, "png_set_mDCV(blue(y))"), + png_fixed_ITU(png_ptr, maxDL, "png_set_mDCV(maxDL)"), + png_fixed_ITU(png_ptr, minDL, "png_set_mDCV(minDL)")); +} +# endif /* FLOATING_POINT */ +#endif /* mDCV */ + +#ifdef PNG_eXIf_SUPPORTED +void +png_set_eXIf_1(const png_struct *png_ptr, png_info *info_ptr, + png_uint_32 num_exif, png_byte *exif) +{ + png_byte *new_exif; + + png_debug1(1, "in %s storage function", "eXIf"); + + if (png_ptr == NULL || info_ptr == NULL || + (png_ptr->mode & PNG_WROTE_eXIf) != 0 || + exif == NULL) + return; + + new_exif = png_voidcast(png_byte *, png_malloc_warn(png_ptr, num_exif)); + + if (new_exif == NULL) + { + png_warning(png_ptr, "Insufficient memory for eXIf chunk data"); + return; + } + + memcpy(new_exif, exif, (size_t)num_exif); + + png_free_data(png_ptr, info_ptr, PNG_FREE_EXIF, 0); + + info_ptr->num_exif = num_exif; + info_ptr->exif = new_exif; + info_ptr->free_me |= PNG_FREE_EXIF; + info_ptr->valid |= PNG_INFO_eXIf; +} +#endif /* eXIf */ + #ifdef PNG_gAMA_SUPPORTED -void PNGFAPI -png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr, +void +png_set_gAMA_fixed(const png_struct *png_ptr, png_info *info_ptr, png_fixed_point file_gamma) { png_debug1(1, "in %s storage function", "gAMA"); @@ -144,13 +357,13 @@ png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr, if (png_ptr == NULL || info_ptr == NULL) return; - png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma); - png_colorspace_sync_info(png_ptr, info_ptr); + info_ptr->gamma = file_gamma; + info_ptr->valid |= PNG_INFO_gAMA; } # ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma) +void +png_set_gAMA(const png_struct *png_ptr, png_info *info_ptr, double file_gamma) { png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma, "png_set_gAMA")); @@ -159,15 +372,16 @@ png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma) #endif #ifdef PNG_hIST_SUPPORTED -void PNGAPI -png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_uint_16p hist) +void +png_set_hIST(const png_struct *png_ptr, png_info *info_ptr, + const png_uint_16 *hist) { + png_uint_16 safe_hist[PNG_MAX_PALETTE_LENGTH]; int i; png_debug1(1, "in %s storage function", "hIST"); - if (png_ptr == NULL || info_ptr == NULL) + if (png_ptr == NULL || info_ptr == NULL || hist == NULL) return; if (info_ptr->num_palette == 0 || info_ptr->num_palette @@ -179,32 +393,37 @@ png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr, return; } + /* Snapshot the caller's hist before freeing, in case it points to + * info_ptr->hist (getter-to-setter aliasing). + */ + memcpy(safe_hist, hist, (unsigned int)info_ptr->num_palette * + (sizeof (png_uint_16))); + hist = safe_hist; + png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0); /* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in * version 1.2.1 */ - info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr, + info_ptr->hist = png_voidcast(png_uint_16 *, png_malloc_warn(png_ptr, PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16)))); if (info_ptr->hist == NULL) { png_warning(png_ptr, "Insufficient memory for hIST chunk data"); - return; } - info_ptr->free_me |= PNG_FREE_HIST; - for (i = 0; i < info_ptr->num_palette; i++) info_ptr->hist[i] = hist[i]; + info_ptr->free_me |= PNG_FREE_HIST; info_ptr->valid |= PNG_INFO_hIST; } #endif -void PNGAPI -png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr, +void +png_set_IHDR(const png_struct *png_ptr, png_info *info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, int interlace_type, int compression_type, int filter_type) @@ -243,14 +462,16 @@ png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr, info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width); #ifdef PNG_APNG_SUPPORTED - /* for non-animated png. this may be overwritten from an acTL chunk later */ + /* Assume a non-animated PNG in the beginning. This may be overridden after + * seeing an acTL chunk later. + */ info_ptr->num_frames = 1; #endif } #ifdef PNG_oFFs_SUPPORTED -void PNGAPI -png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr, +void +png_set_oFFs(const png_struct *png_ptr, png_info *info_ptr, png_int_32 offset_x, png_int_32 offset_y, int unit_type) { png_debug1(1, "in %s storage function", "oFFs"); @@ -266,12 +487,12 @@ png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr, #endif #ifdef PNG_pCAL_SUPPORTED -void PNGAPI -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, - int nparams, png_const_charp units, png_charpp params) +void +png_set_pCAL(const png_struct *png_ptr, png_info *info_ptr, + const char *purpose, png_int_32 X0, png_int_32 X1, int type, + int nparams, const char *units, char **params) { - png_size_t length; + size_t length; int i; png_debug1(1, "in %s storage function", "pCAL"); @@ -313,7 +534,7 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, } } - info_ptr->pcal_purpose = png_voidcast(png_charp, + info_ptr->pcal_purpose = png_voidcast(char *, png_malloc_warn(png_ptr, length)); if (info_ptr->pcal_purpose == NULL) @@ -325,6 +546,8 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, memcpy(info_ptr->pcal_purpose, purpose, length); + info_ptr->free_me |= PNG_FREE_PCAL; + png_debug(3, "storing X0, X1, type, and nparams in info"); info_ptr->pcal_X0 = X0; info_ptr->pcal_X1 = X1; @@ -335,30 +558,28 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, png_debug1(3, "allocating units for info (%lu bytes)", (unsigned long)length); - info_ptr->pcal_units = png_voidcast(png_charp, + info_ptr->pcal_units = png_voidcast(char *, png_malloc_warn(png_ptr, length)); if (info_ptr->pcal_units == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL units"); - return; } memcpy(info_ptr->pcal_units, units, length); - info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr, - (png_size_t)(((unsigned int)nparams + 1) * (sizeof (png_charp))))); + info_ptr->pcal_params = png_voidcast(char **, png_malloc_warn(png_ptr, + (size_t)(((unsigned int)nparams + 1) * (sizeof (char *))))); if (info_ptr->pcal_params == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL params"); - return; } memset(info_ptr->pcal_params, 0, ((unsigned int)nparams + 1) * - (sizeof (png_charp))); + (sizeof (char *))); for (i = 0; i < nparams; i++) { @@ -366,12 +587,11 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, png_debug2(3, "allocating parameter %d for info (%lu bytes)", i, (unsigned long)length); - info_ptr->pcal_params[i] = (png_charp)png_malloc_warn(png_ptr, length); + info_ptr->pcal_params[i] = (char *)png_malloc_warn(png_ptr, length); if (info_ptr->pcal_params[i] == NULL) { png_warning(png_ptr, "Insufficient memory for pCAL parameter"); - return; } @@ -379,16 +599,15 @@ png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr, } info_ptr->valid |= PNG_INFO_pCAL; - info_ptr->free_me |= PNG_FREE_PCAL; } #endif #ifdef PNG_sCAL_SUPPORTED -void PNGAPI -png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, - int unit, png_const_charp swidth, png_const_charp sheight) +void +png_set_sCAL_s(const png_struct *png_ptr, png_info *info_ptr, + int unit, const char *swidth, const char *sheight) { - png_size_t lengthw = 0, lengthh = 0; + size_t lengthw = 0, lengthh = 0; png_debug1(1, "in %s storage function", "sCAL"); @@ -415,7 +634,7 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw); - info_ptr->scal_s_width = png_voidcast(png_charp, + info_ptr->scal_s_width = png_voidcast(char *, png_malloc_warn(png_ptr, lengthw)); if (info_ptr->scal_s_width == NULL) @@ -431,28 +650,27 @@ png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr, png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh); - info_ptr->scal_s_height = png_voidcast(png_charp, + info_ptr->scal_s_height = png_voidcast(char *, png_malloc_warn(png_ptr, lengthh)); if (info_ptr->scal_s_height == NULL) { - png_free (png_ptr, info_ptr->scal_s_width); + png_free(png_ptr, info_ptr->scal_s_width); info_ptr->scal_s_width = NULL; png_warning(png_ptr, "Memory allocation failed while processing sCAL"); - return; } memcpy(info_ptr->scal_s_height, sheight, lengthh); - info_ptr->valid |= PNG_INFO_sCAL; info_ptr->free_me |= PNG_FREE_SCAL; + info_ptr->valid |= PNG_INFO_sCAL; } # ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit, +void +png_set_sCAL(const png_struct *png_ptr, png_info *info_ptr, int unit, double width, double height) { png_debug1(1, "in %s storage function", "sCAL"); @@ -481,8 +699,8 @@ png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit, # endif # ifdef PNG_FIXED_POINT_SUPPORTED -void PNGAPI -png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit, +void +png_set_sCAL_fixed(const png_struct *png_ptr, png_info *info_ptr, int unit, png_fixed_point width, png_fixed_point height) { png_debug1(1, "in %s storage function", "sCAL"); @@ -510,8 +728,8 @@ png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit, #endif #ifdef PNG_pHYs_SUPPORTED -void PNGAPI -png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr, +void +png_set_pHYs(const png_struct *png_ptr, png_info *info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type) { png_debug1(1, "in %s storage function", "pHYs"); @@ -526,11 +744,11 @@ png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr, } #endif -void PNGAPI -png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, - png_const_colorp palette, int num_palette) +void +png_set_PLTE(png_struct *png_ptr, png_info *info_ptr, + const png_color *palette, int num_palette) { - + png_color safe_palette[PNG_MAX_PALETTE_LENGTH]; png_uint_32 max_palette_length; png_debug1(1, "in %s storage function", "PLTE"); @@ -564,37 +782,55 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_error(png_ptr, "Invalid palette"); } - /* It may not actually be necessary to set png_ptr->palette here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - * - * 1.6.0: the above statement appears to be incorrect; something has to set - * the palette inside png_struct on read. + /* Snapshot the caller's palette before freeing, in case it points to + * info_ptr->palette (getter-to-setter aliasing). */ + if (num_palette > 0) + memcpy(safe_palette, palette, (unsigned int)num_palette * + (sizeof (png_color))); + + palette = safe_palette; + png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead * of num_palette entries, in case of an invalid PNG file or incorrect * call to png_set_PLTE() with too-large sample values. + * + * Allocate independent buffers for info_ptr and png_ptr so that the + * lifetime of png_ptr->palette is decoupled from the lifetime of + * info_ptr->palette. Previously, these two pointers were aliased, + * which caused a use-after-free vulnerability if png_free_data freed + * info_ptr->palette while png_ptr->palette was still in use by the + * row transform functions (e.g. png_do_expand_palette). + * + * Both buffers are allocated with png_calloc to zero-fill, because + * the ARM NEON palette riffle reads all 256 entries unconditionally, + * regardless of num_palette. */ - png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr, + png_free(png_ptr, png_ptr->palette); + png_ptr->palette = png_voidcast(png_color *, png_calloc(png_ptr, + PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); + info_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr, PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); + png_ptr->num_palette = info_ptr->num_palette = (png_uint_16)num_palette; if (num_palette > 0) + { + memcpy(info_ptr->palette, palette, (unsigned int)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->num_palette = png_ptr->num_palette = (png_uint_16)num_palette; + } info_ptr->free_me |= PNG_FREE_PLTE; - info_ptr->valid |= PNG_INFO_PLTE; } #ifdef PNG_sBIT_SUPPORTED -void PNGAPI -png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_color_8p sig_bit) +void +png_set_sBIT(const png_struct *png_ptr, png_info *info_ptr, + const png_color_8 *sig_bit) { png_debug1(1, "in %s storage function", "sBIT"); @@ -607,20 +843,20 @@ png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr, #endif #ifdef PNG_sRGB_SUPPORTED -void PNGAPI -png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent) +void +png_set_sRGB(const png_struct *png_ptr, png_info *info_ptr, int srgb_intent) { png_debug1(1, "in %s storage function", "sRGB"); if (png_ptr == NULL || info_ptr == NULL) return; - (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent); - png_colorspace_sync_info(png_ptr, info_ptr); + info_ptr->rendering_intent = srgb_intent; + info_ptr->valid |= PNG_INFO_sRGB; } -void PNGAPI -png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, +void +png_set_sRGB_gAMA_and_cHRM(const png_struct *png_ptr, png_info *info_ptr, int srgb_intent) { png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM"); @@ -628,28 +864,33 @@ png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr, if (png_ptr == NULL || info_ptr == NULL) return; - if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, - srgb_intent) != 0) - { - /* This causes the gAMA and cHRM to be written too */ - info_ptr->colorspace.flags |= - PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM; - } + png_set_sRGB(png_ptr, info_ptr, srgb_intent); + +# ifdef PNG_gAMA_SUPPORTED + png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); +# endif /* gAMA */ - png_colorspace_sync_info(png_ptr, info_ptr); +# ifdef PNG_cHRM_SUPPORTED + png_set_cHRM_fixed(png_ptr, info_ptr, + /* color x y */ + /* white */ 31270, 32900, + /* red */ 64000, 33000, + /* green */ 30000, 60000, + /* blue */ 15000, 6000); +# endif /* cHRM */ } #endif /* sRGB */ #ifdef PNG_iCCP_SUPPORTED -void PNGAPI -png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_charp name, int compression_type, - png_const_bytep profile, png_uint_32 proflen) +void +png_set_iCCP(const png_struct *png_ptr, png_info *info_ptr, + const char *name, int compression_type, + const png_byte *profile, png_uint_32 proflen) { - png_charp new_iccp_name; - png_bytep new_iccp_profile; - png_size_t length; + char *new_iccp_name; + png_byte *new_iccp_profile; + size_t length; png_debug1(1, "in %s storage function", "iCCP"); @@ -659,29 +900,8 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, if (compression_type != PNG_COMPRESSION_TYPE_BASE) png_app_error(png_ptr, "Invalid iCCP compression method"); - /* Set the colorspace first because this validates the profile; do not - * override previously set app cHRM or gAMA here (because likely as not the - * application knows better than libpng what the correct values are.) Pass - * the info_ptr color_type field to png_colorspace_set_ICC because in the - * write case it has not yet been stored in png_ptr. - */ - { - int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name, - proflen, profile, info_ptr->color_type); - - png_colorspace_sync_info(png_ptr, info_ptr); - - /* Don't do any of the copying if the profile was bad, or inconsistent. */ - if (result == 0) - return; - - /* But do write the gAMA and cHRM chunks from the profile. */ - info_ptr->colorspace.flags |= - PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM; - } - length = strlen(name)+1; - new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length)); + new_iccp_name = png_voidcast(char *, png_malloc_warn(png_ptr, length)); if (new_iccp_name == NULL) { @@ -691,7 +911,7 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, } memcpy(new_iccp_name, name, length); - new_iccp_profile = png_voidcast(png_bytep, + new_iccp_profile = png_voidcast(png_byte *, png_malloc_warn(png_ptr, proflen)); if (new_iccp_profile == NULL) @@ -716,9 +936,9 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, #endif #ifdef PNG_TEXT_SUPPORTED -void PNGAPI -png_set_text(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_textp text_ptr, int num_text) +void +png_set_text(const png_struct *png_ptr, png_info *info_ptr, + const png_text *text_ptr, int num_text) { int ret; ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text); @@ -728,16 +948,17 @@ png_set_text(png_const_structrp png_ptr, png_inforp info_ptr, } int /* PRIVATE */ -png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_textp text_ptr, int num_text) +png_set_text_2(const png_struct *png_ptr, png_info *info_ptr, + const png_text *text_ptr, int num_text) { int i; + png_textp old_text = NULL; - png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U : - (unsigned long)png_ptr->chunk_name); + png_debug1(1, "in text storage function, chunk typeid = 0x%lx", + png_ptr == NULL ? 0xabadca11UL : (unsigned long)png_ptr->chunk_name); if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL) - return(0); + return 0; /* Make sure we have enough space in the "text" array in info_struct * to hold all of the incoming text_ptr objects. This compare can't overflow @@ -748,7 +969,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, { int old_num_text = info_ptr->num_text; int max_text; - png_textp new_text = NULL; + png_text *new_text = NULL; /* Calculate an appropriate max_text, checking for overflow. */ max_text = old_num_text; @@ -766,7 +987,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, /* Now allocate a new array and copy the old members in; this does all * the overflow checks. */ - new_text = png_voidcast(png_textp,png_realloc_array(png_ptr, + new_text = png_voidcast(png_text *,png_realloc_array(png_ptr, info_ptr->text, old_num_text, max_text-old_num_text, sizeof *new_text)); } @@ -779,7 +1000,10 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, return 1; } - png_free(png_ptr, info_ptr->text); + /* Defer freeing the old array until after the copy loop below, + * in case text_ptr aliases info_ptr->text (getter-to-setter). + */ + old_text = info_ptr->text; info_ptr->text = new_text; info_ptr->free_me |= PNG_FREE_TEXT; @@ -793,7 +1017,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, { size_t text_length, key_len; size_t lang_len, lang_key_len; - png_textp textp = &(info_ptr->text[info_ptr->num_text]); + png_text *textp = &(info_ptr->text[info_ptr->num_text]); if (text_ptr[i].key == NULL) continue; @@ -857,13 +1081,14 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, textp->compression = text_ptr[i].compression; } - textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr, + textp->key = png_voidcast(char *,png_malloc_base(png_ptr, key_len + text_length + lang_len + lang_key_len + 4)); if (textp->key == NULL) { png_chunk_report(png_ptr, "text chunk: out of memory", PNG_CHUNK_WRITE_ERROR); + png_free(png_ptr, old_text); return 1; } @@ -917,14 +1142,16 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, png_debug1(3, "transferred text chunk %d", info_ptr->num_text); } - return(0); + png_free(png_ptr, old_text); + + return 0; } #endif #ifdef PNG_tIME_SUPPORTED -void PNGAPI -png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr, - png_const_timep mod_time) +void +png_set_tIME(const png_struct *png_ptr, png_info *info_ptr, + const png_time *mod_time) { png_debug1(1, "in %s storage function", "tIME"); @@ -948,9 +1175,9 @@ png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr, #endif #ifdef PNG_tRNS_SUPPORTED -void PNGAPI -png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, - png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color) +void +png_set_tRNS(png_struct *png_ptr, png_info *info_ptr, + const png_byte *trans_alpha, int num_trans, const png_color_16 *trans_color) { png_debug1(1, "in %s storage function", "tRNS"); @@ -960,25 +1187,50 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, if (trans_alpha != NULL) { - /* It may not actually be necessary to set png_ptr->trans_alpha here; - * we do it for backward compatibility with the way the png_handle_tRNS - * function used to do the allocation. - * - * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively - * relies on png_set_tRNS storing the information in png_struct - * (otherwise it won't be there for the code in pngrtran.c). + /* Snapshot the caller's trans_alpha before freeing, in case it + * points to info_ptr->trans_alpha (getter-to-setter aliasing). */ + png_byte safe_trans[PNG_MAX_PALETTE_LENGTH]; + + if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) + memcpy(safe_trans, trans_alpha, (size_t)num_trans); + + trans_alpha = safe_trans; png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0); if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH) { - /* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */ - info_ptr->trans_alpha = png_voidcast(png_bytep, + /* Allocate info_ptr's copy of the transparency data. + * Initialize all entries to fully opaque (0xff), then overwrite + * the first num_trans entries with the actual values. + */ + info_ptr->trans_alpha = png_voidcast(png_byte *, + png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); + memset(info_ptr->trans_alpha, 0xff, PNG_MAX_PALETTE_LENGTH); + memcpy(info_ptr->trans_alpha, trans_alpha, (size_t)num_trans); + info_ptr->free_me |= PNG_FREE_TRNS; + info_ptr->valid |= PNG_INFO_tRNS; + + /* Allocate an independent copy for png_struct, so that the + * lifetime of png_ptr->trans_alpha is decoupled from the + * lifetime of info_ptr->trans_alpha. Previously these two + * pointers were aliased, which caused a use-after-free if + * png_free_data freed info_ptr->trans_alpha while + * png_ptr->trans_alpha was still in use by the row transform + * functions (e.g. png_do_expand_palette). + */ + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->trans_alpha = png_voidcast(png_bytep, png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH)); - memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans); + memset(png_ptr->trans_alpha, 0xff, PNG_MAX_PALETTE_LENGTH); + memcpy(png_ptr->trans_alpha, trans_alpha, (size_t)num_trans); + } + else + { + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->trans_alpha = NULL; } - png_ptr->trans_alpha = info_ptr->trans_alpha; } if (trans_color != NULL) @@ -1009,16 +1261,16 @@ png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr, if (num_trans != 0) { - info_ptr->valid |= PNG_INFO_tRNS; info_ptr->free_me |= PNG_FREE_TRNS; + info_ptr->valid |= PNG_INFO_tRNS; } } #endif #ifdef PNG_sPLT_SUPPORTED -void PNGAPI -png_set_sPLT(png_const_structrp png_ptr, - png_inforp info_ptr, png_const_sPLT_tp entries, int nentries) +void +png_set_sPLT(const png_struct *png_ptr, + png_info *info_ptr, const png_sPLT_t *entries, int nentries) /* * entries - array of png_sPLT_t structures * to be added to the list of palettes @@ -1028,7 +1280,10 @@ png_set_sPLT(png_const_structrp png_ptr, * added. */ { - png_sPLT_tp np; + png_sPLT_t *np; + png_sPLT_t *old_spalettes; + + png_debug1(1, "in %s storage function", "sPLT"); if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL) return; @@ -1036,7 +1291,7 @@ png_set_sPLT(png_const_structrp png_ptr, /* Use the internal realloc function, which checks for all the possible * overflows. Notice that the parameters are (int) and (size_t) */ - np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr, + np = png_voidcast(png_sPLT_t *,png_realloc_array(png_ptr, info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries, sizeof *np)); @@ -1044,11 +1299,14 @@ png_set_sPLT(png_const_structrp png_ptr, { /* Out of memory or too many chunks */ png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR); - return; } - png_free(png_ptr, info_ptr->splt_palettes); + /* Defer freeing the old array until after the copy loop below, + * in case entries aliases info_ptr->splt_palettes (getter-to-setter). + */ + old_spalettes = info_ptr->splt_palettes; + info_ptr->splt_palettes = np; info_ptr->free_me |= PNG_FREE_SPLT; @@ -1056,7 +1314,7 @@ png_set_sPLT(png_const_structrp png_ptr, do { - png_size_t length; + size_t length; /* Skip invalid input entries */ if (entries->name == NULL || entries->entries == NULL) @@ -1073,7 +1331,7 @@ png_set_sPLT(png_const_structrp png_ptr, * on trying to add sPLT chunks. */ length = strlen(entries->name) + 1; - np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length)); + np->name = png_voidcast(char *, png_malloc_base(png_ptr, length)); if (np->name == NULL) break; @@ -1084,7 +1342,7 @@ png_set_sPLT(png_const_structrp png_ptr, * goes wrong; this code must free it. png_malloc_array produces no * warnings; use a png_chunk_report (below) if there is an error. */ - np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr, + np->entries = png_voidcast(png_sPLT_entry *, png_malloc_array(png_ptr, entries->nentries, sizeof (png_sPLT_entry))); if (np->entries == NULL) @@ -1107,8 +1365,11 @@ png_set_sPLT(png_const_structrp png_ptr, info_ptr->valid |= PNG_INFO_sPLT; ++(info_ptr->splt_palettes_num); ++np; + ++entries; } - while (++entries, --nentries); + while (--nentries); + + png_free(png_ptr, old_spalettes); if (nentries > 0) png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR); @@ -1117,147 +1378,145 @@ png_set_sPLT(png_const_structrp png_ptr, #ifdef PNG_APNG_SUPPORTED png_uint_32 PNGAPI -png_set_acTL(png_structp png_ptr, png_infop info_ptr, - png_uint_32 num_frames, png_uint_32 num_plays) +png_set_acTL(png_struct *png_ptr, png_info *info_ptr, + png_uint_32 num_frames, png_uint_32 num_plays) { - png_debug1(1, "in %s storage function", "acTL"); - - if (png_ptr == NULL || info_ptr == NULL) - { - png_warning(png_ptr, - "Call to png_set_acTL() with NULL png_ptr " - "or info_ptr ignored"); - return (0); - } - if (num_frames == 0) - { - png_warning(png_ptr, - "Ignoring attempt to set acTL with num_frames zero"); - return (0); - } - if (num_frames > PNG_UINT_31_MAX) - { - png_warning(png_ptr, - "Ignoring attempt to set acTL with num_frames > 2^31-1"); - return (0); - } - if (num_plays > PNG_UINT_31_MAX) - { - png_warning(png_ptr, - "Ignoring attempt to set acTL with num_plays > 2^31-1"); - return (0); - } - - info_ptr->num_frames = num_frames; - info_ptr->num_plays = num_plays; - - info_ptr->valid |= PNG_INFO_acTL; - - return (1); + png_debug1(1, "in %s storage function", "acTL"); + + if (png_ptr == NULL || info_ptr == NULL) + { + png_warning(png_ptr, + "Ignoring call to png_set_acTL with NULL libpng object args"); + return 0; + } + if (num_frames == 0) + { + png_warning(png_ptr, + "Ignoring attempt to set acTL with num_frames zero"); + return 0; + } + if (num_frames > PNG_UINT_31_MAX) + { + png_warning(png_ptr, + "Ignoring attempt to set acTL with num_frames > 2^31-1"); + return 0; + } + if (num_plays > PNG_UINT_31_MAX) + { + png_warning(png_ptr, + "Ignoring attempt to set acTL with num_plays > 2^31-1"); + return 0; + } + + info_ptr->num_frames = num_frames; + info_ptr->num_plays = num_plays; + + info_ptr->valid |= PNG_INFO_acTL; + + return 1; } -/* delay_num and delay_den can hold any 16-bit values including zero */ png_uint_32 PNGAPI -png_set_next_frame_fcTL(png_structp png_ptr, png_infop info_ptr, - png_uint_32 width, png_uint_32 height, - png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, - png_byte dispose_op, png_byte blend_op) +png_set_next_frame_fcTL(png_struct *png_ptr, png_info *info_ptr, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op) { - png_debug1(1, "in %s storage function", "fcTL"); - - if (png_ptr == NULL || info_ptr == NULL) - { - png_warning(png_ptr, - "Call to png_set_fcTL() with NULL png_ptr or info_ptr " - "ignored"); - return (0); - } - - png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, - delay_num, delay_den, dispose_op, blend_op); - - if (blend_op == PNG_BLEND_OP_OVER) - { - if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0 && - png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) == 0) - { - png_warning(png_ptr, "PNG_BLEND_OP_OVER is meaningless " - "and wasteful for opaque images, ignored"); - blend_op = PNG_BLEND_OP_SOURCE; - } - } - - info_ptr->next_frame_width = width; - info_ptr->next_frame_height = height; - info_ptr->next_frame_x_offset = x_offset; - info_ptr->next_frame_y_offset = y_offset; - info_ptr->next_frame_delay_num = delay_num; - info_ptr->next_frame_delay_den = delay_den; - info_ptr->next_frame_dispose_op = dispose_op; - info_ptr->next_frame_blend_op = blend_op; - - info_ptr->valid |= PNG_INFO_fcTL; - - return (1); + png_debug1(1, "in %s storage function", "fcTL"); + + if (png_ptr == NULL || info_ptr == NULL) + { + png_warning(png_ptr, + "Ignoring call to png_set_fcTL with NULL libpng object args"); + return 0; + } + + png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, + delay_num, delay_den, dispose_op, blend_op); + + /* No checking is required for delay_num and delay_den. + * They can hold any 16-bit value, including zero. + */ + + if (blend_op == PNG_fcTL_BLEND_OP_OVER) + { + if (!(png_ptr->color_type & PNG_COLOR_MASK_ALPHA) && + !(png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) + { + png_warning(png_ptr, + "Ignoring wasteful fcTL BLEND_OP_OVER in opaque images"); + blend_op = PNG_fcTL_BLEND_OP_SOURCE; + } + } + + info_ptr->next_frame_width = width; + info_ptr->next_frame_height = height; + info_ptr->next_frame_x_offset = x_offset; + info_ptr->next_frame_y_offset = y_offset; + info_ptr->next_frame_delay_num = delay_num; + info_ptr->next_frame_delay_den = delay_den; + info_ptr->next_frame_dispose_op = dispose_op; + info_ptr->next_frame_blend_op = blend_op; + + info_ptr->valid |= PNG_INFO_fcTL; + + return 1; } void /* PRIVATE */ -png_ensure_fcTL_is_valid(png_structp png_ptr, - png_uint_32 width, png_uint_32 height, - png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, - png_byte dispose_op, png_byte blend_op) +png_ensure_fcTL_is_valid(png_struct *png_ptr, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op) { - if (width == 0 || width > PNG_UINT_31_MAX) - png_error(png_ptr, "invalid width in fcTL (0 or > 2^31-1)"); - if (height == 0 || height > PNG_UINT_31_MAX) - png_error(png_ptr, "invalid height in fcTL (0 or > 2^31-1)"); - if (x_offset > PNG_UINT_31_MAX) - png_error(png_ptr, "invalid x_offset in fcTL (> 2^31-1)"); - if (y_offset > PNG_UINT_31_MAX) - png_error(png_ptr, "invalid y_offset in fcTL (> 2^31-1)"); - if (width + x_offset > png_ptr->first_frame_width || - height + y_offset > png_ptr->first_frame_height) - png_error(png_ptr, "dimensions of a frame are greater than " - "the ones in IHDR"); - - if (dispose_op != PNG_DISPOSE_OP_NONE && - dispose_op != PNG_DISPOSE_OP_BACKGROUND && - dispose_op != PNG_DISPOSE_OP_PREVIOUS) - png_error(png_ptr, "invalid dispose_op in fcTL"); - - if (blend_op != PNG_BLEND_OP_SOURCE && - blend_op != PNG_BLEND_OP_OVER) - png_error(png_ptr, "invalid blend_op in fcTL"); - - PNG_UNUSED(delay_num) - PNG_UNUSED(delay_den) + if (width == 0 || width > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid frame width in fcTL"); + if (height == 0 || height > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid frame height in fcTL"); + if (x_offset > PNG_UINT_31_MAX || y_offset > PNG_UINT_31_MAX) + png_error(png_ptr, "Invalid frame offset in fcTL"); + if (width + x_offset > png_ptr->first_frame_width || + height + y_offset > png_ptr->first_frame_height) + png_error(png_ptr, "Oversized frame in fcTL"); + + if (dispose_op != PNG_fcTL_DISPOSE_OP_NONE && + dispose_op != PNG_fcTL_DISPOSE_OP_BACKGROUND && + dispose_op != PNG_fcTL_DISPOSE_OP_PREVIOUS) + png_error(png_ptr, "Invalid dispose_op in fcTL"); + + if (blend_op != PNG_fcTL_BLEND_OP_SOURCE && + blend_op != PNG_fcTL_BLEND_OP_OVER) + png_error(png_ptr, "Invalid blend_op in fcTL"); + + PNG_UNUSED(delay_num) + PNG_UNUSED(delay_den) } png_uint_32 PNGAPI -png_set_first_frame_is_hidden(png_structp png_ptr, png_infop info_ptr, +png_set_first_frame_is_hidden(png_struct *png_ptr, png_info *info_ptr, png_byte is_hidden) { - png_debug(1, "in png_first_frame_is_hidden()"); + png_debug(1, "in png_first_frame_is_hidden"); - if (png_ptr == NULL) - return 0; + if (png_ptr == NULL) + return 0; - if (is_hidden != 0) - png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; - else - png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN; + if (is_hidden) + png_ptr->apng_flags |= PNG_FIRST_FRAME_HIDDEN; + else + png_ptr->apng_flags &= ~PNG_FIRST_FRAME_HIDDEN; - PNG_UNUSED(info_ptr) + PNG_UNUSED(info_ptr) - return 1; + return 1; } -#endif /* APNG */ +#endif /* PNG_APNG_SUPPORTED */ #ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED static png_byte -check_location(png_const_structrp png_ptr, int location) +check_location(const png_struct *png_ptr, int location) { location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT); @@ -1293,11 +1552,12 @@ check_location(png_const_structrp png_ptr, int location) return (png_byte)location; } -void PNGAPI -png_set_unknown_chunks(png_const_structrp png_ptr, - png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns) +void +png_set_unknown_chunks(const png_struct *png_ptr, + png_info *info_ptr, const png_unknown_chunk *unknowns, int num_unknowns) { - png_unknown_chunkp np; + png_unknown_chunk *np; + png_unknown_chunk *old_unknowns; if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 || unknowns == NULL) @@ -1333,7 +1593,7 @@ png_set_unknown_chunks(png_const_structrp png_ptr, * undefined behavior. Now png_chunk_report is used to provide behavior * appropriate to read or write. */ - np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr, + np = png_voidcast(png_unknown_chunk *, png_realloc_array(png_ptr, info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns, sizeof *np)); @@ -1341,11 +1601,14 @@ png_set_unknown_chunks(png_const_structrp png_ptr, { png_chunk_report(png_ptr, "too many unknown chunks", PNG_CHUNK_WRITE_ERROR); - return; } - png_free(png_ptr, info_ptr->unknown_chunks); + /* Defer freeing the old array until after the copy loop below, + * in case unknowns aliases info_ptr->unknown_chunks (getter-to-setter). + */ + old_unknowns = info_ptr->unknown_chunks; + info_ptr->unknown_chunks = np; /* safe because it is initialized */ info_ptr->free_me |= PNG_FREE_UNKN; @@ -1368,7 +1631,7 @@ png_set_unknown_chunks(png_const_structrp png_ptr, else { - np->data = png_voidcast(png_bytep, + np->data = png_voidcast(png_byte *, png_malloc_base(png_ptr, unknowns->size)); if (np->data == NULL) @@ -1390,10 +1653,12 @@ png_set_unknown_chunks(png_const_structrp png_ptr, ++np; ++(info_ptr->unknown_chunks_num); } + + png_free(png_ptr, old_unknowns); } -void PNGAPI -png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr, +void +png_set_unknown_chunk_location(const png_struct *png_ptr, png_info *info_ptr, int chunk, int location) { /* This API is pretty pointless in 1.6.0 because the location can be set @@ -1422,8 +1687,8 @@ png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr, #endif /* STORE_UNKNOWN_CHUNKS */ #ifdef PNG_MNG_FEATURES_SUPPORTED -png_uint_32 PNGAPI -png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features) +png_uint_32 +png_permit_mng_features(png_struct *png_ptr, png_uint_32 mng_features) { png_debug(1, "in png_permit_mng_features"); @@ -1438,7 +1703,7 @@ png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features) #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED static unsigned int -add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep) +add_one_chunk(png_byte *list, unsigned int count, const png_byte *add, int keep) { unsigned int i; @@ -1465,11 +1730,11 @@ add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep) return count; } -void PNGAPI -png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, - png_const_bytep chunk_list, int num_chunks_in) +void +png_set_keep_unknown_chunks(png_struct *png_ptr, int keep, + const png_byte *chunk_list, int num_chunks_in) { - png_bytep new_list; + png_byte *new_list; unsigned int num_chunks, old_num_chunks; if (png_ptr == NULL) @@ -1496,13 +1761,20 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, /* Ignore all unknown chunks and all chunks recognized by * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND */ - static PNG_CONST png_byte chunks_to_ignore[] = { + static const png_byte chunks_to_ignore[] = { + 97, 99, 84, 76, '\0', /* acTL */ 98, 75, 71, 68, '\0', /* bKGD */ 99, 72, 82, 77, '\0', /* cHRM */ + 99, 73, 67, 80, '\0', /* cICP */ + 99, 76, 76, 73, '\0', /* cLLI */ + 101, 88, 73, 102, '\0', /* eXIf */ + 102, 99, 84, 76, '\0', /* fcTL */ + 102, 100, 65, 84, '\0', /* fdAT */ 103, 65, 77, 65, '\0', /* gAMA */ 104, 73, 83, 84, '\0', /* hIST */ 105, 67, 67, 80, '\0', /* iCCP */ 105, 84, 88, 116, '\0', /* iTXt */ + 109, 68, 67, 86, '\0', /* mDCV */ 111, 70, 70, 115, '\0', /* oFFs */ 112, 67, 65, 76, '\0', /* pCAL */ 112, 72, 89, 115, '\0', /* pHYs */ @@ -1554,7 +1826,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, */ if (keep != 0) { - new_list = png_voidcast(png_bytep, png_malloc(png_ptr, + new_list = png_voidcast(png_byte *, png_malloc(png_ptr, 5 * (num_chunks + old_num_chunks))); if (old_num_chunks > 0) @@ -1574,8 +1846,8 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep, */ if (new_list != NULL) { - png_const_bytep inlist; - png_bytep outlist; + const png_byte *inlist; + png_byte *outlist; unsigned int i; for (i=0; ivalid &= (unsigned int)(~mask); @@ -1728,10 +2002,12 @@ png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask) #ifdef PNG_SET_USER_LIMITS_SUPPORTED /* This function was added to libpng 1.2.6 */ -void PNGAPI -png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, +void +png_set_user_limits(png_struct *png_ptr, png_uint_32 user_width_max, png_uint_32 user_height_max) { + png_debug(1, "in png_set_user_limits"); + /* Images with dimensions larger than these limits will be * rejected by png_set_IHDR(). To accept any PNG datastream * regardless of dimensions, set both limits to 0x7fffffff. @@ -1744,27 +2020,47 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, } /* This function was added to libpng 1.4.0 */ -void PNGAPI -png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max) +void +png_set_chunk_cache_max(png_struct *png_ptr, png_uint_32 user_chunk_cache_max) { + png_debug(1, "in png_set_chunk_cache_max"); + if (png_ptr != NULL) png_ptr->user_chunk_cache_max = user_chunk_cache_max; } /* This function was added to libpng 1.4.1 */ -void PNGAPI -png_set_chunk_malloc_max (png_structrp png_ptr, +void +png_set_chunk_malloc_max(png_struct *png_ptr, png_alloc_size_t user_chunk_malloc_max) { + png_debug(1, "in png_set_chunk_malloc_max"); + + /* pngstruct::user_chunk_malloc_max is initialized to a non-zero value in + * png.c. This API supports '0' for unlimited, make sure the correct + * (unlimited) value is set here to avoid a need to check for 0 everywhere + * the parameter is used. + */ if (png_ptr != NULL) - png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; + { + if (user_chunk_malloc_max == 0U) /* unlimited */ + { +# ifdef PNG_MAX_MALLOC_64K + png_ptr->user_chunk_malloc_max = 65536U; +# else + png_ptr->user_chunk_malloc_max = PNG_SIZE_MAX; +# endif + } + else + png_ptr->user_chunk_malloc_max = user_chunk_malloc_max; + } } #endif /* ?SET_USER_LIMITS */ #ifdef PNG_BENIGN_ERRORS_SUPPORTED -void PNGAPI -png_set_benign_errors(png_structrp png_ptr, int allowed) +void +png_set_benign_errors(png_struct *png_ptr, int allowed) { png_debug(1, "in png_set_benign_errors"); @@ -1785,7 +2081,7 @@ png_set_benign_errors(png_structrp png_ptr, int allowed) #endif /* BENIGN_ERRORS */ #ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED - /* Whether to report invalid palette index; added at libng-1.5.10. + /* Whether to report invalid palette index; added at libpng-1.5.10. * It is possible for an indexed (color-type==3) PNG file to contain * pixels with invalid (out-of-range) indexes if the PLTE chunk has * fewer entries than the image's bit-depth would allow. We recover @@ -1793,8 +2089,8 @@ png_set_benign_errors(png_structrp png_ptr, int allowed) * (opaque black). By default, when this occurs libpng will issue * a benign error. This API can be used to override that behavior. */ -void PNGAPI -png_set_check_for_invalid_index(png_structrp png_ptr, int allowed) +void +png_set_check_for_invalid_index(png_struct *png_ptr, int allowed) { png_debug(1, "in png_set_check_for_invalid_index"); @@ -1819,10 +2115,10 @@ png_set_check_for_invalid_index(png_structrp png_ptr, int allowed) * valid one could not be generated, and the caller must png_error. */ png_uint_32 /* PRIVATE */ -png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) +png_check_keyword(png_struct *png_ptr, const char *key, png_byte *new_key) { #ifdef PNG_WARNINGS_SUPPORTED - png_const_charp orig_key = key; + const char *orig_key = key; #endif png_uint_32 key_len = 0; int bad_character = 0; @@ -1841,14 +2137,16 @@ png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) png_byte ch = (png_byte)*key++; if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/)) - *new_key++ = ch, ++key_len, space = 0; + { + *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; + *new_key++ = 32; ++key_len; space = 1; /* If the character was not a space then it is invalid. */ if (ch != 32) @@ -1861,7 +2159,7 @@ png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key) if (key_len > 0 && space != 0) /* trailing space */ { - --key_len, --new_key; + --key_len; --new_key; if (bad_character == 0) bad_character = 32; } diff --git a/media/libpng/pngsimd.c b/media/libpng/pngsimd.c new file mode 100644 index 0000000000..7bd7b5361b --- /dev/null +++ b/media/libpng/pngsimd.c @@ -0,0 +1,144 @@ +/* pngsimd.c - hardware (cpu/arch) specific code + * + * Copyright (c) 2018-2024 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * 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_TARGET_CODE_IMPLEMENTATION +/* This is set by pngtarget.h iff there is some target code to be compiled. + */ + +/* Each piece of separate hardware support code must have a "init" file defined + * in PNG_TARGET_CODE_IMPLEMENTATION and included here. + * + * The "check" header set PNG_TARGET_CODE_IMPLEMENTATION and that file *MUST* + * supply macro definitions as follows. Note that all functions must be static + * to avoid clashes with other implementations. + * + * png_target_impl + * string constant + * REQUIRED + * This must be a string naming the implementation. + * + * png_target_free_data_impl + * static void png_target_free_data_impl(png_struct *) + * REQUIRED if PNG_TARGET_STORES_DATA is defined + * UNDEFINED if PNG_TARGET_STORES_DATA is not defined + * A function to free data stored in png_struct::target_data. + * + * png_target_init_filter_functions_impl [flag: png_target_filters] + * OPTIONAL + * Contains code to overwrite the png_struct::read_filter array, see + * the definition of png_init_filter_functions. Need not be defined, + * only called if target_state contains png_target_filters. + * + * png_target_do_expand_palette_impl [flag: png_target_expand_palette] + * static function + * OPTIONAL + * Handles the transform. Need not be defined, only called if the + * state contains png_target_, may set this flag to zero, may + * return false to indicate that the transform was not done (so the + * C implementation must then execute). + * + * Note that pngtarget.h verifies that at least one thing is implemented, the + * checks below ensure that the corresponding _impl macro is defined. + */ + +/* This will fail in an obvious way with a meaningful error message if the file + * does not exist: + */ +#include PNG_TARGET_CODE_IMPLEMENTATION + +#ifndef png_target_impl +# error TARGET SPECIFIC CODE: PNG_TARGET_CODE_IMPLEMENTATION is defined but\ + png_hareware_impl is not +#endif + +#if defined(PNG_TARGET_STORES_DATA) != defined(png_target_free_data_impl) +# error TARGET SPECIFIC CODE: png_target_free_data_impl unexpected setting +#endif + +#if defined(PNG_TARGET_IMPLEMENTS_FILTERS) !=\ + defined(png_target_init_filter_functions_impl) +# error TARGET SPECIFIC CODE: png_target_init_filter_functions_impl unexpected\ + setting +#endif + +#if defined(PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE) !=\ + defined(png_target_do_expand_palette_impl) +# error TARGET SPECIFIC CODE: png_target_do_expand_palette_impl unexpected\ + setting +#endif + +void +png_target_init(png_struct *pp) +{ + /* Initialize png_struct::target_state if required. */ +# ifdef png_target_init_filter_functions_impl +# define PNG_TARGET_FILTER_SUPPORT png_target_filters +# else +# define PNG_TARGET_FILTER_SUPPORT 0U +# endif +# ifdef png_target_do_expand_palette_impl +# define PNG_TARGET_EXPAND_PALETTE_SUPPORT png_target_expand_palette +# else +# define PNG_TARGET_EXPAND_PALETTE_SUPPORT 0U +# endif + +# define PNG_TARGET_SUPPORT (PNG_TARGET_FILTER_SUPPORT |\ + PNG_TARGET_EXPAND_PALETTE_SUPPORT) + +# if PNG_TARGET_SUPPORT != 0U + pp->target_state = PNG_TARGET_SUPPORT; +# else + PNG_UNUSED(pp); +# endif +} + +#ifdef PNG_TARGET_STORES_DATA +void +png_target_free_data(png_struct *pp) +{ + /* Free any data allocated in the png_struct::target_data. + */ + if (pp->target_data != NULL) + { + png_target_free_data_impl(pp); + if (pp->target_data != NULL) + png_error(pp, png_target_impl ": allocated data not released"); + } +} +#endif + +#ifdef PNG_TARGET_IMPLEMENTS_FILTERS +void +png_target_init_filter_functions(png_struct *pp, unsigned int bpp) +{ + if (((pp->options >> PNG_TARGET_SPECIFIC_CODE) & 3) == PNG_OPTION_ON && + (pp->target_state & png_target_filters) != 0) + png_target_init_filter_functions_impl(pp, bpp); +} +#endif /* filters */ + +#ifdef PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE +int +png_target_do_expand_palette(png_struct *pp, png_row_info *rip) + /*const png_byte *row, const png_byte **ssp, const png_byte **ddp) */ +{ + /* This is exactly like 'png_do_expand_palette' except that there is a check + * on the options and target_state: + */ + return ((pp->options >> PNG_TARGET_SPECIFIC_CODE) & 3) == PNG_OPTION_ON && + (pp->target_state & png_target_expand_palette) != 0 && + png_target_do_expand_palette_impl(pp, rip, pp->row_buf + 1, + pp->palette, pp->trans_alpha, pp->num_trans); +} +#endif /* EXPAND_PALETTE */ +#endif /* PNG_TARGET_ARCH */ diff --git a/media/libpng/pngstruct.h b/media/libpng/pngstruct.h index 79af5e5e86..0bdeebfb05 100644 --- a/media/libpng/pngstruct.h +++ b/media/libpng/pngstruct.h @@ -1,21 +1,18 @@ - -/* pngstruct.h - header file for PNG reference library +/* pngstruct.h - internal structures for libpng * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ -/* The structure that holds the information to read and write PNG files. - * The only people who need to care about what is inside of this are the - * people who will be modifying the library for their own special needs. - * It should NOT be accessed directly by an application. - */ +#ifndef PNGPRIV_H +# error This file must not be included by applications; please include +#endif #ifndef PNGSTRUCT_H #define PNGSTRUCT_H @@ -33,21 +30,10 @@ # undef const #endif -/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility - * with older builds. - */ -#if ZLIB_VERNUM < 0x1260 -# define PNGZ_MSG_CAST(s) png_constcast(char*,s) -# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b) -#else -# define PNGZ_MSG_CAST(s) (s) -# define PNGZ_INPUT_CAST(b) (b) -#endif - /* 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 * 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 * 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.) @@ -62,7 +48,7 @@ typedef struct png_compression_buffer { struct png_compression_buffer *next; png_byte output[1]; /* actually zbuf_size */ -} png_compression_buffer, *png_compression_bufferp; +} png_compression_buffer; #define PNG_COMPRESSION_BUFFER_SIZE(pp)\ (offsetof(png_compression_buffer, output) + (pp)->zbuffer_size) @@ -70,13 +56,7 @@ typedef struct png_compression_buffer /* Colorspace support; structures used in png_struct, png_info and in internal * functions to hold and communicate information about the color space. - * - * PNG_COLORSPACE_SUPPORTED is only required if the application will perform - * colorspace corrections, otherwise all the colorspace information can be - * skipped and the size of libpng can be reduced (significantly) by compiling - * out the colorspace support. */ -#ifdef PNG_COLORSPACE_SUPPORTED /* The chromaticities of the red, green and blue colorants and the chromaticity * of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)). */ @@ -97,48 +77,36 @@ typedef struct png_XYZ png_fixed_point green_X, green_Y, green_Z; png_fixed_point blue_X, blue_Y, blue_Z; } png_XYZ; -#endif /* COLORSPACE */ -#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) -/* A colorspace is all the above plus, potentially, profile information; - * however at present libpng does not use the profile internally so it is only - * stored in the png_info struct (if iCCP is supported.) The rendering intent - * is retained here and is checked. - * - * The file gamma encoding information is also stored here and gamma correction - * is done by libpng, whereas color correction must currently be done by the - * application. +/* Chunk index values as an enum, PNG_INDEX_unknown is also a count of the + * number of chunks. */ -typedef struct png_colorspace +#define PNG_CHUNK(cHNK, i) PNG_INDEX_ ## cHNK = (i), +typedef enum { -#ifdef PNG_GAMMA_SUPPORTED - png_fixed_point gamma; /* File gamma */ -#endif - -#ifdef PNG_COLORSPACE_SUPPORTED - png_xy end_points_xy; /* End points as chromaticities */ - png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */ - png_uint_16 rendering_intent; /* Rendering intent of a profile */ -#endif + PNG_KNOWN_CHUNKS + PNG_INDEX_unknown +} png_index; +#undef PNG_CHUNK - /* Flags are always defined to simplify the code. */ - png_uint_16 flags; /* As defined below */ -} png_colorspace, * PNG_RESTRICT png_colorspacerp; +/* Chunk flag values. These are (png_uint_32 values) with exactly one bit set + * and can be combined into a flag set with bitwise 'or'. + * + * TODO: C23: convert these macros to C23 inlines (which are static). + */ +#define png_chunk_flag_from_index(i) (0x80000000U >> (31 - (i))) + /* The flag corresponding to the given png_index enum value. This is defined + * for png_unknown as well (until it reaches the value 32) but this should + * not be relied on. + */ -typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp; +#define png_file_has_chunk(png_ptr, i)\ + (((png_ptr)->chunks & png_chunk_flag_from_index(i)) != 0) + /* The chunk has been recorded in png_struct */ -/* General flags for the 'flags' field */ -#define PNG_COLORSPACE_HAVE_GAMMA 0x0001 -#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002 -#define PNG_COLORSPACE_HAVE_INTENT 0x0004 -#define PNG_COLORSPACE_FROM_gAMA 0x0008 -#define PNG_COLORSPACE_FROM_cHRM 0x0010 -#define PNG_COLORSPACE_FROM_sRGB 0x0020 -#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040 -#define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */ -#define PNG_COLORSPACE_INVALID 0x8000 -#define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags)) -#endif /* COLORSPACE || GAMMA */ +#define png_file_add_chunk(png_ptr, i)\ + ((void)((png_ptr)->chunks |= png_chunk_flag_from_index(i))) + /* Record the chunk in the png_struct */ struct png_struct_def { @@ -152,10 +120,10 @@ struct png_struct_def #ifdef PNG_WARNINGS_SUPPORTED png_error_ptr warning_fn; /* function for printing warnings */ #endif - png_voidp error_ptr; /* user supplied struct for error functions */ + void *error_ptr; /* user supplied struct for error functions */ png_rw_ptr write_data_fn; /* function for writing output data */ png_rw_ptr read_data_fn; /* function for reading input data */ - png_voidp io_ptr; /* ptr to application struct for I/O functions */ + void *io_ptr; /* ptr to application struct for I/O functions */ #ifdef PNG_READ_USER_TRANSFORM_SUPPORTED png_user_transform_ptr read_user_transform_fn; /* user read transform */ @@ -169,7 +137,7 @@ struct png_struct_def #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) - png_voidp user_transform_ptr; /* user supplied struct for user transform */ + void *user_transform_ptr; /* user supplied struct for user transform */ png_byte user_transform_depth; /* bit depth of user transformed pixels */ png_byte user_transform_channels; /* channels in user transformed pixels */ #endif @@ -183,7 +151,7 @@ struct png_struct_def z_stream zstream; /* decompression structure */ #ifdef PNG_WRITE_SUPPORTED - png_compression_bufferp zbuffer_list; /* Created on demand during write */ + png_compression_buffer *zbuffer_list; /* Created on demand during write */ uInt zbuffer_size; /* size of the actual buffer */ int zlib_level; /* holds zlib compression level */ @@ -210,33 +178,38 @@ struct png_struct_def int zlib_set_strategy; #endif + png_uint_32 chunks; /* PNG_CF_ for every chunk read or (NYI) written */ +# define png_has_chunk(png_ptr, cHNK)\ + png_file_has_chunk(png_ptr, PNG_INDEX_ ## cHNK) + /* Convenience accessor - use this to check for a known chunk by name */ + png_uint_32 width; /* width of image in pixels */ png_uint_32 height; /* height of image in pixels */ png_uint_32 num_rows; /* number of rows in current pass */ 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 row_number; /* current row in interlace pass */ png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ - png_bytep prev_row; /* buffer to save previous (unfiltered) row. + png_byte *prev_row; /* buffer to save previous (unfiltered) row. * While reading this is a pointer into * big_prev_row; while writing it is separately * allocated if needed. */ - png_bytep row_buf; /* buffer to save current (unfiltered) row. + png_byte *row_buf; /* buffer to save current (unfiltered) row. * While reading, this is a pointer into * big_row_buf; while writing it is separately * allocated. */ #ifdef PNG_WRITE_FILTER_SUPPORTED - png_bytep try_row; /* buffer to save trial row when filtering */ - png_bytep tst_row; /* buffer to save best trial row when filtering */ + png_byte *try_row; /* buffer to save trial row when filtering */ + png_byte *tst_row; /* buffer to save best trial row when filtering */ #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 crc; /* current chunk CRC value */ - png_colorp palette; /* palette from the input file */ + png_color *palette; /* palette from the input file */ png_uint_16 num_palette; /* number of color entries in palette */ /* Added at libpng-1.5.10 */ @@ -263,9 +236,7 @@ struct png_struct_def /* pixel depth used for the row buffers */ png_byte transformed_pixel_depth; /* 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) png_uint_16 filler; /* filler bytes for pixel expansion */ #endif @@ -286,33 +257,40 @@ struct png_struct_def png_uint_32 flush_rows; /* number of rows written since last flush */ #endif +#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED + png_xy chromaticities; /* From mDVC, cICP, [iCCP], sRGB or cHRM */ +#endif + #ifdef PNG_READ_GAMMA_SUPPORTED int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */ - png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */ + png_fixed_point screen_gamma; /* screen gamma value (display exponent) */ + png_fixed_point file_gamma; /* file gamma value (encoding exponent) */ + png_fixed_point chunk_gamma; /* from cICP, iCCP, sRGB or gAMA */ + png_fixed_point default_gamma;/* from png_set_alpha_mode */ - png_bytep gamma_table; /* gamma table for 8-bit depth files */ - png_uint_16pp gamma_16_table; /* gamma table for 16-bit depth files */ + png_byte *gamma_table; /* gamma table for 8-bit depth files */ + png_uint_16 **gamma_16_table; /* gamma table for 16-bit depth files */ #if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) - png_bytep gamma_from_1; /* converts from 1.0 to screen */ - png_bytep gamma_to_1; /* converts from file to 1.0 */ - png_uint_16pp gamma_16_from_1; /* converts from 1.0 to screen */ - png_uint_16pp gamma_16_to_1; /* converts from file to 1.0 */ + png_byte *gamma_from_1; /* converts from 1.0 to screen */ + png_byte *gamma_to_1; /* converts from file to 1.0 */ + png_uint_16 **gamma_16_from_1; /* converts from 1.0 to screen */ + png_uint_16 **gamma_16_to_1; /* converts from file to 1.0 */ #endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ -#endif +#endif /* READ_GAMMA */ #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_sBIT_SUPPORTED) png_color_8 sig_bit; /* significant bits in each available channel */ #endif #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 #if defined(PNG_tRNS_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) \ || defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) - png_bytep trans_alpha; /* alpha values for paletted files */ + png_byte *trans_alpha; /* alpha values for paletted files */ png_color_16 trans_color; /* transparent color for non-paletted files */ #endif @@ -322,62 +300,43 @@ struct png_struct_def png_progressive_info_ptr info_fn; /* called after header data fully read */ png_progressive_row_ptr row_fn; /* called after a prog. row is decoded */ png_progressive_end_ptr end_fn; /* called after image is complete */ - png_bytep save_buffer_ptr; /* current location in save_buffer */ - png_bytep save_buffer; /* buffer for previously read data */ - png_bytep current_buffer_ptr; /* current location in current_buffer */ - png_bytep current_buffer; /* buffer for recently used data */ + png_byte *save_buffer_ptr; /* current location in save_buffer */ + png_byte *save_buffer; /* buffer for previously read data */ + png_byte *current_buffer_ptr; /* current location in current_buffer */ + png_byte *current_buffer; /* buffer for recently used data */ png_uint_32 push_length; /* size of current input chunk */ png_uint_32 skip_length; /* bytes to skip in input data */ - png_size_t save_buffer_size; /* amount of data now in save_buffer */ - png_size_t save_buffer_max; /* total size of save_buffer */ - png_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 save_buffer_size; /* amount of data now in save_buffer */ + size_t save_buffer_max; /* total size of save_buffer */ + size_t buffer_size; /* total amount of available input data */ + size_t current_buffer_size; /* amount of data now in current_buffer */ int process_mode; /* what push library is currently doing */ int cur_palette; /* current push library palette index */ - #endif /* PROGRESSIVE_READ */ -#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__) -/* For the Borland special 64K segment handler */ - png_bytepp offset_table_ptr; - png_bytep offset_table; - png_uint_16 offset_table_number; - png_uint_16 offset_table_count; - png_uint_16 offset_table_count_free; -#endif - #ifdef PNG_READ_QUANTIZE_SUPPORTED - png_bytep palette_lookup; /* lookup table for quantizing */ - png_bytep quantize_index; /* index translation for palette files */ + png_byte *palette_lookup; /* lookup table for quantizing */ + png_byte *quantize_index; /* index translation for palette files */ #endif /* Options */ -#ifdef PNG_SET_OPTION_SUPPORTED - png_byte options; /* On/off state (up to 4 options) */ -#endif - -#if PNG_LIBPNG_VER < 10700 -/* To do: remove this from libpng-1.7 */ -#ifdef PNG_TIME_RFC1123_SUPPORTED - char time_buffer[29]; /* String to hold RFC 1123 time text */ -#endif -#endif + png_uint_32 options; /* On/off state (up to 16 options) */ /* New members added in libpng-1.0.6 */ png_uint_32 free_me; /* flags items libpng is responsible for freeing */ #ifdef PNG_USER_CHUNKS_SUPPORTED - png_voidp user_chunk_ptr; + void *user_chunk_ptr; #ifdef PNG_READ_USER_CHUNKS_SUPPORTED png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */ -#endif -#endif +#endif /* READ_USER_CHUNKS */ +#endif /* USER_CHUNKS */ #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED int unknown_default; /* As PNG_HANDLE_* */ unsigned int num_chunk_list; /* Number of entries in the list */ - png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name + png_byte * chunk_list; /* List of png_byte[5]; the textual chunk name * followed by a PNG_HANDLE_* byte */ #endif @@ -422,26 +381,25 @@ struct png_struct_def png_uint_32 num_frames_to_write; png_uint_32 num_frames_written; #endif -#endif /* APNG */ +#endif /* PNG_APNG_SUPPORTED */ /* New members added in libpng-1.2.0 */ /* New members added in libpng-1.0.2 but first enabled by default in 1.2.0 */ #ifdef PNG_USER_MEM_SUPPORTED - png_voidp mem_ptr; /* user supplied struct for mem functions */ + void *mem_ptr; /* user supplied struct for mem functions */ png_malloc_ptr malloc_fn; /* function for allocating memory */ png_free_ptr free_fn; /* function for freeing memory */ #endif /* New member added in libpng-1.0.13 and 1.2.0 */ - png_bytep big_row_buf; /* buffer to save current (unfiltered) row */ + png_byte *big_row_buf; /* buffer to save current (unfiltered) row */ #ifdef PNG_READ_QUANTIZE_SUPPORTED /* The following three members were added at version 1.0.14 and 1.2.4 */ - png_bytep quantize_sort; /* working sort array */ - png_bytep index_to_palette; /* where the original index currently is + png_byte *index_to_palette; /* where the original index currently is in the palette */ - png_bytep palette_to_index; /* which original index points to this + png_byte *palette_to_index; /* which original index points to this palette color */ #endif @@ -472,11 +430,11 @@ struct png_struct_def #endif /* 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 /* New member added in libpng-1.2.30 */ - png_bytep read_buffer; /* buffer for reading chunk data */ + png_byte * read_buffer; /* buffer for reading chunk data */ png_alloc_size_t read_buffer_size; /* current size of the buffer */ #endif #ifdef PNG_SEQUENTIAL_READ_SUPPORTED @@ -489,16 +447,23 @@ struct png_struct_def #endif /* New member added in libpng-1.5.6 */ - png_bytep big_prev_row; + png_byte *big_prev_row; /* New member added in libpng-1.5.7 */ - void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info, - png_bytep row, png_const_bytep prev_row); - -#ifdef PNG_READ_SUPPORTED -#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED) - png_colorspace colorspace; -#endif + void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_info *row_info, + png_byte *row, const png_byte *prev_row); + +/* NOTE: prior to libpng-1.8 this also checked that PNG_ARM_NEON_IMPLEMENTATION + * is defined, however it was always defined... The code also checked that + * READ_EXPAND is supported but that will lead to bugs when some hardware + * implementation uses it for some other palette related thing. + * [[libpng-1.8]] changed to target_data for storing arbitrary data. + */ +#ifdef PNG_TARGET_CODE_IMPLEMENTATION /* file providing target specific code */ +# ifdef PNG_TARGET_STORES_DATA + void * target_data; +# endif + png_uint_32 target_state; /* managed by libpng */ #endif }; #endif /* PNGSTRUCT_H */ diff --git a/media/libpng/pngtarget.h b/media/libpng/pngtarget.h new file mode 100644 index 0000000000..4ff0ea626f --- /dev/null +++ b/media/libpng/pngtarget.h @@ -0,0 +1,130 @@ +/* pngtarget.h - target configuration file for libpng + * + * libpng version 1.6.44.git + * + * Copyright (c) 2024 John Bowler + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * [[Added to libpng1.8]] + * + * This header file discovers whether the target machine has support for target + * (normally CPU) specific code such as SIMD instructions. It is included by + * pngpriv.h immediately after pnglibconf.h to establish compile-time (as + * opposed to configuration time) requirements for the build of libpng + * + * The header only defines a very limited number of macros and it only defines + * macros; no functions are declared, no types etc. + * + * Every target architecture must have the following file: + * + * /check.h + * + * This file contains checks based on compiler flags to determine if + * target-specific code can be implemented for this architecture with this set + * of compiler options. Define + * + * PNG_TARGET_CODE_IMPLEMENTATION + * + * To the quoted relative path name of a single C file to include to obtain the + * implementation of the target specific code. For example: + * + * "arm/arm_init.c" + * "intel/intel_init.c" + * + * This file will be included by pngsmid.c so the string must be a valid + * relative path name from that file. See the file pngsmid.c for the definition + * of what the C file must do. + * + * When it defines PNG_TARGET_CODE_IMPLEMENTATION the check file may also + * define: + * + * PNG_TARGET_STORES_DATA + * If set a void *pointer called "target_data" will be defined in + * pngstruct.h. The initialization code included in pngsimd.c must then + * also implement a function to free the data called png_target_free_data, + * see png_simd.c. + * + * PNG_TARGET_ROW_ALIGNMENT + * If set this defines a power-of-2 required memory alignment for rows + * passed to the read "filter". If not set this defaults to 1. + * + * PNG_TARGET_IMPLEMENTS_FILTERS + * If defined this indicates to the system that target specific + * implementations of the read filters may be available. This must be set + * to cause a target specific filter implementation to be used. + * + * PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE + * If defined this indicates to the system that target specific + * code for rgb_do_expand_palette is available. This must be defined to + * cause such implementations to be used. + * + * It MUST NOT define these macros unless it also defines + * PNG_TARGET_CODE_IMPLEMENTATION. At least one of the 'IMPLEMENTS' macros must + * be defined; this file will produce an error diagnostic if not. + * + * If the check.h file needs to define other macros, for example for use in the + * PNG_TARGET_CODE_IMPLEMENTATION file macros must have the form: + * + * PNG_TARGET__... + * + * Where ARCH the architecture directory (the directory containing check.h) in + * upper case. See pngsimd.c for more information about function definitions + * used to implement the code. + */ +#ifndef PNGTARGET_H +#define PNGTARGET_H + +#ifdef PNG_TARGET_SPECIFIC_CODE_SUPPORTED /* from pnglibconf.h */ +# ifdef PNG_READ_SUPPORTED /* checked here as a convenience */ +# include "arm/check.h" +# include "intel/check.h" +# include "loongarch/check.h" +# include "mips/check.h" +# include "powerpc/check.h" +#endif +#endif /* PNG_TARGET_SPECIFIC_CODE_SUPPORTED */ + +/* This is also a convenience to avoid checking in every check.h: */ +#ifndef PNG_READ_EXPAND_SUPPORTED +# undef PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE +#endif + +/* Now check the condition above. Note that these checks consider the composite + * result of all the above includes; if errors are preceded by warnings about + * redefinition of the macros those need to be fixed first. + */ +#ifdef PNG_TARGET_CODE_IMPLEMENTATION /* There is target-specific code */ +/* List all the supported target specific code types here: */ +# if !defined(PNG_TARGET_IMPLEMENTS_FILTERS) &&\ + !defined(PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE) +# error PNG_TARGET_CODE_IMPLEMENTATION without any implementations. + +/* Currently only row alignments which are a power of 2 and less than 17 are + * supported: the current code always aligns to 16 bytes (but may not in the + * future). + */ +# if defined(PNG_TARGET_ROW_ALIGNMENT) && (\ + PNG_TARGET_ROW_ALIGNMENT > 16 /*too big*/ ||\ + PNG_TARGET_ROW_ALIGNMENT !=\ + (PNG_TARGET_ROW_ALIGNMENT & -PNG_TARGET_ROW_ALIGNMENT)) /*!power of 2*/ +# error unsupported TARGET_ROW_ALIGNMENT +# endif /* PNG_TARGET_ROW_ALIGNMENT check */ +#endif /* Target specific code macro checks. */ +#endif /* PNG_TARGET_SPECIFIC_CODE_SUPPORTED */ + +#ifndef PNG_TARGET_CODE_IMPLEMENTATION +# if defined(PNG_TARGET_STORES_DATA) ||\ + defined(PNG_TARGET_ROW_ALIGNMENT) ||\ + defined(PNG_TARGET_IMPLEMENTS_FILTERS) ||\ + defined(PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE) +# error PNG_TARGET_ macro defined without target specfic code. +# endif /* Check PNG_TARGET_ macros are not defined. */ +#endif /* PNG_TARGET_CODE_IMPLEMENTATION */ + +#ifndef PNG_TARGET_ROW_ALIGNMENT +# define PNG_TARGET_ROW_ALIGNMENT 1 +#endif +#endif /* PNGTARGET_H */ diff --git a/media/libpng/pngtest.c b/media/libpng/pngtest.c new file mode 100644 index 0000000000..f1ff6eb21e --- /dev/null +++ b/media/libpng/pngtest.c @@ -0,0 +1,2296 @@ +/* pngtest.c - a test program for libpng + * + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * This program reads in a PNG image, writes it out again, and then + * compares the two files. If the files are identical, this shows that + * the basic chunk handling, filtering, and (de)compression code is working + * properly. It does not currently test all of the transforms, although + * it probably should. + * + * The program will report "FAIL" in certain legitimate cases: + * 1) when the compression level or filter selection method is changed. + * 2) when the maximum IDAT size (PNG_ZBUF_SIZE in pngconf.h) is not 8192. + * 3) unknown unsafe-to-copy ancillary chunks or unknown critical chunks + * exist in the input file. + * 4) others not listed here... + * In these cases, it is best to check with another tool such as "pngcheck" + * to see what the differences between the two files are. + * + * If a filename is given on the command-line, then this file is used + * for the input, rather than the default "pngtest.png". This allows + * testing a wide variety of files easily. You can also test a number + * of files at once by typing "pngtest -m file1.png file2.png ..." + */ + +#define _POSIX_SOURCE 1 + +#include +#include +#include +#define STDERR stdout + +#ifdef PNG_ZLIB_HEADER +# include PNG_ZLIB_HEADER /* defined by pnglibconf.h from 1.7 */ +#else +# include +#endif + +#include "png.h" + +/* This hack was introduced for historical reasons, and we are + * still keeping it in libpng-1.6.x for compatibility reasons. + */ +#define STDERR stdout + +/* Ensure that all version numbers in png.h are consistent with one another. */ +#if (PNG_LIBPNG_VER != PNG_LIBPNG_VER_MAJOR * 10000 + \ + PNG_LIBPNG_VER_MINOR * 100 + \ + PNG_LIBPNG_VER_RELEASE) || \ + (PNG_LIBPNG_VER_SHAREDLIB != PNG_LIBPNG_VER_MAJOR * 10 + \ + PNG_LIBPNG_VER_MINOR) || \ + (PNG_LIBPNG_VER_SHAREDLIB != PNG_LIBPNG_VER_SONUM) || \ + (PNG_LIBPNG_VER_SHAREDLIB != PNG_LIBPNG_VER_DLLNUM) +# error Inconsistent version numbers in "png.h" +#endif + +/* In version 1.6.1, we added support for the configure test harness, which + * uses 77 to indicate a skipped test. On the other hand, in cmake build tests, + * we still need to succeed on a skipped test, so: + */ +#if defined(HAVE_CONFIG_H) +# define SKIP 77 +#else +# define SKIP 0 +#endif + +/* Known chunks that exist in pngtest.png must be supported, or pngtest will + * fail simply as a result of re-ordering them. This may be fixed in the next + * generation of libpng. + * + * pngtest allocates a single row buffer for each row and overwrites it, + * therefore if the write side doesn't support the writing of interlaced images + * nothing can be done for an interlaced image (and the code below will fail + * horribly trying to write extra data after writing garbage). + */ +#if defined PNG_READ_SUPPORTED && /* else nothing can be done */ \ + defined PNG_READ_bKGD_SUPPORTED && \ + defined PNG_READ_cHRM_SUPPORTED && \ + defined PNG_READ_gAMA_SUPPORTED && \ + defined PNG_READ_oFFs_SUPPORTED && \ + defined PNG_READ_pCAL_SUPPORTED && \ + defined PNG_READ_pHYs_SUPPORTED && \ + defined PNG_READ_sBIT_SUPPORTED && \ + defined PNG_READ_sCAL_SUPPORTED && \ + defined PNG_READ_sRGB_SUPPORTED && \ + defined PNG_READ_sPLT_SUPPORTED && \ + defined PNG_READ_tEXt_SUPPORTED && \ + defined PNG_READ_tIME_SUPPORTED && \ + defined PNG_READ_zTXt_SUPPORTED && \ + (defined PNG_WRITE_INTERLACING_SUPPORTED || PNG_LIBPNG_VER >= 10700) + +/* Copied from pngpriv.h but only used in error messages below. */ +#ifndef PNG_ZBUF_SIZE +# define PNG_ZBUF_SIZE 8192 +#endif + +#ifndef PNG_DEBUG +# define PNG_DEBUG 0 +#endif + +#if PNG_DEBUG > 1 +# define pngtest_debug(m) ((void)fprintf(stderr, m "\n")) +# define pngtest_debug1(m, p1) ((void)fprintf(stderr, m "\n", p1)) +# define pngtest_debug2(m, p1, p2) ((void)fprintf(stderr, m "\n", p1, p2)) +#elif PNG_DEBUG == 0 || PNG_DEBUG == 1 +# define pngtest_debug(m) ((void)0) +# define pngtest_debug1(m, p1) ((void)0) +# define pngtest_debug2(m, p1, p2) ((void)0) +#else /* PNG_DEBUG < 0 */ +# error Bad PNG_DEBUG value +#endif + +/* Turn on CPU timing +#define PNGTEST_TIMING +*/ + +#ifndef PNG_FLOATING_POINT_SUPPORTED +#undef PNGTEST_TIMING +#endif + +#ifdef PNGTEST_TIMING +static float t_start, t_stop, t_decode, t_encode, t_misc; +#include +#endif + +#ifdef PNG_TIME_RFC1123_SUPPORTED +static int tIME_chunk_present = 0; +static char tIME_string[29] = "tIME chunk is not present"; +/* This use case is deprecated. + * See the declaration of png_convert_to_rfc1123_buffer for more details. + */ +#endif + +static int verbose = 0; +static int strict = 0; +static int relaxed = 0; +static int xfail = 0; +static int unsupported_chunks = 0; /* chunk unsupported by libpng in input */ +static int error_count = 0; /* count calls to png_error */ +static int warning_count = 0; /* count calls to png_warning */ + +/* Example of using row callbacks to make a simple progress meter */ +static int status_pass = 1; +static int status_dots_requested = 0; +static int status_dots = 1; + +static void +read_row_callback(png_struct *png_ptr, png_uint_32 row_number, int pass) +{ + /* The callback should always receive correct parameters. */ + if (png_ptr == NULL) + png_error(png_ptr, "read_row_callback: bad png_ptr"); + if (row_number > PNG_UINT_31_MAX) + png_error(png_ptr, "read_row_callback: bad row number"); + if (pass < 0 || pass > 7) + png_error(png_ptr, "read_row_callback: bad pass"); + + if (status_pass != pass) + { + fprintf(stdout, "\n Pass %d: ", pass); + status_pass = pass; + status_dots = 31; + } + + status_dots--; + + if (status_dots == 0) + { + fprintf(stdout, "\n "); + status_dots = 30; + } + + fprintf(stdout, "r"); +} + +#ifdef PNG_WRITE_SUPPORTED +static void +write_row_callback(png_struct *png_ptr, png_uint_32 row_number, int pass) +{ + /* The callback should always receive correct parameters. */ + if (png_ptr == NULL) + png_error(png_ptr, "write_row_callback: bad png_ptr"); + if (row_number > PNG_UINT_31_MAX) + png_error(png_ptr, "write_row_callback: bad row number"); + if (pass < 0 || pass > 7) + png_error(png_ptr, "write_row_callback: bad pass"); + + fprintf(stdout, "w"); +} +#endif + + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED +/* Example of using a user transform callback (doesn't do anything at present). + */ +static void +read_user_callback(png_struct *png_ptr, png_row_info *row_info, png_byte *data) +{ + /* The callback should always receive correct parameters. */ + if (png_ptr == NULL) + png_error(png_ptr, "read_user_callback: bad png_ptr"); + if (row_info == NULL) + png_error(png_ptr, "read_user_callback: bad row info"); + if (data == NULL) + png_error(png_ptr, "read_user_callback: bad data"); +} +#endif + +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED +/* Example of using user transform callback (we don't transform anything, + * but merely count the zero samples) + */ + +static png_uint_32 zero_samples; + +static void +count_zero_samples(png_struct *png_ptr, png_row_info *row_info, png_byte *data) +{ + png_byte *dp = data; + + /* The callback should always receive correct parameters. */ + if (png_ptr == NULL) + png_error(png_ptr, "count_zero_samples: bad png_ptr"); + if (row_info == NULL) + png_error(png_ptr, "count_zero_samples: bad row info"); + if (data == NULL) + png_error(png_ptr, "count_zero_samples: bad data"); + + /* Contents of row_info: + * png_uint_32 width width of row + * png_uint_32 rowbytes number of bytes in row + * png_byte color_type color type of pixels + * png_byte bit_depth bit depth of samples + * png_byte channels number of channels (1-4) + * png_byte pixel_depth bits per pixel (depth*channels) + */ + + /* Counts the number of zero samples (or zero pixels if color_type is 3 */ + + if (row_info->color_type == 0 || row_info->color_type == 3) + { + int pos = 0; + png_uint_32 n, nstop; + + for (n = 0, nstop = row_info->width; n < nstop; n++) + { + if (row_info->bit_depth == 1) + { + if (((*dp << pos++ ) & 0x80) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 2) + { + if (((*dp << (pos+=2)) & 0xc0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 4) + { + if (((*dp << (pos+=4)) & 0xf0) == 0) + zero_samples++; + + if (pos == 8) + { + pos = 0; + dp++; + } + } + + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + dp += 2; + } + } + } + else /* Other color types */ + { + png_uint_32 n, nstop; + int channel; + int color_channels = row_info->channels; + if (row_info->color_type > 3) + color_channels--; + + for (n = 0, nstop = row_info->width; n < nstop; n++) + { + for (channel = 0; channel < color_channels; channel++) + { + if (row_info->bit_depth == 8) + if (*dp++ == 0) + zero_samples++; + + if (row_info->bit_depth == 16) + { + if ((*dp | *(dp+1)) == 0) + zero_samples++; + + dp += 2; + } + } + if (row_info->color_type > 3) + { + dp++; + if (row_info->bit_depth == 16) + dp++; + } + } + } +} +#endif /* WRITE_USER_TRANSFORM */ + +#ifndef PNG_STDIO_SUPPORTED +/* START of code to validate stdio-free compilation */ +/* These copies of the default read/write functions come from pngrio.c and + * pngwio.c. They allow "don't include stdio" testing of the library. + * This is the function that does the actual reading of data. If you are + * not reading from a standard C stream, you should create a replacement + * read_data function and use it at run time with png_set_read_fn(), rather + * than changing the library. + */ + +#ifdef PNG_IO_STATE_SUPPORTED +void +pngtest_check_io_state(png_struct *png_ptr, size_t data_length, + png_uint_32 io_op) +{ + png_uint_32 io_state = png_get_io_state(png_ptr); + int err = 0; + + /* Check if the current operation (reading / writing) is as expected. */ + if ((io_state & PNG_IO_MASK_OP) != io_op) + png_error(png_ptr, "Incorrect operation in I/O state"); + + /* Check if the buffer size specific to the current location + * (file signature / header / data / crc) is as expected. + */ + switch ((io_state & PNG_IO_MASK_LOC) != 0) + { + case PNG_IO_SIGNATURE: + if (data_length > 8) + err = 1; + break; + case PNG_IO_CHUNK_HDR: + if (data_length != 8) + err = 1; + break; + case PNG_IO_CHUNK_DATA: + break; /* no restrictions here */ + case PNG_IO_CHUNK_CRC: + if (data_length != 4) + err = 1; + break; + default: + err = 1; /* uninitialized */ + } + if (err != 0) + png_error(png_ptr, "Bad I/O state or buffer size"); +} +#endif + +static void +pngtest_read_data(png_struct *png_ptr, png_byte *data, size_t length) +{ + size_t check = 0; + void *io_ptr; + + if (png_ptr == NULL) + png_error(png_ptr, "pngtest_read_data: bad png_ptr"); + + /* 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. + */ + io_ptr = png_get_io_ptr(png_ptr); + if (io_ptr != NULL) + check = fread(data, 1, length, (FILE *)io_ptr); + + if (check != length) + png_error(png_ptr, "Read Error"); + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_READING); +#endif +} + +#ifdef PNG_WRITE_FLUSH_SUPPORTED +static void +pngtest_flush(png_struct *png_ptr) +{ + if (png_ptr == NULL) + png_error(png_ptr, "pngtest_flush: bad png_ptr"); + + /* Do nothing; fflush() is said to be just a waste of energy. */ +} +#endif + +/* This is the function that does the actual writing of data. If you are + * not writing to a standard C stream, you should create a replacement + * write_data function and use it at run time with png_set_write_fn(), rather + * than changing the library. + */ +static void +pngtest_write_data(png_struct *png_ptr, png_byte *data, size_t length) +{ + size_t check; + + if (png_ptr == NULL) + png_error(png_ptr, "pngtest_write_data: bad png_ptr"); + + check = fwrite(data, 1, length, (FILE *)png_get_io_ptr(png_ptr)); + + if (check != length) + png_error(png_ptr, "Write Error"); + +#ifdef PNG_IO_STATE_SUPPORTED + pngtest_check_io_state(png_ptr, length, PNG_IO_WRITING); +#endif +} +#endif /* !STDIO */ + +/* This function is called when there is a warning, but the library thinks + * it can continue anyway. Replacement functions don't have to do anything + * here if you don't want to. In the default configuration, png_ptr is + * not used, but it is passed in case it may be useful. + */ +typedef struct +{ + const char *file_name; +} pngtest_error_parameters; + +static void +pngtest_warning(png_struct *png_ptr, const char *message) +{ + const char *name = "UNKNOWN (ERROR!)"; + pngtest_error_parameters *test = + (pngtest_error_parameters*)png_get_error_ptr(png_ptr); + + ++warning_count; + + if (test != NULL && test->file_name != NULL) + name = test->file_name; + + fprintf(STDERR, "\n%s: libpng warning: %s\n", name, message); +} + +/* This is the default error handling function. Note that replacements for + * this function MUST NOT RETURN, or the program will likely crash. This + * function is used by default, or if the program supplies NULL for the + * error function pointer in png_set_error_fn(). + */ +static void +pngtest_error(png_struct *png_ptr, const char *message) +{ + ++error_count; + + pngtest_warning(png_ptr, message); + /* We can return because png_error calls the default handler, which is + * actually OK in this case. + */ +} + +/* END of code to validate stdio-free compilation */ + +/* START of code to validate memory allocation and deallocation */ +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + +/* Allocate memory. For reasonable files, size should never exceed + * 64K. However, zlib may allocate more than 64K if you don't tell + * it not to. See zconf.h and png.h for more information. zlib does + * need to allocate exactly 64K, so whatever you call here must + * have the ability to do that. + * + * This piece of code can be compiled to validate max 64K allocations + * by setting MAXSEG_64K in zlib zconf.h *or* PNG_MAX_MALLOC_64K. + */ +typedef struct memory_information +{ + png_alloc_size_t size; + void *pointer; + struct memory_information *next; +} memory_information; +typedef memory_information *memory_infop; + +static memory_infop pinformation = NULL; +static int current_allocation = 0; +static int maximum_allocation = 0; +static int total_allocation = 0; +static int num_allocations = 0; + +void *png_debug_malloc(png_struct *png_ptr, + png_alloc_size_t size); +void png_debug_free(png_struct *png_ptr, void *ptr); + +void * +png_debug_malloc(png_struct *png_ptr, png_alloc_size_t size) +{ + /* png_malloc has already tested for NULL; png_create_struct calls + * png_debug_malloc directly, with png_ptr == NULL which is OK + */ + + if (size == 0) + return NULL; + + /* This calls the library allocator twice, once to get the requested + buffer and once to get a new free list entry. */ + { + /* Disable malloc_fn and free_fn */ + memory_infop pinfo; + png_set_mem_fn(png_ptr, NULL, NULL, NULL); + pinfo = (memory_infop)png_malloc(png_ptr, + (sizeof *pinfo)); + pinfo->size = size; + current_allocation += size; + total_allocation += size; + ++num_allocations; + + if (current_allocation > maximum_allocation) + maximum_allocation = current_allocation; + + pinfo->pointer = png_malloc(png_ptr, size); + /* Restore malloc_fn and free_fn */ + + png_set_mem_fn(png_ptr, + NULL, png_debug_malloc, png_debug_free); + + if (size != 0 && pinfo->pointer == NULL) + { + current_allocation -= size; + total_allocation -= size; + png_error(png_ptr, + "out of memory in pngtest->png_debug_malloc"); + } + + pinfo->next = pinformation; + pinformation = pinfo; + /* Make sure the caller isn't assuming zeroed memory. */ + memset(pinfo->pointer, 0xdd, pinfo->size); + + if (verbose != 0) + printf("png_malloc %lu bytes at %p\n", (unsigned long)size, + pinfo->pointer); + + return (void *)pinfo->pointer; + } +} + +/* Free a pointer. It is removed from the list at the same time. */ +void +png_debug_free(png_struct *png_ptr, void *ptr) +{ + if (png_ptr == NULL) + fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + + if (ptr == 0) + { +#if 0 /* This happens all the time. */ + fprintf(STDERR, "WARNING: freeing NULL pointer\n"); +#endif + return; + } + + /* Unlink the element from the list. */ + if (pinformation != NULL) + { + memory_infop *ppinfo = &pinformation; + + for (;;) + { + memory_infop pinfo = *ppinfo; + + if (pinfo->pointer == ptr) + { + *ppinfo = pinfo->next; + current_allocation -= pinfo->size; + if (current_allocation < 0) + fprintf(STDERR, "Duplicate free of memory\n"); + /* We must free the list element too, but first kill + the memory that is to be freed. */ + memset(ptr, 0x55, pinfo->size); + free(pinfo); + pinfo = NULL; + break; + } + + if (pinfo->next == NULL) + { + fprintf(STDERR, "Pointer %p not found\n", ptr); + break; + } + + ppinfo = &pinfo->next; + } + } + + /* Finally free the data. */ + if (verbose != 0) + printf("Freeing %p\n", ptr); + + if (ptr != NULL) + free(ptr); + ptr = NULL; +} +#endif /* USER_MEM && DEBUG */ +/* END of code to test memory allocation/deallocation */ + + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED +/* Demonstration of user chunk support of the sTER and vpAg chunks */ + +/* (sTER is a public chunk not yet known by libpng. vpAg is a private +chunk used in ImageMagick to store "virtual page" size). */ + +typedef struct user_chunk_info_def +{ + const png_info *info_ptr; + png_uint_32 vpAg_width, vpAg_height; + png_byte vpAg_units; + png_byte sTER_mode; + int location[2]; +} user_chunk_info; + +/* Used for location and order; zero means nothing. */ +#define have_sTER 0x01 +#define have_vpAg 0x02 +#define before_PLTE 0x10 +#define before_IDAT 0x20 +#define after_IDAT 0x40 + +static void +init_user_chunk_info(const png_info *info_ptr, user_chunk_info *chunk_data) +{ + memset(chunk_data, 0, sizeof(*chunk_data)); + chunk_data->info_ptr = info_ptr; +} + +static int +set_chunk_location(png_struct *png_ptr, user_chunk_info *chunk_data, int what) +{ + int location; + + if ((chunk_data->location[0] & what) != 0 || + (chunk_data->location[1] & what) != 0) + return 0; /* we already have one of these */ + + /* Find where we are (the code below zeroes info_ptr to indicate that the + * chunks before the first IDAT have been read.) + */ + if (chunk_data->info_ptr == NULL) /* after IDAT */ + location = what | after_IDAT; + + else if (png_get_valid(png_ptr, chunk_data->info_ptr, PNG_INFO_PLTE) != 0) + location = what | before_IDAT; + + else + location = what | before_PLTE; + + if (chunk_data->location[0] == 0) + chunk_data->location[0] = location; + + else + chunk_data->location[1] = location; + + return 1; /* handled */ +} + +static int +read_user_chunk_callback(png_struct *png_ptr, png_unknown_chunk *chunk) +{ + user_chunk_info *my_user_chunk_data = + (user_chunk_info*)png_get_user_chunk_ptr(png_ptr); + + if (my_user_chunk_data == NULL) + png_error(png_ptr, "lost pointer to user chunk data"); + + /* Return one of the following: + * return -n; chunk had an error + * return 0; did not recognize + * return n; success + * + * The unknown chunk structure contains the chunk data: + * png_byte name[5]; + * png_byte *data; + * size_t size; + * + * Note that libpng has already taken care of the CRC handling. + */ + + if (chunk->name[0] == 115 && chunk->name[1] == 84 && /* s T */ + chunk->name[2] == 69 && chunk->name[3] == 82) /* E R */ + { + /* Found sTER chunk */ + if (chunk->size != 1) + return -1; /* Error return */ + + if (chunk->data[0] != 0 && chunk->data[0] != 1) + return -1; /* Invalid mode */ + + if (set_chunk_location(png_ptr, my_user_chunk_data, have_sTER) != 0) + { + my_user_chunk_data->sTER_mode = chunk->data[0]; + return 1; + } + + else + return 0; /* duplicate sTER - give it to libpng */ + } + + if (chunk->name[0] != 118 || chunk->name[1] != 112 || /* v p */ + chunk->name[2] != 65 || chunk->name[3] != 103) /* A g */ + return 0; /* Did not recognize */ + + /* Found ImageMagick vpAg chunk */ + + if (chunk->size != 9) + return -1; /* Error return */ + + if (set_chunk_location(png_ptr, my_user_chunk_data, have_vpAg) == 0) + return 0; /* duplicate vpAg */ + + my_user_chunk_data->vpAg_width = png_get_uint_31(png_ptr, chunk->data); + my_user_chunk_data->vpAg_height = png_get_uint_31(png_ptr, chunk->data + 4); + my_user_chunk_data->vpAg_units = chunk->data[8]; + + return 1; +} + +#ifdef PNG_WRITE_SUPPORTED +static void +write_sTER_chunk(png_struct *write_ptr, user_chunk_info *data) +{ + png_byte sTER[5] = {115, 84, 69, 82, '\0'}; + + if (verbose != 0) + fprintf(STDERR, "\n stereo mode = %d\n", data->sTER_mode); + + png_write_chunk(write_ptr, sTER, &data->sTER_mode, 1); +} + +static void +write_vpAg_chunk(png_struct *write_ptr, user_chunk_info *data) +{ + png_byte vpAg[5] = {118, 112, 65, 103, '\0'}; + + png_byte vpag_chunk_data[9]; + + if (verbose != 0) + fprintf(STDERR, " vpAg = %lu x %lu, units = %d\n", + (unsigned long)data->vpAg_width, + (unsigned long)data->vpAg_height, + data->vpAg_units); + + png_save_uint_32(vpag_chunk_data, data->vpAg_width); + png_save_uint_32(vpag_chunk_data + 4, data->vpAg_height); + vpag_chunk_data[8] = data->vpAg_units; + png_write_chunk(write_ptr, vpAg, vpag_chunk_data, 9); +} + +static void +write_chunks(png_struct *write_ptr, user_chunk_info *data, int location) +{ + int i; + + /* Notice that this preserves the original chunk order, however chunks + * intercepted by the callback will be written *after* chunks passed to + * libpng. This will actually reverse a pair of sTER chunks or a pair of + * vpAg chunks, resulting in an error later. This is not worth worrying + * about - the chunks should not be duplicated! + */ + for (i = 0; i < 2; ++i) + { + if (data->location[i] == (location | have_sTER)) + write_sTER_chunk(write_ptr, data); + + else if (data->location[i] == (location | have_vpAg)) + write_vpAg_chunk(write_ptr, data); + } +} +#endif /* WRITE */ +#else /* !READ_USER_CHUNKS */ +# define write_chunks(pp,loc) ((void)0) +#endif +/* END of code to demonstrate user chunk support */ + +/* START of code to check that libpng has the required text support; this only + * checks for the write support because if read support is missing the chunk + * will simply not be reported back to pngtest. + */ +#ifdef PNG_TEXT_SUPPORTED +static void +pngtest_check_text_support(png_struct *png_ptr, png_text *text_ptr, + int num_text) +{ + while (num_text > 0) + { + switch (text_ptr[--num_text].compression) + { + case PNG_TEXT_COMPRESSION_NONE: + break; + + case PNG_TEXT_COMPRESSION_zTXt: +# ifndef PNG_WRITE_zTXt_SUPPORTED + ++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 + break; + + case PNG_ITXT_COMPRESSION_NONE: + case PNG_ITXT_COMPRESSION_zTXt: +# ifndef PNG_WRITE_iTXt_SUPPORTED + ++unsupported_chunks; + text_ptr[num_text].compression = PNG_TEXT_COMPRESSION_NONE; +# endif + break; + + default: + /* This is an error */ + png_error(png_ptr, "invalid text chunk compression field"); + break; + } + } +} +#endif +/* END of code to check that libpng has the required text support */ + +/* Test one file */ +static int +test_one_file(const char *inname, const char *outname) +{ + static FILE *fpin; + static FILE *fpout; /* "static" prevents setjmp corruption */ + pngtest_error_parameters error_parameters; + png_struct *read_ptr; + png_info *read_info_ptr; + png_info *end_info_ptr; +#ifdef PNG_WRITE_SUPPORTED + png_struct *write_ptr; + png_info *write_info_ptr; + png_info *write_end_info_ptr; +#ifdef PNG_WRITE_FILTER_SUPPORTED + int interlace_preserved = 1; +#endif /* WRITE_FILTER */ +#else /* !WRITE */ + png_struct *write_ptr = NULL; + png_info *write_info_ptr = NULL; + png_info *write_end_info_ptr = NULL; +#endif /* !WRITE */ + png_byte *row_buf; + png_uint_32 y; + png_uint_32 width, height; + int bit_depth, color_type; + user_chunk_info my_user_chunk_data; + int pass, num_passes; +#ifdef PNG_READ_APNG_SUPPORTED + png_uint_32 num_frames; + png_uint_32 num_plays; +#endif + + row_buf = NULL; + error_parameters.file_name = inname; + + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find input file %s\n", inname); + return 1; + } + + if ((fpout = fopen(outname, "wb")) == NULL) + { + fprintf(STDERR, "Could not open output file %s\n", outname); + fclose(fpin); + return 1; + } + + pngtest_debug("Allocating read and write structures"); +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + read_ptr = + png_create_read_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + read_ptr = + png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif + png_set_error_fn(read_ptr, &error_parameters, pngtest_error, + pngtest_warning); + +#ifdef PNG_WRITE_SUPPORTED +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + write_ptr = + png_create_write_struct_2(PNG_LIBPNG_VER_STRING, NULL, + NULL, NULL, NULL, png_debug_malloc, png_debug_free); +#else + write_ptr = + png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#endif + png_set_error_fn(write_ptr, &error_parameters, pngtest_error, + pngtest_warning); +#endif + pngtest_debug("Allocating read_info, write_info and end_info structures"); + read_info_ptr = png_create_info_struct(read_ptr); + end_info_ptr = png_create_info_struct(read_ptr); +#ifdef PNG_WRITE_SUPPORTED + write_info_ptr = png_create_info_struct(write_ptr); + write_end_info_ptr = png_create_info_struct(write_ptr); +#endif + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + init_user_chunk_info(read_info_ptr, &my_user_chunk_data); + png_set_read_user_chunk_fn(read_ptr, &my_user_chunk_data, + read_user_chunk_callback); +#endif + +#ifdef PNG_SETJMP_SUPPORTED + pngtest_debug("Setting jmpbuf for read struct"); + if (setjmp(png_jmpbuf(read_ptr))) + { + fprintf(STDERR, "%s -> %s: libpng read error\n", inname, outname); + png_free(read_ptr, row_buf); + row_buf = NULL; + if (verbose != 0) + fprintf(STDERR, " destroy read structs\n"); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#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_write_struct(&write_ptr, &write_info_ptr); +#endif + fclose(fpin); + fclose(fpout); + return 1; + } + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Setting jmpbuf for write struct"); + + if (setjmp(png_jmpbuf(write_ptr))) + { + 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); + if (verbose != 0) + fprintf(STDERR, " destroying write structs\n"); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + png_destroy_write_struct(&write_ptr, &write_info_ptr); + fclose(fpin); + fclose(fpout); + return 1; + } +#endif +#endif + +#ifdef PNG_BENIGN_ERRORS_SUPPORTED + if (strict != 0) + { + /* Treat png_benign_error() as errors on read */ + png_set_benign_errors(read_ptr, 0); + +# ifdef PNG_WRITE_SUPPORTED + /* Treat them as errors on write */ + png_set_benign_errors(write_ptr, 0); +# endif + + /* 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 + * changed with '--relaxed'. + */ + } + + else if (relaxed != 0) + { + /* Allow application (pngtest) errors and warnings to pass */ + png_set_benign_errors(read_ptr, 1); + + /* Turn off CRC checking while reading */ + 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 + +# ifdef PNG_WRITE_SUPPORTED + png_set_benign_errors(write_ptr, 1); +# endif + + } +#endif /* BENIGN_ERRORS */ + + pngtest_debug("Initializing input and output streams"); +#ifdef PNG_STDIO_SUPPORTED + png_init_io(read_ptr, fpin); +# ifdef PNG_WRITE_SUPPORTED + png_init_io(write_ptr, fpout); +# endif +#else + png_set_read_fn(read_ptr, (void *)fpin, pngtest_read_data); +# ifdef PNG_WRITE_SUPPORTED + png_set_write_fn(write_ptr, (void *)fpout, pngtest_write_data, +# ifdef PNG_WRITE_FLUSH_SUPPORTED + pngtest_flush); +# else + NULL); +# endif +# endif +#endif + + if (status_dots_requested == 1) + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, write_row_callback); +#endif + png_set_read_status_fn(read_ptr, read_row_callback); + } + + else + { +#ifdef PNG_WRITE_SUPPORTED + png_set_write_status_fn(write_ptr, NULL); +#endif + png_set_read_status_fn(read_ptr, NULL); + } + +#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED + png_set_read_user_transform_fn(read_ptr, read_user_callback); +#endif +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + zero_samples = 0; + png_set_write_user_transform_fn(write_ptr, count_zero_samples); +#endif + +#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + /* Preserve all the unknown chunks, if possible. If this is disabled, then + * even if the png_{get,set}_unknown_chunks stuff is enabled, we can't use + * libpng to *save* the unknown chunks on read (because we can't switch the + * save option on!) + * + * Notice that if SET_UNKNOWN_CHUNKS is *not* supported, the reader will + * discard all unknown chunks, and the writer will write them all. + */ +#ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED + png_set_keep_unknown_chunks(read_ptr, PNG_HANDLE_CHUNK_ALWAYS, + NULL, 0); +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_set_keep_unknown_chunks(write_ptr, PNG_HANDLE_CHUNK_ALWAYS, + NULL, 0); +#endif +#endif + + pngtest_debug("Reading info struct"); + png_read_info(read_ptr, read_info_ptr); + +#ifdef PNG_READ_USER_CHUNKS_SUPPORTED + /* This is a bit of a hack; there is no obvious way in the callback function + * to determine that the chunks before the first IDAT have been read, so + * remove the info_ptr (which is only used to determine position relative to + * PLTE) here to indicate that we are after the IDAT. + */ + my_user_chunk_data.info_ptr = NULL; +#endif + + pngtest_debug("Transferring info struct"); + { + int interlace_type, compression_type, filter_type; + + if (png_get_IHDR(read_ptr, read_info_ptr, &width, &height, &bit_depth, + &color_type, &interlace_type, &compression_type, &filter_type) != 0) + { + png_set_IHDR(write_ptr, write_info_ptr, width, height, bit_depth, + color_type, interlace_type, compression_type, filter_type); + /* num_passes may not be available below if interlace support is not + * provided by libpng for both read and write. + */ + switch (interlace_type) + { + case PNG_INTERLACE_NONE: + num_passes = 1; + break; + + case PNG_INTERLACE_ADAM7: + num_passes = 7; + break; + + default: + png_error(read_ptr, "invalid interlace type"); + /*NOT REACHED*/ + } + } + + else + png_error(read_ptr, "png_get_IHDR failed"); + } +#ifdef PNG_FIXED_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM_fixed(read_ptr, read_info_ptr, &white_x, &white_y, + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0) + { + png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + png_fixed_point gamma; + + if (png_get_gAMA_fixed(read_ptr, read_info_ptr, &gamma) != 0) + png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma); + } +#endif +#ifdef PNG_cLLI_SUPPORTED + { + png_uint_32 maxCLL; + png_uint_32 maxFALL; + + if (png_get_cLLI_fixed(read_ptr, read_info_ptr, &maxCLL, &maxFALL) != 0) + png_set_cLLI_fixed(write_ptr, write_info_ptr, maxCLL, maxFALL); + } +#endif +#ifdef PNG_mDCV_SUPPORTED + { + png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + png_uint_32 maxDL; + png_uint_32 minDL; + + if (png_get_mDCV_fixed(read_ptr, read_info_ptr, &white_x, &white_y, + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y, + &maxDL, &minDL) != 0) + png_set_mDCV_fixed(write_ptr, write_info_ptr, white_x, white_y, + red_x, red_y, green_x, green_y, blue_x, blue_y, + maxDL, minDL); + } +#endif +#else /* Use floating point versions */ +#ifdef PNG_FLOATING_POINT_SUPPORTED +#ifdef PNG_cHRM_SUPPORTED + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, + blue_y; + + if (png_get_cHRM(read_ptr, read_info_ptr, &white_x, &white_y, &red_x, + &red_y, &green_x, &green_y, &blue_x, &blue_y) != 0) + { + png_set_cHRM(write_ptr, write_info_ptr, white_x, white_y, red_x, + red_y, green_x, green_y, blue_x, blue_y); + } + } +#endif +#ifdef PNG_gAMA_SUPPORTED + { + double gamma; + + if (png_get_gAMA(read_ptr, read_info_ptr, &gamma) != 0) + png_set_gAMA(write_ptr, write_info_ptr, gamma); + } +#endif +#ifdef PNG_cLLI_SUPPORTED + { + double maxCLL; + double maxFALL; + + if (png_get_cLLI(read_ptr, read_info_ptr, &maxCLL, &maxFALL) != 0) + png_set_cLLI(write_ptr, write_info_ptr, maxCLL, maxFALL); + } +#endif +#ifdef PNG_mDCV_SUPPORTED + { + double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y; + double maxDL; + double minDL; + + if (png_get_mDCV(read_ptr, read_info_ptr, &white_x, &white_y, + &red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y, + &maxDL, &minDL) != 0) + png_set_mDCV(write_ptr, write_info_ptr, white_x, white_y, + red_x, red_y, green_x, green_y, blue_x, blue_y, + maxDL, minDL); + } +#endif +#endif /* Floating point */ +#endif /* Fixed point */ +#ifdef PNG_cICP_SUPPORTED + { + png_byte colour_primaries; + png_byte transfer_function; + png_byte matrix_coefficients; + png_byte video_full_range_flag; + + if (png_get_cICP(read_ptr, read_info_ptr, + &colour_primaries, &transfer_function, + &matrix_coefficients, &video_full_range_flag) != 0) + png_set_cICP(write_ptr, write_info_ptr, + colour_primaries, transfer_function, + matrix_coefficients, video_full_range_flag); + } +#endif +#ifdef PNG_iCCP_SUPPORTED + { + char *name; + png_byte *profile; + png_uint_32 proflen; + int compression_type; + + if (png_get_iCCP(read_ptr, read_info_ptr, &name, &compression_type, + &profile, &proflen) != 0) + { + png_set_iCCP(write_ptr, write_info_ptr, name, compression_type, + profile, proflen); + } + } +#endif +#ifdef PNG_sRGB_SUPPORTED + { + int intent; + + if (png_get_sRGB(read_ptr, read_info_ptr, &intent) != 0) + png_set_sRGB(write_ptr, write_info_ptr, intent); + } +#endif + { + png_color *palette; + int num_palette; + + if (png_get_PLTE(read_ptr, read_info_ptr, &palette, &num_palette) != 0) + png_set_PLTE(write_ptr, write_info_ptr, palette, num_palette); + } +#ifdef PNG_bKGD_SUPPORTED + { + png_color_16 *background; + + if (png_get_bKGD(read_ptr, read_info_ptr, &background) != 0) + png_set_bKGD(write_ptr, write_info_ptr, background); + } +#endif +#ifdef PNG_READ_eXIf_SUPPORTED + { + png_byte *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 + { + png_uint_16 *hist; + + if (png_get_hIST(read_ptr, read_info_ptr, &hist) != 0) + png_set_hIST(write_ptr, write_info_ptr, hist); + } +#endif +#ifdef PNG_oFFs_SUPPORTED + { + png_int_32 offset_x, offset_y; + int unit_type; + + if (png_get_oFFs(read_ptr, read_info_ptr, &offset_x, &offset_y, + &unit_type) != 0) + png_set_oFFs(write_ptr, write_info_ptr, offset_x, offset_y, unit_type); + } +#endif +#ifdef PNG_pCAL_SUPPORTED + { + char *purpose; + char *units; + char **params; + png_int_32 X0, X1; + int type, nparams; + + if (png_get_pCAL(read_ptr, read_info_ptr, &purpose, &X0, &X1, &type, + &nparams, &units, ¶ms) != 0) + png_set_pCAL(write_ptr, write_info_ptr, purpose, X0, X1, type, + nparams, units, params); + } +#endif +#ifdef PNG_pHYs_SUPPORTED + { + png_uint_32 res_x, res_y; + int unit_type; + + if (png_get_pHYs(read_ptr, read_info_ptr, &res_x, &res_y, + &unit_type) != 0) + png_set_pHYs(write_ptr, write_info_ptr, res_x, res_y, unit_type); + } +#endif +#ifdef PNG_sBIT_SUPPORTED + { + png_color_8 *sig_bit; + + if (png_get_sBIT(read_ptr, read_info_ptr, &sig_bit) != 0) + png_set_sBIT(write_ptr, write_info_ptr, sig_bit); + } +#endif +#ifdef PNG_sCAL_SUPPORTED +#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ + defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) + { + int unit; + double scal_width, scal_height; + + if (png_get_sCAL(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height) != 0) + png_set_sCAL(write_ptr, write_info_ptr, unit, scal_width, scal_height); + } +#else +#ifdef PNG_FIXED_POINT_SUPPORTED + { + int unit; + char *scal_width, *scal_height; + + if (png_get_sCAL_s(read_ptr, read_info_ptr, &unit, &scal_width, + &scal_height) != 0) + { + png_set_sCAL_s(write_ptr, write_info_ptr, unit, scal_width, + scal_height); + } + } +#endif +#endif +#endif + +#ifdef PNG_sPLT_SUPPORTED + { + png_sPLT_t *entries; + + int num_entries = png_get_sPLT(read_ptr, read_info_ptr, &entries); + if (num_entries != 0) + png_set_sPLT(write_ptr, write_info_ptr, entries, num_entries); + } +#endif + +#ifdef PNG_TEXT_SUPPORTED + { + png_text *text_ptr; + int num_text; + + if (png_get_text(read_ptr, read_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + + pngtest_check_text_support(read_ptr, text_ptr, num_text); + + if (verbose != 0) + { + int i; + + fprintf(STDERR,"\n"); + for (i = 0; i < num_text; i++) + { + fprintf(STDERR," Text compression[%d]=%d\n", + i, text_ptr[i].compression); + } + } + + png_set_text(write_ptr, write_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_tIME_SUPPORTED + { + png_time *mod_time; + + if (png_get_tIME(read_ptr, read_info_ptr, &mod_time) != 0) + { + png_set_tIME(write_ptr, write_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0) + tIME_string[(sizeof tIME_string) - 1] = '\0'; + + else + { + strncpy(tIME_string, "*** invalid time ***", (sizeof tIME_string)); + tIME_string[(sizeof tIME_string) - 1] = '\0'; + } + + tIME_chunk_present++; +#endif /* TIME_RFC1123 */ + } + } +#endif +#ifdef PNG_tRNS_SUPPORTED + { + png_byte *trans_alpha; + int num_trans; + png_color_16 *trans_color; + + if (png_get_tRNS(read_ptr, read_info_ptr, &trans_alpha, &num_trans, + &trans_color) != 0) + { + int sample_max = (1 << bit_depth); + /* libpng doesn't reject a tRNS chunk with out-of-range samples */ + if (!((color_type == PNG_COLOR_TYPE_GRAY && + (int)trans_color->gray > sample_max) || + (color_type == PNG_COLOR_TYPE_RGB && + ((int)trans_color->red > sample_max || + (int)trans_color->green > sample_max || + (int)trans_color->blue > sample_max)))) + png_set_tRNS(write_ptr, write_info_ptr, trans_alpha, num_trans, + trans_color); + } + } +#endif + +#ifdef PNG_READ_APNG_SUPPORTED + if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL)) + { + if (png_get_acTL(read_ptr, read_info_ptr, &num_frames, &num_plays)) + { + png_byte is_hidden; + pngtest_debug2("Handling acTL chunks (frames %ld, plays %ld)", + num_frames, num_plays); + png_set_acTL(write_ptr, write_info_ptr, num_frames, num_plays); + is_hidden = png_get_first_frame_is_hidden(read_ptr, read_info_ptr); + png_set_first_frame_is_hidden(write_ptr, write_info_ptr, is_hidden); + } + } +#endif + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunk *unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, read_info_ptr, + &unknowns); + + if (num_unknowns != 0) + png_set_unknown_chunks(write_ptr, write_info_ptr, unknowns, + num_unknowns); + } +#endif + +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Writing info struct"); + + /* Write the info in two steps so that if we write the 'unknown' chunks here + * they go to the correct place. + */ + png_write_info_before_PLTE(write_ptr, write_info_ptr); + + write_chunks(write_ptr, &my_user_chunk_data, before_PLTE); /* before PLTE */ + + png_write_info(write_ptr, write_info_ptr); + + write_chunks(write_ptr, &my_user_chunk_data, before_IDAT); /* after PLTE */ + + png_write_info(write_ptr, write_end_info_ptr); + + write_chunks(write_ptr, &my_user_chunk_data, 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 + + pngtest_debug("Writing row data"); + +#if defined(PNG_READ_INTERLACING_SUPPORTED) &&\ + defined(PNG_WRITE_INTERLACING_SUPPORTED) + /* Both must be defined for libpng to be able to handle the interlace, + * otherwise it gets handled below by simply reading and writing the passes + * 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 + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; +#endif +#ifdef PNG_READ_APNG_SUPPORTED + if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_acTL)) + { + png_uint_32 frame; + for (frame = 0; frame < num_frames; frame++) + { + png_uint_32 frame_width; + png_uint_32 frame_height; + png_uint_32 x_offset; + png_uint_32 y_offset; + png_uint_16 delay_num; + png_uint_16 delay_den; + png_byte dispose_op; + png_byte blend_op; + png_read_frame_head(read_ptr, read_info_ptr); + if (png_get_valid(read_ptr, read_info_ptr, PNG_INFO_fcTL)) + { + png_get_next_frame_fcTL(read_ptr, read_info_ptr, + &frame_width, &frame_height, + &x_offset, &y_offset, + &delay_num, &delay_den, + &dispose_op, &blend_op); + } + else + { + frame_width = width; + frame_height = height; + x_offset = 0; + y_offset = 0; + delay_num = 1; + delay_den = 1; + dispose_op = PNG_fcTL_DISPOSE_OP_NONE; + blend_op = PNG_fcTL_BLEND_OP_SOURCE; + } +#ifdef PNG_WRITE_APNG_SUPPORTED + png_write_frame_head(write_ptr, write_info_ptr, (png_byte **)&row_buf, + frame_width, frame_height, + x_offset, y_offset, + delay_num, delay_den, + dispose_op, blend_op); +#endif + 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(frame_width, pass) > 0) + pass_height = PNG_PASS_ROWS(frame_height, pass); + + else + pass_height = 0; + } + + else /* not interlaced */ + pass_height = frame_height; +# else +# define pass_height frame_height +# endif + + pngtest_debug1("Writing row data for pass %d", pass); + for (y = 0; y < pass_height; y++) + { +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", + pass, y); + + row_buf = (png_byte *)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug2("\t0x%08lx (%lu bytes)", (unsigned long)row_buf, + (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr)); +#endif /* !SINGLE_ROWBUF_ALLOC */ + + png_read_rows(read_ptr, (png_byte **)&row_buf, NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_byte **)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* PNG_WRITE_SUPPORTED */ + +#ifndef SINGLE_ROWBUF_ALLOC + pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y); + png_free(read_ptr, row_buf); + row_buf = NULL; +#endif /* !SINGLE_ROWBUF_ALLOC */ + } +# ifdef pass_height +# undef pass_height +# endif + } +#ifdef PNG_WRITE_APNG_SUPPORTED + png_write_frame_tail(write_ptr, write_info_ptr); +#endif + } + } + else +#endif + 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); + for (y = 0; y < pass_height; y++) + { + pngtest_debug2("Allocating row buffer (pass %d, y = %u)...", pass, y); + + row_buf = (png_byte *)png_malloc(read_ptr, + png_get_rowbytes(read_ptr, read_info_ptr)); + + pngtest_debug2("\t%p (%lu bytes)", row_buf, + (unsigned long)png_get_rowbytes(read_ptr, read_info_ptr)); + + png_read_rows(read_ptr, (png_byte **)&row_buf, NULL, 1); + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_decode += (t_stop - t_start); + t_start = t_stop; +#endif + png_write_rows(write_ptr, (png_byte **)&row_buf, 1); +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_encode += (t_stop - t_start); + t_start = t_stop; +#endif +#endif /* WRITE */ + + pngtest_debug2("Freeing row buffer (pass %d, y = %u)", pass, y); + png_free(read_ptr, row_buf); + row_buf = NULL; + } +# ifdef pass_height +# undef pass_height +# endif + } + +#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED +# ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(read_ptr, read_info_ptr, PNG_FREE_UNKN, -1); +# endif +# ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + png_free_data(write_ptr, write_info_ptr, PNG_FREE_UNKN, -1); +# endif +#endif + + pngtest_debug("Reading and writing end_info data"); + + png_read_end(read_ptr, end_info_ptr); +#ifdef PNG_TEXT_SUPPORTED + { + png_text *text_ptr; + int num_text; + + if (png_get_text(read_ptr, end_info_ptr, &text_ptr, &num_text) > 0) + { + pngtest_debug1("Handling %d iTXt/tEXt/zTXt chunks", num_text); + + pngtest_check_text_support(read_ptr, text_ptr, num_text); + + if (verbose != 0) + { + int i; + + fprintf(STDERR,"\n"); + for (i = 0; i < num_text; i++) + { + fprintf(STDERR," Text compression[%d]=%d\n", + i, text_ptr[i].compression); + } + } + + png_set_text(write_ptr, write_end_info_ptr, text_ptr, num_text); + } + } +#endif +#ifdef PNG_READ_eXIf_SUPPORTED + { + png_byte *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 + { + png_time *mod_time; + + if (png_get_tIME(read_ptr, end_info_ptr, &mod_time) != 0) + { + png_set_tIME(write_ptr, write_end_info_ptr, mod_time); +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (png_convert_to_rfc1123_buffer(tIME_string, mod_time) != 0) + tIME_string[(sizeof tIME_string) - 1] = '\0'; + + else + { + strncpy(tIME_string, "*** invalid time ***", sizeof tIME_string); + tIME_string[(sizeof tIME_string)-1] = '\0'; + } + + tIME_chunk_present++; +#endif /* TIME_RFC1123 */ + } + } +#endif +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + { + png_unknown_chunk *unknowns; + int num_unknowns = png_get_unknown_chunks(read_ptr, end_info_ptr, + &unknowns); + + if (num_unknowns != 0) + png_set_unknown_chunks(write_ptr, write_end_info_ptr, unknowns, + num_unknowns); + } +#endif + +#ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED + /* Normally one would use Z_DEFAULT_STRATEGY for text compression. + * This is here just to make pngtest replicate the results from libpng + * versions prior to 1.5.4, and to test this new API. + */ + png_set_text_compression_strategy(write_ptr, Z_FILTERED); +#endif + + /* When the unknown vpAg/sTER chunks are written by pngtest the only way to + * do it is to write them *before* calling png_write_end. When unknown + * chunks are written by libpng, however, they are written just before IEND. + * There seems to be no way round this, however vpAg/sTER are not expected + * after IDAT. + */ + write_chunks(write_ptr, &my_user_chunk_data, after_IDAT); + + png_write_end(write_ptr, write_end_info_ptr); +#endif + +#ifdef PNG_EASY_ACCESS_SUPPORTED + if (verbose != 0) + { + png_uint_32 iwidth, iheight; + iwidth = png_get_image_width(write_ptr, write_info_ptr); + iheight = png_get_image_height(write_ptr, write_info_ptr); + fprintf(STDERR, "\n Image width = %lu, height = %lu\n", + (unsigned long)iwidth, (unsigned long)iheight); + } +#endif + + pngtest_debug("Destroying data structs"); + pngtest_debug("Destroying read_ptr, read_info_ptr, end_info_ptr"); + png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); +#ifdef PNG_WRITE_SUPPORTED + pngtest_debug("Destroying write_end_info_ptr"); + png_destroy_info_struct(write_ptr, &write_end_info_ptr); + pngtest_debug("Destroying write_ptr, write_info_ptr"); + png_destroy_write_struct(&write_ptr, &write_info_ptr); +#endif + pngtest_debug("Destruction complete."); + + fclose(fpin); + fclose(fpout); + + /* Summarize any warnings or errors and in 'strict' mode fail the test. + * Unsupported chunks can result in warnings, in that case ignore the strict + * setting, otherwise fail the test on warnings as well as errors. + */ + if (error_count > 0) + { + /* We don't really expect to get here because of the setjmp handling + * above, but this is safe. + */ + fprintf(STDERR, "\n %s: %d libpng errors found (%d warnings)", + inname, error_count, warning_count); + + if (strict != 0) + return 1; + } + +# ifdef PNG_WRITE_SUPPORTED + /* If there is no write support nothing was written! */ + else if (unsupported_chunks > 0) + { + fprintf(STDERR, "\n %s: unsupported chunks (%d)%s", + inname, unsupported_chunks, strict ? ": IGNORED --strict!" : ""); + } +# endif + + else if (warning_count > 0) + { + fprintf(STDERR, "\n %s: %d libpng warnings found", + inname, warning_count); + + if (strict != 0) + return 1; + } + + pngtest_debug("Opening files for comparison"); + if ((fpin = fopen(inname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", inname); + return 1; + } + + if ((fpout = fopen(outname, "rb")) == NULL) + { + fprintf(STDERR, "Could not find file %s\n", outname); + fclose(fpin); + return 1; + } + +#if defined (PNG_WRITE_SUPPORTED) /* else nothing was written */ &&\ + defined (PNG_WRITE_FILTER_SUPPORTED) + if (interlace_preserved != 0) /* else the files will be changed */ + { + for (;;) + { + static int wrote_question = 0; + size_t num_in, num_out; + char inbuf[256], outbuf[256]; + + num_in = fread(inbuf, 1, sizeof inbuf, fpin); + num_out = fread(outbuf, 1, sizeof outbuf, fpout); + + if (num_in != num_out) + { + fprintf(STDERR, "\nFiles %s and %s are of a different size\n", + inname, outname); + + if (wrote_question == 0 && unsupported_chunks == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum IDAT" + " chunk size (%d bytes),\n", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + " compression level (zlib default),\n"); + fprintf(STDERR, + " and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + fclose(fpin); + fclose(fpout); + + if (strict != 0 && unsupported_chunks == 0) + return 1; + + else + return 0; + } + + if (num_in == 0) + break; + + if (memcmp(inbuf, outbuf, num_in)) + { + fprintf(STDERR, "\nFiles %s and %s are different\n", inname, + outname); + + if (wrote_question == 0 && unsupported_chunks == 0) + { + fprintf(STDERR, + " Was %s written with the same maximum" + " IDAT chunk size (%d bytes),\n", + inname, PNG_ZBUF_SIZE); + fprintf(STDERR, + " compression level (zlib default),\n"); + fprintf(STDERR, + " and zlib version (%s)?\n\n", + ZLIB_VERSION); + wrote_question = 1; + } + + fclose(fpin); + fclose(fpout); + + /* NOTE: the unsupported_chunks escape is permitted here because + * unsupported text chunk compression will result in the compression + * mode being changed (to NONE) yet, in the test case, the result + * can be exactly the same size! + */ + if (strict != 0 && unsupported_chunks == 0) + return 1; + + else + return 0; + } + } + } +#endif /* WRITE && WRITE_FILTER */ + + fclose(fpin); + fclose(fpout); + + return 0; +} + +/* Input and output filenames */ +#ifdef RISCOS +static const char *inname = "pngtest/png"; +static const char *outname = "pngout/png"; +#else +static const char *inname = "pngtest.png"; +static const char *outname = "pngout.png"; +#endif + +int +main(int argc, char *argv[]) +{ + int multiple = 0; + int ierror = 0; + + png_struct *dummy_ptr; + + fprintf(STDERR, "\n Testing libpng version %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " with zlib version %s\n", ZLIB_VERSION); + fprintf(STDERR, "%s", png_get_copyright(NULL)); + /* Show the version of libpng used in building the library */ + fprintf(STDERR, " library (%lu):%s", + (unsigned long)png_access_version_number(), + png_get_header_version(NULL)); + + /* Show the version of libpng used in building the application */ + fprintf(STDERR, " pngtest (%lu):%s", (unsigned long)PNG_LIBPNG_VER, + PNG_HEADER_VERSION_STRING); + + /* Do some consistency checking on the memory allocation settings, I'm + * not sure this matters, but it is nice to know, the first of these + * tests should be impossible because of the way the macros are set + * in pngconf.h + */ +#if defined(MAXSEG_64K) && !defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: Zlib compiled for max 64k, libpng not\n"); +#endif + /* I think the following can happen. */ +#if !defined(MAXSEG_64K) && defined(PNG_MAX_MALLOC_64K) + fprintf(STDERR, " NOTE: libpng compiled for max 64k, zlib not\n"); +#endif + + if (strcmp(png_libpng_ver, PNG_LIBPNG_VER_STRING) != 0) + { + fprintf(STDERR, "Warning: mismatching versions of png.h and png.c\n"); + fprintf(STDERR, " png.h version string: %s\n", PNG_LIBPNG_VER_STRING); + fprintf(STDERR, " png.c version string: %s\n\n", png_libpng_ver); + ++ierror; + } + + if (argc > 1) + { + if (strcmp(argv[1], "-m") == 0) + { + multiple = 1; + status_dots_requested = 0; + } + + else if (strcmp(argv[1], "-mv") == 0 || + strcmp(argv[1], "-vm") == 0 ) + { + multiple = 1; + verbose = 1; + status_dots_requested = 1; + } + + else if (strcmp(argv[1], "-v") == 0) + { + verbose = 1; + status_dots_requested = 1; + inname = argv[2]; + } + + else if (strcmp(argv[1], "--strict") == 0) + { + status_dots_requested = 0; + verbose = 1; + inname = argv[2]; + strict++; + relaxed = 0; + multiple = 1; + } + + else if (strcmp(argv[1], "--relaxed") == 0) + { + status_dots_requested = 0; + verbose = 1; + inname = argv[2]; + strict = 0; + 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 + { + inname = argv[1]; + status_dots_requested = 0; + } + } + + if (multiple == 0 && argc == 3 + verbose) + outname = argv[2 + verbose]; + + if ((multiple == 0 && argc > 3 + verbose) || + (multiple != 0 && argc < 2)) + { + fprintf(STDERR, + "usage: %s [infile.png] [outfile.png]\n\t%s -m {infile.png}\n", + argv[0], argv[0]); + fprintf(STDERR, + " reads/writes one PNG file (without -m) or multiple files (-m)\n"); + fprintf(STDERR, + " with -m %s is used as a temporary file\n", outname); + exit(1); + } + + if (multiple != 0) + { + int i; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + for (i = 2; i < argc; ++i) + { + int kerror; + fprintf(STDERR, "\n Testing %s:", argv[i]); +#if PNG_DEBUG > 0 + fprintf(STDERR, "\n"); +#endif + kerror = test_one_file(argv[i], outname); + if (kerror == 0) + { +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n", tIME_string); + + tIME_chunk_present = 0; +#endif /* TIME_RFC1123 */ + } + + else + { + if (xfail) + fprintf(STDERR, " XFAIL\n"); + else + { + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation - allocation_now); + + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + + while (pinfo != NULL) + { + fprintf(STDERR, " %lu bytes at %p\n", + (unsigned long)pinfo->size, + pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + + else + { + int i; + for (i = 0; i < 3; ++i) + { + int kerror; +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + int allocation_now = current_allocation; +#endif + if (i == 1) + status_dots_requested = 1; + + else if (verbose == 0) + status_dots_requested = 0; + + if (i == 0 || verbose == 1 || ierror != 0) + { + fprintf(STDERR, "\n Testing %s:", inname); +#if PNG_DEBUG > 0 + fprintf(STDERR, "\n"); +#endif + } + + kerror = test_one_file(inname, outname); + + if (kerror == 0) + { + if (verbose == 1 || i == 2) + { +#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED + fprintf(STDERR, "\n PASS (%lu zero samples)\n", + (unsigned long)zero_samples); +#else + fprintf(STDERR, " PASS\n"); +#endif +#ifdef PNG_TIME_RFC1123_SUPPORTED + if (tIME_chunk_present != 0) + fprintf(STDERR, " tIME = %s\n", tIME_string); +#endif /* TIME_RFC1123 */ + } + } + + else + { + if (verbose == 0 && i != 2) + { + fprintf(STDERR, "\n Testing %s:", inname); +#if PNG_DEBUG > 0 + fprintf(STDERR, "\n"); +#endif + } + + if (xfail) + fprintf(STDERR, " XFAIL\n"); + else + { + fprintf(STDERR, " FAIL\n"); + ierror += kerror; + } + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + if (allocation_now != current_allocation) + fprintf(STDERR, "MEMORY ERROR: %d bytes lost\n", + current_allocation - allocation_now); + + if (current_allocation != 0) + { + memory_infop pinfo = pinformation; + + fprintf(STDERR, "MEMORY ERROR: %d bytes still allocated\n", + current_allocation); + + while (pinfo != NULL) + { + fprintf(STDERR, " %lu bytes at %p\n", + (unsigned long)pinfo->size, pinfo->pointer); + pinfo = pinfo->next; + } + } +#endif + } +#if defined(PNG_USER_MEM_SUPPORTED) && PNG_DEBUG + fprintf(STDERR, " Current memory allocation: %10d bytes\n", + current_allocation); + fprintf(STDERR, " Maximum memory allocation: %10d bytes\n", + maximum_allocation); + fprintf(STDERR, " Total memory allocation: %10d bytes\n", + total_allocation); + fprintf(STDERR, " Number of allocations: %10d\n", + num_allocations); +#endif + } + +#ifdef PNGTEST_TIMING + t_stop = (float)clock(); + t_misc += (t_stop - t_start); + t_start = t_stop; + fprintf(STDERR, " CPU time used = %.3f seconds", + (t_misc+t_decode+t_encode)/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " (decoding %.3f,\n", + t_decode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " encoding %.3f ,", + t_encode/(float)CLOCKS_PER_SEC); + fprintf(STDERR, " other %.3f seconds)\n\n", + t_misc/(float)CLOCKS_PER_SEC); +#endif + + if (ierror == 0) + fprintf(STDERR, " libpng passes test\n"); + + else + fprintf(STDERR, " libpng FAILS test\n"); + + dummy_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); +#ifdef PNG_USER_LIMITS_SUPPORTED + fprintf(STDERR, " Default limits:\n"); + fprintf(STDERR, " width_max = %lu\n", + (unsigned long) png_get_user_width_max(dummy_ptr)); + fprintf(STDERR, " height_max = %lu\n", + (unsigned long) png_get_user_height_max(dummy_ptr)); + if (png_get_chunk_cache_max(dummy_ptr) == 0) + fprintf(STDERR, " cache_max = unlimited\n"); + else + fprintf(STDERR, " cache_max = %lu\n", + (unsigned long) png_get_chunk_cache_max(dummy_ptr)); + if (png_get_chunk_malloc_max(dummy_ptr) == 0) + fprintf(STDERR, " malloc_max = unlimited\n"); + else + fprintf(STDERR, " malloc_max = %lu\n", + (unsigned long) png_get_chunk_malloc_max(dummy_ptr)); +#endif + png_destroy_read_struct(&dummy_ptr, NULL, NULL); + + return (ierror != 0); +} +#else +int +main(void) +{ + fprintf(STDERR, + " test ignored because libpng was not built with read support\n"); + /* And skip this test */ + return SKIP; +} +#endif diff --git a/media/libpng/pngtest.png b/media/libpng/pngtest.png new file mode 100644 index 0000000000..7dc251c1fe Binary files /dev/null and b/media/libpng/pngtest.png differ diff --git a/media/libpng/pngtrans.c b/media/libpng/pngtrans.c index da7413fb80..a6cab0cdf0 100644 --- a/media/libpng/pngtrans.c +++ b/media/libpng/pngtrans.c @@ -1,10 +1,9 @@ - /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -17,8 +16,8 @@ #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) /* Turn on BGR-to-RGB mapping */ -void PNGAPI -png_set_bgr(png_structrp png_ptr) +void +png_set_bgr(png_struct *png_ptr) { png_debug(1, "in png_set_bgr"); @@ -31,8 +30,8 @@ png_set_bgr(png_structrp png_ptr) #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) /* Turn on 16-bit byte swapping */ -void PNGAPI -png_set_swap(png_structrp png_ptr) +void +png_set_swap(png_struct *png_ptr) { png_debug(1, "in png_set_swap"); @@ -46,8 +45,8 @@ png_set_swap(png_structrp png_ptr) #if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED) /* Turn on pixel packing */ -void PNGAPI -png_set_packing(png_structrp png_ptr) +void +png_set_packing(png_struct *png_ptr) { png_debug(1, "in png_set_packing"); @@ -66,8 +65,8 @@ png_set_packing(png_structrp png_ptr) #if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED) /* Turn on packed pixel swapping */ -void PNGAPI -png_set_packswap(png_structrp png_ptr) +void +png_set_packswap(png_struct *png_ptr) { png_debug(1, "in png_set_packswap"); @@ -80,14 +79,43 @@ png_set_packswap(png_structrp png_ptr) #endif #if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED) -void PNGAPI -png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits) +void +png_set_shift(png_struct *png_ptr, const png_color_8 *true_bits) { png_debug(1, "in png_set_shift"); - if (png_ptr == NULL) + if (png_ptr == NULL || true_bits == NULL) return; + /* Check the shift values before passing them on to png_do_shift. */ + { + png_byte bit_depth = png_ptr->bit_depth; + int invalid = 0; + + if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) + { + if (true_bits->red == 0 || true_bits->red > bit_depth || + true_bits->green == 0 || true_bits->green > bit_depth || + true_bits->blue == 0 || true_bits->blue > bit_depth) + invalid = 1; + } + else + { + if (true_bits->gray == 0 || true_bits->gray > bit_depth) + invalid = 1; + } + + if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 && + (true_bits->alpha == 0 || true_bits->alpha > bit_depth)) + invalid = 1; + + if (invalid) + { + png_app_error(png_ptr, "png_set_shift: invalid shift values"); + return; + } + } + png_ptr->transformations |= PNG_SHIFT; png_ptr->shift = *true_bits; } @@ -95,18 +123,18 @@ png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits) #if defined(PNG_READ_INTERLACING_SUPPORTED) || \ defined(PNG_WRITE_INTERLACING_SUPPORTED) -int PNGAPI -png_set_interlace_handling(png_structrp png_ptr) +int +png_set_interlace_handling(png_struct *png_ptr) { png_debug(1, "in png_set_interlace handling"); if (png_ptr != 0 && png_ptr->interlaced != 0) { png_ptr->transformations |= PNG_INTERLACE; - return (7); + return 7; } - return (1); + return 1; } #endif @@ -116,8 +144,8 @@ png_set_interlace_handling(png_structrp png_ptr) * for 48-bit input data, as well as to avoid problems with some compilers * that don't like bytes as parameters. */ -void PNGAPI -png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc) +void +png_set_filler(png_struct *png_ptr, png_uint_32 filler, int filler_loc) { png_debug(1, "in png_set_filler"); @@ -201,8 +229,8 @@ png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc) } /* Added to libpng-1.2.7 */ -void PNGAPI -png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc) +void +png_set_add_alpha(png_struct *png_ptr, png_uint_32 filler, int filler_loc) { png_debug(1, "in png_set_add_alpha"); @@ -219,8 +247,8 @@ png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc) #if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \ defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED) -void PNGAPI -png_set_swap_alpha(png_structrp png_ptr) +void +png_set_swap_alpha(png_struct *png_ptr) { png_debug(1, "in png_set_swap_alpha"); @@ -233,8 +261,8 @@ png_set_swap_alpha(png_structrp png_ptr) #if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \ defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED) -void PNGAPI -png_set_invert_alpha(png_structrp png_ptr) +void +png_set_invert_alpha(png_struct *png_ptr) { png_debug(1, "in png_set_invert_alpha"); @@ -246,8 +274,8 @@ png_set_invert_alpha(png_structrp png_ptr) #endif #if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED) -void PNGAPI -png_set_invert_mono(png_structrp png_ptr) +void +png_set_invert_mono(png_struct *png_ptr) { png_debug(1, "in png_set_invert_mono"); @@ -259,7 +287,7 @@ png_set_invert_mono(png_structrp png_ptr) /* Invert monochrome grayscale data */ void /* PRIVATE */ -png_do_invert(png_row_infop row_info, png_bytep row) +png_do_invert(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_invert"); @@ -268,9 +296,9 @@ png_do_invert(png_row_infop row_info, png_bytep row) */ if (row_info->color_type == PNG_COLOR_TYPE_GRAY) { - png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + png_byte *rp = row; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i++) { @@ -282,9 +310,9 @@ png_do_invert(png_row_infop row_info, png_bytep row) else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && row_info->bit_depth == 8) { - png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + png_byte *rp = row; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i += 2) { @@ -297,9 +325,9 @@ png_do_invert(png_row_infop row_info, png_bytep row) else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && row_info->bit_depth == 16) { - png_bytep rp = row; - png_size_t i; - png_size_t istop = row_info->rowbytes; + png_byte *rp = row; + size_t i; + size_t istop = row_info->rowbytes; for (i = 0; i < istop; i += 4) { @@ -316,13 +344,13 @@ png_do_invert(png_row_infop row_info, png_bytep row) #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) /* Swaps byte order on 16-bit depth images */ void /* PRIVATE */ -png_do_swap(png_row_infop row_info, png_bytep row) +png_do_swap(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_swap"); if (row_info->bit_depth == 16) { - png_bytep rp = row; + png_byte *rp = row; png_uint_32 i; png_uint_32 istop= row_info->width * row_info->channels; @@ -345,7 +373,7 @@ png_do_swap(png_row_infop row_info, png_bytep row) #endif #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, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, @@ -380,7 +408,7 @@ static PNG_CONST png_byte onebppswaptable[256] = { 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, 0x20, 0x60, 0xA0, 0xE0, 0x30, 0x70, 0xB0, 0xF0, 0x04, 0x44, 0x84, 0xC4, 0x14, 0x54, 0x94, 0xD4, @@ -415,7 +443,7 @@ static PNG_CONST png_byte twobppswaptable[256] = { 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, 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0, 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, @@ -452,16 +480,15 @@ static PNG_CONST png_byte fourbppswaptable[256] = { /* Swaps pixel packing order within bytes */ void /* PRIVATE */ -png_do_packswap(png_row_infop row_info, png_bytep row) +png_do_packswap(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_packswap"); if (row_info->bit_depth < 8) { - png_bytep rp; - png_const_bytep end, table; - - end = row + row_info->rowbytes; + const png_byte *table; + png_byte *rp; + png_byte *row_end = row + row_info->rowbytes; if (row_info->bit_depth == 1) table = onebppswaptable; @@ -475,7 +502,7 @@ png_do_packswap(png_row_infop row_info, png_bytep row) else return; - for (rp = row; rp < end; rp++) + for (rp = row; rp < row_end; rp++) *rp = table[*rp]; } } @@ -492,11 +519,13 @@ png_do_packswap(png_row_infop row_info, png_bytep row) * end (not in the middle) of each pixel. */ void /* PRIVATE */ -png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) +png_do_strip_channel(png_row_info *row_info, png_byte *row, int at_start) { - png_bytep sp = row; /* source pointer */ - png_bytep dp = row; /* destination pointer */ - png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */ + png_byte *sp = row; /* source pointer */ + png_byte *dp = row; /* destination pointer */ + png_byte *ep = row + row_info->rowbytes; /* One beyond end of row */ + + png_debug(1, "in png_do_strip_channel"); /* At the start sp will point to the first byte to copy and dp to where * it is copied to. ep always points just beyond the end of the row, so @@ -514,11 +543,15 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ ++sp; 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 */ while (sp < ep) - *dp++ = *sp, sp += 2; + { + *dp++ = *sp; sp += 2; + } row_info->pixel_depth = 8; } @@ -528,10 +561,14 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ sp += 2; else /* Skip initial channel and, for sp, the filler */ - sp += 4, dp += 2; + { + sp += 4; dp += 2; + } while (sp < ep) - *dp++ = *sp++, *dp++ = *sp, sp += 3; + { + *dp++ = *sp++; *dp++ = *sp; sp += 3; + } row_info->pixel_depth = 16; } @@ -554,11 +591,15 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ ++sp; 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. */ while (sp < ep) - *dp++ = *sp++, *dp++ = *sp++, *dp++ = *sp, sp += 2; + { + *dp++ = *sp++; *dp++ = *sp++; *dp++ = *sp; sp += 2; + } row_info->pixel_depth = 24; } @@ -568,14 +609,16 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) if (at_start != 0) /* Skip initial filler */ sp += 2; else /* Skip initial channels and, for sp, the filler */ - sp += 8, dp += 6; + { + sp += 8; dp += 6; + } while (sp < ep) { /* Copy 6 bytes, skip 2 */ - *dp++ = *sp++, *dp++ = *sp++; - *dp++ = *sp++, *dp++ = *sp++; - *dp++ = *sp++, *dp++ = *sp, sp += 3; + *dp++ = *sp++; *dp++ = *sp++; + *dp++ = *sp++; *dp++ = *sp++; + *dp++ = *sp++; *dp++ = *sp; sp += 3; } row_info->pixel_depth = 48; @@ -595,14 +638,14 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start) return; /* The filler channel has gone already */ /* Fix the rowbytes value. */ - row_info->rowbytes = (unsigned int)(dp-row); + row_info->rowbytes = (size_t)(dp-row); } #endif #if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED) /* Swaps red and blue bytes within a pixel */ void /* PRIVATE */ -png_do_bgr(png_row_infop row_info, png_bytep row) +png_do_bgr(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_bgr"); @@ -613,7 +656,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row) { if (row_info->color_type == PNG_COLOR_TYPE_RGB) { - png_bytep rp; + png_byte *rp; png_uint_32 i; for (i = 0, rp = row; i < row_width; i++, rp += 3) @@ -626,7 +669,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row) else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - png_bytep rp; + png_byte *rp; png_uint_32 i; for (i = 0, rp = row; i < row_width; i++, rp += 4) @@ -643,7 +686,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row) { if (row_info->color_type == PNG_COLOR_TYPE_RGB) { - png_bytep rp; + png_byte *rp; png_uint_32 i; for (i = 0, rp = row; i < row_width; i++, rp += 6) @@ -659,7 +702,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row) else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) { - png_bytep rp; + png_byte *rp; png_uint_32 i; for (i = 0, rp = row; i < row_width; i++, rp += 8) @@ -682,8 +725,10 @@ png_do_bgr(png_row_infop row_info, png_bytep row) defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED) /* Added at libpng-1.5.10 */ void /* PRIVATE */ -png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) +png_do_check_palette_indexes(png_struct *png_ptr, png_row_info *row_info) { + png_debug(1, "in png_do_check_palette_indexes"); + if (png_ptr->num_palette < (1 << row_info->bit_depth) && png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */ { @@ -694,7 +739,7 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) * forms produced on either GCC or MSVC. */ int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width); - png_bytep rp = png_ptr->row_buf + row_info->rowbytes; + png_byte *rp = png_ptr->row_buf + row_info->rowbytes; switch (row_info->bit_depth) { @@ -784,9 +829,9 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \ defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED) #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -void PNGAPI -png_set_user_transform_info(png_structrp png_ptr, png_voidp - user_transform_ptr, int user_transform_depth, int user_transform_channels) +void +png_set_user_transform_info(png_struct *png_ptr, void *user_transform_ptr, + int user_transform_depth, int user_transform_channels) { png_debug(1, "in png_set_user_transform_info"); @@ -815,19 +860,19 @@ png_set_user_transform_info(png_structrp png_ptr, png_voidp * are called. */ #ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED -png_voidp PNGAPI -png_get_user_transform_ptr(png_const_structrp png_ptr) +void * +png_get_user_transform_ptr(const png_struct *png_ptr) { if (png_ptr == NULL) - return (NULL); + return NULL; return png_ptr->user_transform_ptr; } #endif #ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED -png_uint_32 PNGAPI -png_get_current_row_number(png_const_structrp png_ptr) +png_uint_32 +png_get_current_row_number(const png_struct *png_ptr) { /* See the comments in png.h - this is the sub-image row when reading an * interlaced image. @@ -838,8 +883,8 @@ png_get_current_row_number(png_const_structrp png_ptr) return PNG_UINT_32_MAX; /* help the app not to fail silently */ } -png_byte PNGAPI -png_get_current_pass_number(png_const_structrp png_ptr) +png_byte +png_get_current_pass_number(const png_struct *png_ptr) { if (png_ptr != NULL) return png_ptr->pass; diff --git a/media/libpng/pngusr.dfa b/media/libpng/pngusr.dfa new file mode 100644 index 0000000000..83067c38c0 --- /dev/null +++ b/media/libpng/pngusr.dfa @@ -0,0 +1,14 @@ +# pngusr.dfa +# +# Build time configuration of libpng +# +# Enter build configuration options in this file +# +# Security settings: by default these limits are unset, you can change them +# here by entering the appropriate values as #defines preceded by '@' (to cause, +# them to be passed through to the build of pnglibconf.h), for example: +# +# @# define PNG_USER_WIDTH_MAX 65535 +# @# define PNG_USER_HEIGHT_MAX 65535 +# @# define PNG_USER_CHUNK_CACHE_MAX 256 +# @# define PNG_USER_CHUNK_MALLOC_MAX 640000 diff --git a/media/libpng/pngwio.c b/media/libpng/pngwio.c index 37c7c3a7f0..709ebdcd6a 100644 --- a/media/libpng/pngwio.c +++ b/media/libpng/pngwio.c @@ -1,10 +1,9 @@ - /* pngwio.c - functions for data output * - * Last changed in libpng 1.6.24 [August 4, 2016] - * Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2025 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2014,2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -30,11 +29,11 @@ */ void /* PRIVATE */ -png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) +png_write_data(png_struct *png_ptr, const png_byte *data, size_t length) { /* NOTE: write_data_fn must not change the buffer! */ if (png_ptr->write_data_fn != NULL ) - (*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data), + (*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_byte *,data), length); else @@ -47,15 +46,15 @@ png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length) * write_data function and use it at run time with png_set_write_fn(), rather * than changing the library. */ -void PNGCBAPI -png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) +void +png_default_write_data(png_struct *png_ptr, png_byte *data, size_t length) { - png_size_t check; + size_t check; if (png_ptr == NULL) return; - check = fwrite(data, 1, length, (png_FILE_p)(png_ptr->io_ptr)); + check = fwrite(data, 1, length, (FILE *)png_ptr->io_ptr); if (check != length) png_error(png_ptr, "Write Error"); @@ -68,22 +67,22 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length) */ #ifdef PNG_WRITE_FLUSH_SUPPORTED void /* PRIVATE */ -png_flush(png_structrp png_ptr) +png_flush(png_struct *png_ptr) { if (png_ptr->output_flush_fn != NULL) (*(png_ptr->output_flush_fn))(png_ptr); } # ifdef PNG_STDIO_SUPPORTED -void PNGCBAPI -png_default_flush(png_structp png_ptr) +void +png_default_flush(png_struct *png_ptr) { - png_FILE_p io_ptr; + FILE *io_ptr; if (png_ptr == NULL) return; - io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr)); + io_ptr = png_voidcast(FILE *, png_ptr->io_ptr); fflush(io_ptr); } # endif @@ -118,8 +117,8 @@ png_default_flush(png_structp png_ptr) * a good idea if io_ptr does not point to a standard * *FILE structure. */ -void PNGAPI -png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr, +void +png_set_write_fn(png_struct *png_ptr, void *io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn) { if (png_ptr == NULL) diff --git a/media/libpng/pngwrite.c b/media/libpng/pngwrite.c index b44d04fb69..f067ec1b5a 100644 --- a/media/libpng/pngwrite.c +++ b/media/libpng/pngwrite.c @@ -1,10 +1,9 @@ - /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -21,12 +20,12 @@ #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED /* Write out all the unknown chunks for the current given location */ static void -write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, +write_unknown_chunks(png_struct *png_ptr, const png_info *info_ptr, unsigned int where) { if (info_ptr->unknown_chunks_num != 0) { - png_const_unknown_chunkp up; + const png_unknown_chunk *up; png_debug(5, "writing extra chunks"); @@ -75,13 +74,13 @@ write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, * library. If you have a new chunk to add, make a function to write it, * and put it in the correct location here. If you want the chunk written * after the image data, put it in png_write_end(). I strongly encourage - * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing - * the chunk, as that will keep the code from breaking if you want to just - * write a plain PNG file. If you have long comments, I suggest writing - * them in png_write_end(), and compressing them. + * you to supply a PNG_INFO_ flag, and check info_ptr->valid before + * writing the chunk, as that will keep the code from breaking if you want + * to just write a plain PNG file. If you have long comments, I suggest + * writing them in png_write_end(), and compressing them. */ -void PNGAPI -png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) +void +png_write_info_before_PLTE(png_struct *png_ptr, const png_info *info_ptr) { png_debug(1, "in png_write_info_before_PLTE"); @@ -129,71 +128,104 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) * flag here too. */ #ifdef PNG_WRITE_APNG_SUPPORTED - if ((info_ptr->valid & PNG_INFO_acTL) != 0) - png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays); + if ((info_ptr->valid & PNG_INFO_acTL) != 0) + png_write_acTL(png_ptr, info_ptr->num_frames, info_ptr->num_plays); #endif -#ifdef PNG_GAMMA_SUPPORTED -# ifdef PNG_WRITE_gAMA_SUPPORTED - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && - (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 && - (info_ptr->valid & PNG_INFO_gAMA) != 0) - png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma); -# endif + +#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED + /* Write unknown chunks first; PNG v3 establishes a precedence order + * for colourspace chunks. It is certain therefore that new + * colourspace chunks will have a precedence and very likely it will be + * higher than all known so far. Writing the unknown chunks here is + * most likely to present the chunks in the most convenient order. + * + * FUTURE: maybe write chunks in the order the app calls png_set_chnk + * to give the app control. + */ + write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); #endif -#ifdef PNG_COLORSPACE_SUPPORTED - /* Write only one of sRGB or an ICC profile. If a profile was supplied - * and it matches one of the known sRGB ones issue a warning. - */ -# ifdef PNG_WRITE_iCCP_SUPPORTED - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && - (info_ptr->valid & PNG_INFO_iCCP) != 0) - { -# ifdef PNG_WRITE_sRGB_SUPPORTED - if ((info_ptr->valid & PNG_INFO_sRGB) != 0) - png_app_warning(png_ptr, - "profile matches sRGB but writing iCCP instead"); -# endif +#ifdef PNG_WRITE_sBIT_SUPPORTED + /* PNG v3: a streaming app will need to see this before cICP because + * the information is helpful in handling HLG encoding (which is + * natively 10 bits but gets expanded to 16 in PNG.) + * + * The app shouldn't care about the order ideally, but it might have + * no choice. In PNG v3, apps are allowed to reject PNGs where the + * APNG chunks are out of order so it behooves libpng to be nice here. + */ + if ((info_ptr->valid & PNG_INFO_sBIT) != 0) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); +#endif + /* PNG v3: the July 2004 version of the TR introduced the concept of colour + * space priority. As above it therefore behooves libpng to write the colour + * space chunks in the priority order so that a streaming app need not buffer + * them. + * + * PNG v3: Chunks mDCV and cLLI provide ancillary information for the + * interpretation of the colourspace chunks but do not require support for + * those chunks so are outside the "COLORSPACE" check but before the write of + * the colourspace chunks themselves. + */ +#ifdef PNG_WRITE_cLLI_SUPPORTED + if ((info_ptr->valid & PNG_INFO_cLLI) != 0) + { + png_write_cLLI_fixed(png_ptr, info_ptr->maxCLL, info_ptr->maxFALL); + } +#endif +#ifdef PNG_WRITE_mDCV_SUPPORTED + if ((info_ptr->valid & PNG_INFO_mDCV) != 0) + { + png_write_mDCV_fixed(png_ptr, + info_ptr->mastering_red_x, info_ptr->mastering_red_y, + info_ptr->mastering_green_x, info_ptr->mastering_green_y, + info_ptr->mastering_blue_x, info_ptr->mastering_blue_y, + info_ptr->mastering_white_x, info_ptr->mastering_white_y, + info_ptr->mastering_maxDL, info_ptr->mastering_minDL); + } +#endif + +# ifdef PNG_WRITE_cICP_SUPPORTED /* Priority 4 */ + if ((info_ptr->valid & PNG_INFO_cICP) != 0) + { + png_write_cICP(png_ptr, + info_ptr->cicp_colour_primaries, + info_ptr->cicp_transfer_function, + info_ptr->cicp_matrix_coefficients, + info_ptr->cicp_video_full_range_flag); + } +# endif + +# ifdef PNG_WRITE_iCCP_SUPPORTED /* Priority 3 */ + if ((info_ptr->valid & PNG_INFO_iCCP) != 0) + { png_write_iCCP(png_ptr, info_ptr->iccp_name, - info_ptr->iccp_profile); + info_ptr->iccp_profile, info_ptr->iccp_proflen); } -# ifdef PNG_WRITE_sRGB_SUPPORTED - else -# endif # endif -# ifdef PNG_WRITE_sRGB_SUPPORTED - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && - (info_ptr->valid & PNG_INFO_sRGB) != 0) - png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); +# ifdef PNG_WRITE_sRGB_SUPPORTED /* Priority 2 */ + if ((info_ptr->valid & PNG_INFO_sRGB) != 0) + png_write_sRGB(png_ptr, info_ptr->rendering_intent); # endif /* WRITE_sRGB */ -#endif /* COLORSPACE */ - -#ifdef PNG_WRITE_sBIT_SUPPORTED - if ((info_ptr->valid & PNG_INFO_sBIT) != 0) - png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); -#endif -#ifdef PNG_COLORSPACE_SUPPORTED -# ifdef PNG_WRITE_cHRM_SUPPORTED - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && - (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 && - (info_ptr->valid & PNG_INFO_cHRM) != 0) - png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy); +# ifdef PNG_WRITE_gAMA_SUPPORTED /* Priority 1 */ + if ((info_ptr->valid & PNG_INFO_gAMA) != 0) + png_write_gAMA_fixed(png_ptr, info_ptr->gamma); # endif -#endif -#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED - write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); -#endif +# ifdef PNG_WRITE_cHRM_SUPPORTED /* Also priority 1 */ + if ((info_ptr->valid & PNG_INFO_cHRM) != 0) + png_write_cHRM_fixed(png_ptr, &info_ptr->cHRM); +# endif png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; } } -void PNGAPI -png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) +void +png_write_info(png_struct *png_ptr, const png_info *info_ptr) { #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) int i; @@ -241,6 +273,14 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); #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); + png_ptr->mode |= PNG_WROTE_eXIf; + } +#endif + #ifdef PNG_WRITE_hIST_SUPPORTED if ((info_ptr->valid & PNG_INFO_hIST) != 0) png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); @@ -353,8 +393,8 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) * in png_write_info(), do not write them again here. If you have long * comments, I suggest writing them here, and compressing them. */ -void PNGAPI -png_write_end(png_structrp png_ptr, png_inforp info_ptr) +void +png_write_end(png_struct *png_ptr, png_info *info_ptr) { png_debug(1, "in png_write_end"); @@ -364,16 +404,17 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) if ((png_ptr->mode & PNG_HAVE_IDAT) == 0) png_error(png_ptr, "No IDATs written into file"); +#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && + png_ptr->num_palette_max >= png_ptr->num_palette) + png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); +#endif + #ifdef PNG_WRITE_APNG_SUPPORTED if (png_ptr->num_frames_written != png_ptr->num_frames_to_write) png_error(png_ptr, "Not enough frames written"); #endif -#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED - if (png_ptr->num_palette_max > png_ptr->num_palette) - png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); -#endif - /* See if user wants us to write information chunks */ if (info_ptr != NULL) { @@ -441,6 +482,13 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) } } #endif + +#ifdef PNG_WRITE_eXIf_SUPPORTED + if ((info_ptr->valid & PNG_INFO_eXIf) != 0 && + (png_ptr->mode & PNG_WROTE_eXIf) == 0) + png_write_eXIf(png_ptr, info_ptr->exif, info_ptr->num_exif); +#endif + #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT); #endif @@ -466,8 +514,8 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr) } #ifdef PNG_CONVERT_tIME_SUPPORTED -void PNGAPI -png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime) +void +png_convert_from_struct_tm(png_time *ptime, const struct tm * ttime) { png_debug(1, "in png_convert_from_struct_tm"); @@ -479,25 +527,36 @@ png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime) ptime->second = (png_byte)ttime->tm_sec; } -void PNGAPI -png_convert_from_time_t(png_timep ptime, time_t ttime) +void +png_convert_from_time_t(png_time *ptime, time_t ttime) { struct tm *tbuf; png_debug(1, "in png_convert_from_time_t"); tbuf = gmtime(&ttime); + if (tbuf == NULL) + { + /* TODO: add a safe function which takes a png_ptr argument and raises + * a png_error if the ttime argument is invalid and the call to gmtime + * fails as a consequence. + */ + memset(ptime, 0, sizeof(*ptime)); + return; + } + png_convert_from_struct_tm(ptime, tbuf); } #endif /* Initialize png_ptr structure, and allocate any memory needed */ -PNG_FUNCTION(png_structp,PNGAPI -png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) +PNG_FUNCTION(png_struct *, +png_create_write_struct,(const char *user_png_ver, void *error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn), + PNG_ALLOCATED) { #ifndef PNG_USER_MEM_SUPPORTED - png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + png_struct *png_ptr = png_create_png_struct(user_png_ver, error_ptr, error_fn, warn_fn, NULL, NULL, NULL); #else return png_create_write_struct_2(user_png_ver, error_ptr, error_fn, @@ -505,12 +564,13 @@ png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, } /* Alternate initialize png_ptr structure, and allocate any memory needed */ -PNG_FUNCTION(png_structp,PNGAPI -png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, - png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, - png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) +PNG_FUNCTION(png_struct *, +png_create_write_struct_2,(const char *user_png_ver, void *error_ptr, + png_error_ptr error_fn, png_error_ptr warn_fn, void *mem_ptr, + png_malloc_ptr malloc_fn, png_free_ptr free_fn), + PNG_ALLOCATED) { - png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, + png_struct *png_ptr = png_create_png_struct(user_png_ver, error_ptr, error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); #endif /* USER_MEM */ if (png_ptr != NULL) @@ -573,12 +633,12 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, * have called png_set_interlace_handling(), you will have to * "write" the image seven times. */ -void PNGAPI -png_write_rows(png_structrp png_ptr, png_bytepp row, +void +png_write_rows(png_struct *png_ptr, png_byte **row, png_uint_32 num_rows) { png_uint_32 i; /* row counter */ - png_bytepp rp; /* row pointer */ + png_byte **rp; /* row pointer */ png_debug(1, "in png_write_rows"); @@ -595,12 +655,12 @@ png_write_rows(png_structrp png_ptr, png_bytepp row, /* Write the image. You only need to call this function once, even * if you are writing an interlaced image. */ -void PNGAPI -png_write_image(png_structrp png_ptr, png_bytepp image) +void +png_write_image(png_struct *png_ptr, png_byte **image) { png_uint_32 i; /* row index */ int pass, num_pass; /* pass variables */ - png_bytepp rp; /* points to current row */ + png_byte **rp; /* points to current row */ if (png_ptr == NULL) return; @@ -629,7 +689,7 @@ png_write_image(png_structrp png_ptr, png_bytepp image) #ifdef PNG_MNG_FEATURES_SUPPORTED /* Performs intrapixel differencing */ static void -png_do_write_intrapixel(png_row_infop row_info, png_bytep row) +png_do_write_intrapixel(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_write_intrapixel"); @@ -639,7 +699,7 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) png_uint_32 row_width = row_info->width; if (row_info->bit_depth == 8) { - png_bytep rp; + png_byte *rp; png_uint_32 i; if (row_info->color_type == PNG_COLOR_TYPE_RGB) @@ -661,7 +721,7 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) #ifdef PNG_WRITE_16BIT_SUPPORTED else if (row_info->bit_depth == 16) { - png_bytep rp; + png_byte *rp; png_uint_32 i; if (row_info->color_type == PNG_COLOR_TYPE_RGB) @@ -692,18 +752,18 @@ png_do_write_intrapixel(png_row_infop row_info, png_bytep row) #endif /* MNG_FEATURES */ /* Called by user to write a row of image data */ -void PNGAPI -png_write_row(png_structrp png_ptr, png_const_bytep row) +void +png_write_row(png_struct *png_ptr, const png_byte *row) { /* 1.5.6: moved from png_struct to be a local structure: */ png_row_info row_info; - if (png_ptr == NULL) - return; - png_debug2(1, "in png_write_row (row %u, pass %d)", png_ptr->row_number, png_ptr->pass); + if (png_ptr == NULL) + return; + /* Initialize transformations and other stuff if first time */ if (png_ptr->row_number == 0 && png_ptr->pass == 0) { @@ -902,8 +962,8 @@ png_write_row(png_structrp png_ptr, png_const_bytep row) #ifdef PNG_WRITE_FLUSH_SUPPORTED /* Set the automatic flush interval or 0 to turn flushing off */ -void PNGAPI -png_set_flush(png_structrp png_ptr, int nrows) +void +png_set_flush(png_struct *png_ptr, int nrows) { png_debug(1, "in png_set_flush"); @@ -914,8 +974,8 @@ png_set_flush(png_structrp png_ptr, int nrows) } /* Flush the current output buffers now */ -void PNGAPI -png_write_flush(png_structrp png_ptr) +void +png_write_flush(png_struct *png_ptr) { png_debug(1, "in png_write_flush"); @@ -934,7 +994,7 @@ png_write_flush(png_structrp png_ptr) /* Free any memory used in png_ptr struct without freeing the struct itself. */ static void -png_write_destroy(png_structrp png_ptr) +png_write_destroy(png_struct *png_ptr) { png_debug(1, "in png_write_destroy"); @@ -960,6 +1020,16 @@ png_write_destroy(png_structrp png_ptr) png_ptr->chunk_list = NULL; #endif +#if defined(PNG_tRNS_SUPPORTED) + /* Free the independent copy of trans_alpha owned by png_struct. */ + png_free(png_ptr, png_ptr->trans_alpha); + png_ptr->trans_alpha = NULL; +#endif + + /* Free the independent copy of the palette owned by png_struct. */ + png_free(png_ptr, png_ptr->palette); + png_ptr->palette = NULL; + /* The error handling and memory handling information is left intact at this * point: the jmp_buf may still have to be freed. See png_destroy_png_struct * for how this happens. @@ -973,14 +1043,14 @@ png_write_destroy(png_structrp png_ptr) * inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it * has no png_ptr.) */ -void PNGAPI -png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) +void +png_destroy_write_struct(png_struct **png_ptr_ptr, png_info **info_ptr_ptr) { png_debug(1, "in png_destroy_write_struct"); if (png_ptr_ptr != NULL) { - png_structrp png_ptr = *png_ptr_ptr; + png_struct *png_ptr = *png_ptr_ptr; if (png_ptr != NULL) /* added in libpng 1.6.0 */ { @@ -994,8 +1064,8 @@ png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) } /* Allow the application to select one or more row filters to use. */ -void PNGAPI -png_set_filter(png_structrp png_ptr, int method, int filters) +void +png_set_filter(png_struct *png_ptr, int method, int filters) { png_debug(1, "in png_set_filter"); @@ -1016,8 +1086,8 @@ png_set_filter(png_structrp png_ptr, int method, int filters) case 5: case 6: case 7: png_app_error(png_ptr, "Unknown row filter for method 0"); - /* FALL THROUGH */ #endif /* WRITE_FILTER */ + /* FALLTHROUGH */ case PNG_FILTER_VALUE_NONE: png_ptr->do_filter = PNG_FILTER_NONE; break; @@ -1103,13 +1173,13 @@ png_set_filter(png_structrp png_ptr, int method, int filters) png_ptr->width) + 1; if (png_ptr->try_row == NULL) - png_ptr->try_row = png_voidcast(png_bytep, + png_ptr->try_row = png_voidcast(png_byte *, png_malloc(png_ptr, buf_size)); if (num_filters > 1) { if (png_ptr->tst_row == NULL) - png_ptr->tst_row = png_voidcast(png_bytep, + png_ptr->tst_row = png_voidcast(png_byte *, png_malloc(png_ptr, buf_size)); } } @@ -1120,40 +1190,9 @@ png_set_filter(png_structrp png_ptr, int method, int filters) png_error(png_ptr, "Unknown custom filter method"); } -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ -/* Provide floating and fixed point APIs */ -#ifdef PNG_FLOATING_POINT_SUPPORTED -void PNGAPI -png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method, - int num_weights, png_const_doublep filter_weights, - png_const_doublep filter_costs) -{ - PNG_UNUSED(png_ptr) - PNG_UNUSED(heuristic_method) - PNG_UNUSED(num_weights) - PNG_UNUSED(filter_weights) - PNG_UNUSED(filter_costs) -} -#endif /* FLOATING_POINT */ - -#ifdef PNG_FIXED_POINT_SUPPORTED -void PNGAPI -png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method, - int num_weights, png_const_fixed_point_p filter_weights, - png_const_fixed_point_p filter_costs) -{ - PNG_UNUSED(png_ptr) - PNG_UNUSED(heuristic_method) - PNG_UNUSED(num_weights) - PNG_UNUSED(filter_weights) - PNG_UNUSED(filter_costs) -} -#endif /* FIXED_POINT */ -#endif /* WRITE_WEIGHTED_FILTER */ - #ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED -void PNGAPI -png_set_compression_level(png_structrp png_ptr, int level) +void +png_set_compression_level(png_struct *png_ptr, int level) { png_debug(1, "in png_set_compression_level"); @@ -1163,8 +1202,8 @@ png_set_compression_level(png_structrp png_ptr, int level) png_ptr->zlib_level = level; } -void PNGAPI -png_set_compression_mem_level(png_structrp png_ptr, int mem_level) +void +png_set_compression_mem_level(png_struct *png_ptr, int mem_level) { png_debug(1, "in png_set_compression_mem_level"); @@ -1174,8 +1213,8 @@ png_set_compression_mem_level(png_structrp png_ptr, int mem_level) png_ptr->zlib_mem_level = mem_level; } -void PNGAPI -png_set_compression_strategy(png_structrp png_ptr, int strategy) +void +png_set_compression_strategy(png_struct *png_ptr, int strategy) { png_debug(1, "in png_set_compression_strategy"); @@ -1191,9 +1230,11 @@ png_set_compression_strategy(png_structrp png_ptr, int strategy) /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a * smaller value of window_bits if it can do so safely. */ -void PNGAPI -png_set_compression_window_bits(png_structrp png_ptr, int window_bits) +void +png_set_compression_window_bits(png_struct *png_ptr, int window_bits) { + png_debug(1, "in png_set_compression_window_bits"); + if (png_ptr == NULL) return; @@ -1218,8 +1259,8 @@ png_set_compression_window_bits(png_structrp png_ptr, int window_bits) png_ptr->zlib_window_bits = window_bits; } -void PNGAPI -png_set_compression_method(png_structrp png_ptr, int method) +void +png_set_compression_method(png_struct *png_ptr, int method) { png_debug(1, "in png_set_compression_method"); @@ -1238,8 +1279,8 @@ png_set_compression_method(png_structrp png_ptr, int method) /* The following were added to libpng-1.5.4 */ #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED -void PNGAPI -png_set_text_compression_level(png_structrp png_ptr, int level) +void +png_set_text_compression_level(png_struct *png_ptr, int level) { png_debug(1, "in png_set_text_compression_level"); @@ -1249,8 +1290,8 @@ png_set_text_compression_level(png_structrp png_ptr, int level) png_ptr->zlib_text_level = level; } -void PNGAPI -png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level) +void +png_set_text_compression_mem_level(png_struct *png_ptr, int mem_level) { png_debug(1, "in png_set_text_compression_mem_level"); @@ -1260,8 +1301,8 @@ png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level) png_ptr->zlib_text_mem_level = mem_level; } -void PNGAPI -png_set_text_compression_strategy(png_structrp png_ptr, int strategy) +void +png_set_text_compression_strategy(png_struct *png_ptr, int strategy) { png_debug(1, "in png_set_text_compression_strategy"); @@ -1274,9 +1315,11 @@ png_set_text_compression_strategy(png_structrp png_ptr, int strategy) /* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a * smaller value of window_bits if it can do so safely. */ -void PNGAPI -png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits) +void +png_set_text_compression_window_bits(png_struct *png_ptr, int window_bits) { + png_debug(1, "in png_set_text_compression_window_bits"); + if (png_ptr == NULL) return; @@ -1295,8 +1338,8 @@ png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits) png_ptr->zlib_text_window_bits = window_bits; } -void PNGAPI -png_set_text_compression_method(png_structrp png_ptr, int method) +void +png_set_text_compression_method(png_struct *png_ptr, int method) { png_debug(1, "in png_set_text_compression_method"); @@ -1311,9 +1354,11 @@ png_set_text_compression_method(png_structrp png_ptr, int method) #endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ /* end of API added to libpng-1.5.4 */ -void PNGAPI -png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn) +void +png_set_write_status_fn(png_struct *png_ptr, png_write_status_ptr write_row_fn) { + png_debug(1, "in png_set_write_status_fn"); + if (png_ptr == NULL) return; @@ -1321,9 +1366,9 @@ png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn) } #ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED -void PNGAPI -png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr - write_user_transform_fn) +void +png_set_write_user_transform_fn(png_struct *png_ptr, + png_user_transform_ptr write_user_transform_fn) { png_debug(1, "in png_set_write_user_transform_fn"); @@ -1337,10 +1382,12 @@ png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr #ifdef PNG_INFO_IMAGE_SUPPORTED -void PNGAPI -png_write_png(png_structrp png_ptr, png_inforp info_ptr, - int transforms, voidp params) +void +png_write_png(png_struct *png_ptr, png_info *info_ptr, + int transforms, void *params) { + png_debug(1, "in png_write_png"); + if (png_ptr == NULL || info_ptr == NULL) return; @@ -1459,22 +1506,61 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr, } #endif +#ifdef PNG_WRITE_APNG_SUPPORTED +void PNGAPI +png_write_frame_head(png_struct *png_ptr, png_info *info_ptr, + png_byte **row_pointers, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op) +{ + png_debug(1, "in png_write_frame_head"); + + /* There is a chance this has been set after png_write_info was called, + * so it would be set but not written. Is there a way to be sure? + */ + if (!(info_ptr->valid & PNG_INFO_acTL)) + png_error(png_ptr, "Cannot write APNG frame: missing acTL"); + + png_write_reset(png_ptr); + + png_write_reinit(png_ptr, info_ptr, width, height); + + if (!(png_ptr->num_frames_written == 0 && + (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN))) + png_write_fcTL(png_ptr, width, height, x_offset, y_offset, + delay_num, delay_den, dispose_op, blend_op); + + PNG_UNUSED(row_pointers) +} + +void PNGAPI +png_write_frame_tail(png_struct *png_ptr, png_info *info_ptr) +{ + png_debug(1, "in png_write_frame_tail"); + + png_ptr->num_frames_written++; + + PNG_UNUSED(info_ptr) +} +#endif /* PNG_WRITE_APNG_SUPPORTED */ #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED /* Initialize the write structure - general purpose utility. */ static int -png_image_write_init(png_imagep image) +png_image_write_init(png_image *image) { - png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image, + png_struct *png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image, png_safe_error, png_safe_warning); if (png_ptr != NULL) { - png_infop info_ptr = png_create_info_struct(png_ptr); + png_info *info_ptr = png_create_info_struct(png_ptr); if (info_ptr != NULL) { - png_controlp control = png_voidcast(png_controlp, + png_control *control = png_voidcast(png_control *, png_malloc_warn(png_ptr, (sizeof *control))); if (control != NULL) @@ -1502,18 +1588,20 @@ png_image_write_init(png_imagep image) /* Arguments to png_image_write_main: */ typedef struct { - /* Arguments: */ - png_imagep image; - png_const_voidp buffer; - png_int_32 row_stride; - png_const_voidp colormap; - int convert_to_8bit; - /* Local variables: */ - png_const_voidp first_row; - ptrdiff_t row_bytes; - png_voidp local_row; + /* Arguments */ + png_image *image; + const void *buffer; + png_int_32 row_stride; + const void *colormap; + int convert_to_8bit; + + /* Instance variables */ + const void *first_row; + void *local_row; + ptrdiff_t row_step; + /* Byte count for memory writing */ - png_bytep memory; + png_byte *memory; png_alloc_size_t memory_bytes; /* not used for STDIO */ png_alloc_size_t output_bytes; /* running total */ } png_image_write_control; @@ -1523,18 +1611,18 @@ typedef struct * png_image format value. */ static int -png_write_image_16bit(png_voidp argument) +png_write_image_16bit(void *argument) { png_image_write_control *display = png_voidcast(png_image_write_control*, argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; + png_image *image = display->image; + png_struct *png_ptr = image->opaque->png_ptr; - png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, + const png_uint_16 *input_row = png_voidcast(const png_uint_16 *, display->first_row); - png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); - png_uint_16p row_end; - const unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? + png_uint_16 *output_row = png_voidcast(png_uint_16 *, display->local_row); + png_uint_16 *row_end; + unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; int aindex = 0; png_uint_32 y = image->height; @@ -1566,12 +1654,12 @@ png_write_image_16bit(png_voidp argument) for (; y > 0; --y) { - png_const_uint_16p in_ptr = input_row; - png_uint_16p out_ptr = output_row; + const png_uint_16 *in_ptr = input_row; + png_uint_16 *out_ptr = output_row; 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; int c; @@ -1619,8 +1707,9 @@ png_write_image_16bit(png_voidp argument) ++out_ptr; } - png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); - input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); + png_write_row(png_ptr, + png_voidcast(const png_byte *, display->local_row)); + input_row += display->row_step / 2; } return 1; @@ -1634,7 +1723,7 @@ png_write_image_16bit(png_voidp argument) * 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. */ -# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) +# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+((alpha)>>1))/(alpha)) static png_byte png_unpremultiply(png_uint_32 component, png_uint_32 alpha, @@ -1682,23 +1771,23 @@ png_unpremultiply(png_uint_32 component, png_uint_32 alpha, } static int -png_write_image_8bit(png_voidp argument) +png_write_image_8bit(void *argument) { png_image_write_control *display = png_voidcast(png_image_write_control*, argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; + png_image *image = display->image; + png_struct *png_ptr = image->opaque->png_ptr; - png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, + const png_uint_16 *input_row = png_voidcast(const png_uint_16 *, display->first_row); - png_bytep output_row = png_voidcast(png_bytep, display->local_row); + png_byte *output_row = png_voidcast(png_byte *, display->local_row); png_uint_32 y = image->height; - const unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? + unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0) { - png_bytep row_end; + png_byte *row_end; int aindex; # ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED @@ -1718,8 +1807,8 @@ png_write_image_8bit(png_voidp argument) for (; y > 0; --y) { - png_const_uint_16p in_ptr = input_row; - png_bytep out_ptr = output_row; + const png_uint_16 *in_ptr = input_row; + png_byte *out_ptr = output_row; while (out_ptr < row_end) { @@ -1744,9 +1833,9 @@ png_write_image_8bit(png_voidp argument) ++out_ptr; } /* while out_ptr < row_end */ - png_write_row(png_ptr, png_voidcast(png_const_bytep, + png_write_row(png_ptr, png_voidcast(const png_byte *, display->local_row)); - input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); + input_row += display->row_step / 2; } /* while y */ } @@ -1755,12 +1844,12 @@ png_write_image_8bit(png_voidp argument) /* No alpha channel, so the row_end really is the end of the row and it * is sufficient to loop over the components one by one. */ - png_bytep row_end = output_row + image->width * channels; + png_byte *row_end = output_row + image->width * channels; for (; y > 0; --y) { - png_const_uint_16p in_ptr = input_row; - png_bytep out_ptr = output_row; + const png_uint_16 *in_ptr = input_row; + png_byte *out_ptr = output_row; while (out_ptr < row_end) { @@ -1771,7 +1860,7 @@ png_write_image_8bit(png_voidp argument) } png_write_row(png_ptr, output_row); - input_row += (png_uint_16)display->row_bytes/(sizeof (png_uint_16)); + input_row += display->row_step / 2; } } @@ -1781,25 +1870,25 @@ png_write_image_8bit(png_voidp argument) static void png_image_set_PLTE(png_image_write_control *display) { - const png_imagep image = display->image; + png_image *image = display->image; const void *cmap = display->colormap; - const int entries = image->colormap_entries > 256 ? 256 : + int entries = image->colormap_entries > 256 ? 256 : (int)image->colormap_entries; /* NOTE: the caller must check for cmap != NULL and entries != 0 */ - const png_uint_32 format = image->format; - const unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); + png_uint_32 format = image->format; + unsigned int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); # if defined(PNG_FORMAT_BGR_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; # else # define afirst 0 # endif # 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 # define bgr 0 # endif @@ -1818,7 +1907,7 @@ png_image_set_PLTE(png_image_write_control *display) */ if ((format & PNG_FORMAT_FLAG_LINEAR) != 0) { - png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap); + const png_uint_16 *entry = png_voidcast(const png_uint_16 *, cmap); entry += (unsigned int)i * channels; @@ -1874,7 +1963,7 @@ png_image_set_PLTE(png_image_write_control *display) else /* Color-map has sRGB values */ { - png_const_bytep entry = png_voidcast(png_const_bytep, cmap); + const png_byte *entry = png_voidcast(const png_byte *, cmap); entry += (unsigned int)i * channels; @@ -1884,7 +1973,7 @@ png_image_set_PLTE(png_image_write_control *display) tRNS[i] = entry[afirst ? 0 : 3]; if (tRNS[i] < 255) num_trans = i+1; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 3: palette[i].blue = entry[afirst + (2 ^ bgr)]; palette[i].green = entry[afirst + 1]; @@ -1895,7 +1984,7 @@ png_image_set_PLTE(png_image_write_control *display) tRNS[i] = entry[1 ^ afirst]; if (tRNS[i] < 255) num_trans = i+1; - /* FALL THROUGH */ + /* FALLTHROUGH */ case 1: palette[i].blue = palette[i].red = palette[i].green = entry[afirst]; @@ -1925,20 +2014,20 @@ png_image_set_PLTE(png_image_write_control *display) } static int -png_image_write_main(png_voidp argument) +png_image_write_main(void *argument) { png_image_write_control *display = png_voidcast(png_image_write_control*, argument); - png_imagep image = display->image; - png_structrp png_ptr = image->opaque->png_ptr; - png_inforp info_ptr = image->opaque->info_ptr; + png_image *image = display->image; + png_struct *png_ptr = image->opaque->png_ptr; + png_info *info_ptr = image->opaque->info_ptr; png_uint_32 format = image->format; /* The following four ints are actually booleans */ int colormap = (format & PNG_FORMAT_FLAG_COLORMAP); int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */ 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 /* Make sure we error out on any bad situation */ @@ -1949,18 +2038,18 @@ png_image_write_main(png_voidp argument) * and total image size to ensure that they are within the system limits. */ { - const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); + unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); if (image->width <= 0x7fffffffU/channels) /* no overflow */ { png_uint_32 check; - const png_uint_32 png_row_stride = image->width * channels; + png_uint_32 png_row_stride = image->width * channels; if (display->row_stride == 0) display->row_stride = (png_int_32)/*SAFE*/png_row_stride; if (display->row_stride < 0) - check = (png_uint_32)(-display->row_stride); + check = -(png_uint_32)display->row_stride; else check = (png_uint_32)display->row_stride; @@ -2050,9 +2139,9 @@ png_image_write_main(png_voidp argument) */ if (write_16bit != 0) { - PNG_CONST png_uint_16 le = 0x0001; + png_uint_16 le = 0x0001; - if ((*(png_const_bytep) & le) != 0) + if ((*(const png_byte *) & le) != 0) png_set_swap(png_ptr); } @@ -2086,17 +2175,17 @@ png_image_write_main(png_voidp argument) png_error(png_ptr, "png_write_image: unsupported transformation"); { - png_const_bytep row = png_voidcast(png_const_bytep, display->buffer); - ptrdiff_t row_bytes = display->row_stride; + const png_byte *row = png_voidcast(const png_byte *, display->buffer); + ptrdiff_t row_step = display->row_stride; if (linear != 0) - row_bytes *= (sizeof (png_uint_16)); + row_step *= 2; - if (row_bytes < 0) - row += (image->height-1) * (-row_bytes); + if (row_step < 0) + row += (image->height-1) * (-row_step); display->first_row = row; - display->row_bytes = row_bytes; + display->row_step = row_step; } /* Apply 'fast' options if the flag is set. */ @@ -2117,10 +2206,9 @@ png_image_write_main(png_voidp argument) * before it is written. This only applies when the input is 16-bit and * either there is an alpha channel or it is converted to 8-bit. */ - if ((linear != 0 && alpha != 0 ) || - (colormap == 0 && display->convert_to_8bit != 0)) + if (linear != 0 && (alpha != 0 || display->convert_to_8bit != 0)) { - png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_byte *row = png_voidcast(png_byte *, png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr))); int result; @@ -2143,14 +2231,14 @@ png_image_write_main(png_voidp argument) */ else { - png_const_bytep row = png_voidcast(png_const_bytep, display->first_row); - ptrdiff_t row_bytes = display->row_bytes; + const png_byte *row = png_voidcast(const png_byte *, display->first_row); + ptrdiff_t row_step = display->row_step; png_uint_32 y = image->height; for (; y > 0; --y) { png_write_row(png_ptr, row); - row += row_bytes; + row += row_step; } } @@ -2158,14 +2246,12 @@ png_image_write_main(png_voidp argument) return 1; } - -static void (PNGCBAPI -image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, - png_size_t size) +static void +image_memory_write(png_struct *png_ptr, png_byte *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)*/); - const png_alloc_size_t ob = display->output_bytes; + png_alloc_size_t ob = display->output_bytes; /* Check for overflow; this should never happen: */ if (size <= ((png_alloc_size_t)-1) - ob) @@ -2185,14 +2271,14 @@ image_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, png_error(png_ptr, "png_image_write_to_memory: PNG too big"); } -static void (PNGCBAPI -image_memory_flush)(png_structp png_ptr) +static void +image_memory_flush(png_struct *png_ptr) { PNG_UNUSED(png_ptr) } static int -png_image_write_memory(png_voidp argument) +png_image_write_memory(void *argument) { png_image_write_control *display = png_voidcast(png_image_write_control*, argument); @@ -2207,10 +2293,10 @@ png_image_write_memory(png_voidp argument) 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) +int +png_image_write_to_memory(png_image *image, void *memory, + png_alloc_size_t *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) @@ -2234,7 +2320,7 @@ png_image_write_to_memory(png_imagep image, void *memory, display.row_stride = row_stride; display.colormap = colormap; display.convert_to_8bit = convert_to_8bit; - display.memory = png_voidcast(png_bytep, memory); + display.memory = png_voidcast(png_byte *, memory); display.memory_bytes = *memory_bytes; display.output_bytes = 0; @@ -2274,11 +2360,11 @@ png_image_write_to_memory(png_imagep image, void *memory, } #ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED -int PNGAPI -png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, +int +png_image_write_to_stdio(png_image *image, FILE *file, int convert_to_8bit, const void *buffer, png_int_32 row_stride, const void *colormap) { - /* Write the image to the given (FILE*). */ + /* Write the image to the given FILE object. */ if (image != NULL && image->version == PNG_IMAGE_VERSION) { if (file != NULL && buffer != NULL) @@ -2323,8 +2409,8 @@ png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, return 0; } -int PNGAPI -png_image_write_to_file(png_imagep image, const char *file_name, +int +png_image_write_to_file(png_image *image, const char *file_name, int convert_to_8bit, const void *buffer, png_int_32 row_stride, const void *colormap) { @@ -2391,42 +2477,4 @@ png_image_write_to_file(png_imagep image, const char *file_name, } #endif /* SIMPLIFIED_WRITE_STDIO */ #endif /* SIMPLIFIED_WRITE */ - -#ifdef PNG_WRITE_APNG_SUPPORTED -void PNGAPI -png_write_frame_head(png_structp png_ptr, png_infop info_ptr, - png_bytepp row_pointers, png_uint_32 width, png_uint_32 height, - png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, - png_byte blend_op) -{ - png_debug(1, "in png_write_frame_head"); - - /* there is a chance this has been set after png_write_info was called, - * so it would be set but not written. is there a way to be sure? */ - if ((info_ptr->valid & PNG_INFO_acTL) == 0) - png_error(png_ptr, "png_write_frame_head(): acTL not set"); - - png_write_reset(png_ptr); - - png_write_reinit(png_ptr, info_ptr, width, height); - - if ((png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) == 0 || - png_ptr->num_frames_written != 0) - png_write_fcTL(png_ptr, width, height, x_offset, y_offset, - delay_num, delay_den, dispose_op, blend_op); - - PNG_UNUSED(row_pointers) -} - -void PNGAPI -png_write_frame_tail(png_structp png_ptr, png_infop info_ptr) -{ - png_debug(1, "in png_write_frame_tail"); - - png_ptr->num_frames_written++; - - PNG_UNUSED(info_ptr) -} -#endif /* WRITE_APNG */ #endif /* WRITE */ diff --git a/media/libpng/pngwtran.c b/media/libpng/pngwtran.c index 377b43e5ca..02bce82859 100644 --- a/media/libpng/pngwtran.c +++ b/media/libpng/pngwtran.c @@ -1,10 +1,9 @@ - /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer @@ -22,7 +21,7 @@ * should be 1 (this only happens on grayscale and paletted images). */ static void -png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) +png_do_pack(png_row_info *row_info, png_byte *row, png_uint_32 bit_depth) { png_debug(1, "in png_do_pack"); @@ -33,7 +32,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) { case 1: { - png_bytep sp, dp; + png_byte *sp, *dp; int mask, v; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -70,7 +69,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) case 2: { - png_bytep sp, dp; + png_byte *sp, *dp; unsigned int shift; int v; png_uint_32 i; @@ -110,7 +109,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) case 4: { - png_bytep sp, dp; + png_byte *sp, *dp; unsigned int shift; int v; png_uint_32 i; @@ -169,8 +168,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) * data to 0 to 15. */ static void -png_do_shift(png_row_infop row_info, png_bytep row, - png_const_color_8p bit_depth) +png_do_shift(png_row_info *row_info, png_byte *row, + const png_color_8 *bit_depth) { png_debug(1, "in png_do_shift"); @@ -211,10 +210,10 @@ png_do_shift(png_row_infop row_info, png_bytep row, /* With low row depths, could only be grayscale, so one channel */ if (row_info->bit_depth < 8) { - png_bytep bp = row; - png_size_t i; + png_byte *bp = row; + size_t i; 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) mask = 0x55; @@ -248,14 +247,13 @@ png_do_shift(png_row_infop row_info, png_bytep row, else if (row_info->bit_depth == 8) { - png_bytep bp = row; + png_byte *bp = row; png_uint_32 i; png_uint_32 istop = channels * row_info->width; for (i = 0; i < istop; i++, bp++) { - - const unsigned int c = i%channels; + unsigned int c = i%channels; int j; unsigned int v, out; @@ -277,13 +275,13 @@ png_do_shift(png_row_infop row_info, png_bytep row, else { - png_bytep bp; + png_byte *bp; png_uint_32 i; png_uint_32 istop = channels * row_info->width; for (bp = row, i = 0; i < istop; i++) { - const unsigned int c = i%channels; + unsigned int c = i%channels; int j; unsigned int value, v; @@ -308,7 +306,7 @@ png_do_shift(png_row_infop row_info, png_bytep row, #ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED static void -png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) +png_do_write_swap_alpha(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_write_swap_alpha"); @@ -318,7 +316,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This converts from ARGB to RGBA */ - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -336,7 +334,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) else { /* This converts from AARRGGBB to RRGGBBAA */ - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -363,7 +361,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This converts from AG to GA */ - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -379,7 +377,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) else { /* This converts from AAGG to GGAA */ - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -402,7 +400,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row) #ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED static void -png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) +png_do_write_invert_alpha(png_row_info *row_info, png_byte *row) { png_debug(1, "in png_do_write_invert_alpha"); @@ -412,7 +410,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This inverts the alpha channel in RGBA */ - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -432,7 +430,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) else { /* This inverts the alpha channel in RRGGBBAA */ - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -459,7 +457,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) if (row_info->bit_depth == 8) { /* This inverts the alpha channel in GA */ - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -474,7 +472,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) else { /* This inverts the alpha channel in GGAA */ - png_bytep sp, dp; + png_byte *sp, *dp; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -499,7 +497,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) * transformations is significant. */ void /* PRIVATE */ -png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) +png_do_write_transformations(png_struct *png_ptr, png_row_info *row_info) { png_debug(1, "in png_do_write_transformations"); @@ -514,7 +512,7 @@ png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info) (png_ptr, /* png_ptr */ row_info, /* row_info: */ /* 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 bit_depth; bit depth of samples */ /* png_byte channels; number of channels (1-4) */ diff --git a/media/libpng/pngwutil.c b/media/libpng/pngwutil.c index a33f7b8d7b..dae8850feb 100644 --- a/media/libpng/pngwutil.c +++ b/media/libpng/pngwutil.c @@ -1,27 +1,44 @@ - /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.6.26 [October 20, 2016] - * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson - * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) - * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) + * Copyright (c) 2018-2026 Cosmin Truta + * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson + * Copyright (c) 1996-1997 Andreas Dilger + * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h + * + * This file contains routines that are only called from within + * libpng itself during the course of writing an image. */ #include "pngpriv.h" #ifdef PNG_WRITE_SUPPORTED +#ifdef PNG_WRITE_INTERLACING_SUPPORTED +/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */ + +/* Start of interlace block */ +static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; +/* Offset to next interlace block */ +static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; +/* Start of interlace block in the y direction */ +static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; +/* Offset to next interlace block in the y direction */ +static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; + +/* TODO: Move these arrays to a common utility module to avoid duplication. */ +#endif + #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED /* Place a 32-bit number into a buffer in PNG byte order. We work * with unsigned numbers for convenience, although one supported * ancillary chunk uses signed (two's complement) numbers. */ -void PNGAPI -png_save_uint_32(png_bytep buf, png_uint_32 i) +void +png_save_uint_32(png_byte *buf, png_uint_32 i) { buf[0] = (png_byte)((i >> 24) & 0xffU); buf[1] = (png_byte)((i >> 16) & 0xffU); @@ -33,8 +50,8 @@ png_save_uint_32(png_bytep buf, png_uint_32 i) * The parameter is declared unsigned int, not png_uint_16, * just to avoid potential problems on pre-ANSI C compilers. */ -void PNGAPI -png_save_uint_16(png_bytep buf, unsigned int i) +void +png_save_uint_16(png_byte *buf, unsigned int i) { buf[0] = (png_byte)((i >> 8) & 0xffU); buf[1] = (png_byte)( i & 0xffU); @@ -47,8 +64,8 @@ png_save_uint_16(png_bytep buf, unsigned int i) * we should call png_set_sig_bytes() to tell libpng how many of the * bytes have already been written. */ -void PNGAPI -png_write_sig(png_structrp png_ptr) +void +png_write_sig(png_struct *png_ptr) { png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; @@ -59,7 +76,7 @@ png_write_sig(png_structrp png_ptr) /* Write the rest of the 8 byte signature */ 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) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; @@ -70,7 +87,7 @@ png_write_sig(png_structrp png_ptr) * passing in png_write_chunk_data(). */ static void -png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name, +png_write_chunk_header(png_struct *png_ptr, png_uint_32 chunk_name, png_uint_32 length) { png_byte buf[8]; @@ -111,8 +128,8 @@ png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name, #endif } -void PNGAPI -png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, +void +png_write_chunk_start(png_struct *png_ptr, const png_byte *chunk_string, png_uint_32 length) { png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length); @@ -123,9 +140,8 @@ png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, * sum of the lengths from these calls *must* add up to the total_length * given to png_write_chunk_header(). */ -void PNGAPI -png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, - png_size_t length) +void +png_write_chunk_data(png_struct *png_ptr, const png_byte *data, size_t length) { /* Write the data, and run the CRC over it */ if (png_ptr == NULL) @@ -143,8 +159,8 @@ png_write_chunk_data(png_structrp png_ptr, png_const_bytep data, } /* Finish a chunk started with png_write_chunk_header(). */ -void PNGAPI -png_write_chunk_end(png_structrp png_ptr) +void +png_write_chunk_end(png_struct *png_ptr) { png_byte buf[4]; @@ -160,7 +176,7 @@ png_write_chunk_end(png_structrp png_ptr) /* Write the crc in a single operation */ 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 @@ -173,8 +189,8 @@ png_write_chunk_end(png_structrp png_ptr) * functions instead. */ static void -png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, - png_const_bytep data, png_size_t length) +png_write_complete_chunk(png_struct *png_ptr, png_uint_32 chunk_name, + const png_byte *data, size_t length) { if (png_ptr == NULL) return; @@ -189,9 +205,9 @@ png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, } /* This is the API that calls the internal function above. */ -void PNGAPI -png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, - png_const_bytep data, png_size_t length) +void +png_write_chunk(png_struct *png_ptr, const png_byte *chunk_string, + const png_byte *data, size_t length) { png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, length); @@ -202,7 +218,7 @@ png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, * point at which a lower LZ window size can be used.) */ static png_alloc_size_t -png_image_size(png_structrp png_ptr) +png_image_size(png_struct *png_ptr) { /* Only return sizes up to the maximum of a png_uint_32; do this by limiting * the width and height used to 15 bits. @@ -248,7 +264,7 @@ png_image_size(png_structrp png_ptr) * compressed.) */ static void -optimize_cmf(png_bytep data, png_alloc_size_t data_size) +optimize_cmf(png_byte *data, png_alloc_size_t data_size) { /* Optimize the CMF field in the zlib stream. The resultant zlib stream is * still compliant to the stream specification. @@ -290,7 +306,7 @@ optimize_cmf(png_bytep data, png_alloc_size_t data_size) /* Initialize the compressor for the appropriate type of compression. */ static int -png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, +png_deflate_claim(png_struct *png_ptr, png_uint_32 owner, png_alloc_size_t data_size) { if (png_ptr->zowner != 0) @@ -314,7 +330,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, /* Attempt sane error recovery */ if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */ { - png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT"); + png_ptr->zstream.msg = "in use by IDAT"; return Z_STREAM_ERROR; } @@ -437,9 +453,9 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, /* Clean up (or trim) a linked list of compression buffers. */ void /* PRIVATE */ -png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp) +png_free_buffer_list(png_struct *png_ptr, png_compression_buffer **listp) { - png_compression_bufferp list = *listp; + png_compression_buffer *list = *listp; if (list != NULL) { @@ -447,7 +463,7 @@ png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp) do { - png_compression_bufferp next = list->next; + png_compression_buffer *next = list->next; png_free(png_ptr, list); list = next; @@ -469,14 +485,14 @@ png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp) */ typedef struct { - png_const_bytep input; /* The uncompressed input data */ - png_alloc_size_t input_len; /* Its length */ - png_uint_32 output_len; /* Final compressed length */ - png_byte output[1024]; /* First block of output */ + const png_byte *input; /* The uncompressed input data */ + png_alloc_size_t input_len; /* Its length */ + png_uint_32 output_len; /* Final compressed length */ + png_byte output[1024]; /* First block of output */ } compression_state; static void -png_text_compress_init(compression_state *comp, png_const_bytep input, +png_text_compress_init(compression_state *comp, const png_byte *input, png_alloc_size_t input_len) { comp->input = input; @@ -486,7 +502,7 @@ png_text_compress_init(compression_state *comp, png_const_bytep input, /* Compress the data in the compression state input */ static int -png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, +png_text_compress(png_struct *png_ptr, png_uint_32 chunk_name, compression_state *comp, png_uint_32 prefix_len) { int ret; @@ -513,12 +529,12 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, * in size. */ { - png_compression_bufferp *end = &png_ptr->zbuffer_list; + png_compression_buffer **end = &png_ptr->zbuffer_list; png_alloc_size_t input_len = comp->input_len; /* may be zero! */ png_uint_32 output_len; /* zlib updates these for us: */ - png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input); + png_ptr->zstream.next_in = comp->input; png_ptr->zstream.avail_in = 0; /* Set below */ png_ptr->zstream.next_out = comp->output; png_ptr->zstream.avail_out = (sizeof comp->output); @@ -555,7 +571,7 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, next = *end; if (next == NULL) { - next = png_voidcast(png_compression_bufferp, png_malloc_base + next = png_voidcast(png_compression_buffer *, png_malloc_base (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); if (next == NULL) @@ -602,7 +618,7 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, */ if (output_len + prefix_len >= PNG_UINT_31_MAX) { - png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long"); + png_ptr->zstream.msg = "compressed data too long"; ret = Z_MEM_ERROR; } @@ -635,10 +651,10 @@ png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, /* Ship the compressed text out via chunk writes */ static void -png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp) +png_write_compressed_data_out(png_struct *png_ptr, compression_state *comp) { png_uint_32 output_len = comp->output_len; - png_const_bytep output = comp->output; + const png_byte *output = comp->output; png_uint_32 avail = (sizeof comp->output); png_compression_buffer *next = png_ptr->zbuffer_list; @@ -670,11 +686,12 @@ png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp) * information being correct. */ void /* PRIVATE */ -png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, +png_write_IHDR(png_struct *png_ptr, png_uint_32 width, png_uint_32 height, int bit_depth, int color_type, int compression_type, int filter_type, int interlace_type) { png_byte buf[13]; /* Buffer to store the IHDR info */ + int is_invalid_depth; png_debug(1, "in png_write_IHDR"); @@ -700,11 +717,11 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, break; case PNG_COLOR_TYPE_RGB: + is_invalid_depth = (bit_depth != 8); #ifdef PNG_WRITE_16BIT_SUPPORTED - if (bit_depth != 8 && bit_depth != 16) -#else - if (bit_depth != 8) + is_invalid_depth = (is_invalid_depth && bit_depth != 16); #endif + if (is_invalid_depth) png_error(png_ptr, "Invalid bit depth for RGB image"); png_ptr->channels = 3; @@ -726,18 +743,22 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, break; case PNG_COLOR_TYPE_GRAY_ALPHA: - if (bit_depth != 8 && bit_depth != 16) + is_invalid_depth = (bit_depth != 8); +#ifdef PNG_WRITE_16BIT_SUPPORTED + is_invalid_depth = (is_invalid_depth && bit_depth != 16); +#endif + if (is_invalid_depth) png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); png_ptr->channels = 2; break; case PNG_COLOR_TYPE_RGB_ALPHA: + is_invalid_depth = (bit_depth != 8); #ifdef PNG_WRITE_16BIT_SUPPORTED - if (bit_depth != 8 && bit_depth != 16) -#else - if (bit_depth != 8) + is_invalid_depth = (is_invalid_depth && bit_depth != 16); #endif + if (is_invalid_depth) png_error(png_ptr, "Invalid bit depth for RGBA image"); png_ptr->channels = 4; @@ -815,7 +836,7 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, buf[12] = (png_byte)interlace_type; /* 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); #ifdef PNG_WRITE_APNG_SUPPORTED png_ptr->first_frame_width = width; @@ -840,11 +861,11 @@ png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, * structure. */ void /* PRIVATE */ -png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, +png_write_PLTE(png_struct *png_ptr, const png_color *palette, png_uint_32 num_pal) { png_uint_32 max_palette_length, i; - png_const_colorp pal_ptr; + const png_color *pal_ptr; png_byte buf[3]; png_debug(1, "in png_write_PLTE"); @@ -882,31 +903,15 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, png_debug1(3, "num_palette = %d", png_ptr->num_palette); png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); -#ifdef PNG_POINTER_INDEXING_SUPPORTED for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) { buf[0] = pal_ptr->red; buf[1] = pal_ptr->green; buf[2] = pal_ptr->blue; - png_write_chunk_data(png_ptr, buf, (png_size_t)3); - } - -#else - /* This is a little slower but some buggy compilers need to do this - * instead - */ - pal_ptr=palette; - - for (i = 0; i < num_pal; i++) - { - buf[0] = pal_ptr[i].red; - buf[1] = pal_ptr[i].green; - 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 png_write_chunk_end(png_ptr); png_ptr->mode |= PNG_HAVE_PLTE; } @@ -929,7 +934,7 @@ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, * checks on the 'mode' flags while doing this. */ void /* PRIVATE */ -png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, +png_compress_IDAT(png_struct *png_ptr, const png_byte *input, png_alloc_size_t input_len, int flush) { if (png_ptr->zowner != png_IDAT) @@ -941,7 +946,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, */ if (png_ptr->zbuffer_list == NULL) { - png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp, + png_ptr->zbuffer_list = png_voidcast(png_compression_buffer *, png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); png_ptr->zbuffer_list->next = NULL; } @@ -964,7 +969,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, * terminates the operation. The _out values are maintained across calls to * this function, but the input must be reset each time. */ - png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); + png_ptr->zstream.next_in = input; png_ptr->zstream.avail_in = 0; /* set below */ for (;;) { @@ -991,7 +996,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, */ if (png_ptr->zstream.avail_out == 0) { - png_bytep data = png_ptr->zbuffer_list->output; + png_byte *data = png_ptr->zbuffer_list->output; uInt size = png_ptr->zbuffer_size; /* Write an IDAT containing the data then reset the buffer. The @@ -1003,14 +1008,17 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, optimize_cmf(data, png_image_size(png_ptr)); #endif + if (size > 0) + { #ifdef PNG_WRITE_APNG_SUPPORTED - if (png_ptr->num_frames_written == 0) -#endif - png_write_complete_chunk(png_ptr, png_IDAT, data, size); -#ifdef PNG_WRITE_APNG_SUPPORTED - else - png_write_fdAT(png_ptr, data, size); -#endif /* WRITE_APNG */ + if (png_ptr->num_frames_written == 0) + png_write_complete_chunk(png_ptr, png_IDAT, data, size); + else + png_write_fdAT(png_ptr, data, size); +#else + png_write_complete_chunk(png_ptr, png_IDAT, data, size); +#endif /* PNG_WRITE_APNG_SUPPORTED */ + } png_ptr->mode |= PNG_HAVE_IDAT; @@ -1048,7 +1056,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, /* This is the end of the IDAT data; any pending output must be * flushed. For small PNG files we may still be at the beginning. */ - png_bytep data = png_ptr->zbuffer_list->output; + png_byte *data = png_ptr->zbuffer_list->output; uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out; #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED @@ -1057,14 +1065,17 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, optimize_cmf(data, png_image_size(png_ptr)); #endif + if (size > 0) + { #ifdef PNG_WRITE_APNG_SUPPORTED - if (png_ptr->num_frames_written == 0) -#endif - png_write_complete_chunk(png_ptr, png_IDAT, data, size); -#ifdef PNG_WRITE_APNG_SUPPORTED - else - png_write_fdAT(png_ptr, data, size); -#endif /* WRITE_APNG */ + if (png_ptr->num_frames_written == 0) + png_write_complete_chunk(png_ptr, png_IDAT, data, size); + else + png_write_fdAT(png_ptr, data, size); +#else + png_write_complete_chunk(png_ptr, png_IDAT, data, size); +#endif /* PNG_WRITE_APNG_SUPPORTED */ + } png_ptr->zstream.avail_out = 0; png_ptr->zstream.next_out = NULL; @@ -1085,18 +1096,18 @@ png_compress_IDAT(png_structrp png_ptr, png_const_bytep input, /* Write an IEND chunk */ void /* PRIVATE */ -png_write_IEND(png_structrp png_ptr) +png_write_IEND(png_struct *png_ptr) { 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; } #ifdef PNG_WRITE_gAMA_SUPPORTED /* Write a gAMA chunk */ void /* PRIVATE */ -png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) +png_write_gAMA_fixed(png_struct *png_ptr, png_fixed_point file_gamma) { png_byte buf[4]; @@ -1104,14 +1115,14 @@ png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) /* file_gamma is saved in 1/100,000ths */ 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 #ifdef PNG_WRITE_sRGB_SUPPORTED /* Write a sRGB chunk */ void /* PRIVATE */ -png_write_sRGB(png_structrp png_ptr, int srgb_intent) +png_write_sRGB(png_struct *png_ptr, int srgb_intent) { png_byte buf[1]; @@ -1122,18 +1133,17 @@ png_write_sRGB(png_structrp png_ptr, int srgb_intent) "Invalid sRGB rendering intent specified"); 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 #ifdef PNG_WRITE_iCCP_SUPPORTED /* Write an iCCP chunk */ void /* PRIVATE */ -png_write_iCCP(png_structrp png_ptr, png_const_charp name, - png_const_bytep profile) +png_write_iCCP(png_struct *png_ptr, const char *name, + const png_byte *profile, png_uint_32 profile_len) { png_uint_32 name_len; - png_uint_32 profile_len; png_byte new_name[81]; /* 1 byte for the compression byte */ compression_state comp; png_uint_32 temp; @@ -1146,11 +1156,12 @@ png_write_iCCP(png_structrp png_ptr, png_const_charp name, if (profile == NULL) png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */ - profile_len = png_get_uint_32(profile); - if (profile_len < 132) png_error(png_ptr, "ICC profile too short"); + if (png_get_uint_32(profile) != profile_len) + png_error(png_ptr, "Incorrect data in iCCP"); + temp = (png_uint_32) (*(profile+8)); if (temp > 3 && (profile_len & 0x03)) png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)"); @@ -1191,17 +1202,14 @@ png_write_iCCP(png_structrp png_ptr, png_const_charp name, #ifdef PNG_WRITE_sPLT_SUPPORTED /* Write a sPLT chunk */ void /* PRIVATE */ -png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) +png_write_sPLT(png_struct *png_ptr, const png_sPLT_t *spalette) { png_uint_32 name_len; png_byte new_name[80]; png_byte entrybuf[10]; - png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); - png_size_t palette_size = entry_size * (png_size_t)spalette->nentries; - png_sPLT_entryp ep; -#ifndef PNG_POINTER_INDEXING_SUPPORTED - int i; -#endif + size_t entry_size = (spalette->depth == 8 ? 6 : 10); + size_t palette_size = entry_size * (size_t)spalette->nentries; + png_sPLT_entry *ep; png_debug(1, "in png_write_sPLT"); @@ -1214,13 +1222,11 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) png_write_chunk_header(png_ptr, png_sPLT, (png_uint_32)(name_len + 2 + palette_size)); - png_write_chunk_data(png_ptr, (png_bytep)new_name, - (png_size_t)(name_len + 1)); + png_write_chunk_data(png_ptr, (png_byte *)new_name, (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 */ -#ifdef PNG_POINTER_INDEXING_SUPPORTED for (ep = spalette->entries; epentries + spalette->nentries; ep++) { if (spalette->depth == 8) @@ -1243,31 +1249,6 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) png_write_chunk_data(png_ptr, entrybuf, entry_size); } -#else - ep=spalette->entries; - for (i = 0; i>spalette->nentries; i++) - { - if (spalette->depth == 8) - { - entrybuf[0] = (png_byte)ep[i].red; - entrybuf[1] = (png_byte)ep[i].green; - entrybuf[2] = (png_byte)ep[i].blue; - entrybuf[3] = (png_byte)ep[i].alpha; - png_save_uint_16(entrybuf + 4, ep[i].frequency); - } - - else - { - png_save_uint_16(entrybuf + 0, ep[i].red); - png_save_uint_16(entrybuf + 2, ep[i].green); - png_save_uint_16(entrybuf + 4, ep[i].blue); - png_save_uint_16(entrybuf + 6, ep[i].alpha); - png_save_uint_16(entrybuf + 8, ep[i].frequency); - } - - png_write_chunk_data(png_ptr, entrybuf, entry_size); - } -#endif png_write_chunk_end(png_ptr); } @@ -1276,10 +1257,10 @@ png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) #ifdef PNG_WRITE_sBIT_SUPPORTED /* Write the sBIT chunk */ void /* PRIVATE */ -png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) +png_write_sBIT(png_struct *png_ptr, const png_color_8 *sbit, int color_type) { png_byte buf[4]; - png_size_t size; + size_t size; png_debug(1, "in png_write_sBIT"); @@ -1335,7 +1316,7 @@ png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) #ifdef PNG_WRITE_cHRM_SUPPORTED /* Write the cHRM chunk */ void /* PRIVATE */ -png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy) +png_write_cHRM_fixed(png_struct *png_ptr, const png_xy *xy) { png_byte buf[32]; @@ -1361,8 +1342,8 @@ png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy) #ifdef PNG_WRITE_tRNS_SUPPORTED /* Write the tRNS chunk */ void /* PRIVATE */ -png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, - png_const_color_16p tran, int num_trans, int color_type) +png_write_tRNS(png_struct *png_ptr, const png_byte *trans_alpha, + const png_color_16 *tran, int num_trans, int color_type) { png_byte buf[6]; @@ -1379,7 +1360,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, /* Write the chunk out as it is */ 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) @@ -1394,7 +1375,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, } 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) @@ -1414,7 +1395,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, 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 @@ -1427,7 +1408,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, #ifdef PNG_WRITE_bKGD_SUPPORTED /* Write the background chunk */ void /* PRIVATE */ -png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) +png_write_bKGD(png_struct *png_ptr, const png_color_16 *back, int color_type) { png_byte buf[6]; @@ -1447,7 +1428,7 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) } 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) @@ -1468,7 +1449,7 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) 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 @@ -1482,15 +1463,104 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) } 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 + +#ifdef PNG_WRITE_cICP_SUPPORTED +/* Write the cICP data */ +void /* PRIVATE */ +png_write_cICP(png_struct *png_ptr, + png_byte colour_primaries, png_byte transfer_function, + png_byte matrix_coefficients, png_byte video_full_range_flag) +{ + png_byte buf[4]; + + png_debug(1, "in png_write_cICP"); + + png_write_chunk_header(png_ptr, png_cICP, 4); + + buf[0] = colour_primaries; + buf[1] = transfer_function; + buf[2] = matrix_coefficients; + buf[3] = video_full_range_flag; + png_write_chunk_data(png_ptr, buf, 4); + + png_write_chunk_end(png_ptr); +} +#endif + +#ifdef PNG_WRITE_cLLI_SUPPORTED +void /* PRIVATE */ +png_write_cLLI_fixed(png_struct *png_ptr, png_uint_32 maxCLL, + png_uint_32 maxFALL) +{ + png_byte buf[8]; + + png_debug(1, "in png_write_cLLI_fixed"); + + png_save_uint_32(buf, maxCLL); + png_save_uint_32(buf + 4, maxFALL); + + png_write_complete_chunk(png_ptr, png_cLLI, buf, 8); +} +#endif + +#ifdef PNG_WRITE_mDCV_SUPPORTED +void /* PRIVATE */ +png_write_mDCV_fixed(png_struct *png_ptr, + png_uint_16 red_x, png_uint_16 red_y, + png_uint_16 green_x, png_uint_16 green_y, + png_uint_16 blue_x, png_uint_16 blue_y, + png_uint_16 white_x, png_uint_16 white_y, + png_uint_32 maxDL, png_uint_32 minDL) +{ + png_byte buf[24]; + + png_debug(1, "in png_write_mDCV_fixed"); + + png_save_uint_16(buf + 0, red_x); + png_save_uint_16(buf + 2, red_y); + png_save_uint_16(buf + 4, green_x); + png_save_uint_16(buf + 6, green_y); + png_save_uint_16(buf + 8, blue_x); + png_save_uint_16(buf + 10, blue_y); + png_save_uint_16(buf + 12, white_x); + png_save_uint_16(buf + 14, white_y); + png_save_uint_32(buf + 16, maxDL); + png_save_uint_32(buf + 20, minDL); + + png_write_complete_chunk(png_ptr, png_mDCV, buf, 24); +} +#endif + +#ifdef PNG_WRITE_eXIf_SUPPORTED +/* Write the Exif data */ +void /* PRIVATE */ +png_write_eXIf(png_struct *png_ptr, png_byte *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 /* Write the histogram */ void /* PRIVATE */ -png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) +png_write_hIST(png_struct *png_ptr, const png_uint_16 *hist, int num_hist) { int i; png_byte buf[3]; @@ -1511,7 +1581,7 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) for (i = 0; i < num_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); @@ -1521,8 +1591,8 @@ png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) #ifdef PNG_WRITE_tEXt_SUPPORTED /* Write a tEXt chunk */ void /* PRIVATE */ -png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, - png_size_t text_len) +png_write_tEXt(png_struct *png_ptr, const char *key, const char *text, + size_t text_len) { png_uint_32 key_len; png_byte new_key[80]; @@ -1555,7 +1625,7 @@ png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, png_write_chunk_data(png_ptr, new_key, key_len + 1); if (text_len != 0) - png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len); + png_write_chunk_data(png_ptr, (const png_byte *)text, text_len); png_write_chunk_end(png_ptr); } @@ -1564,7 +1634,7 @@ png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, #ifdef PNG_WRITE_zTXt_SUPPORTED /* Write a compressed text chunk */ void /* PRIVATE */ -png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, +png_write_zTXt(png_struct *png_ptr, const char *key, const char *text, int compression) { png_uint_32 key_len; @@ -1592,7 +1662,7 @@ png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, ++key_len; /* Compute the compressed data; do it now for the length */ - png_text_compress_init(&comp, (png_const_bytep)text, + png_text_compress_init(&comp, (const png_byte *)text, text == NULL ? 0 : strlen(text)); if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK) @@ -1615,11 +1685,11 @@ png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, #ifdef PNG_WRITE_iTXt_SUPPORTED /* Write an iTXt chunk */ void /* PRIVATE */ -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_write_iTXt(png_struct *png_ptr, int compression, const char *key, + const char *lang, const char *lang_key, const char *text) { 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]; compression_state comp; @@ -1648,7 +1718,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, } new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; - ++key_len; /* for the keywod separator */ + ++key_len; /* for the keyword separator */ /* We leave it to the application to meet PNG-1.0 requirements on the * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of @@ -1677,7 +1747,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, else prefix_len = (png_uint_32)(prefix_len + lang_key_len); - png_text_compress_init(&comp, (png_const_bytep)text, strlen(text)); + png_text_compress_init(&comp, (const png_byte *)text, strlen(text)); if (compression != 0) { @@ -1698,15 +1768,15 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, png_write_chunk_data(png_ptr, new_key, key_len); - png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len); + png_write_chunk_data(png_ptr, (const png_byte *)lang, lang_len); - png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len); + png_write_chunk_data(png_ptr, (const png_byte *)lang_key, lang_key_len); if (compression != 0) png_write_compressed_data_out(png_ptr, &comp); else - png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len); + png_write_chunk_data(png_ptr, (const png_byte *)text, comp.output_len); png_write_chunk_end(png_ptr); } @@ -1715,7 +1785,7 @@ png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, #ifdef PNG_WRITE_oFFs_SUPPORTED /* Write the oFFs chunk */ void /* PRIVATE */ -png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset, +png_write_oFFs(png_struct *png_ptr, png_int_32 x_offset, png_int_32 y_offset, int unit_type) { png_byte buf[9]; @@ -1729,19 +1799,19 @@ 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); 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 #ifdef PNG_WRITE_pCAL_SUPPORTED /* Write the pCAL chunk (described in the PNG extensions document) */ void /* PRIVATE */ -png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, - png_int_32 X1, int type, int nparams, png_const_charp units, - png_charpp params) +png_write_pCAL(png_struct *png_ptr, char *purpose, png_int_32 X0, + png_int_32 X1, int type, int nparams, const char *units, + char **params) { png_uint_32 purpose_len; - png_size_t units_len, total_len; - png_size_tp params_len; + size_t units_len, total_len; + size_t *params_len; png_byte buf[10]; png_byte new_purpose[80]; int i; @@ -1763,8 +1833,8 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, png_debug1(3, "pCAL units length = %d", (int)units_len); total_len = purpose_len + units_len + 10; - params_len = (png_size_tp)png_malloc(png_ptr, - (png_alloc_size_t)((png_alloc_size_t)nparams * (sizeof (png_size_t)))); + params_len = (size_t *)png_malloc(png_ptr, + (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 * null terminator for the last parameter. @@ -1784,12 +1854,12 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, png_save_int_32(buf + 4, X1); buf[8] = (png_byte)type; buf[9] = (png_byte)nparams; - png_write_chunk_data(png_ptr, buf, (png_size_t)10); - png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); + png_write_chunk_data(png_ptr, buf, 10); + png_write_chunk_data(png_ptr, (const png_byte *)units, (size_t)units_len); for (i = 0; i < nparams; i++) { - png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]); + png_write_chunk_data(png_ptr, (const png_byte *)params[i], params_len[i]); } png_free(png_ptr, params_len); @@ -1800,11 +1870,11 @@ png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, #ifdef PNG_WRITE_sCAL_SUPPORTED /* Write the sCAL chunk */ void /* PRIVATE */ -png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, - png_const_charp height) +png_write_sCAL_s(png_struct *png_ptr, int unit, const char *width, + const char *height) { 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"); @@ -1830,7 +1900,7 @@ png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, #ifdef PNG_WRITE_pHYs_SUPPORTED /* Write the pHYs chunk */ void /* PRIVATE */ -png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, +png_write_pHYs(png_struct *png_ptr, png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit, int unit_type) { @@ -1845,7 +1915,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); 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 @@ -1854,7 +1924,7 @@ png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, * or png_convert_from_time_t(), or fill in the structure yourself. */ void /* PRIVATE */ -png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) +png_write_tIME(png_struct *png_ptr, const png_time *mod_time) { png_byte buf[7]; @@ -1875,106 +1945,90 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time) buf[5] = mod_time->minute; 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 #ifdef PNG_WRITE_APNG_SUPPORTED void /* PRIVATE */ -png_write_acTL(png_structp png_ptr, - png_uint_32 num_frames, png_uint_32 num_plays) +png_write_acTL(png_struct *png_ptr, + png_uint_32 num_frames, png_uint_32 num_plays) { - png_byte buf[8]; + png_byte buf[8]; - png_debug(1, "in png_write_acTL"); + png_debug(1, "in png_write_acTL"); - png_ptr->num_frames_to_write = num_frames; + png_ptr->num_frames_to_write = num_frames; - if ((png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) != 0) - num_frames--; + if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN) + num_frames--; - png_save_uint_32(buf, num_frames); - png_save_uint_32(buf + 4, num_plays); + png_save_uint_32(buf, num_frames); + png_save_uint_32(buf + 4, num_plays); - png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8); + png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8); } void /* PRIVATE */ -png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height, - png_uint_32 x_offset, png_uint_32 y_offset, - png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op, - png_byte blend_op) +png_write_fcTL(png_struct *png_ptr, + png_uint_32 width, png_uint_32 height, + png_uint_32 x_offset, png_uint_32 y_offset, + png_uint_16 delay_num, png_uint_16 delay_den, + png_byte dispose_op, png_byte blend_op) { - png_byte buf[26]; - - png_debug(1, "in png_write_fcTL"); - - if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0)) - png_error(png_ptr, "x and/or y offset for the first frame aren't 0"); - if (png_ptr->num_frames_written == 0 && - (width != png_ptr->first_frame_width || - height != png_ptr->first_frame_height)) - png_error(png_ptr, "width and/or height in the first frame's fcTL " - "don't match the ones in IHDR"); - - /* more error checking */ - png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, - delay_num, delay_den, dispose_op, blend_op); - - png_save_uint_32(buf, png_ptr->next_seq_num); - png_save_uint_32(buf + 4, width); - png_save_uint_32(buf + 8, height); - png_save_uint_32(buf + 12, x_offset); - png_save_uint_32(buf + 16, y_offset); - png_save_uint_16(buf + 20, delay_num); - png_save_uint_16(buf + 22, delay_den); - buf[24] = dispose_op; - buf[25] = blend_op; - - png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26); - - png_ptr->next_seq_num++; + png_byte buf[26]; + + png_debug(1, "in png_write_fcTL"); + + if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0)) + png_error(png_ptr, "Non-zero frame offset in leading fcTL"); + if (png_ptr->num_frames_written == 0 && + (width != png_ptr->first_frame_width || + height != png_ptr->first_frame_height)) + png_error(png_ptr, "Incorrect frame size in leading fcTL"); + + /* More error checking. */ + png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset, + delay_num, delay_den, dispose_op, blend_op); + + png_save_uint_32(buf, png_ptr->next_seq_num); + png_save_uint_32(buf + 4, width); + png_save_uint_32(buf + 8, height); + png_save_uint_32(buf + 12, x_offset); + png_save_uint_32(buf + 16, y_offset); + png_save_uint_16(buf + 20, delay_num); + png_save_uint_16(buf + 22, delay_den); + buf[24] = dispose_op; + buf[25] = blend_op; + + png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26); + + png_ptr->next_seq_num++; } void /* PRIVATE */ -png_write_fdAT(png_structp png_ptr, - png_const_bytep data, png_size_t length) +png_write_fdAT(png_struct *png_ptr, + const png_byte *data, png_size_t length) { - png_byte buf[4]; + png_byte buf[4]; - png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length)); + png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length)); - png_save_uint_32(buf, png_ptr->next_seq_num); - png_write_chunk_data(png_ptr, buf, 4); + png_save_uint_32(buf, png_ptr->next_seq_num); + png_write_chunk_data(png_ptr, buf, 4); - png_write_chunk_data(png_ptr, data, length); + png_write_chunk_data(png_ptr, data, length); - png_write_chunk_end(png_ptr); + png_write_chunk_end(png_ptr); - png_ptr->next_seq_num++; + png_ptr->next_seq_num++; } -#endif /* WRITE_APNG */ +#endif /* PNG_WRITE_APNG_SUPPORTED */ /* Initializes the row writing capability of libpng */ void /* PRIVATE */ -png_write_start_row(png_structrp png_ptr) +png_write_start_row(png_struct *png_ptr) { -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* 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}; -#endif - png_alloc_size_t buf_size; int usr_pixel_depth; @@ -1992,7 +2046,7 @@ png_write_start_row(png_structrp png_ptr) png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; /* Set up row buffer */ - png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); + png_ptr->row_buf = png_voidcast(png_byte *, png_malloc(png_ptr, buf_size)); png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; @@ -2015,7 +2069,8 @@ png_write_start_row(png_structrp png_ptr) { int num_filters = 0; - png_ptr->try_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); + png_ptr->try_row = png_voidcast(png_byte *, + png_malloc(png_ptr, buf_size)); if (filters & PNG_FILTER_SUB) num_filters++; @@ -2030,7 +2085,7 @@ png_write_start_row(png_structrp png_ptr) num_filters++; if (num_filters > 1) - png_ptr->tst_row = png_voidcast(png_bytep, png_malloc(png_ptr, + png_ptr->tst_row = png_voidcast(png_byte *, png_malloc(png_ptr, buf_size)); } @@ -2038,7 +2093,7 @@ png_write_start_row(png_structrp png_ptr) * filters. */ if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0) - png_ptr->prev_row = png_voidcast(png_bytep, + png_ptr->prev_row = png_voidcast(png_byte *, png_calloc(png_ptr, buf_size)); #endif /* WRITE_FILTER */ @@ -2072,24 +2127,8 @@ png_write_start_row(png_structrp png_ptr) /* Internal use only. Called when finished processing a row of data. */ void /* PRIVATE */ -png_write_finish_row(png_structrp png_ptr) +png_write_finish_row(png_struct *png_ptr) { -#ifdef PNG_WRITE_INTERLACING_SUPPORTED - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - - /* Start of interlace block in the y direction */ - static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; - - /* 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}; -#endif - png_debug(1, "in png_write_finish_row"); /* Next row */ @@ -2141,8 +2180,8 @@ png_write_finish_row(png_structrp png_ptr) { if (png_ptr->prev_row != NULL) memset(png_ptr->prev_row, 0, - (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* - png_ptr->usr_bit_depth, png_ptr->width)) + 1); + PNG_ROWBYTES(png_ptr->usr_channels * + png_ptr->usr_bit_depth, png_ptr->width) + 1); return; } @@ -2163,16 +2202,8 @@ png_write_finish_row(png_structrp png_ptr) * See the default: case for the easiest code to understand. */ void /* PRIVATE */ -png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) +png_do_write_interlace(png_row_info *row_info, png_byte *row, int pass) { - /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ - - /* Start of interlace block */ - static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; - - /* Offset to next interlace block */ - static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; - png_debug(1, "in png_do_write_interlace"); /* We don't have to do anything on the last pass (6) */ @@ -2183,8 +2214,8 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) { case 1: { - png_bytep sp; - png_bytep dp; + png_byte *sp; + png_byte *dp; unsigned int shift; int d; int value; @@ -2198,7 +2229,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; 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; d |= (value << shift); @@ -2221,8 +2252,8 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) case 2: { - png_bytep sp; - png_bytep dp; + png_byte *sp; + png_byte *dp; unsigned int shift; int d; int value; @@ -2236,7 +2267,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; 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; d |= (value << shift); @@ -2258,8 +2289,8 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) case 4: { - png_bytep sp; - png_bytep dp; + png_byte *sp; + png_byte *dp; unsigned int shift; int d; int value; @@ -2272,7 +2303,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) for (i = png_pass_start[pass]; i < row_width; 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; d |= (value << shift); @@ -2294,11 +2325,11 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) default: { - png_bytep sp; - png_bytep dp; + png_byte *sp; + png_byte *dp; png_uint_32 i; png_uint_32 row_width = row_info->width; - png_size_t pixel_bytes; + size_t pixel_bytes; /* Start at the beginning */ dp = row; @@ -2311,7 +2342,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) i += png_pass_inc[pass]) { /* 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 */ if (dp != sp) @@ -2341,17 +2372,17 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) * chosen filter. */ static void /* PRIVATE */ -png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t row_bytes); +png_write_filtered_row(png_struct *png_ptr, png_byte *filtered_row, + size_t row_bytes); #ifdef PNG_WRITE_FILTER_SUPPORTED -static png_size_t /* PRIVATE */ -png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) +static size_t /* PRIVATE */ +png_setup_sub_row(png_struct *png_ptr, png_uint_32 bpp, + size_t row_bytes, size_t lmins) { - png_bytep rp, dp, lp; - png_size_t i; - png_size_t sum = 0; + png_byte *rp, *dp, *lp; + size_t i; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; @@ -2381,15 +2412,15 @@ png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, break; } - return (sum); + return sum; } static void /* PRIVATE */ -png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes) +png_setup_sub_row_only(png_struct *png_ptr, png_uint_32 bpp, + size_t row_bytes) { - png_bytep rp, dp, lp; - png_size_t i; + png_byte *rp, *dp, *lp; + size_t i; png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; @@ -2406,13 +2437,12 @@ png_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp, } } -static png_size_t /* PRIVATE */ -png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, - const png_size_t lmins) +static size_t /* PRIVATE */ +png_setup_up_row(png_struct *png_ptr, size_t row_bytes, size_t lmins) { - png_bytep rp, dp, pp; - png_size_t i; - png_size_t sum = 0; + png_byte *rp, *dp, *pp; + size_t i; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; @@ -2432,13 +2462,13 @@ png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, break; } - return (sum); + return sum; } static void /* PRIVATE */ -png_setup_up_row_only(png_structrp png_ptr, const png_size_t row_bytes) +png_setup_up_row_only(png_struct *png_ptr, size_t row_bytes) { - png_bytep rp, dp, pp; - png_size_t i; + png_byte *rp, *dp, *pp; + size_t i; png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; @@ -2450,13 +2480,13 @@ png_setup_up_row_only(png_structrp png_ptr, const png_size_t row_bytes) } } -static png_size_t /* PRIVATE */ -png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) +static size_t /* PRIVATE */ +png_setup_avg_row(png_struct *png_ptr, png_uint_32 bpp, + size_t row_bytes, size_t lmins) { - png_bytep rp, dp, pp, lp; + png_byte *rp, *dp, *pp, *lp; png_uint_32 i; - png_size_t sum = 0; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; @@ -2488,13 +2518,13 @@ png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, break; } - return (sum); + return sum; } static void /* PRIVATE */ -png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes) +png_setup_avg_row_only(png_struct *png_ptr, png_uint_32 bpp, + size_t row_bytes) { - png_bytep rp, dp, pp, lp; + png_byte *rp, *dp, *pp, *lp; png_uint_32 i; png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; @@ -2512,13 +2542,13 @@ png_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, } } -static png_size_t /* PRIVATE */ -png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes, const png_size_t lmins) +static size_t /* PRIVATE */ +png_setup_paeth_row(png_struct *png_ptr, png_uint_32 bpp, + size_t row_bytes, size_t lmins) { - png_bytep rp, dp, pp, cp, lp; - png_size_t i; - png_size_t sum = 0; + png_byte *rp, *dp, *pp, *cp, *lp; + size_t i; + size_t sum = 0; unsigned int v; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; @@ -2571,14 +2601,14 @@ png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, break; } - return (sum); + return sum; } static void /* PRIVATE */ -png_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp, - const png_size_t row_bytes) +png_setup_paeth_row_only(png_struct *png_ptr, png_uint_32 bpp, + size_t row_bytes) { - png_bytep rp, dp, pp, cp, lp; - png_size_t i; + png_byte *rp, *dp, *pp, *cp, *lp; + size_t i; png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; @@ -2618,17 +2648,17 @@ png_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp, #endif /* WRITE_FILTER */ void /* PRIVATE */ -png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) +png_write_find_filter(png_struct *png_ptr, png_row_info *row_info) { #ifndef PNG_WRITE_FILTER_SUPPORTED png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); #else unsigned int filter_to_do = png_ptr->do_filter; - png_bytep row_buf; - png_bytep best_row; + png_byte *row_buf; + png_byte *best_row; png_uint_32 bpp; - png_size_t mins; - png_size_t row_bytes = row_info->rowbytes; + size_t mins; + size_t row_bytes = row_info->rowbytes; png_debug(1, "in png_write_find_filter"); @@ -2644,11 +2674,10 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) * from zero, using anything >= 128 as negative numbers. This is known * as the "minimum sum of absolute differences" heuristic. Other * heuristics are the "weighted minimum sum of absolute differences" - * (experimental and can in theory improve compression), and the "zlib - * predictive" method (not implemented yet), which does test compressions - * of lines using different filter methods, and then chooses the - * (series of) filter(s) that give minimum compressed data size (VERY - * computationally expensive). + * method (experimented, then abandoned), and the "zlib predictive" method + * (not implemented yet), which does test compression of lines using + * different filter methods, and then chooses the (series of) filter(s) + * that give minimum compressed data size (VERY computationally expensive). * * GRR 980525: consider also * @@ -2682,9 +2711,9 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* Overflow not possible and multiple filters in the list, including the * 'none' filter. */ - png_bytep rp; - png_size_t sum = 0; - png_size_t i; + png_byte *rp; + size_t sum = 0; + size_t i; unsigned int v; { @@ -2712,8 +2741,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_SUB) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); @@ -2738,8 +2767,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_UP) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_up_row(png_ptr, row_bytes, lmins); @@ -2764,8 +2793,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_AVG) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); @@ -2790,8 +2819,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) else if ((filter_to_do & PNG_FILTER_PAETH) != 0) { - png_size_t sum; - png_size_t lmins = mins; + size_t sum; + size_t lmins = mins; sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); @@ -2815,8 +2844,8 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* Do the actual writing of a previously filtered row. */ static void -png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, - png_size_t full_row_length/*includes filter byte*/) +png_write_filtered_row(png_struct *png_ptr, png_byte *filtered_row, + size_t full_row_length/*includes filter byte*/) { png_debug(1, "in png_write_filtered_row"); @@ -2828,7 +2857,7 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, /* Swap the current and previous rows */ if (png_ptr->prev_row != NULL) { - png_bytep tptr; + png_byte *tptr; tptr = png_ptr->prev_row; png_ptr->prev_row = png_ptr->row_buf; @@ -2852,36 +2881,34 @@ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, #ifdef PNG_WRITE_APNG_SUPPORTED void /* PRIVATE */ -png_write_reset(png_structp png_ptr) +png_write_reset(png_struct *png_ptr) { - png_ptr->row_number = 0; - png_ptr->pass = 0; - png_ptr->mode &= ~PNG_HAVE_IDAT; + png_ptr->row_number = 0; + png_ptr->pass = 0; + png_ptr->mode &= ~PNG_HAVE_IDAT; } void /* PRIVATE */ -png_write_reinit(png_structp png_ptr, png_infop info_ptr, +png_write_reinit(png_struct *png_ptr, png_info *info_ptr, png_uint_32 width, png_uint_32 height) { - if (png_ptr->num_frames_written == 0 && - (width != png_ptr->first_frame_width || - height != png_ptr->first_frame_height)) - png_error(png_ptr, "width and/or height in the first frame's fcTL " - "don't match the ones in IHDR"); - if (width > png_ptr->first_frame_width || - height > png_ptr->first_frame_height) - png_error(png_ptr, "width and/or height for a frame greater than " - "the ones in IHDR"); - - png_set_IHDR(png_ptr, info_ptr, width, height, - info_ptr->bit_depth, info_ptr->color_type, - info_ptr->interlace_type, info_ptr->compression_type, - info_ptr->filter_type); - - png_ptr->width = width; - png_ptr->height = height; - png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); - png_ptr->usr_width = png_ptr->width; + if (png_ptr->num_frames_written == 0 && + (width != png_ptr->first_frame_width || + height != png_ptr->first_frame_height)) + png_error(png_ptr, "Incorrect frame size in leading fcTL"); + if (width > png_ptr->first_frame_width || + height > png_ptr->first_frame_height) + png_error(png_ptr, "Oversized frame in fcTL"); + + png_set_IHDR(png_ptr, info_ptr, width, height, + info_ptr->bit_depth, info_ptr->color_type, + info_ptr->interlace_type, info_ptr->compression_type, + info_ptr->filter_type); + + png_ptr->width = width; + png_ptr->height = height; + png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); + png_ptr->usr_width = png_ptr->width; } -#endif /* WRITE_APNG */ +#endif /* PNG_WRITE_APNG_SUPPORTED */ #endif /* WRITE */ diff --git a/media/libpng/powerpc/.editorconfig b/media/libpng/powerpc/.editorconfig new file mode 100644 index 0000000000..de2e98ab42 --- /dev/null +++ b/media/libpng/powerpc/.editorconfig @@ -0,0 +1,8 @@ +# https://editorconfig.org + +root = false + +# FIXME +[*.[ch]] +max_doc_length = unset +max_line_length = unset diff --git a/media/libpng/powerpc/check.h b/media/libpng/powerpc/check.h new file mode 100644 index 0000000000..dc09d494b8 --- /dev/null +++ b/media/libpng/powerpc/check.h @@ -0,0 +1,22 @@ +/* powerpc/check.h - POWERPC optimised filter functions + * + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2017 Glenn Randers-Pehrson + * Written by Vadim Barkov, 2017. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ +#if defined(__PPC64__) && defined(__ALTIVEC__) && defined(PNG_READ_SUPPORTED) + +#include + +#ifdef __VSX__ +# define PNG_TARGET_CODE_IMPLEMENTATION "powerpc/powerpc_init.c" + /* PNG_TARGET_STORES_DATA */ +# define PNG_TARGET_IMPLEMENTS_FILTERS + /* PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE */ + /* PNG_TARGET_ROW_ALIGNMENT */ +#endif /* __VSX__ */ +#endif /* __PPC64__ && __ALTIVEC__ && READ */ diff --git a/media/libpng/powerpc/filter_vsx_intrinsics.c b/media/libpng/powerpc/filter_vsx_intrinsics.c new file mode 100644 index 0000000000..52d8a6dfe1 --- /dev/null +++ b/media/libpng/powerpc/filter_vsx_intrinsics.c @@ -0,0 +1,752 @@ +/* filter_vsx_intrinsics.c - PowerPC optimised filter functions + * + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2017 Glenn Randers-Pehrson + * Written by Vadim Barkov, 2017. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ + +#define vec_ld_unaligned(vec,data) vec = vec_vsx_ld(0,data) +#define vec_st_unaligned(vec,data) vec_vsx_st(vec,0,data) + +/* Functions in this file look at most 3 pixels (a,b,c) to predict the 4th (d). + * They're positioned like this: + * prev: c b + * row: a d + * The Sub filter predicts d=a, Avg d=(a+b)/2, and Paeth predicts d to be + * whichever of a, b, or c is closest to p=a+b-c. + * ( this is taken from ../intel/filter_sse2_intrinsics.c ) + */ + +#define vsx_declare_common_vars(row_info,row,prev_row,offset) \ + png_byte i;\ + png_byte *rp = row + offset;\ + const png_byte *pp = prev_row;\ + size_t unaligned_top = 16 - (((size_t)rp % 16));\ + size_t istop;\ + if(unaligned_top == 16)\ + unaligned_top = 0;\ + istop = row_info->rowbytes;\ + if((unaligned_top < istop))\ + istop -= unaligned_top;\ + else{\ + unaligned_top = istop;\ + istop = 0;\ + } + +static void +png_read_filter_row_up_vsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + vector unsigned char rp_vec; + vector unsigned char pp_vec; + vsx_declare_common_vars(row_info,row,prev_row,0) + + /* Altivec operations require 16-byte aligned data + * but input can be unaligned. So we calculate + * unaligned part as usual. + */ + for (i = 0; i < unaligned_top; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + + /* Using SIMD while we can */ + while( istop >= 16 ) + { + rp_vec = vec_ld(0,rp); + vec_ld_unaligned(pp_vec,pp); + + rp_vec = vec_add(rp_vec,pp_vec); + + vec_st(rp_vec,0,rp); + + pp += 16; + rp += 16; + istop -= 16; + } + + if(istop > 0) + { + /* If byte count of row is not divisible by 16 + * we will process remaining part as usual + */ + for (i = 0; i < istop; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff); + rp++; + } + } +} + +static const vector unsigned char VSX_LEFTSHIFTED1_4 = {16,16,16,16, 0, 1, 2, 3,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_LEFTSHIFTED2_4 = {16,16,16,16,16,16,16,16, 4, 5, 6, 7,16,16,16,16}; +static const vector unsigned char VSX_LEFTSHIFTED3_4 = {16,16,16,16,16,16,16,16,16,16,16,16, 8, 9,10,11}; + +static const vector unsigned char VSX_LEFTSHIFTED1_3 = {16,16,16, 0, 1, 2,16,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_LEFTSHIFTED2_3 = {16,16,16,16,16,16, 3, 4, 5,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_LEFTSHIFTED3_3 = {16,16,16,16,16,16,16,16,16, 6, 7, 8,16,16,16,16}; +static const vector unsigned char VSX_LEFTSHIFTED4_3 = {16,16,16,16,16,16,16,16,16,16,16,16, 9,10,11,16}; + +static const vector unsigned char VSX_NOT_SHIFTED1_4 = {16,16,16,16, 4, 5, 6, 7,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_NOT_SHIFTED2_4 = {16,16,16,16,16,16,16,16, 8, 9,10,11,16,16,16,16}; +static const vector unsigned char VSX_NOT_SHIFTED3_4 = {16,16,16,16,16,16,16,16,16,16,16,16,12,13,14,15}; + +static const vector unsigned char VSX_NOT_SHIFTED1_3 = {16,16,16, 3, 4, 5,16,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_NOT_SHIFTED2_3 = {16,16,16,16,16,16, 6, 7, 8,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_NOT_SHIFTED3_3 = {16,16,16,16,16,16,16,16,16, 9,10,11,16,16,16,16}; +static const vector unsigned char VSX_NOT_SHIFTED4_3 = {16,16,16,16,16,16,16,16,16,16,16,16,12,13,14,16}; + +static const vector unsigned char VSX_CHAR_ZERO = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; +#ifdef __LITTLE_ENDIAN__ + +static const vector unsigned char VSX_CHAR_TO_SHORT1_4 = { 4,16, 5,16, 6,16, 7,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_CHAR_TO_SHORT2_4 = { 8,16, 9,16,10,16,11,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_CHAR_TO_SHORT3_4 = {12,16,13,16,14,16,15,16,16,16,16,16,16,16,16,16}; + +static const vector unsigned char VSX_SHORT_TO_CHAR1_4 = {16,16,16,16, 0, 2, 4, 6,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_SHORT_TO_CHAR2_4 = {16,16,16,16,16,16,16,16, 0, 2, 4, 6,16,16,16,16}; +static const vector unsigned char VSX_SHORT_TO_CHAR3_4 = {16,16,16,16,16,16,16,16,16,16,16,16, 0, 2, 4, 6}; + +static const vector unsigned char VSX_CHAR_TO_SHORT1_3 = { 3,16, 4,16, 5,16,16,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_CHAR_TO_SHORT2_3 = { 6,16, 7,16, 8,16,16,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_CHAR_TO_SHORT3_3 = { 9,16,10,16,11,16,16,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_CHAR_TO_SHORT4_3 = {12,16,13,16,14,16,16,16,16,16,16,16,16,16,16,16}; + +static const vector unsigned char VSX_SHORT_TO_CHAR1_3 = {16,16,16, 0, 2, 4,16,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_SHORT_TO_CHAR2_3 = {16,16,16,16,16,16, 0, 2, 4,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_SHORT_TO_CHAR3_3 = {16,16,16,16,16,16,16,16,16, 0, 2, 4,16,16,16,16}; +static const vector unsigned char VSX_SHORT_TO_CHAR4_3 = {16,16,16,16,16,16,16,16,16,16,16,16, 0, 2, 4,16}; + +#elif defined(__BIG_ENDIAN__) + +static const vector unsigned char VSX_CHAR_TO_SHORT1_4 = {16, 4,16, 5,16, 6,16, 7,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_CHAR_TO_SHORT2_4 = {16, 8,16, 9,16,10,16,11,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_CHAR_TO_SHORT3_4 = {16,12,16,13,16,14,16,15,16,16,16,16,16,16,16,16}; + +static const vector unsigned char VSX_SHORT_TO_CHAR1_4 = {16,16,16,16, 1, 3, 5, 7,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_SHORT_TO_CHAR2_4 = {16,16,16,16,16,16,16,16, 1, 3, 5, 7,16,16,16,16}; +static const vector unsigned char VSX_SHORT_TO_CHAR3_4 = {16,16,16,16,16,16,16,16,16,16,16,16, 1, 3, 5, 7}; + +static const vector unsigned char VSX_CHAR_TO_SHORT1_3 = {16, 3,16, 4,16, 5,16,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_CHAR_TO_SHORT2_3 = {16, 6,16, 7,16, 8,16,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_CHAR_TO_SHORT3_3 = {16, 9,16,10,16,11,16,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_CHAR_TO_SHORT4_3 = {16,12,16,13,16,14,16,16,16,16,16,16,16,16,16,16}; + +static const vector unsigned char VSX_SHORT_TO_CHAR1_3 = {16,16,16, 1, 3, 5,16,16,16,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_SHORT_TO_CHAR2_3 = {16,16,16,16,16,16, 1, 3, 5,16,16,16,16,16,16,16}; +static const vector unsigned char VSX_SHORT_TO_CHAR3_3 = {16,16,16,16,16,16,16,16,16, 1, 3, 5,16,16,16,16}; +static const vector unsigned char VSX_SHORT_TO_CHAR4_3 = {16,16,16,16,16,16,16,16,16,16,16,16, 1, 3, 5,16}; + +#endif + +#define vsx_char_to_short(vec,offset,bpp) (vector unsigned short)vec_perm((vec),VSX_CHAR_ZERO,VSX_CHAR_TO_SHORT##offset##_##bpp) +#define vsx_short_to_char(vec,offset,bpp) vec_perm(((vector unsigned char)(vec)),VSX_CHAR_ZERO,VSX_SHORT_TO_CHAR##offset##_##bpp) + +#ifdef PNG_USE_ABS +# define vsx_abs(number) abs(number) +#else +# define vsx_abs(number) (number > 0) ? (number) : -(number) +#endif + +static void +png_read_filter_row_sub4_vsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + png_byte bpp = 4; + + vector unsigned char rp_vec; + vector unsigned char part_vec; + + vsx_declare_common_vars(row_info,row,prev_row,bpp) + + PNG_UNUSED(pp) + + /* Altivec operations require 16-byte aligned data + * but input can be unaligned. So we calculate + * unaligned part as usual. + */ + for (i = 0; i < unaligned_top; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); + rp++; + } + + /* Using SIMD while we can */ + while( istop >= 16 ) + { + for(i=0;i < bpp ; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); + rp++; + } + rp -= bpp; + + rp_vec = vec_ld(0,rp); + part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_4); + rp_vec = vec_add(rp_vec,part_vec); + + part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_4); + rp_vec = vec_add(rp_vec,part_vec); + + part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_4); + rp_vec = vec_add(rp_vec,part_vec); + + vec_st(rp_vec,0,rp); + + rp += 16; + istop -= 16; + } + + if(istop > 0) + for (i = 0; i < istop % 16; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*(rp - bpp))) & 0xff); + rp++; + } + +} + +static void +png_read_filter_row_sub3_vsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + png_byte bpp = 3; + + vector unsigned char rp_vec; + vector unsigned char part_vec; + + vsx_declare_common_vars(row_info,row,prev_row,bpp) + + PNG_UNUSED(pp) + + /* Altivec operations require 16-byte aligned data + * but input can be unaligned. So we calculate + * unaligned part as usual. + */ + for (i = 0; i < unaligned_top; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); + rp++; + } + + /* Using SIMD while we can */ + while( istop >= 16 ) + { + for(i=0;i < bpp ; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); + rp++; + } + rp -= bpp; + + rp_vec = vec_ld(0,rp); + part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_3); + rp_vec = vec_add(rp_vec,part_vec); + + part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_3); + rp_vec = vec_add(rp_vec,part_vec); + + part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_3); + rp_vec = vec_add(rp_vec,part_vec); + + part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED4_3); + rp_vec = vec_add(rp_vec,part_vec); + + vec_st(rp_vec,0,rp); + rp += 15; + istop -= 16; + + /* Since 16 % bpp = 16 % 3 = 1, last element of array must + * be proceeded manually + */ + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); + rp++; + } + + if(istop > 0) + for (i = 0; i < istop % 16; i++) + { + *rp = (png_byte)(((int)(*rp) + (int)(*(rp-bpp))) & 0xff); + rp++; + } +} + +static void +png_read_filter_row_avg4_vsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + png_byte bpp = 4; + + vector unsigned char rp_vec; + vector unsigned char pp_vec; + vector unsigned char pp_part_vec; + vector unsigned char rp_part_vec; + vector unsigned char avg_vec; + + vsx_declare_common_vars(row_info,row,prev_row,bpp) + rp -= bpp; + if(istop >= bpp) + istop -= bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + + rp++; + } + + /* Altivec operations require 16-byte aligned data + * but input can be unaligned. So we calculate + * unaligned part as usual. + */ + for (i = 0; i < unaligned_top; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); + + rp++; + } + + /* Using SIMD while we can */ + while( istop >= 16 ) + { + for(i=0;i < bpp ; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); + + rp++; + } + rp -= bpp; + pp -= bpp; + + vec_ld_unaligned(pp_vec,pp); + rp_vec = vec_ld(0,rp); + + rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_4); + pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED1_4); + avg_vec = vec_avg(rp_part_vec,pp_part_vec); + avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1))); + rp_vec = vec_add(rp_vec,avg_vec); + + rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_4); + pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED2_4); + avg_vec = vec_avg(rp_part_vec,pp_part_vec); + avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1))); + rp_vec = vec_add(rp_vec,avg_vec); + + rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_4); + pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED3_4); + avg_vec = vec_avg(rp_part_vec,pp_part_vec); + avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1))); + rp_vec = vec_add(rp_vec,avg_vec); + + vec_st(rp_vec,0,rp); + + rp += 16; + pp += 16; + istop -= 16; + } + + if(istop > 0) + for (i = 0; i < istop % 16; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); + + rp++; + } +} + +static void +png_read_filter_row_avg3_vsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + png_byte bpp = 3; + + vector unsigned char rp_vec; + vector unsigned char pp_vec; + vector unsigned char pp_part_vec; + vector unsigned char rp_part_vec; + vector unsigned char avg_vec; + + vsx_declare_common_vars(row_info,row,prev_row,bpp) + rp -= bpp; + if(istop >= bpp) + istop -= bpp; + + for (i = 0; i < bpp; i++) + { + *rp = (png_byte)(((int)(*rp) + + ((int)(*pp++) / 2 )) & 0xff); + + rp++; + } + + /* Altivec operations require 16-byte aligned data + * but input can be unaligned. So we calculate + * unaligned part as usual. + */ + for (i = 0; i < unaligned_top; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); + + rp++; + } + + /* Using SIMD while we can */ + while( istop >= 16 ) + { + for(i=0;i < bpp ; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); + + rp++; + } + rp -= bpp; + pp -= bpp; + + vec_ld_unaligned(pp_vec,pp); + rp_vec = vec_ld(0,rp); + + rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED1_3); + pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED1_3); + avg_vec = vec_avg(rp_part_vec,pp_part_vec); + avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1))); + rp_vec = vec_add(rp_vec,avg_vec); + + rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED2_3); + pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED2_3); + avg_vec = vec_avg(rp_part_vec,pp_part_vec); + avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1))); + rp_vec = vec_add(rp_vec,avg_vec); + + rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED3_3); + pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED3_3); + avg_vec = vec_avg(rp_part_vec,pp_part_vec); + avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1))); + rp_vec = vec_add(rp_vec,avg_vec); + + rp_part_vec = vec_perm(rp_vec,VSX_CHAR_ZERO,VSX_LEFTSHIFTED4_3); + pp_part_vec = vec_perm(pp_vec,VSX_CHAR_ZERO,VSX_NOT_SHIFTED4_3); + avg_vec = vec_avg(rp_part_vec,pp_part_vec); + avg_vec = vec_sub(avg_vec, vec_and(vec_xor(rp_part_vec,pp_part_vec),vec_splat_u8(1))); + rp_vec = vec_add(rp_vec,avg_vec); + + vec_st(rp_vec,0,rp); + + rp += 15; + pp += 15; + istop -= 16; + + /* Since 16 % bpp = 16 % 3 = 1, last element of array must + * be proceeded manually + */ + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); + rp++; + } + + if(istop > 0) + for (i = 0; i < istop % 16; i++) + { + *rp = (png_byte)(((int)(*rp) + + (int)(*pp++ + *(rp-bpp)) / 2 ) & 0xff); + + rp++; + } +} + +/* Bytewise c ? t : e. */ +#define if_then_else(c,t,e) vec_sel(e,t,c) + +#define vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp) {\ + c = *(pp - bpp);\ + a = *(rp - bpp);\ + b = *pp++;\ + p = b - c;\ + pc = a - c;\ + pa = vsx_abs(p);\ + pb = vsx_abs(pc);\ + pc = vsx_abs(p + pc);\ + if (pb < pa) pa = pb, a = b;\ + if (pc < pa) a = c;\ + a += *rp;\ + *rp++ = (png_byte)a;\ + } + +static void +png_read_filter_row_paeth4_vsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + png_byte bpp = 4; + + int a, b, c, pa, pb, pc, p; + vector unsigned char rp_vec; + vector unsigned char pp_vec; + vector unsigned short a_vec,b_vec,c_vec,nearest_vec; + vector signed short pa_vec,pb_vec,pc_vec,smallest_vec; + + vsx_declare_common_vars(row_info,row,prev_row,bpp) + rp -= bpp; + if(istop >= bpp) + istop -= bpp; + + /* Process the first pixel in the row completely (this is the same as 'up' + * because there is only one candidate predictor for the first row). + */ + for(i = 0; i < bpp ; i++) + { + *rp = (png_byte)( *rp + *pp); + rp++; + pp++; + } + + for(i = 0; i < unaligned_top ; i++) + { + vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp) + } + + while( istop >= 16) + { + for(i = 0; i < bpp ; i++) + { + vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp) + } + + rp -= bpp; + pp -= bpp; + rp_vec = vec_ld(0,rp); + vec_ld_unaligned(pp_vec,pp); + + a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_4),1,4); + b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED1_4),1,4); + c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_4),1,4); + pa_vec = (vector signed short) vec_sub(b_vec,c_vec); + pb_vec = (vector signed short) vec_sub(a_vec , c_vec); + pc_vec = vec_add(pa_vec,pb_vec); + pa_vec = vec_abs(pa_vec); + pb_vec = vec_abs(pb_vec); + pc_vec = vec_abs(pc_vec); + smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec)); + nearest_vec = if_then_else( + vec_cmpeq(pa_vec,smallest_vec), + a_vec, + if_then_else( + vec_cmpeq(pb_vec,smallest_vec), + b_vec, + c_vec + ) + ); + rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,1,4))); + + a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_4),2,4); + b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED2_4),2,4); + c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_4),2,4); + pa_vec = (vector signed short) vec_sub(b_vec,c_vec); + pb_vec = (vector signed short) vec_sub(a_vec , c_vec); + pc_vec = vec_add(pa_vec,pb_vec); + pa_vec = vec_abs(pa_vec); + pb_vec = vec_abs(pb_vec); + pc_vec = vec_abs(pc_vec); + smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec)); + nearest_vec = if_then_else( + vec_cmpeq(pa_vec,smallest_vec), + a_vec, + if_then_else( + vec_cmpeq(pb_vec,smallest_vec), + b_vec, + c_vec + ) + ); + rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,2,4))); + + a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_4),3,4); + b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED3_4),3,4); + c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_4),3,4); + pa_vec = (vector signed short) vec_sub(b_vec,c_vec); + pb_vec = (vector signed short) vec_sub(a_vec , c_vec); + pc_vec = vec_add(pa_vec,pb_vec); + pa_vec = vec_abs(pa_vec); + pb_vec = vec_abs(pb_vec); + pc_vec = vec_abs(pc_vec); + smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec)); + nearest_vec = if_then_else( + vec_cmpeq(pa_vec,smallest_vec), + a_vec, + if_then_else( + vec_cmpeq(pb_vec,smallest_vec), + b_vec, + c_vec + ) + ); + rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,3,4))); + + vec_st(rp_vec,0,rp); + + rp += 16; + pp += 16; + istop -= 16; + } + + if(istop > 0) + for (i = 0; i < istop % 16; i++) + { + vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp) + } +} + +static void +png_read_filter_row_paeth3_vsx(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + png_byte bpp = 3; + + int a, b, c, pa, pb, pc, p; + vector unsigned char rp_vec; + vector unsigned char pp_vec; + vector unsigned short a_vec,b_vec,c_vec,nearest_vec; + vector signed short pa_vec,pb_vec,pc_vec,smallest_vec; + + vsx_declare_common_vars(row_info,row,prev_row,bpp) + rp -= bpp; + if(istop >= bpp) + istop -= bpp; + + /* Process the first pixel in the row completely (this is the same as 'up' + * because there is only one candidate predictor for the first row). + */ + for(i = 0; i < bpp ; i++) + { + *rp = (png_byte)( *rp + *pp); + rp++; + pp++; + } + + for(i = 0; i < unaligned_top ; i++) + { + vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp) + } + + while( istop >= 16) + { + for(i = 0; i < bpp ; i++) + { + vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp) + } + + rp -= bpp; + pp -= bpp; + rp_vec = vec_ld(0,rp); + vec_ld_unaligned(pp_vec,pp); + + a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_3),1,3); + b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED1_3),1,3); + c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED1_3),1,3); + pa_vec = (vector signed short) vec_sub(b_vec,c_vec); + pb_vec = (vector signed short) vec_sub(a_vec , c_vec); + pc_vec = vec_add(pa_vec,pb_vec); + pa_vec = vec_abs(pa_vec); + pb_vec = vec_abs(pb_vec); + pc_vec = vec_abs(pc_vec); + smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec)); + nearest_vec = if_then_else( + vec_cmpeq(pa_vec,smallest_vec), + a_vec, + if_then_else( + vec_cmpeq(pb_vec,smallest_vec), + b_vec, + c_vec + ) + ); + rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,1,3))); + + a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_3),2,3); + b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED2_3),2,3); + c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED2_3),2,3); + pa_vec = (vector signed short) vec_sub(b_vec,c_vec); + pb_vec = (vector signed short) vec_sub(a_vec , c_vec); + pc_vec = vec_add(pa_vec,pb_vec); + pa_vec = vec_abs(pa_vec); + pb_vec = vec_abs(pb_vec); + pc_vec = vec_abs(pc_vec); + smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec)); + nearest_vec = if_then_else( + vec_cmpeq(pa_vec,smallest_vec), + a_vec, + if_then_else( + vec_cmpeq(pb_vec,smallest_vec), + b_vec, + c_vec + ) + ); + rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,2,3))); + + a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_3),3,3); + b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED3_3),3,3); + c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED3_3),3,3); + pa_vec = (vector signed short) vec_sub(b_vec,c_vec); + pb_vec = (vector signed short) vec_sub(a_vec , c_vec); + pc_vec = vec_add(pa_vec,pb_vec); + pa_vec = vec_abs(pa_vec); + pb_vec = vec_abs(pb_vec); + pc_vec = vec_abs(pc_vec); + smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec)); + nearest_vec = if_then_else( + vec_cmpeq(pa_vec,smallest_vec), + a_vec, + if_then_else( + vec_cmpeq(pb_vec,smallest_vec), + b_vec, + c_vec + ) + ); + rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,3,3))); + + a_vec = vsx_char_to_short(vec_perm(rp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED4_3),4,3); + b_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_NOT_SHIFTED4_3),4,3); + c_vec = vsx_char_to_short(vec_perm(pp_vec , VSX_CHAR_ZERO , VSX_LEFTSHIFTED4_3),4,3); + pa_vec = (vector signed short) vec_sub(b_vec,c_vec); + pb_vec = (vector signed short) vec_sub(a_vec , c_vec); + pc_vec = vec_add(pa_vec,pb_vec); + pa_vec = vec_abs(pa_vec); + pb_vec = vec_abs(pb_vec); + pc_vec = vec_abs(pc_vec); + smallest_vec = vec_min(pc_vec, vec_min(pa_vec,pb_vec)); + nearest_vec = if_then_else( + vec_cmpeq(pa_vec,smallest_vec), + a_vec, + if_then_else( + vec_cmpeq(pb_vec,smallest_vec), + b_vec, + c_vec + ) + ); + rp_vec = vec_add(rp_vec,(vsx_short_to_char(nearest_vec,4,3))); + + vec_st(rp_vec,0,rp); + + rp += 15; + pp += 15; + istop -= 16; + + /* Since 16 % bpp = 16 % 3 = 1, last element of array must + * be proceeded manually + */ + vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp) + } + + if(istop > 0) + for (i = 0; i < istop % 16; i++) + { + vsx_paeth_process(rp,pp,a,b,c,pa,pb,pc,bpp) + } +} diff --git a/media/libpng/powerpc/powerpc_init.c b/media/libpng/powerpc/powerpc_init.c new file mode 100644 index 0000000000..b02aca1fdf --- /dev/null +++ b/media/libpng/powerpc/powerpc_init.c @@ -0,0 +1,42 @@ +/* powerpc_init.c - POWERPC optimised filter functions + * + * Copyright (c) 2018 Cosmin Truta + * Copyright (c) 2017 Glenn Randers-Pehrson + * Written by Vadim Barkov, 2017. + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + */ +#define png_target_impl "powerpc-vsx" + +#include +#include "filter_vsx_intrinsics.c" + +static void +png_init_filter_functions_vsx(png_struct *pp, unsigned int bpp) +{ + /* IMPORTANT: DO NOT DEFINE EXTERNAL FUNCTIONS HERE + * + * This is because external functions must be declared with + * PNG_INTERNAL_FUNCTION in pngpriv.h; without this the PNG_PREFIX option to + * the build will not work (it will not know about these symbols). + */ + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_vsx; + + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_vsx; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_vsx; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_vsx; + } + + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_vsx; + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_vsx; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_vsx; + } +} + +#define png_target_init_filter_functions_impl png_init_filter_functions_vsx diff --git a/media/libpng/riscv/.editorconfig b/media/libpng/riscv/.editorconfig new file mode 100644 index 0000000000..de2e98ab42 --- /dev/null +++ b/media/libpng/riscv/.editorconfig @@ -0,0 +1,8 @@ +# https://editorconfig.org + +root = false + +# FIXME +[*.[ch]] +max_doc_length = unset +max_line_length = unset diff --git a/media/libpng/riscv/filter_rvv_intrinsics.c b/media/libpng/riscv/filter_rvv_intrinsics.c new file mode 100644 index 0000000000..70762767d0 --- /dev/null +++ b/media/libpng/riscv/filter_rvv_intrinsics.c @@ -0,0 +1,290 @@ +/* filter_rvv_intrinsics.c - RISC-V Vector optimized filter functions + * + * Copyright (c) 2023 Google LLC + * Written by Manfred SCHLAEGL, 2022 + * Revised by: + * - Dragoș Tiselice , May 2023 + * - Filip Wasil , March 2025 + * - Liang Junzhao , November 2025 + * - Alexander Smorkalov , December 2025 + * + * 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_RISCV_RVV_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */ + +#include + +void +png_read_filter_row_up_rvv(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t len = row_info->rowbytes; + + for (size_t vl; len > 0; len -= vl, row += vl, prev_row += vl) + { + vl = __riscv_vsetvl_e8m8(len); + + vuint8m8_t prev_vals = __riscv_vle8_v_u8m8(prev_row, vl); + vuint8m8_t row_vals = __riscv_vle8_v_u8m8(row, vl); + + row_vals = __riscv_vadd_vv_u8m8(row_vals, prev_vals, vl); + + __riscv_vse8_v_u8m8(row, row_vals, vl); + } +} + +static inline void +png_read_filter_row_sub_rvv(size_t len, size_t bpp, unsigned char *row) +{ + png_byte *rp_end = row + len; + + /* + * row: | a | x | + * + * a = a + x + * + * a .. [v0](e8) + * x .. [v8](e8) + */ + + size_t vl = __riscv_vsetvl_e8m1(bpp); + + /* a = *row */ + vuint8m1_t a = __riscv_vle8_v_u8m1(row, vl); + row += bpp; + + while (row < rp_end) + { + /* x = *row */ + vuint8m1_t x = __riscv_vle8_v_u8m1(row, vl); + + /* a = a + x */ + a = __riscv_vadd_vv_u8m1(a, x, vl); + + /* *row = a */ + __riscv_vse8_v_u8m1(row, a, vl); + row += bpp; + } +} + +void +png_read_filter_row_sub3_rvv(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t len = row_info->rowbytes; + + png_read_filter_row_sub_rvv(len, 3, row); + + PNG_UNUSED(prev_row) +} + +void +png_read_filter_row_sub4_rvv(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t len = row_info->rowbytes; + + png_read_filter_row_sub_rvv(len, 4, row); + + PNG_UNUSED(prev_row) +} + +static inline void +png_read_filter_row_avg_rvv(size_t len, size_t bpp, unsigned char *row, + const unsigned char *prev_row) +{ + png_byte *rp_end = row + len; + + /* + * row: | a | x | + * prev_row: | | b | + * + * a .. [v2](e8) + * b .. [v4](e8) + * x .. [v8](e8) + * tmp .. [v12-v13](e16) + */ + + /* first pixel */ + + size_t vl = __riscv_vsetvl_e8m1(bpp); + + /* b = *prev_row */ + vuint8m1_t b = __riscv_vle8_v_u8m1(prev_row, vl); + prev_row += bpp; + + /* x = *row */ + vuint8m1_t x = __riscv_vle8_v_u8m1(row, vl); + + /* b = b / 2 */ + b = __riscv_vsrl_vx_u8m1(b, 1, vl); + + /* a = x + b */ + vuint8m1_t a = __riscv_vadd_vv_u8m1(b, x, vl); + + /* *row = a */ + __riscv_vse8_v_u8m1(row, a, vl); + row += bpp; + + /* remaining pixels */ + while (row < rp_end) + { + /* b = *prev_row */ + b = __riscv_vle8_v_u8m1(prev_row, vl); + prev_row += bpp; + + /* x = *row */ + x = __riscv_vle8_v_u8m1(row, vl); + + /* a = (a + b) / 2, round to zero with vxrm = 2 */ + a = __riscv_vaaddu_vv_u8m1(a, b, 2, vl); + + /* a += x */ + a = __riscv_vadd_vv_u8m1(a, x, vl); + + /* *row = a */ + __riscv_vse8_v_u8m1(row, a, vl); + row += bpp; + } +} + +void +png_read_filter_row_avg3_rvv(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t len = row_info->rowbytes; + + png_read_filter_row_avg_rvv(len, 3, row, prev_row); + + PNG_UNUSED(prev_row) +} + +void +png_read_filter_row_avg4_rvv(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t len = row_info->rowbytes; + + png_read_filter_row_avg_rvv(len, 4, row, prev_row); + + PNG_UNUSED(prev_row) +} + +static inline void +png_read_filter_row_paeth_rvv(size_t len, size_t bpp, unsigned char *row, + const unsigned char *prev) +{ + png_byte *rp_end = row + len; + + /* + * row: | a | x | + * prev: | c | b | + * + * a .. [v2](e8) + * b .. [v4](e8) + * c .. [v6](e8) + * x .. [v8](e8) + * p .. [v12-v13](e16) + * pa, pb, pc .. [v16-v17, v20-v21, v24-v25](e16) + */ + + /* first pixel */ + + size_t vl = __riscv_vsetvl_e8m1(bpp); + + /* a = *row */ + vuint8m1_t a = __riscv_vle8_v_u8m1(row, vl); + + /* c = *prev */ + vuint8m1_t c = __riscv_vle8_v_u8m1(prev, vl); + + /* a += c */ + a = __riscv_vadd_vv_u8m1(a, c, vl); + + /* *row = a */ + __riscv_vse8_v_u8m1(row, a, vl); + row += bpp; + prev += bpp; + + /* remaining pixels */ + + while (row < rp_end) + { + /* b = *prev */ + vuint8m1_t b = __riscv_vle8_v_u8m1(prev, vl); + prev += bpp; + + /* x = *row */ + vuint8m1_t x = __riscv_vle8_v_u8m1(row, vl); + + /* p = b - c and pc = a - c */ + vuint16m2_t p = __riscv_vwsubu_vv_u16m2(b, c, vl); + vuint16m2_t pc = __riscv_vwsubu_vv_u16m2(a, c, vl); + + /* pa = |p| */ + vuint16m2_t tmp = __riscv_vrsub_vx_u16m2(p, 0, vl); + vuint16m2_t pa = __riscv_vminu_vv_u16m2(p, tmp, vl); + + /* pb = |pc| */ + tmp = __riscv_vrsub_vx_u16m2(pc, 0, vl); + vuint16m2_t pb = __riscv_vminu_vv_u16m2(pc, tmp, vl); + + /* pc = |p + pc| */ + pc = __riscv_vadd_vv_u16m2(p, pc, vl); + tmp = __riscv_vrsub_vx_u16m2(pc, 0, vl); + pc = __riscv_vminu_vv_u16m2(pc, tmp, vl); + + /* + * The key insight is that we want the minimum of pa, pb, pc. + * - If pa <= pb and pa <= pc, use a + * - Else if pb <= pc, use b + * - Else use c + */ + + /* if (pb < pa) { pa = pb; a = b; } */ + vbool8_t m1 = __riscv_vmsltu_vv_u16m2_b8(pb, pa, vl); + pa = __riscv_vmerge_vvm_u16m2(pa, pb, m1, vl); + a = __riscv_vmerge_vvm_u8m1(a, b, m1, vl); + + /* if (pc < pa) a = c; */ + vbool8_t m2 = __riscv_vmsltu_vv_u16m2_b8(pc, pa, vl); + a = __riscv_vmerge_vvm_u8m1(a, c, m2, vl); + + /* a = result + x */ + a = __riscv_vadd_vv_u8m1(a, x, vl); + + /* *row = a */ + __riscv_vse8_v_u8m1(row, a, vl); + row += bpp; + + /* c = b for next iteration */ + c = b; + } +} +void +png_read_filter_row_paeth3_rvv(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t len = row_info->rowbytes; + + png_read_filter_row_paeth_rvv(len, 3, row, prev_row); +} + +void +png_read_filter_row_paeth4_rvv(png_row_info *row_info, png_byte *row, + const png_byte *prev_row) +{ + size_t len = row_info->rowbytes; + + png_read_filter_row_paeth_rvv(len, 4, row, prev_row); +} + +#endif /* PNG_RISCV_RVV_IMPLEMENTATION == 1 */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/media/libpng/riscv/riscv_init.c b/media/libpng/riscv/riscv_init.c new file mode 100644 index 0000000000..5064de5561 --- /dev/null +++ b/media/libpng/riscv/riscv_init.c @@ -0,0 +1,45 @@ +/* riscv_init.c - RISC-V Vector optimized filter functions + * + * Copyright (c) 2023 Google LLC + * Written by Dragoș Tiselice , May 2023. + * Filip Wasil , March 2025. + * 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_RISCV_RVV_IMPLEMENTATION == 1 + +#include + +#ifndef PNG_ALIGNED_MEMORY_SUPPORTED +# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED" +#endif + +void +png_init_filter_functions_rvv(png_struct *pp, unsigned int bpp) +{ + png_debug(1, "in png_init_filter_functions_rvv"); + + pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_rvv; + + if (bpp == 3) + { + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_rvv; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_rvv; + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_rvv; + } + else if (bpp == 4) + { + pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_rvv; + pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_rvv; + pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_rvv; + } +} + +#endif /* PNG_RISCV_RVV_IMPLEMENTATION == 1 */ +#endif /* PNG_READ_SUPPORTED */ diff --git a/media/libpng/sse2/check.h b/media/libpng/sse2/check.h new file mode 100644 index 0000000000..1081a57215 --- /dev/null +++ b/media/libpng/sse2/check.h @@ -0,0 +1,35 @@ +/* intel/check.h - 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 + */ +/* PNG_INTEL_SSE_IMPLEMENTATION is used in the actual implementation to select + * the correct code. + */ +#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 + +#if PNG_INTEL_SSE_IMPLEMENTATION > 0 +# define PNG_TARGET_CODE_IMPLEMENTATION "intel/intel_init.c" + /*PNG_TARGET_STORES_DATA*/ +# define PNG_TARGET_IMPLEMENTS_FILTERS + /*PNG_TARGET_IMPLEMENTS_EXPAND_PALETTE*/ +# define PNG_TARGET_ROW_ALIGNMENT 16 +#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */ diff --git a/media/libpng/sse2/filter_sse2_intrinsics.c b/media/libpng/sse2/filter_sse2_intrinsics.c index 6254e41f1e..16e12a94e6 100644 --- a/media/libpng/sse2/filter_sse2_intrinsics.c +++ b/media/libpng/sse2/filter_sse2_intrinsics.c @@ -1,24 +1,14 @@ - /* filter_sse2_intrinsics.c - SSE2 optimized filter functions * - * Copyright (c) 2016 Google, Inc. + * 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, which was - * Copyright (c) 2014,2016 Glenn Randers-Pehrson - * - * Last changed in libpng 1.6.24 [August 4, 2016] + * 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 /* Functions in this file look at most 3 pixels (a,b,c) to predict the 4th (d). @@ -29,50 +19,51 @@ * whichever of a, b, or c is closest to p=a+b-c. */ -static __m128i load4(const void* p) { - return _mm_cvtsi32_si128(*(const int*)p); +static __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*)p = _mm_cvtsi128_si32(v); +static void +store4(void *p, __m128i v) +{ + int tmp = _mm_cvtsi128_si32(v); + memcpy(p, &tmp, sizeof(int)); } -static __m128i load3(const void* p) { - /* We'll load 2 bytes, then 1 byte, - * then mask them together, and finally load into SSE. - */ - const png_uint_16* p01 = p; - const png_byte* p2 = (const png_byte*)(p01+1); - - png_uint_32 v012 = (png_uint_32)(*p01) - | (png_uint_32)(*p2) << 16; - return load4(&v012); +static __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) { - /* We'll pull from SSE as a 32-bit int, then write - * its bottom two bytes, then its third byte. - */ - png_uint_32 v012; - store4(&v012, v); - - png_uint_16* p01 = p; - png_byte* p2 = (png_byte*)(p01+1); - *p01 = v012; - *p2 = v012 >> 16; +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) +static void +png_read_filter_row_sub3_sse2(png_row_info *row_info, png_byte *row, + const png_byte *prev) { /* The Sub filter predicts each pixel as the previous pixel, a. * There is no pixel to the left of the first pixel. It's encoded directly. * That works with our main loop if we just say that left pixel was zero. */ - png_debug(1, "in png_read_filter_row_sub3_sse2"); + size_t rb; + __m128i a, d = _mm_setzero_si128(); - int rb = row_info->rowbytes; + 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); @@ -89,20 +80,25 @@ void png_read_filter_row_sub3_sse2(png_row_infop row_info, png_bytep row, 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) +static void +png_read_filter_row_sub4_sse2(png_row_info *row_info, png_byte *row, + const png_byte *prev) { /* The Sub filter predicts each pixel as the previous pixel, a. * There is no pixel to the left of the first pixel. It's encoded directly. * That works with our main loop if we just say that left pixel was zero. */ - png_debug(1, "in png_read_filter_row_sub4_sse2"); + size_t rb; + __m128i a, d = _mm_setzero_si128(); - int rb = row_info->rowbytes; - while (rb > 0) { + 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); @@ -110,28 +106,35 @@ void png_read_filter_row_sub4_sse2(png_row_infop row_info, png_bytep row, 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) +static void +png_read_filter_row_avg3_sse2(png_row_info *row_info, png_byte *row, + const png_byte *prev) { /* The Avg filter predicts each pixel as the (truncated) average of a and b. * There's no pixel to the left of the first pixel. Luckily, it's * predicted to be half of the pixel above it. So again, this works * perfectly with our loop if we make sure a starts at zero. */ - png_debug(1, "in png_read_filter_row_avg3_sse2"); + + size_t rb; + const __m128i zero = _mm_setzero_si128(); - __m128i b; + + __m128i b; __m128i a, d = zero; - int rb = row_info->rowbytes; + 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 */ - __m128i avg = _mm_avg_epu8(a,b); + 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))); @@ -143,11 +146,12 @@ void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row, 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 */ - __m128i avg = _mm_avg_epu8(a,b); + 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))); @@ -161,26 +165,30 @@ void png_read_filter_row_avg3_sse2(png_row_infop row_info, png_bytep row, } } -void png_read_filter_row_avg4_sse2(png_row_infop row_info, png_bytep row, - png_const_bytep prev) +static void +png_read_filter_row_avg4_sse2(png_row_info *row_info, png_byte *row, + const png_byte *prev) { /* The Avg filter predicts each pixel as the (truncated) average of a and b. * There's no pixel to the left of the first pixel. Luckily, it's * predicted to be half of the pixel above it. So again, this works * perfectly with our loop if we make sure a starts at zero. */ - png_debug(1, "in png_read_filter_row_avg4_sse2"); + size_t rb; const __m128i zero = _mm_setzero_si128(); - __m128i b; + __m128i b; __m128i a, d = zero; - int rb = row_info->rowbytes; - while (rb > 0) { + 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 */ - __m128i avg = _mm_avg_epu8(a,b); + 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))); @@ -195,7 +203,9 @@ void png_read_filter_row_avg4_sse2(png_row_infop row_info, png_bytep row, } /* Returns |x| for 16-bit lanes. */ -static __m128i abs_i16(__m128i x) { +static __m128i +abs_i16(__m128i x) +{ #if PNG_INTEL_SSE_IMPLEMENTATION >= 2 return _mm_abs_epi16(x); #else @@ -214,7 +224,9 @@ static __m128i abs_i16(__m128i x) { } /* Bytewise c ? t : e. */ -static __m128i if_then_else(__m128i c, __m128i t, __m128i 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 @@ -222,8 +234,9 @@ static __m128i if_then_else(__m128i c, __m128i t, __m128i e) { #endif } -void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row, - png_const_bytep prev) +static void +png_read_filter_row_paeth3_sse2(png_row_info *row_info, png_byte *row, + const png_byte *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: @@ -238,38 +251,42 @@ void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row, * Here we zero b and d, which become c and a respectively at the start of * the loop. */ - png_debug(1, "in png_read_filter_row_paeth3_sse2"); + size_t rb; const __m128i zero = _mm_setzero_si128(); __m128i c, b = zero, a, d = zero; - int rb = row_info->rowbytes; + 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) */ - __m128i pa = _mm_sub_epi16(b,c); + + pa = _mm_sub_epi16(b,c); /* (p-b) == (a+b-c - b) == (a-c) */ - __m128i pb = _mm_sub_epi16(a,c); + pb = _mm_sub_epi16(a,c); /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */ - __m128i pc = _mm_add_epi16(pa,pb); + pc = _mm_add_epi16(pa,pb); pa = abs_i16(pa); /* |p-a| */ pb = abs_i16(pb); /* |p-b| */ pc = abs_i16(pc); /* |p-c| */ - __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); + smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); /* Paeth breaks ties favoring a over b over c. */ - __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, - if_then_else(_mm_cmpeq_epi16(smallest, pb), b, - c)); + 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); @@ -283,26 +300,27 @@ void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row, /* 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) */ - __m128i pa = _mm_sub_epi16(b,c); + pa = _mm_sub_epi16(b,c); /* (p-b) == (a+b-c - b) == (a-c) */ - __m128i pb = _mm_sub_epi16(a,c); + pb = _mm_sub_epi16(a,c); /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */ - __m128i pc = _mm_add_epi16(pa,pb); + pc = _mm_add_epi16(pa,pb); pa = abs_i16(pa); /* |p-a| */ pb = abs_i16(pb); /* |p-b| */ pc = abs_i16(pc); /* |p-c| */ - __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); + smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); /* Paeth breaks ties favoring a over b over c. */ - __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, + nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, if_then_else(_mm_cmpeq_epi16(smallest, pb), b, c)); @@ -316,8 +334,9 @@ void png_read_filter_row_paeth3_sse2(png_row_infop row_info, png_bytep row, } } -void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row, - png_const_bytep prev) +static void +png_read_filter_row_paeth4_sse2(png_row_info *row_info, png_byte *row, + const png_byte *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: @@ -332,13 +351,16 @@ void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row, * Here we zero b and d, which become c and a respectively at the start of * the loop. */ - png_debug(1, "in png_read_filter_row_paeth4_sse2"); + size_t rb; const __m128i zero = _mm_setzero_si128(); + __m128i pa,pb,pc,smallest,nearest; __m128i c, b = zero, a, d = zero; - int rb = row_info->rowbytes; - while (rb > 0) { + 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. */ @@ -346,22 +368,22 @@ void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row, a = d; d = _mm_unpacklo_epi8(load4(row ), zero); /* (p-a) == (a+b-c - a) == (b-c) */ - __m128i pa = _mm_sub_epi16(b,c); + pa = _mm_sub_epi16(b,c); /* (p-b) == (a+b-c - b) == (a-c) */ - __m128i pb = _mm_sub_epi16(a,c); + pb = _mm_sub_epi16(a,c); /* (p-c) == (a+b-c - c) == (a+b-c-c) == (b-c)+(a-c) */ - __m128i pc = _mm_add_epi16(pa,pb); + pc = _mm_add_epi16(pa,pb); pa = abs_i16(pa); /* |p-a| */ pb = abs_i16(pb); /* |p-b| */ pc = abs_i16(pc); /* |p-c| */ - __m128i smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); + smallest = _mm_min_epi16(pc, _mm_min_epi16(pa, pb)); /* Paeth breaks ties favoring a over b over c. */ - __m128i nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, + nearest = if_then_else(_mm_cmpeq_epi16(smallest, pa), a, if_then_else(_mm_cmpeq_epi16(smallest, pb), b, c)); @@ -374,6 +396,3 @@ void png_read_filter_row_paeth4_sse2(png_row_infop row_info, png_bytep row, rb -= 4; } } - -#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */ -#endif /* READ */ diff --git a/media/libpng/sse2/intel_init.c b/media/libpng/sse2/intel_init.c index 3f7fd7d3b6..693955d47b 100644 --- a/media/libpng/sse2/intel_init.c +++ b/media/libpng/sse2/intel_init.c @@ -1,25 +1,20 @@ - /* intel_init.c - SSE2 optimized filter functions * - * Copyright (c) 2016 Google, Inc. - * Written by Mike Klein and Matt Sarett - * Derived from arm/arm_init.c, which was - * Copyright (c) 2014,2016 Glenn Randers-Pehrson - * - * Last changed in libpng 1.6.22 [May 26, 2016] + * 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 */ +#define png_target_impl "intel-sse" -#include "../pngpriv.h" - -#ifdef PNG_READ_SUPPORTED -#if PNG_INTEL_SSE_IMPLEMENTATION > 0 +#include "filter_sse2_intrinsics.c" -void -png_init_filter_functions_sse2(png_structp pp, unsigned int bpp) +static void +png_init_filter_functions_sse2(png_struct *pp, unsigned int bpp) { /* The techniques used to implement each of these filters in SSE operate on * one pixel at a time. @@ -50,5 +45,4 @@ png_init_filter_functions_sse2(png_structp pp, unsigned int bpp) */ } -#endif /* PNG_INTEL_SSE_IMPLEMENTATION > 0 */ -#endif /* PNG_READ_SUPPORTED */ +#define png_target_init_filter_functions_impl png_init_filter_functions_sse2 diff --git a/testing/crashtest/crashtests.list b/testing/crashtest/crashtests.list index 863c10b9f6..7ad965e50f 100644 --- a/testing/crashtest/crashtests.list +++ b/testing/crashtest/crashtests.list @@ -57,8 +57,6 @@ include ../../layout/xul/crashtests/crashtests.list include ../../layout/xul/grid/crashtests/crashtests.list include ../../layout/xul/tree/crashtests/crashtests.list -include ../../media/libpng/crashtests/crashtests.list - include ../../netwerk/test/crashtests/crashtests.list include ../../parser/htmlparser/tests/crashtests/crashtests.list