0
0
mirror of https://github.com/opencv/opencv.git synced 2026-01-18 17:21:42 +01:00

Updated libpng to v1.6.52 and added RISC-V optimimizations. (#28111)

* Updated libpng to v1.6.51 and added RISC-V optimimizations.

* Force 3rdparty build for CI test.

* Added RISC-V RVV diagnostics for PNG.

* RISC-V RVV diagnostic fix.

* Disabled incorrect in-place flip HAL on RISC-V RVV.

* Disabled risc-v rvv of  png_read_filter_row_paeth in libpng.

* Set PNG simd configuration defaults accornding to OpenCV settings.

* Update to libpng 1.6.52 with RISC-V RVV fix.

* Build fix for RISC-V RVV.

* Reverted CI changes.
This commit is contained in:
Alexander Smorkalov
2025-12-05 17:17:22 +03:00
committed by GitHub
28 changed files with 3317 additions and 3291 deletions

View File

@@ -74,8 +74,13 @@ endif()
# Set definitions and sources for PowerPC.
if(TARGET_ARCH MATCHES "^(powerpc|ppc64)")
if (CPU_VSX_SUPPORTED)
set(CPU_VSX_SUPPORTED_STR "on")
else()
set(CPU_VSX_SUPPORTED_STR "off")
endif()
set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off)
set(PNG_POWERPC_VSX "on"
set(PNG_POWERPC_VSX ${CPU_VSX_SUPPORTED_STR}
CACHE STRING "Enable POWERPC VSX optimizations: on|off; on is default")
set_property(CACHE PNG_POWERPC_VSX
PROPERTY STRINGS ${PNG_POWERPC_VSX_POSSIBLE_VALUES})
@@ -114,8 +119,13 @@ endif()
# Set definitions and sources for MIPS.
if(TARGET_ARCH MATCHES "^(mipsel|mips64el)")
if (CPU_MSA_SUPPORTED)
set(CPU_MSA_SUPPORTED_STR "on")
else()
set(CPU_MSA_SUPPORTED_STR "off")
endif()
set(PNG_MIPS_MSA_POSSIBLE_VALUES on off)
set(PNG_MIPS_MSA "on"
set(PNG_MIPS_MSA ${CPU_MSA_SUPPORTED_STR}
CACHE STRING "Enable MIPS_MSA optimizations: on|off; on is default")
set_property(CACHE PNG_MIPS_MSA
PROPERTY STRINGS ${PNG_MIPS_MSA_POSSIBLE_VALUES})
@@ -154,9 +164,14 @@ endif()
# Set definitions and sources for LoongArch.
if(TARGET_ARCH MATCHES "^(loongarch)")
if (CPU_LSX_SUPPORTED)
set(CPU_LSX_SUPPORTED_STR "on")
else()
set(CPU_LSX_SUPPORTED_STR "off")
endif()
include(CheckCCompilerFlag)
set(PNG_LOONGARCH_LSX_POSSIBLE_VALUES on off)
set(PNG_LOONGARCH_LSX "on"
set(PNG_LOONGARCH_LSX ${CPU_LSX_SUPPORTED_STR}
CACHE STRING "Enable LOONGARCH_LSX optimizations: on|off; on is default")
set_property(CACHE PNG_LOONGARCH_LSX
PROPERTY STRINGS ${PNG_LOONGARCH_LSX_POSSIBLE_VALUES})
@@ -172,7 +187,7 @@ if(TARGET_ARCH MATCHES "^(loongarch)")
set_source_files_properties(${libpng_loongarch_sources}
PROPERTIES
COMPILE_FLAGS "-mlsx")
list(APPEND lib_srcs ${libpng_loongarch_sources})
list(APPEND lib_srcs ${libpng_loongarch_sources})
add_definitions(-DPNG_LOONGARCH_LSX_OPT=1)
else()
message(FATAL_ERROR "Compiler does not support -mlsx option")
@@ -182,6 +197,47 @@ if(TARGET_ARCH MATCHES "^(loongarch)")
endif()
endif()
# Set definitions and sources for RISC-V.
if(TARGET_ARCH MATCHES "^(riscv)")
if (CPU_RVV_SUPPORTED)
set(CPU_RVV_SUPPORTED_STR "on")
else()
set(CPU_RVV_SUPPORTED_STR "off")
endif()
include(CheckCCompilerFlag)
set(PNG_RISCV_RVV_POSSIBLE_VALUES on off)
set(PNG_RISCV_RVV ${CPU_RVV_SUPPORTED_STR}
CACHE STRING "Enable RISC-V Vector optimizations: on|off; off is default")
set_property(CACHE PNG_RISCV_RVV
PROPERTY STRINGS ${PNG_RISCV_RVV_POSSIBLE_VALUES})
list(FIND PNG_RISCV_RVV_POSSIBLE_VALUES ${PNG_RISCV_RVV} index)
if(index EQUAL -1)
message(FATAL_ERROR "PNG_RISCV_RVV must be one of [${PNG_RISCV_RVV_POSSIBLE_VALUES}]")
elseif(NOT PNG_RISCV_RVV STREQUAL "off")
check_c_source_compiles("
#include <riscv_vector.h>
int main() {
const float src[] = { 0.0f, 0.0f, 0.0f, 0.0f };
uint64_t ptr[2] = {0x0908060504020100, 0xFFFFFFFF0E0D0C0A};
vuint8m1_t a = __riscv_vreinterpret_v_u64m1_u8m1(__riscv_vle64_v_u64m1(ptr, 2));
vfloat32m1_t val = __riscv_vle32_v_f32m1((const float*)(src), 4);
return (int)__riscv_vfmv_f_s_f32m1_f32(val);
}" COMPILER_SUPPORTS_RVV)
if(NOT COMPILER_SUPPORTS_RVV)
message(FATAL_ERROR "Compiler does not support RISC-V Vector extension or its unable to detect it")
endif()
list(APPEND lib_srcs riscv/filter_rvv_intrinsics.c riscv/riscv_init.c)
if(PNG_RISCV_RVV STREQUAL "on")
add_definitions(-DPNG_RISCV_RVV_OPT=2)
else()
add_definitions(-DPNG_RISCV_RVV_OPT=0)
endif()
else()
add_definitions(-DPNG_RISCV_RVV_OPT=0)
endif()
endif()
else(PNG_HARDWARE_OPTIMIZATIONS)
# Set definitions and sources for ARM.
@@ -209,6 +265,11 @@ if(TARGET_ARCH MATCHES "^(loongarch)")
add_definitions(-DPNG_LOONGARCH_LSX_OPT=0)
endif()
# Set definitions and sources for RISC-V.
if(TARGET_ARCH MATCHES "^(riscv)")
add_definitions(-DPNG_RISCV_RVV_OPT=0)
endif()
endif(PNG_HARDWARE_OPTIMIZATIONS)
# ----------------------------------------------------------------------------------

View File

@@ -35,14 +35,14 @@
#ifndef PNG_ARM_NEON_FILE
# if defined(__aarch64__) || defined(_M_ARM64)
/* ARM Neon is expected to be unconditionally available on ARM64. */
# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on ARM64"
# error PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on ARM64
# elif defined(__ARM_NEON__) || defined(__ARM_NEON)
/* ARM Neon is expected to be available on the target CPU architecture. */
# error "PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on this CPU arch"
# error PNG_ARM_NEON_CHECK_SUPPORTED must not be defined on this CPU arch
# elif defined(__linux__)
# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c"
# else
# error "No support for run-time ARM Neon checking; use compile-time options"
# error No support for run-time ARM Neon checking; use compile-time options
# endif
#endif
@@ -53,7 +53,7 @@ static int png_have_neon(png_structp png_ptr);
#endif /* PNG_ARM_NEON_CHECK_SUPPORTED */
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
# error ALIGNED_MEMORY is required; please define PNG_ALIGNED_MEMORY_SUPPORTED
#endif
void

View File

@@ -48,7 +48,7 @@ static int png_have_msa(png_structp png_ptr);
#include PNG_MIPS_MSA_FILE
#else /* PNG_MIPS_MSA_FILE */
# error "PNG_MIPS_MSA_FILE undefined: no support for run-time MIPS MSA checks"
# error PNG_MIPS_MSA_FILE undefined: no support for run-time MIPS MSA checks
#endif /* PNG_MIPS_MSA_FILE */
#endif /* PNG_MIPS_MSA_CHECK_SUPPORTED */
@@ -66,12 +66,12 @@ static int png_have_mmi();
#include PNG_MIPS_MMI_FILE
#else /* PNG_MIPS_MMI_FILE */
# error "PNG_MIPS_MMI_FILE undefined: no support for run-time MIPS MMI checks"
# error PNG_MIPS_MMI_FILE undefined: no support for run-time MIPS MMI checks
#endif /* PNG_MIPS_MMI_FILE */
#endif /* PNG_MIPS_MMI_CHECK_SUPPORTED*/
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
# error ALIGNED_MEMORY is required; please define PNG_ALIGNED_MEMORY_SUPPORTED
#endif
/* MIPS supports two optimizations: MMI and MSA. The appropriate

View File

@@ -0,0 +1,13 @@
diff --git a/3rdparty/libpng/riscv/filter_rvv_intrinsics.c b/3rdparty/libpng/riscv/filter_rvv_intrinsics.c
index 8d277d14cd..7e61fb89fb 100644
--- a/3rdparty/libpng/riscv/filter_rvv_intrinsics.c
+++ b/3rdparty/libpng/riscv/filter_rvv_intrinsics.c
@@ -142,7 +142,7 @@ png_read_filter_row_avg_rvv(size_t len, size_t bpp, unsigned char* row,
x = __riscv_vle8_v_u8m1(row, vl);
/* a = (a + b) / 2, round to zero with vxrm = 2 */
- a = __riscv_vaaddu_wx_u8m1(a, b, 2, vl);
+ a = __riscv_vaaddu_vv_u8m1(a, b, 2, vl);
/* a += x */
a = __riscv_vadd_vv_u8m1(a, x, vl);

1284
3rdparty/libpng/png.c vendored

File diff suppressed because it is too large Load Diff

176
3rdparty/libpng/png.h vendored
View File

@@ -1,6 +1,6 @@
/* png.h - header file for PNG reference library
*
* libpng version 1.6.45
* libpng version 1.6.52
*
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
@@ -14,7 +14,7 @@
* libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
* 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.45, January 2025:
* libpng versions 1.6.36, December 2018, through 1.6.52, December 2025:
* Cosmin Truta
* See also "Contributing Authors", below.
*/
@@ -238,7 +238,7 @@
* ...
* 1.5.30 15 10530 15.so.15.30[.0]
* ...
* 1.6.45 16 10645 16.so.16.45[.0]
* 1.6.52 16 10651 16.so.16.52[.0]
*
* Henceforth the source version will match the shared-library major and
* minor numbers; the shared-library major version number will be used for
@@ -274,7 +274,7 @@
*/
/* Version information for png.h - this should match the version in png.c */
#define PNG_LIBPNG_VER_STRING "1.6.45"
#define PNG_LIBPNG_VER_STRING "1.6.52"
#define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
/* The versions of shared library builds should stay in sync, going forward */
@@ -285,7 +285,7 @@
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
#define PNG_LIBPNG_VER_MINOR 6
#define PNG_LIBPNG_VER_RELEASE 45
#define PNG_LIBPNG_VER_RELEASE 52
/* This should be zero for a public release, or non-zero for a
* development version.
@@ -316,7 +316,7 @@
* From version 1.0.1 it is:
* XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
#define PNG_LIBPNG_VER 10645 /* 1.6.45 */
#define PNG_LIBPNG_VER 10652 /* 1.6.52 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -426,7 +426,7 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
typedef char* png_libpng_version_1_6_45;
typedef char* png_libpng_version_1_6_52;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
@@ -744,7 +744,21 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */
#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */
#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */
#define PNG_INFO_cICP 0x20000U
#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
@@ -1556,7 +1570,7 @@ 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(74, void, png_init_io, (png_structrp png_ptr, FILE *fp));
#endif
/* Replace the (error and abort), and warning functions with user
@@ -1976,15 +1990,44 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
#ifdef PNG_cICP_SUPPORTED
PNG_EXPORT(250, png_uint_32, png_get_cICP, (png_const_structrp png_ptr,
png_inforp info_ptr, png_bytep colour_primaries,
png_const_inforp info_ptr, png_bytep colour_primaries,
png_bytep transfer_function, png_bytep matrix_coefficients,
png_bytep video_full_range_flag));
#endif
#ifdef PNG_cICP_SUPPORTED
PNG_EXPORT(251, void, png_set_cICP, (png_const_structrp png_ptr,
png_inforp 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(252, png_uint_32, png_get_cLLI, (png_const_structrp png_ptr,
png_const_inforp info_ptr, double *maximum_content_light_level,
double *maximum_frame_average_light_level))
PNG_FIXED_EXPORT(253, png_uint_32, png_get_cLLI_fixed,
(png_const_structrp png_ptr, png_const_inforp 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_32p maximum_content_light_level_scaled_by_10000,
png_uint_32p maximum_frame_average_light_level_scaled_by_10000))
#endif
#ifdef PNG_cLLI_SUPPORTED
PNG_FP_EXPORT(254, void, png_set_cLLI, (png_const_structrp png_ptr,
png_inforp info_ptr, double maximum_content_light_level,
double maximum_frame_average_light_level))
PNG_FIXED_EXPORT(255, void, png_set_cLLI_fixed, (png_const_structrp png_ptr,
png_inforp 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_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr,
png_inforp info_ptr, png_bytep *exif));
@@ -2029,6 +2072,60 @@ PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr,
int color_type, int interlace_method, int compression_method,
int filter_method));
#ifdef PNG_mDCV_SUPPORTED
PNG_FP_EXPORT(256, png_uint_32, png_get_mDCV, (png_const_structrp png_ptr,
png_const_inforp 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(257, png_uint_32, png_get_mDCV_fixed,
(png_const_structrp png_ptr, png_const_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,
/* Mastering display luminance in cd/m2 (nits) multiplied (scaled) by
* 10,000.
*/
png_uint_32p mastering_display_maximum_luminance_scaled_by_10000,
png_uint_32p mastering_display_minimum_luminance_scaled_by_10000))
#endif
#ifdef PNG_mDCV_SUPPORTED
PNG_FP_EXPORT(258, void, png_set_mDCV, (png_const_structrp png_ptr,
png_inforp 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(259, void, png_set_mDCV_fixed, (png_const_structrp png_ptr,
png_inforp 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
#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,
@@ -2991,7 +3088,7 @@ PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image,
*/
PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image,
FILE* file));
FILE *file));
/* The PNG header is read from the stdio FILE object. */
#endif /* STDIO */
@@ -3066,7 +3163,7 @@ PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
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*). */
/* 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
@@ -3206,26 +3303,45 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
* selected at run time.
*/
#ifdef PNG_SET_OPTION_SUPPORTED
/* HARDWARE: ARM Neon SIMD instructions 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 */
#endif
#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED
# define PNG_IGNORE_ADLER32 8 /* SOFTWARE: disable Adler32 check on IDAT */
#endif
#ifdef PNG_POWERPC_VSX_API_SUPPORTED
# define PNG_POWERPC_VSX 10 /* HARDWARE: PowerPC VSX SIMD instructions
* supported */
#endif
#ifdef PNG_MIPS_MMI_API_SUPPORTED
# define PNG_MIPS_MMI 12 /* HARDWARE: MIPS MMI SIMD instructions supported */
# define PNG_ARM_NEON 0
#endif
#define PNG_OPTION_NEXT 14 /* Next option - numbers must be even */
/* SOFTWARE: Force maximum window */
#define PNG_MAXIMUM_INFLATE_WINDOW 2
/* SOFTWARE: Check ICC profile for sRGB */
#define PNG_SKIP_sRGB_CHECK_PROFILE 4
/* HARDWARE: MIPS MSA SIMD instructions supported */
#ifdef PNG_MIPS_MSA_API_SUPPORTED
# define PNG_MIPS_MSA 6
#endif
/* SOFTWARE: Disable Adler32 check on IDAT */
#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED
# define PNG_IGNORE_ADLER32 8
#endif
/* HARDWARE: PowerPC VSX SIMD instructions supported */
#ifdef PNG_POWERPC_VSX_API_SUPPORTED
# define PNG_POWERPC_VSX 10
#endif
/* HARDWARE: MIPS MMI SIMD instructions supported */
#ifdef PNG_MIPS_MMI_API_SUPPORTED
# define PNG_MIPS_MMI 12
#endif
/* HARDWARE: RISC-V RVV SIMD instructions supported */
#ifdef PNG_RISCV_RVV_API_SUPPORTED
# define PNG_RISCV_RVV 14
#endif
/* Next option - numbers must be even */
#define PNG_OPTION_NEXT 16
/* Return values: NOTE: there are four values and 'off' is *not* zero */
#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */
@@ -3249,7 +3365,7 @@ PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
* one to use is one more than this.)
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
PNG_EXPORT_LAST_ORDINAL(251);
PNG_EXPORT_LAST_ORDINAL(259);
#endif
#ifdef __cplusplus

View File

@@ -1,6 +1,6 @@
/* pngconf.h - machine-configurable file for libpng
*
* libpng version 1.6.45
* libpng version 1.6.52
*
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
@@ -219,25 +219,13 @@
/* NOTE: PNGCBAPI always defaults to PNGCAPI. */
# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD)
# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed"
# error PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed
# 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 */
# define PNG_DLL_EXPORT __declspec(dllexport)
# ifndef PNG_DLL_IMPORT
# define PNG_DLL_IMPORT __declspec(dllimport)
# endif
#else /* !Windows */
# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
@@ -479,7 +467,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
@@ -487,7 +475,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
@@ -495,7 +483,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
@@ -503,7 +491,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
@@ -511,7 +499,7 @@
#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 and ptrdiff_t.
@@ -592,10 +580,6 @@ 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_STDIO_SUPPORTED
typedef FILE * png_FILE_p;
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
typedef double * png_doublep;
typedef const double * png_const_doublep;
@@ -617,6 +601,15 @@ typedef double * * png_doublepp;
/* Pointers to pointers to pointers; i.e., pointer to array */
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.
*/
typedef FILE * png_FILE_p; /* [Deprecated] */
#endif
#endif /* PNG_BUILDING_SYMBOL_TABLE */
#endif /* PNGCONF_H */

View File

@@ -1,6 +1,6 @@
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
/* pngdebug.h - internal debugging macros for libpng
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2013 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -10,6 +10,10 @@
* and license in png.h
*/
#ifndef PNGPRIV_H
# error This file must not be included by applications; please include <png.h>
#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
@@ -34,9 +38,6 @@
#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

View File

@@ -1,6 +1,6 @@
/* pngerror.c - stub functions for i/o and memory allocation
*
* Copyright (c) 2018-2024 Cosmin Truta
* 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.
@@ -39,46 +39,6 @@ PNG_FUNCTION(void,PNGAPI
png_error,(png_const_structrp png_ptr, png_const_charp 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),
error_message);
@@ -216,21 +176,6 @@ void PNGAPI
png_warning(png_const_structrp png_ptr, png_const_charp 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);
@@ -712,42 +657,9 @@ png_default_error,(png_const_structrp png_ptr, png_const_charp 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", error_message ? error_message :
"undefined");
fprintf(stderr, PNG_STRING_NEWLINE);
#else
PNG_UNUSED(error_message) /* Make compiler happy */
#endif
@@ -785,40 +697,8 @@ static void /* PRIVATE */
png_default_warning(png_const_structrp png_ptr, png_const_charp 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", warning_message);
fprintf(stderr, PNG_STRING_NEWLINE);
#else
PNG_UNUSED(warning_message) /* Make compiler happy */
#endif
@@ -866,12 +746,8 @@ png_get_error_ptr(png_const_structrp png_ptr)
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);
}
PNG_UNUSED(png_ptr)
PNG_UNUSED(strip_mode)
}
#endif
@@ -935,23 +811,37 @@ png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
int /* PRIVATE */
png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg)
{
png_voidp saved_error_buf = image->opaque->error_buf;
const png_voidp saved_error_buf = image->opaque->error_buf;
jmp_buf safe_jmpbuf;
int result;
/* 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;
return result;
if (result)
return 1; /* success */
}
/* On png_error, return via longjmp, pop the jmpbuf, and free the image. */
/* 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;
png_image_free(image);
return 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 0; /* failure */
}
#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
#endif /* READ || WRITE */

View File

@@ -1,6 +1,6 @@
/* pngget.c - retrieval of values from info struct
*
* Copyright (c) 2018-2024 Cosmin Truta
* 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.
@@ -380,7 +380,13 @@ png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns)
* 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
@@ -390,7 +396,7 @@ png_get_x_offset_inches_fixed(png_const_structrp png_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
@@ -518,44 +524,31 @@ png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
# 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)
double *whitex, double *whitey, double *redx, double *redy,
double *greenx, double *greeny, double *bluex, double *bluey)
{
png_debug1(1, "in %s retrieval function", "cHRM");
/* 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.
*/
/* 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 = 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");
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;
}
@@ -568,38 +561,31 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
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)
{
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");
*blue_Z = png_float(png_ptr, XYZ.blue_Z, "cHRM blue Z");
return PNG_INFO_cHRM;
}
@@ -616,29 +602,22 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
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)
{
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;
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;
}
@@ -647,31 +626,24 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
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_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;
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;
}
@@ -688,11 +660,11 @@ png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
{
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;
if (file_gamma != NULL) *file_gamma = info_ptr->gamma;
return PNG_INFO_gAMA;
}
@@ -707,12 +679,13 @@ png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
{
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");
if (file_gamma != NULL)
*file_gamma = png_float(png_ptr, info_ptr->gamma, "gAMA");
return PNG_INFO_gAMA;
}
@@ -729,9 +702,10 @@ png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
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;
if (file_srgb_intent != NULL)
*file_srgb_intent = info_ptr->rendering_intent;
return PNG_INFO_sRGB;
}
@@ -787,7 +761,7 @@ png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
#ifdef PNG_cICP_SUPPORTED
png_uint_32 PNGAPI
png_get_cICP(png_const_structrp png_ptr,
png_inforp info_ptr, png_bytep colour_primaries,
png_const_inforp info_ptr, png_bytep colour_primaries,
png_bytep transfer_function, png_bytep matrix_coefficients,
png_bytep video_full_range_flag)
{
@@ -805,10 +779,115 @@ png_get_cICP(png_const_structrp png_ptr,
return (PNG_INFO_cICP);
}
return (0);
return 0;
}
#endif
#ifdef PNG_cLLI_SUPPORTED
# ifdef PNG_FIXED_POINT_SUPPORTED
png_uint_32 PNGAPI
png_get_cLLI_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_uint_32p maxCLL,
png_uint_32p 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 PNGAPI
png_get_cLLI(png_const_structrp png_ptr, png_const_inforp 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 PNGAPI
png_get_mDCV_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_32p mastering_maxDL, png_uint_32p 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 PNGAPI
png_get_mDCV(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,
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 PNGAPI
png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,

View File

@@ -1,6 +1,6 @@
/* pnginfo.h - header file for PNG reference library
/* pnginfo.h - internal structures for libpng
*
* Copyright (c) 2018 Cosmin Truta
* 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.
@@ -10,43 +10,20 @@
* 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().
#ifndef PNGPRIV_H
# error This file must not be included by applications; please include <png.h>
#endif
/* INTERNAL, PRIVATE definition of a PNG.
*
* The names chosen should be very close to the PNG specification, so
* consult that document for information about the meaning of each field.
* png_info is a modifiable description of a PNG datastream. The fields inside
* this structure are accessed through png_get_<CHUNK>() functions and modified
* using png_set_<CHUNK>() functions.
*
* 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.
*
* 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.
*
* 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
@@ -86,20 +63,6 @@ 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;
#endif
#ifdef PNG_cICP_SUPPORTED
/* cICP chunk data */
png_byte cicp_colour_primaries;
@@ -115,6 +78,24 @@ struct png_info_def
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.
@@ -193,11 +174,8 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
#endif
#ifdef PNG_eXIf_SUPPORTED
int num_exif; /* Added at libpng-1.6.31 */
png_uint_32 num_exif; /* Added at libpng-1.6.31 */
png_bytep exif;
# ifdef PNG_READ_eXIf_SUPPORTED
png_bytep eXIf_buf; /* Added at libpng-1.6.32 */
# endif
#endif
#ifdef PNG_hIST_SUPPORTED
@@ -270,5 +248,16 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
png_bytepp 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
};
#endif /* PNGINFO_H */

View File

@@ -1,6 +1,6 @@
/* pngmem.c - stub functions for memory allocation
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2014,2016 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@@ -72,30 +72,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 (size > PNG_SIZE_MAX) return NULL;
# 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);
# else
PNG_UNUSED(png_ptr)
# endif
else
#endif
return malloc((size_t)size); /* checked for truncation above */
}
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) ||\

View File

@@ -1,6 +1,6 @@
/* pngpread.c - read a png file in push mode
*
* Copyright (c) 2018-2024 Cosmin Truta
* 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.
@@ -193,17 +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_check_chunk_length(png_ptr, png_ptr->push_length);
png_ptr->push_length = png_read_chunk_header(png_ptr);
png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
}
@@ -238,19 +229,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);
@@ -267,12 +266,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)
{
png_ptr->idat_size = png_ptr->push_length;
@@ -285,163 +278,10 @@ 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_cICP_SUPPORTED
else if (png_ptr->chunk_name == png_cICP)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_cICP(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
#ifdef PNG_READ_eXIf_SUPPORTED
else if (png_ptr->chunk_name == png_eXIf)
{
PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_eXIf(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
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;

View File

@@ -1,6 +1,6 @@
/* pngpriv.h - private declarations for use inside libpng
*
* Copyright (c) 2018-2024 Cosmin Truta
* 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.
@@ -19,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 <png.h>
#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
@@ -57,7 +69,6 @@
*/
#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
# include <config.h>
/* Pick up the definition of 'restrict' from config.h if it was read: */
# define PNG_RESTRICT restrict
#endif
@@ -67,9 +78,7 @@
* 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"
/* Local renames may change non-exported API functions from png.h */
#if defined(PNG_PREFIX) && !defined(PNGPREFIX_H)
@@ -134,6 +143,20 @@
# endif
#endif
#ifndef PNG_RISCV_RVV_OPT
/* RISCV_RVV optimizations are being controlled by the compiler settings,
* typically the target compiler will define __riscv but the rvv extension
* availability has to be explicitly stated. This is why if no
* PNG_RISCV_RVV_OPT was defined then a runtime check will be executed.
*
* To enable RISCV_RVV optimizations unconditionally, and compile the
* associated code, pass --enable-riscv-rvv=yes or --enable-riscv-rvv=on
* to configure or put -DPNG_RISCV_RVV_OPT=2 in CPPFLAGS.
*/
# define PNG_RISCV_RVV_OPT 0
#endif
#if PNG_ARM_NEON_OPT > 0
/* NEON optimizations are to be at least considered by libpng, so enable the
* callbacks to do this.
@@ -279,6 +302,16 @@
# define PNG_LOONGARCH_LSX_IMPLEMENTATION 0
#endif
#if PNG_RISCV_RVV_OPT > 0 && __riscv_v >= 1000000
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_rvv
# ifndef PNG_RISCV_RVV_IMPLEMENTATION
/* Use the intrinsics code by default. */
# define PNG_RISCV_RVV_IMPLEMENTATION 1
# endif
#else
# define PNG_RISCV_RVV_IMPLEMENTATION 0
#endif /* PNG_RISCV_RVV_OPT > 0 && __riscv_v >= 1000000 */
/* 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.
@@ -671,13 +704,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 */
@@ -782,6 +815,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.
@@ -800,11 +835,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.
@@ -832,10 +887,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)
#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)
@@ -844,6 +903,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)
@@ -884,11 +944,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 occurence 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.
*/
@@ -901,17 +1024,15 @@
* 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 <zlib.h> 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 directives 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
@@ -952,7 +1073,6 @@ 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),
@@ -971,6 +1091,7 @@ 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))
@@ -978,12 +1099,38 @@ PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr,
double fp, png_const_charp 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,(png_const_structrp png_ptr,
double fp, png_const_charp 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);
#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.)
@@ -1083,9 +1230,6 @@ PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf,
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);
/* 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.
@@ -1137,6 +1281,20 @@ PNG_INTERNAL_FUNCTION(void,png_write_cICP,(png_structrp png_ptr,
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_structrp 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_structrp 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);
@@ -1149,10 +1307,10 @@ PNG_INTERNAL_FUNCTION(void,png_write_eXIf,(png_structrp png_ptr,
#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_const_charp name, png_const_bytep profile, png_uint_32 proflen),
PNG_EMPTY);
/* Writes a previously 'set' profile. The profile argument is **not**
* compressed.
*/
#endif
@@ -1388,6 +1546,23 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_lsx,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
#endif
#if PNG_RISCV_RVV_IMPLEMENTATION == 1
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_rvv,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_rvv,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_rvv,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_rvv,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_rvv,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_rvv,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_rvv,(png_row_infop
row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
#endif
/* Choose the best filter to use and filter the row data */
PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
png_row_infop row_info),PNG_EMPTY);
@@ -1461,124 +1636,36 @@ PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info,
/* The following decodes the appropriate chunks, and does error correction,
* then calls the appropriate callback for the chunk if it is valid.
*/
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;
/* 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_cICP_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_handle_cICP,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_eXIf_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_handle_eXIf,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_gAMA_SUPPORTED
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_const_structrp png_ptr,
png_uint_32 chunk_name),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_check_chunk_length,(png_const_structrp png_ptr,
png_uint_32 chunk_length),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
PNG_INTERNAL_FUNCTION(png_handle_result_code,png_handle_unknown,
(png_structrp png_ptr, png_inforp 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_structrp png_ptr, png_inforp 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,
@@ -1618,8 +1705,6 @@ PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr,
png_bytep buffer, 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,
@@ -1632,109 +1717,28 @@ 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
#endif /* PROGRESSIVE_READ */
/* 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_EMPTY);
/* The 'name' is used for information only */
/* 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_const_charp 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_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_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
#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_structrp 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,
@@ -1996,8 +2000,10 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp 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)
@@ -2006,22 +2012,14 @@ PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
*/
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
#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_EMPTY);
#endif
#ifdef PNG_READ_GAMMA_SUPPORTED
/* The same but gives a reciprocal of the product of two fixed point
@@ -2030,14 +2028,22 @@ PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a),
*/
PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a,
png_fixed_point b),PNG_EMPTY);
#endif
/* 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_EMPTY);
#endif
#ifdef PNG_READ_GAMMA_SUPPORTED
/* 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,
(png_const_structrp png_ptr),PNG_EMPTY);
/* 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.
@@ -2055,6 +2061,22 @@ PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr),
PNG_EMPTY);
PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp 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_structrp 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);
#endif
/* SIMPLIFIED READ/WRITE SUPPORT */
@@ -2153,6 +2175,11 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_lsx,
(png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
#endif
# if PNG_RISCV_RVV_IMPLEMENTATION == 1
PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_rvv,
(png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
#endif
PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
png_const_charp key, png_bytep new_key), PNG_EMPTY);
@@ -2188,4 +2215,3 @@ PNG_INTERNAL_FUNCTION(int,
#endif
#endif /* PNG_VERSION_INFO_ONLY */
#endif /* PNGPRIV_H */

View File

@@ -131,14 +131,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)
@@ -155,8 +152,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)
{
@@ -164,104 +159,8 @@ 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_cICP_SUPPORTED
else if (chunk_name == png_cICP)
png_handle_cICP(png_ptr, info_ptr, length);
#endif
#ifdef PNG_READ_eXIf_SUPPORTED
else if (chunk_name == png_eXIf)
png_handle_eXIf(png_ptr, info_ptr, length);
#endif
#ifdef PNG_READ_gAMA_SUPPORTED
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);
}
}
#endif /* SEQUENTIAL_READ */
@@ -803,13 +702,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);
@@ -843,107 +747,9 @@ 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_cICP_SUPPORTED
else if (chunk_name == png_cICP)
png_handle_cICP(png_ptr, info_ptr, length);
#endif
#ifdef PNG_READ_eXIf_SUPPORTED
else if (chunk_name == png_eXIf)
png_handle_eXIf(png_ptr, info_ptr, length);
#endif
#ifdef PNG_READ_gAMA_SUPPORTED
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 */
@@ -1008,7 +814,8 @@ png_read_destroy(png_structrp png_ptr)
#endif
#if defined(PNG_READ_EXPAND_SUPPORTED) && \
defined(PNG_ARM_NEON_IMPLEMENTATION)
(defined(PNG_ARM_NEON_IMPLEMENTATION) || \
defined(PNG_RISCV_RVV_IMPLEMENTATION))
png_free(png_ptr, png_ptr->riffled_palette);
png_ptr->riffled_palette = NULL;
#endif
@@ -1394,6 +1201,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
@@ -1402,22 +1234,44 @@ 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
* header and fill in all the information. This is executed in a safe context,
* unlike the init routine above.
*/
static int
png_image_is_not_sRGB(png_const_structrp 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 occured 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(png_voidp argument)
{
@@ -1439,17 +1293,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
@@ -1484,7 +1334,7 @@ png_image_read_header(png_voidp argument)
#ifdef PNG_STDIO_SUPPORTED
int PNGAPI
png_image_begin_read_from_stdio(png_imagep image, FILE* file)
png_image_begin_read_from_stdio(png_imagep image, FILE *file)
{
if (image != NULL && image->version == PNG_IMAGE_VERSION)
{
@@ -1637,21 +1487,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 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.
@@ -1680,7 +1527,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_structrp 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)
@@ -2168,24 +2023,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
@@ -2563,6 +2412,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.
@@ -2577,10 +2428,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;
@@ -2612,8 +2466,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.
@@ -3275,6 +3129,54 @@ 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(png_voidp 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_bytep local_row = png_voidcast(png_bytep, display->local_row);
png_bytep first_row = png_voidcast(png_bytep, display->first_row);
ptrdiff_t row_bytes = display->row_bytes;
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_bytep 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. */
memcpy(output_row, local_row, (size_t)row_bytes);
output_row += row_bytes;
}
}
return 1;
}
/* Just the row reading part of png_image_read. */
static int
png_image_read_composite(png_voidp argument)
@@ -3305,6 +3207,7 @@ png_image_read_composite(png_voidp argument)
ptrdiff_t step_row = display->row_bytes;
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)
@@ -3361,20 +3264,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 GitHub Issue #764.)
*/
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;
@@ -3693,6 +3620,7 @@ png_image_read_direct(png_voidp argument)
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
@@ -3744,6 +3672,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 &&
@@ -3799,8 +3733,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(&gtest, output_gamma, png_ptr->colorspace.gamma,
PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0)
if (png_muldiv(&gtest, 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)
@@ -3819,8 +3754,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;
}
@@ -4096,6 +4039,24 @@ 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;
png_voidp 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;

View File

@@ -1,6 +1,6 @@
/* pngrio.c - functions for data input
*
* Copyright (c) 2018 Cosmin Truta
* 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.
@@ -56,7 +56,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, size_t length)
/* 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");

View File

@@ -1,6 +1,6 @@
/* pngrtran.c - transforms the data in a row for PNG readers
*
* Copyright (c) 2018-2024 Cosmin Truta
* 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.
@@ -28,6 +28,12 @@
# endif
#endif
#ifdef PNG_RISCV_RVV_IMPLEMENTATION
# if PNG_RISCV_RVV_IMPLEMENTATION == 1
# define PNG_RISCV_RVV_INTRINSICS_AVAILABLE
# endif
#endif
#ifdef PNG_READ_SUPPORTED
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
@@ -218,9 +224,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 - volage 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
@@ -230,14 +286,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
@@ -279,6 +327,33 @@ convert_gamma_value(png_structrp png_ptr, double output_gamma)
return (png_fixed_point)output_gamma;
}
# endif
static int
unsupported_gamma(png_structrp 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
@@ -286,31 +361,29 @@ void PNGFAPI
png_set_alpha_mode_fixed(png_structrp 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_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 the API users
* who might use the inverse of the gamma value accidentally!
*
* In libpng 1.6.0, we changed from 0.07..3 to 0.01..100, to accommodate
* 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:
@@ -361,17 +434,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
@@ -381,7 +444,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;
@@ -438,9 +501,19 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
{
int 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_bytep)png_malloc(png_ptr,
(png_alloc_size_t)num_palette);
for (i = 0; i < num_palette; i++)
PNG_MAX_PALETTE_LENGTH);
for (i = 0; i < PNG_MAX_PALETTE_LENGTH; i++)
png_ptr->quantize_index[i] = (png_byte)i;
}
@@ -452,15 +525,14 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
* Perhaps not the best solution, but good enough.
*/
int i;
png_bytep quantize_sort;
int i, j;
/* Initialize an array to sort colors */
png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
/* Initialize the local array to sort colors. */
quantize_sort = (png_bytep)png_malloc(png_ptr,
(png_alloc_size_t)num_palette);
/* Initialize the quantize_sort array */
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
@@ -472,19 +544,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;
}
}
@@ -496,18 +567,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];
}
@@ -515,7 +586,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.
@@ -523,13 +594,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];
@@ -567,8 +638,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
{
@@ -819,8 +889,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
@@ -834,17 +904,19 @@ 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");
/* 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.
if (unsupported_gamma(png_ptr, file_gamma, 1/*warn*/) ||
unsupported_gamma(png_ptr, scrn_gamma, 1/*warn*/))
return;
/* 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;
}
@@ -1022,26 +1094,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");
}
}
@@ -1282,6 +1337,80 @@ 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(png_const_structrp 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 oveflows it returns 0 which indicates 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_structrp 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)
{
@@ -1301,59 +1430,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_init_gamma_values(png_ptr) != 0)
png_ptr->transformations |= PNG_GAMMA;
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 undesirable 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);
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
@@ -1425,7 +1517,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
@@ -1568,10 +1660,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 &&
@@ -1627,8 +1719,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;
@@ -1689,19 +1781,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;
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];
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];
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];
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];
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];
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].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];
}
}
}
else
@@ -1719,6 +1843,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) */
@@ -1736,8 +1861,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;
@@ -1987,11 +2112,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)
@@ -4924,13 +5049,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

File diff suppressed because it is too large Load Diff

View File

@@ -41,27 +41,21 @@ png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
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;
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;
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;
png_colorspace_sync_info(png_ptr, info_ptr);
info_ptr->valid |= PNG_INFO_cHRM;
}
void PNGFAPI
@@ -73,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");
@@ -89,11 +84,14 @@ 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
@@ -159,6 +157,163 @@ png_set_cICP(png_const_structrp png_ptr, png_inforp info_ptr,
}
#endif /* cICP */
#ifdef PNG_cLLI_SUPPORTED
void PNGFAPI
png_set_cLLI_fixed(png_const_structrp png_ptr, png_inforp 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 PNGAPI
png_set_cLLI(png_const_structrp png_ptr, png_inforp 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 PNGAPI
png_set_mDCV_fixed(png_const_structrp png_ptr, png_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 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 PNGAPI
png_set_mDCV(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,
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 PNGAPI
png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
@@ -210,8 +365,8 @@ 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
@@ -670,8 +825,8 @@ png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
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
@@ -683,15 +838,20 @@ 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);
png_colorspace_sync_info(png_ptr, info_ptr);
# ifdef PNG_gAMA_SUPPORTED
png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
# endif /* gAMA */
# 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 */
@@ -714,27 +874,6 @@ 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));
@@ -1421,11 +1560,13 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
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 */
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 */
@@ -1687,8 +1828,24 @@ png_set_chunk_malloc_max(png_structrp png_ptr,
{
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 */

View File

@@ -1,6 +1,6 @@
/* pngstruct.h - header file for PNG reference library
/* pngstruct.h - internal structures for libpng
*
* Copyright (c) 2018-2022 Cosmin Truta
* 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.
@@ -10,11 +10,9 @@
* 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 <png.h>
#endif
#ifndef PNGSTRUCT_H
#define PNGSTRUCT_H
@@ -69,13 +67,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)).
*/
@@ -96,48 +88,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
PNG_KNOWN_CHUNKS
PNG_INDEX_unknown
} png_index;
#undef PNG_CHUNK
#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
/* 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 coresponding 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.
*/
/* Flags are always defined to simplify the code. */
png_uint_16 flags; /* As defined below */
} png_colorspace, * PNG_RESTRICT png_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 */
typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
/* 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(pnt_ptr, i)\
((void)((png_ptr)->chunks |= png_chunk_flag_from_index(i)))
/* Record the chunk in the png_struct */
struct png_struct_def
{
@@ -209,6 +189,11 @@ 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 */
@@ -285,9 +270,16 @@ 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 */
@@ -299,7 +291,7 @@ struct png_struct_def
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 */
#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 */
@@ -349,8 +341,8 @@ struct png_struct_def
/* 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
#endif /* TIME_RFC1123 */
#endif /* LIBPNG_VER < 10700 */
/* New members added in libpng-1.0.6 */
@@ -360,8 +352,8 @@ struct png_struct_def
png_voidp 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_* */
@@ -383,7 +375,8 @@ struct png_struct_def
/* New member added in libpng-1.6.36 */
#if defined(PNG_READ_EXPAND_SUPPORTED) && \
defined(PNG_ARM_NEON_IMPLEMENTATION)
(defined(PNG_ARM_NEON_IMPLEMENTATION) || \
defined(PNG_RISCV_RVV_IMPLEMENTATION))
png_bytep riffled_palette; /* buffer for accelerated palette expansion */
#endif
@@ -412,7 +405,6 @@ struct png_struct_def
#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
in the palette */
png_bytep palette_to_index; /* which original index points to this
@@ -468,11 +460,5 @@ struct png_struct_def
/* 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
#endif
};
#endif /* PNGSTRUCT_H */

View File

@@ -1,6 +1,6 @@
/* pngwio.c - functions for data output
*
* Copyright (c) 2018 Cosmin Truta
* 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.
@@ -54,7 +54,7 @@ png_default_write_data(png_structp png_ptr, png_bytep data, size_t length)
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");
@@ -77,12 +77,12 @@ png_flush(png_structrp png_ptr)
void PNGCBAPI
png_default_flush(png_structp 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

View File

@@ -157,8 +157,30 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
* 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 chunkgs 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_COLORSPACE_SUPPORTED
#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)
{
@@ -170,50 +192,28 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
}
# endif
/* PNG v3 change: it is now permitted to write both sRGB and ICC profiles,
* however because the libpng code auto-generates an sRGB for the
* corresponding ICC profiles and because PNG v2 disallowed this we need
* to only write one.
*
* Remove the PNG v2 warning about writing an sRGB ICC profile as well
* because it's invalid with PNG v3.
*/
# ifdef PNG_WRITE_iCCP_SUPPORTED /* Priority 3 */
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
(info_ptr->valid & PNG_INFO_iCCP) != 0)
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 /* Priority 2 */
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);
if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
png_write_sRGB(png_ptr, info_ptr->rendering_intent);
# endif /* WRITE_sRGB */
#endif /* COLORSPACE */
#ifdef PNG_GAMMA_SUPPORTED
# ifdef PNG_WRITE_gAMA_SUPPORTED /* Priority 1 */
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);
if ((info_ptr->valid & PNG_INFO_gAMA) != 0)
png_write_gAMA_fixed(png_ptr, info_ptr->gamma);
# endif
#endif
#ifdef PNG_COLORSPACE_SUPPORTED
# ifdef PNG_WRITE_cHRM_SUPPORTED /* Also priority 1 */
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);
if ((info_ptr->valid & PNG_INFO_cHRM) != 0)
png_write_cHRM_fixed(png_ptr, &info_ptr->cHRM);
# endif
#endif
png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
}
@@ -2173,8 +2173,7 @@ 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_get_rowbytes(png_ptr, info_ptr)));
@@ -2333,7 +2332,7 @@ int PNGAPI
png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
const void *buffer, png_int_32 row_stride, const void *colormap)
{
/* 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)

View File

@@ -1,6 +1,6 @@
/* pngwutil.c - utilities to write a PNG file
*
* Copyright (c) 2018-2024 Cosmin Truta
* 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.
@@ -1132,10 +1132,9 @@ png_write_sRGB(png_structrp png_ptr, int srgb_intent)
/* Write an iCCP chunk */
void /* PRIVATE */
png_write_iCCP(png_structrp png_ptr, png_const_charp name,
png_const_bytep profile)
png_const_bytep 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;
@@ -1148,11 +1147,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)");
@@ -1511,6 +1511,50 @@ png_write_cICP(png_structrp png_ptr,
}
#endif
#ifdef PNG_WRITE_cLLI_SUPPORTED
void /* PRIVATE */
png_write_cLLI_fixed(png_structrp 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_structrp 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 */

View File

@@ -23,7 +23,7 @@
#if PNG_POWERPC_VSX_OPT > 0
#ifndef __VSX__
# error "This code requires VSX support (POWER7 and later). Please provide -mvsx compiler flag."
# error This code requires VSX support (POWER7 and later); please compile with -mvsx
#endif
#define vec_ld_unaligned(vec,data) vec = vec_vsx_ld(0,data)

View File

@@ -46,7 +46,7 @@ static int png_have_vsx(png_structp png_ptr);
#include PNG_POWERPC_VSX_FILE
#else /* PNG_POWERPC_VSX_FILE */
# error "PNG_POWERPC_VSX_FILE undefined: no support for run-time POWERPC VSX checks"
# error PNG_POWERPC_VSX_FILE undefined: no support for run-time POWERPC VSX checks
#endif /* PNG_POWERPC_VSX_FILE */
#endif /* PNG_POWERPC_VSX_CHECK_SUPPORTED */

View File

@@ -0,0 +1,329 @@
/* filter_rvv_intrinsics.c - RISC-V Vector optimized filter functions
*
* Copyright (c) 2023 Google LLC
* Written by Manfred SCHLAEGL, 2022
* Dragoș Tiselice <dtiselice@google.com>, May 2023.
* Filip Wasil <f.wasil@samsung.com>, March 2025.
* Liang Junzhao <junzhao.liang@spacemit.com>, November 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 <riscv_vector.h>
void
png_read_filter_row_up_rvv(png_row_infop row_info, png_bytep row,
png_const_bytep 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_bytep 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_infop row_info, png_bytep row,
png_const_bytep 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_infop row_info, png_bytep row,
png_const_bytep 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_bytep 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_infop row_info, png_bytep row,
png_const_bytep 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_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t len = row_info->rowbytes;
png_read_filter_row_avg_rvv(len, 4, row, prev_row);
PNG_UNUSED(prev_row)
}
#define MIN_CHUNK_LEN 256
#define MAX_CHUNK_LEN 2048
static inline vuint8m1_t
prefix_sum(vuint8m1_t chunk, unsigned char* carry, size_t vl,
size_t max_chunk_len)
{
size_t r;
for (r = 1; r < MIN_CHUNK_LEN; r <<= 1)
{
vbool8_t shift_mask = __riscv_vmsgeu_vx_u8m1_b8(__riscv_vid_v_u8m1(vl), r, vl);
chunk = __riscv_vadd_vv_u8m1_mu(shift_mask, chunk, chunk, __riscv_vslideup_vx_u8m1(__riscv_vundefined_u8m1(), chunk, r, vl), vl);
}
for (r = MIN_CHUNK_LEN; r < MAX_CHUNK_LEN && r < max_chunk_len; r <<= 1)
{
vbool8_t shift_mask = __riscv_vmsgeu_vx_u8m1_b8(__riscv_vid_v_u8m1(vl), r, vl);
chunk = __riscv_vadd_vv_u8m1_mu(shift_mask, chunk, chunk, __riscv_vslideup_vx_u8m1(__riscv_vundefined_u8m1(), chunk, r, vl), vl);
}
chunk = __riscv_vadd_vx_u8m1(chunk, *carry, vl);
*carry = __riscv_vmv_x_s_u8m1_u8(__riscv_vslidedown_vx_u8m1(chunk, vl - 1, vl));
return chunk;
}
static inline vint16m1_t
abs_diff(vuint16m1_t a, vuint16m1_t b, size_t vl)
{
vint16m1_t diff = __riscv_vreinterpret_v_u16m1_i16m1(__riscv_vsub_vv_u16m1(a, b, vl));
vbool16_t mask = __riscv_vmslt_vx_i16m1_b16(diff, 0, vl);
return __riscv_vrsub_vx_i16m1_m(mask, diff, 0, vl);
}
static inline vint16m1_t
abs_sum(vint16m1_t a, vint16m1_t b, size_t vl)
{
return __riscv_vadd_vv_i16m1(a, b, vl);
}
static inline void
png_read_filter_row_paeth_rvv(size_t len, size_t bpp, unsigned char* row,
const unsigned char* prev)
{
png_bytep 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_infop row_info, png_bytep row,
png_const_bytep 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_infop row_info, png_bytep row,
png_const_bytep 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 */

45
3rdparty/libpng/riscv/riscv_init.c vendored Normal file
View File

@@ -0,0 +1,45 @@
/* riscv_init.c - RISC-V Vector optimized filter functions
*
* Copyright (c) 2023 Google LLC
* Written by Dragoș Tiselice <dtiselice@google.com>, May 2023.
* Filip Wasil <f.wasil@samsung.com>, 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 <riscv_vector.h>
#ifndef PNG_ALIGNED_MEMORY_SUPPORTED
# error "ALIGNED_MEMORY is required; set: -DPNG_ALIGNED_MEMORY_SUPPORTED"
#endif
void
png_init_filter_functions_rvv(png_structp 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 */