libpng: Update to 1.6.45

This commit is contained in:
Rémi Verschelde 2025-01-09 14:59:15 +01:00
parent 0e3a5eda86
commit f68d55bcda
34 changed files with 929 additions and 228 deletions

View file

@ -329,8 +329,8 @@ License: BSD-3-clause
Files: ./thirdparty/libpng/
Comment: libpng
Copyright: 1995-2024, The PNG Reference Library Authors.
2018-2024, Cosmin Truta.
Copyright: 1995-2025, The PNG Reference Library Authors.
2018-2025, Cosmin Truta.
2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
1996-1997, Andreas Dilger.
1995-1996, Guy Eric Schalnat, Group 42, Inc.

View file

@ -54,6 +54,9 @@ if env["builtin_libpng"]:
env_thirdparty.Append(CPPDEFINES=["PNG_INTEL_SSE"])
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "intel/intel_init.c")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "intel/filter_sse2_intrinsics.c")
elif env["arch"] == "loongarch64":
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "loongarch/loongarch_lsx_init.c")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "loongarch/filter_lsx_intrinsics.c")
elif env["arch"] == "ppc64":
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "powerpc/powerpc_init.c")
env_thirdparty.add_source_files(thirdparty_obj, thirdparty_dir + "powerpc/filter_vsx_intrinsics.c")

View file

@ -511,14 +511,14 @@ Files extracted from upstream source:
## libpng
- Upstream: http://libpng.org/pub/png/libpng.html
- Version: 1.6.44 (f5e92d76973a7a53f517579bc95d61483bf108c0, 2024)
- Version: 1.6.45 (51f5bd68b9b806d2c92b4318164d28b49357da31, 2024)
- License: libpng/zlib
Files extracted from upstream source:
- All `.c` and `.h` files of the main directory, apart from `example.c` and
`pngtest.c`
- `arm/` (minus `filter_neon.S`), `intel/` and `powerpc/` (minus `.editorconfig`) folders
- `arm/` (minus `filter_neon.S`), `intel/`, `loongarch/`, and `powerpc/` (minus `.editorconfig`) folders
- `scripts/pnglibconf.h.prebuilt` as `pnglibconf.h`
- `LICENSE`

View file

@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
PNG Reference Library License version 2
---------------------------------------
* Copyright (c) 1995-2024 The PNG Reference Library Authors.
* Copyright (c) 2018-2024 Cosmin Truta.
* Copyright (c) 1995-2025 The PNG Reference Library Authors.
* Copyright (c) 2018-2025 Cosmin Truta.
* Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
* Copyright (c) 1996-1997 Andreas Dilger.
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.

View file

@ -1,4 +1,3 @@
/* arm_init.c - NEON optimised filter functions
*
* Copyright (c) 2018-2022 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* filter_neon_intrinsics.c - NEON optimised filter functions
*
* Copyright (c) 2018 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* palette_neon_intrinsics.c - NEON optimised palette expansion functions
*
* Copyright (c) 2018-2019 Cosmin Truta
@ -64,7 +63,7 @@ png_do_expand_palette_rgba8_neon(png_structrp png_ptr, png_row_infop row_info,
{
png_uint_32 row_width = row_info->width;
const png_uint_32 *riffled_palette =
(const png_uint_32 *)png_ptr->riffled_palette;
png_aligncastconst(png_const_uint_32p, png_ptr->riffled_palette);
const png_uint_32 pixels_per_chunk = 4;
png_uint_32 i;

View file

@ -1,4 +1,3 @@
/* filter_sse2_intrinsics.c - SSE2 optimized filter functions
*
* Copyright (c) 2018 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* intel_init.c - SSE2 optimized filter functions
*
* Copyright (c) 2018 Cosmin Truta

View file

@ -0,0 +1,412 @@
/* filter_lsx_intrinsics.c - LSX optimized filter functions
*
* Copyright (c) 2021 Loongson Technology Corporation Limited
* All rights reserved.
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2016 Glenn Randers-Pehrson
* Contributed by Jin Bo (jinbo@loongson.cn)
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#include "../pngpriv.h"
#ifdef PNG_READ_SUPPORTED
#if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 /* intrinsics code from pngpriv.h */
#include <lsxintrin.h>
#define LSX_LD(psrc) __lsx_vld((psrc), 0)
#define LSX_LD_2(psrc, stride, out0, out1) \
{ \
out0 = LSX_LD(psrc); \
out1 = LSX_LD(psrc + stride); \
}
#define LSX_LD_4(psrc, stride, out0, out1, out2, out3) \
{ \
LSX_LD_2(psrc, stride, out0, out1); \
LSX_LD_2(psrc + stride * 2, stride, out2, out3); \
}
#define LSX_ST(in, pdst) __lsx_vst(in, (pdst), 0)
#define LSX_ST_2(in0, in1, pdst, stride) \
{ \
LSX_ST(in0, pdst); \
LSX_ST(in1, pdst + stride); \
}
#define LSX_ST_4(in0, in1, in2, in3, pdst, stride) \
{ \
LSX_ST_2(in0, in1, pdst, stride); \
LSX_ST_2(in2, in3, pdst + stride * 2, stride); \
}
#define LSX_ADD_B(in0, in1, out0) \
{ \
out0 = __lsx_vadd_b(in0, in1); \
}
#define LSX_ADD_B_2(in0, in1, in2, in3, out0, out1) \
{ \
LSX_ADD_B(in0, in1, out0); \
LSX_ADD_B(in2, in3, out1); \
}
#define LSX_ADD_B_4(in0, in1, in2, in3, in4, in5, \
in6, in7, out0, out1, out2, out3) \
{ \
LSX_ADD_B_2(in0, in1, in2, in3, out0, out1); \
LSX_ADD_B_2(in4, in5, in6, in7, out2, out3); \
}
#define LSX_ABS_B_3(in0, in1, in2, out0, out1, out2) \
{ \
out0 = __lsx_vadda_h(in0, zero); \
out1 = __lsx_vadda_h(in1, zero); \
out2 = __lsx_vadda_h(in2, zero); \
}
#define LSX_ILVL_B(in_h, in_l, out0) \
{ \
out0 = __lsx_vilvl_b(in_h, in_l); \
}
#define LSX_ILVL_B_2(in0_h, in0_l, in1_h, in1_l, out0, out1) \
{ \
LSX_ILVL_B(in0_h, in0_l, out0); \
LSX_ILVL_B(in1_h, in1_l, out1); \
}
#define LSX_HSUB_HU_BU_2(in0, in1, out0, out1) \
{ \
out0 = __lsx_vhsubw_hu_bu(in0, in0); \
out1 = __lsx_vhsubw_hu_bu(in1, in1); \
}
#define LSX_CMP_PICK_SMALLER(in0, in1, in2, in3, in4, in5, out0) \
{ \
__m128i _cmph, _cmpb, _in0, _in3; \
_cmph = __lsx_vslt_h(in1, in0); \
_cmpb = __lsx_vpickev_b(_cmph, _cmph); \
_in0 = __lsx_vmin_bu(in0,in1); \
_in3 = __lsx_vbitsel_v(in3, in4, _cmpb); \
_cmph = __lsx_vslt_h(in2, _in0); \
_cmpb = __lsx_vpickev_b(_cmph, _cmph); \
_in3 = __lsx_vbitsel_v(_in3, in5, _cmpb); \
out0 = __lsx_vadd_b(out0, _in3); \
}
void png_read_filter_row_up_lsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
png_bytep rp = row;
png_const_bytep pp = prev_row;
__m128i vec_0, vec_1, vec_2, vec_3;
__m128i vec_4, vec_5, vec_6, vec_7;
while (n >= 64)
{
LSX_LD_4(rp, 16, vec_0, vec_1, vec_2, vec_3);
LSX_LD_4(pp, 16, vec_4, vec_5, vec_6, vec_7);
pp += 64;
LSX_ADD_B_4(vec_0 ,vec_4, vec_1, vec_5, vec_2, vec_6,
vec_3, vec_7, vec_0, vec_1, vec_2, vec_3);
LSX_ST_4(vec_0, vec_1, vec_2, vec_3, rp, 16);
rp += 64;
n -= 64;
}
if (n & 63)
{
if (n >= 32)
{
LSX_LD_2(rp, 16, vec_0, vec_1);
LSX_LD_2(pp, 16, vec_2, vec_3);
pp += 32;
LSX_ADD_B_2(vec_0, vec_2, vec_1, vec_3, vec_0, vec_1);
LSX_ST_2(vec_0, vec_1, rp, 16);
rp += 32;
n -= 32;
}
if (n & 31)
{
if (n >= 16)
{
vec_0 = LSX_LD(rp);
vec_1 = LSX_LD(pp);
pp += 16;
LSX_ADD_B(vec_0, vec_1, vec_0);
LSX_ST(vec_0, rp);
rp += 16;
n -= 16;
}
if (n >= 8)
{
vec_0 = __lsx_vldrepl_d(rp, 0);
vec_1 = __lsx_vldrepl_d(pp, 0);
vec_0 = __lsx_vadd_b(vec_0, vec_1);
__lsx_vstelm_d(vec_0, rp, 0, 0);
rp += 8;
pp += 8;
n -= 8;
}
while (n--)
{
*rp = *rp + *pp++;
rp++;
}
}
}
}
void png_read_filter_row_sub3_lsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
png_uint_32 tmp;
png_bytep nxt = row;
__m128i vec_0, vec_1;
PNG_UNUSED(prev_row);
vec_0 = __lsx_vldrepl_w(nxt, 0);
nxt += 3;
n -= 3;
while (n >= 3)
{
vec_1 = __lsx_vldrepl_w(nxt, 0);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_h(vec_1, nxt, 0, 0);
vec_0 = vec_1;
nxt += 2;
__lsx_vstelm_b(vec_1, nxt, 0, 2);
nxt += 1;
n -= 3;
}
row = nxt - 3;
while (n--)
{
*nxt = *nxt + *row++;
nxt++;
}
}
void png_read_filter_row_sub4_lsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
__m128i vec_0, vec_1;
PNG_UNUSED(prev_row);
vec_0 = __lsx_vldrepl_w(row, 0);
row += 4;
n -= 4;
while (n >= 4)
{
vec_1 = __lsx_vldrepl_w(row, 0);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_w(vec_1, row, 0, 0);
vec_0 = vec_1;
row += 4;
n -= 4;
}
}
void png_read_filter_row_avg3_lsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
png_bytep nxt = row;
png_const_bytep prev_nxt = prev_row;
__m128i vec_0, vec_1, vec_2;
vec_0 = __lsx_vldrepl_w(nxt, 0);
vec_1 = __lsx_vldrepl_w(prev_nxt, 0);
prev_nxt += 3;
vec_1 = __lsx_vsrli_b(vec_1, 1);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_h(vec_1, nxt, 0, 0);
nxt += 2;
__lsx_vstelm_b(vec_1, nxt, 0, 2);
nxt += 1;
n -= 3;
while (n >= 3)
{
vec_2 = vec_1;
vec_0 = __lsx_vldrepl_w(nxt, 0);
vec_1 = __lsx_vldrepl_w(prev_nxt, 0);
prev_nxt += 3;
vec_1 = __lsx_vavg_bu(vec_1, vec_2);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_h(vec_1, nxt, 0, 0);
nxt += 2;
__lsx_vstelm_b(vec_1, nxt, 0, 2);
nxt += 1;
n -= 3;
}
row = nxt - 3;
while (n--)
{
vec_2 = __lsx_vldrepl_b(row, 0);
row++;
vec_0 = __lsx_vldrepl_b(nxt, 0);
vec_1 = __lsx_vldrepl_b(prev_nxt, 0);
prev_nxt++;
vec_1 = __lsx_vavg_bu(vec_1, vec_2);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_b(vec_1, nxt, 0, 0);
nxt++;
}
}
void png_read_filter_row_avg4_lsx(png_row_infop row_info, png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
__m128i vec_0, vec_1, vec_2;
vec_0 = __lsx_vldrepl_w(row, 0);
vec_1 = __lsx_vldrepl_w(prev_row, 0);
prev_row += 4;
vec_1 = __lsx_vsrli_b(vec_1, 1);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_w(vec_1, row, 0, 0);
row += 4;
n -= 4;
while (n >= 4)
{
vec_2 = vec_1;
vec_0 = __lsx_vldrepl_w(row, 0);
vec_1 = __lsx_vldrepl_w(prev_row, 0);
prev_row += 4;
vec_1 = __lsx_vavg_bu(vec_1, vec_2);
vec_1 = __lsx_vadd_b(vec_1, vec_0);
__lsx_vstelm_w(vec_1, row, 0, 0);
row += 4;
n -= 4;
}
}
void png_read_filter_row_paeth3_lsx(png_row_infop row_info,
png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
png_bytep nxt = row;
png_const_bytep prev_nxt = prev_row;
__m128i vec_a, vec_b, vec_c, vec_d;
__m128i vec_pa, vec_pb, vec_pc;
__m128i zero = {0};
vec_a = __lsx_vldrepl_w(nxt, 0);
vec_b = __lsx_vldrepl_w(prev_nxt, 0);
prev_nxt += 3;
vec_d = __lsx_vadd_b(vec_a, vec_b);
__lsx_vstelm_h(vec_d, nxt, 0, 0);
nxt += 2;
__lsx_vstelm_b(vec_d, nxt, 0, 2);
nxt += 1;
n -= 3;
while (n >= 3)
{
vec_a = vec_d;
vec_c = vec_b;
vec_b = __lsx_vldrepl_w(prev_nxt, 0);
prev_nxt += 3;
vec_d = __lsx_vldrepl_w(nxt, 0);
LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb);
LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb);
vec_pc = __lsx_vadd_h(vec_pa, vec_pb);
LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc);
LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d);
__lsx_vstelm_h(vec_d, nxt, 0, 0);
nxt += 2;
__lsx_vstelm_b(vec_d, nxt, 0, 2);
nxt += 1;
n -= 3;
}
prev_row = prev_nxt - 3;
row = nxt - 3;
while (n--)
{
vec_a = __lsx_vldrepl_b(row, 0);
row++;
vec_b = __lsx_vldrepl_b(prev_nxt, 0);
prev_nxt++;
vec_c = __lsx_vldrepl_b(prev_row, 0);
prev_row++;
vec_d = __lsx_vldrepl_b(nxt, 0);
LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb);
LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb);
vec_pc = __lsx_vadd_h(vec_pa, vec_pb);
LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc);
LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d);
__lsx_vstelm_b(vec_d, nxt, 0, 0);
nxt++;
}
}
void png_read_filter_row_paeth4_lsx(png_row_infop row_info,
png_bytep row,
png_const_bytep prev_row)
{
size_t n = row_info->rowbytes;
__m128i vec_a, vec_b, vec_c, vec_d;
__m128i vec_pa, vec_pb, vec_pc;
__m128i zero = {0};
vec_a = __lsx_vldrepl_w(row, 0);
vec_b = __lsx_vldrepl_w(prev_row, 0);
prev_row += 4;
vec_d = __lsx_vadd_b(vec_a, vec_b);
__lsx_vstelm_w(vec_d, row, 0, 0);
row += 4;
n -= 4;
while (n >= 4)
{
vec_a = vec_d;
vec_c = vec_b;
vec_b = __lsx_vldrepl_w(prev_row, 0);
prev_row += 4;
vec_d = __lsx_vldrepl_w(row, 0);
LSX_ILVL_B_2(vec_b, vec_c, vec_a, vec_c, vec_pa, vec_pb);
LSX_HSUB_HU_BU_2(vec_pa, vec_pb, vec_pa, vec_pb);
vec_pc = __lsx_vadd_h(vec_pa, vec_pb);
LSX_ABS_B_3(vec_pa, vec_pb, vec_pc, vec_pa, vec_pb, vec_pc);
LSX_CMP_PICK_SMALLER(vec_pa, vec_pb, vec_pc, vec_a, vec_b, vec_c, vec_d);
__lsx_vstelm_w(vec_d, row, 0, 0);
row += 4;
n -= 4;
}
}
#endif /* PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 (intrinsics) */
#endif /* PNG_READ_SUPPORTED */

View file

@ -0,0 +1,65 @@
/* loongarch_lsx_init.c - LSX optimized filter functions
*
* Copyright (c) 2021 Loongson Technology Corporation Limited
* All rights reserved.
* Contributed by Jin Bo <jinbo@loongson.cn>
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
#include "../pngpriv.h"
#ifdef PNG_READ_SUPPORTED
#if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1
#include <sys/auxv.h>
#define LA_HWCAP_LSX (1<<4)
static int png_has_lsx(void)
{
int flags = 0;
int flag = (int)getauxval(AT_HWCAP);
if (flag & LA_HWCAP_LSX)
return 1;
return 0;
}
void
png_init_filter_functions_lsx(png_structp pp, unsigned int bpp)
{
/* IMPORTANT: any new external functions used here must be declared using
* PNG_INTERNAL_FUNCTION in ../pngpriv.h. This is required so that the
* 'prefix' option to configure works:
*
* ./configure --with-libpng-prefix=foobar_
*
* Verify you have got this right by running the above command, doing a build
* and examining pngprefix.h; it must contain a #define for every external
* function you add. (Notice that this happens automatically for the
* initialization function.)
*/
if (png_has_lsx())
{
pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_lsx;
if (bpp == 3)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_lsx;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_lsx;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth3_lsx;
}
else if (bpp == 4)
{
pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_lsx;
pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_lsx;
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] = png_read_filter_row_paeth4_lsx;
}
}
}
#endif /* PNG_LOONGARCH_LSX_IMPLEMENTATION == 1 */
#endif /* PNG_READ_SUPPORTED */

View file

@ -1,7 +1,6 @@
/* png.c - location for general purpose libpng functions
*
* 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.
@ -14,7 +13,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
typedef png_libpng_version_1_6_44 Your_png_h_is_not_version_1_6_44;
typedef png_libpng_version_1_6_45 Your_png_h_is_not_version_1_6_45;
/* Tells libpng that we have already handled the first "num_bytes" bytes
* of the PNG file signature. If the PNG data is embedded into another
@ -794,8 +793,8 @@ png_get_copyright(png_const_structrp png_ptr)
return PNG_STRING_COPYRIGHT
#else
return PNG_STRING_NEWLINE \
"libpng version 1.6.44" PNG_STRING_NEWLINE \
"Copyright (c) 2018-2024 Cosmin Truta" PNG_STRING_NEWLINE \
"libpng version 1.6.45" PNG_STRING_NEWLINE \
"Copyright (c) 2018-2025 Cosmin Truta" PNG_STRING_NEWLINE \
"Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
@ -1203,22 +1202,66 @@ png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
#endif /* GAMMA */
#ifdef PNG_COLORSPACE_SUPPORTED
static int
png_safe_add(png_int_32 *addend0_and_result, png_int_32 addend1,
png_int_32 addend2) {
/* Safely add three integers. Returns 0 on success, 1 on overlow.
static png_int_32
png_fp_add(png_int_32 addend0, png_int_32 addend1, int *error)
{
/* Safely add two fixed point values setting an error flag and returning 0.5
* on overflow.
* IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
* relying on addition of two positive values producing a negative one is not
* safe.
*/
int addend0 = *addend0_and_result;
if (0x7fffffff - addend0 < addend1)
return 1;
addend0 += addend1;
if (0x7fffffff - addend1 < addend2)
return 1;
*addend0_and_result = addend0 + addend2;
return 0;
if (addend0 > 0)
{
if (0x7fffffff - addend0 >= addend1)
return addend0+addend1;
}
else if (addend0 < 0)
{
if (-0x7fffffff - addend0 <= addend1)
return addend0+addend1;
}
else
return addend1;
*error = 1;
return PNG_FP_1/2;
}
static png_int_32
png_fp_sub(png_int_32 addend0, png_int_32 addend1, int *error)
{
/* As above but calculate addend0-addend1. */
if (addend1 > 0)
{
if (-0x7fffffff + addend1 <= addend0)
return addend0-addend1;
}
else if (addend1 < 0)
{
if (0x7fffffff + addend1 >= addend0)
return addend0-addend1;
}
else
return addend0;
*error = 1;
return PNG_FP_1/2;
}
static int
png_safe_add(png_int_32 *addend0_and_result, png_int_32 addend1,
png_int_32 addend2)
{
/* Safely add three integers. Returns 0 on success, 1 on overflow. Does not
* set the result on overflow.
*/
int error = 0;
int result = png_fp_add(*addend0_and_result,
png_fp_add(addend1, addend2, &error),
&error);
if (!error) *addend0_and_result = result;
return error;
}
/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
@ -1229,7 +1272,7 @@ png_safe_add(png_int_32 *addend0_and_result, png_int_32 addend1,
static int
png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
{
png_int_32 d, dred, dgreen, dwhite, whiteX, whiteY;
png_int_32 d, dred, dgreen, dblue, dwhite, whiteX, whiteY;
/* 'd' in each of the blocks below is just X+Y+Z for each component,
* x, y and z are X,Y,Z/(X+Y+Z).
@ -1237,44 +1280,52 @@ png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
d = XYZ->red_X;
if (png_safe_add(&d, XYZ->red_Y, XYZ->red_Z))
return 1;
if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
return 1;
if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
return 1;
dred = d;
whiteX = XYZ->red_X;
whiteY = XYZ->red_Y;
if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, dred) == 0)
return 1;
if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, dred) == 0)
return 1;
d = XYZ->green_X;
if (png_safe_add(&d, XYZ->green_Y, XYZ->green_Z))
return 1;
if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
return 1;
if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
return 1;
dgreen = d;
whiteX += XYZ->green_X;
whiteY += XYZ->green_Y;
if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, dgreen) == 0)
return 1;
if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, dgreen) == 0)
return 1;
d = XYZ->blue_X;
if (png_safe_add(&d, XYZ->blue_Y, XYZ->blue_Z))
return 1;
if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
dblue = d;
if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, dblue) == 0)
return 1;
if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, dblue) == 0)
return 1;
whiteX += XYZ->blue_X;
whiteY += XYZ->blue_Y;
/* The reference white is simply the sum of the end-point (X,Y,Z) vectors so
* the fillowing calculates (X+Y+Z) of the reference white (media white,
* encoding white) itself:
*/
d = dblue;
if (png_safe_add(&d, dred, dgreen))
return 1;
dwhite = d;
/* Find the white X,Y values from the sum of the red, green and blue X,Y
* values.
*/
d = XYZ->red_X;
if (png_safe_add(&d, XYZ->green_X, XYZ->blue_X))
return 1;
whiteX = d;
d = XYZ->red_Y;
if (png_safe_add(&d, XYZ->green_Y, XYZ->blue_Y))
return 1;
whiteY = d;
if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0)
return 1;
if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0)
@ -1289,6 +1340,29 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
png_fixed_point red_inverse, green_inverse, blue_scale;
png_fixed_point left, right, denominator;
/* Check xy and, implicitly, z. Note that wide gamut color spaces typically
* have end points with 0 tristimulus values (these are impossible end
* points, but they are used to cover the possible colors). We check
* xy->whitey against 5, not 0, to avoid a possible integer overflow.
*
* The limits here will *not* accept ACES AP0, where bluey is -7700
* (-0.0770) because the PNG spec itself requires the xy values to be
* unsigned. whitey is also required to be 5 or more to avoid overflow.
*
* Instead the upper limits have been relaxed to accomodate ACES AP1 where
* redz ends up as -600 (-0.006). ProPhotoRGB was already "in range."
* The new limit accomodates the AP0 and AP1 ranges for z but not AP0 redy.
*/
const png_fixed_point fpLimit = PNG_FP_1+(PNG_FP_1/10);
if (xy->redx < 0 || xy->redx > fpLimit) return 1;
if (xy->redy < 0 || xy->redy > fpLimit-xy->redx) return 1;
if (xy->greenx < 0 || xy->greenx > fpLimit) return 1;
if (xy->greeny < 0 || xy->greeny > fpLimit-xy->greenx) return 1;
if (xy->bluex < 0 || xy->bluex > fpLimit) return 1;
if (xy->bluey < 0 || xy->bluey > fpLimit-xy->bluex) return 1;
if (xy->whitex < 0 || xy->whitex > fpLimit) return 1;
if (xy->whitey < 5 || xy->whitey > fpLimit-xy->whitex) return 1;
/* The reverse calculation is more difficult because the original tristimulus
* value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
* derived values were recorded in the cHRM chunk;
@ -1432,18 +1506,23 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
* (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x)
*
* Accuracy:
* The input values have 5 decimal digits of accuracy. The values are all in
* the range 0 < value < 1, so simple products are in the same range but may
* need up to 10 decimal digits to preserve the original precision and avoid
* underflow. Because we are using a 32-bit signed representation we cannot
* match this; the best is a little over 9 decimal digits, less than 10.
* The input values have 5 decimal digits of accuracy.
*
* In the previous implementation the values were all in the range 0 < value
* < 1, so simple products are in the same range but may need up to 10
* decimal digits to preserve the original precision and avoid underflow.
* Because we are using a 32-bit signed representation we cannot match this;
* the best is a little over 9 decimal digits, less than 10.
*
* This range has now been extended to allow values up to 1.1, or 110,000 in
* fixed point.
*
* The approach used here is to preserve the maximum precision within the
* signed representation. Because the red-scale calculation above uses the
* difference between two products of values that must be in the range -1..+1
* it is sufficient to divide the product by 7; ceil(100,000/32767*2). The
* factor is irrelevant in the calculation because it is applied to both
* numerator and denominator.
* difference between two products of values that must be in the range
* -1.1..+1.1 it is sufficient to divide the product by 8;
* ceil(121,000/32767*2). The factor is irrelevant in the calculation
* because it is applied to both numerator and denominator.
*
* Note that the values of the differences of the products of the
* chromaticities in the above equations tend to be small, for example for
@ -1465,19 +1544,25 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
* Adobe Wide Gamut RGB
* 0.258728243040113 0.724682314948566 0.016589442011321
*/
/* By the argument, above overflow should be impossible here. The return
* value of 2 indicates an internal error to the caller.
int error = 0;
/* By the argument above overflow should be impossible here, however the
* code now simply returns a failure code. The xy subtracts in the arguments
* to png_muldiv are *not* checked for overflow because the checks at the
* start guarantee they are in the range 0..110000 and png_fixed_point is a
* 32-bit signed number.
*/
if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0)
if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 8) == 0)
return 1;
if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 8) == 0)
return 1;
denominator = left - right;
denominator = png_fp_sub(left, right, &error);
if (error) return 1;
/* Now find the red numerator. */
if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 8) == 0)
return 1;
if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 8) == 0)
return 1;
/* Overflow is possible here and it indicates an extreme set of PNG cHRM
@ -1485,29 +1570,35 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
* scale value because this allows us to delay the multiplication of white-y
* into the denominator, which tends to produce a small number.
*/
if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 ||
if (png_muldiv(&red_inverse, xy->whitey, denominator,
png_fp_sub(left, right, &error)) == 0 || error ||
red_inverse <= xy->whitey /* r+g+b scales = white scale */)
return 1;
/* Similarly for green_inverse: */
if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 8) == 0)
return 1;
if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 8) == 0)
return 1;
if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
if (png_muldiv(&green_inverse, xy->whitey, denominator,
png_fp_sub(left, right, &error)) == 0 || error ||
green_inverse <= xy->whitey)
return 1;
/* And the blue scale, the checks above guarantee this can't overflow but it
* can still produce 0 for extreme cHRM values.
*/
blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
png_reciprocal(green_inverse);
if (blue_scale <= 0)
blue_scale = png_fp_sub(png_fp_sub(png_reciprocal(xy->whitey),
png_reciprocal(red_inverse), &error),
png_reciprocal(green_inverse), &error);
if (error || blue_scale <= 0)
return 1;
/* And fill in the png_XYZ: */
/* And fill in the png_XYZ. Again the subtracts are safe because of the
* checks on the xy values at the start (the subtracts just calculate the
* corresponding z values.)
*/
if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0)
return 1;
if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0)

View file

@ -1,9 +1,8 @@
/* png.h - header file for PNG reference library
*
* libpng version 1.6.44
* libpng version 1.6.45
*
* 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.
@ -15,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.44, September 2024:
* libpng versions 1.6.36, December 2018, through 1.6.45, January 2025:
* Cosmin Truta
* See also "Contributing Authors", below.
*/
@ -27,8 +26,8 @@
* PNG Reference Library License version 2
* ---------------------------------------
*
* * Copyright (c) 1995-2024 The PNG Reference Library Authors.
* * Copyright (c) 2018-2024 Cosmin Truta.
* * Copyright (c) 1995-2025 The PNG Reference Library Authors.
* * Copyright (c) 2018-2025 Cosmin Truta.
* * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
* * Copyright (c) 1996-1997 Andreas Dilger.
* * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@ -239,7 +238,7 @@
* ...
* 1.5.30 15 10530 15.so.15.30[.0]
* ...
* 1.6.44 16 10644 16.so.16.44[.0]
* 1.6.45 16 10645 16.so.16.45[.0]
*
* Henceforth the source version will match the shared-library major and
* minor numbers; the shared-library major version number will be used for
@ -275,7 +274,7 @@
*/
/* Version information for png.h - this should match the version in png.c */
#define PNG_LIBPNG_VER_STRING "1.6.44"
#define PNG_LIBPNG_VER_STRING "1.6.45"
#define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
/* The versions of shared library builds should stay in sync, going forward */
@ -286,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 44
#define PNG_LIBPNG_VER_RELEASE 45
/* This should be zero for a public release, or non-zero for a
* development version.
@ -317,7 +316,7 @@
* From version 1.0.1 it is:
* XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
#define PNG_LIBPNG_VER 10644 /* 1.6.44 */
#define PNG_LIBPNG_VER 10645 /* 1.6.45 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@ -427,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_44;
typedef char* png_libpng_version_1_6_45;
/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
*
@ -745,6 +744,7 @@ 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
/* This is used for the transformation routines, as some of them
* change these values for the row. It also should enable using
@ -1974,6 +1974,17 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
png_fixed_point int_blue_Z))
#endif
#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_bytep transfer_function, png_bytep matrix_coefficients,
png_bytep video_full_range_flag));
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_eXIf_SUPPORTED
PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr,
png_inforp info_ptr, png_bytep *exif));
@ -3238,7 +3249,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(249);
PNG_EXPORT_LAST_ORDINAL(251);
#endif
#ifdef __cplusplus

View file

@ -1,9 +1,8 @@
/* pngconf.h - machine-configurable file for libpng
*
* libpng version 1.6.44
* libpng version 1.6.45
*
* Copyright (c) 2018-2024 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.

View file

@ -1,4 +1,3 @@
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
*
* Copyright (c) 2018 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* pngerror.c - stub functions for i/o and memory allocation
*
* Copyright (c) 2018-2024 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* pngget.c - retrieval of values from info struct
*
* Copyright (c) 2018-2024 Cosmin Truta
@ -785,6 +784,31 @@ png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
}
#endif
#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_bytep transfer_function, png_bytep matrix_coefficients,
png_bytep video_full_range_flag)
{
png_debug1(1, "in %s retrieval function", "cICP");
if (png_ptr != NULL && info_ptr != NULL &&
(info_ptr->valid & PNG_INFO_cICP) != 0 &&
colour_primaries != NULL && transfer_function != NULL &&
matrix_coefficients != NULL && video_full_range_flag != NULL)
{
*colour_primaries = info_ptr->cicp_colour_primaries;
*transfer_function = info_ptr->cicp_transfer_function;
*matrix_coefficients = info_ptr->cicp_matrix_coefficients;
*video_full_range_flag = info_ptr->cicp_video_full_range_flag;
return (PNG_INFO_cICP);
}
return (0);
}
#endif
#ifdef PNG_eXIf_SUPPORTED
png_uint_32 PNGAPI
png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,

View file

@ -1,4 +1,3 @@
/* pnginfo.h - header file for PNG reference library
*
* Copyright (c) 2018 Cosmin Truta
@ -101,6 +100,14 @@ struct png_info_def
png_colorspace colorspace;
#endif
#ifdef PNG_cICP_SUPPORTED
/* cICP chunk data */
png_byte cicp_colour_primaries;
png_byte cicp_transfer_function;
png_byte cicp_matrix_coefficients;
png_byte cicp_video_full_range_flag;
#endif
#ifdef PNG_iCCP_SUPPORTED
/* iCCP chunk data. */
png_charp iccp_name; /* profile name */

View file

@ -1,8 +1,8 @@
/* pnglibconf.h - library build configuration */
/* libpng version 1.6.44 */
/* libpng version 1.6.45 */
/* Copyright (c) 2018-2024 Cosmin Truta */
/* Copyright (c) 2018-2025 Cosmin Truta */
/* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
@ -88,6 +88,7 @@
#define PNG_READ_USER_TRANSFORM_SUPPORTED
#define PNG_READ_bKGD_SUPPORTED
#define PNG_READ_cHRM_SUPPORTED
#define PNG_READ_cICP_SUPPORTED
#define PNG_READ_eXIf_SUPPORTED
#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_hIST_SUPPORTED
@ -158,6 +159,7 @@
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
#define PNG_WRITE_bKGD_SUPPORTED
#define PNG_WRITE_cHRM_SUPPORTED
#define PNG_WRITE_cICP_SUPPORTED
#define PNG_WRITE_eXIf_SUPPORTED
#define PNG_WRITE_gAMA_SUPPORTED
#define PNG_WRITE_hIST_SUPPORTED
@ -176,6 +178,7 @@
#define PNG_WRITE_zTXt_SUPPORTED
#define PNG_bKGD_SUPPORTED
#define PNG_cHRM_SUPPORTED
#define PNG_cICP_SUPPORTED
#define PNG_eXIf_SUPPORTED
#define PNG_gAMA_SUPPORTED
#define PNG_hIST_SUPPORTED

View file

@ -1,4 +1,3 @@
/* pngmem.c - stub functions for memory allocation
*
* Copyright (c) 2018 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* pngpread.c - read a png file in push mode
*
* Copyright (c) 2018-2024 Cosmin Truta
@ -32,6 +31,21 @@ if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
if (png_ptr->buffer_size < N) \
{ png_push_save_buffer(png_ptr); return; }
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */
/* Start of interlace block */
static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
/* TODO: Move these arrays to a common utility module to avoid duplication. */
#endif
void PNGAPI
png_process_data(png_structrp png_ptr, png_inforp info_ptr,
png_bytep buffer, size_t buffer_size)
@ -294,6 +308,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
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)
@ -976,27 +998,6 @@ png_push_process_row(png_structrp png_ptr)
void /* PRIVATE */
png_read_push_finish_row(png_structrp png_ptr)
{
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
/* Height of interlace block. This is not currently used - if you need
* it, uncomment it here and in png.h
static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
*/
#endif
png_ptr->row_number++;
if (png_ptr->row_number < png_ptr->num_rows)
return;

View file

@ -1,4 +1,3 @@
/* pngpriv.h - private declarations for use inside libpng
*
* Copyright (c) 2018-2024 Cosmin Truta
@ -835,6 +834,7 @@
#define png_PLTE PNG_U32( 80, 76, 84, 69)
#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_eXIf PNG_U32(101, 88, 73, 102) /* registered July 2017 */
#define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */
#define png_gAMA PNG_U32(103, 65, 77, 65)
@ -1131,6 +1131,12 @@ PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr,
/* The xy value must have been previously validated */
#endif
#ifdef PNG_WRITE_cICP_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_write_cICP,(png_structrp png_ptr,
png_byte colour_primaries, png_byte transfer_function,
png_byte matrix_coefficients, png_byte video_full_range_flag), PNG_EMPTY);
#endif
#ifdef PNG_WRITE_sRGB_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr,
int intent),PNG_EMPTY);
@ -1474,6 +1480,11 @@ 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);

View file

@ -1,7 +1,6 @@
/* pngread.c - read 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.
@ -175,6 +174,11 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
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);
@ -852,6 +856,11 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
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);

View file

@ -1,4 +1,3 @@
/* pngrio.c - functions for data input
*
* Copyright (c) 2018 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* pngrtran.c - transforms the data in a row for PNG readers
*
* Copyright (c) 2018-2024 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* pngrutil.c - utilities to read a PNG file
*
* Copyright (c) 2018-2024 Cosmin Truta
@ -18,6 +17,21 @@
#ifdef PNG_READ_SUPPORTED
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */
/* Start of interlace block */
static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
/* TODO: Move these arrays to a common utility module to avoid duplication. */
#endif
png_uint_32 PNGAPI
png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
{
@ -2032,6 +2046,47 @@ png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
}
#endif
#ifdef PNG_READ_cICP_SUPPORTED
void /* PRIVATE */
png_handle_cICP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[4];
png_debug(1, "in png_handle_cICP");
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
png_chunk_error(png_ptr, "missing IHDR");
else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "out of place");
return;
}
else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cICP) != 0)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "duplicate");
return;
}
else if (length != 4)
{
png_crc_finish(png_ptr, length);
png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 4);
if (png_crc_finish(png_ptr, 0) != 0)
return;
png_set_cICP(png_ptr, info_ptr, buf[0], buf[1], buf[2], buf[3]);
}
#endif
#ifdef PNG_READ_eXIf_SUPPORTED
void /* PRIVATE */
png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
@ -3684,10 +3739,6 @@ void /* PRIVATE */
png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
png_uint_32 transformations /* Because these may affect the byte layout */)
{
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Offset to next interlace block */
static const unsigned int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
png_debug(1, "in png_do_read_interlace");
if (row != NULL && row_info != NULL)
{
@ -4325,20 +4376,6 @@ png_read_finish_IDAT(png_structrp png_ptr)
void /* PRIVATE */
png_read_finish_row(png_structrp png_ptr)
{
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
png_debug(1, "in png_read_finish_row");
png_ptr->row_number++;
if (png_ptr->row_number < png_ptr->num_rows)
@ -4390,20 +4427,6 @@ png_read_finish_row(png_structrp png_ptr)
void /* PRIVATE */
png_read_start_row(png_structrp png_ptr)
{
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
unsigned int max_pixel_depth;
size_t row_bytes;

View file

@ -1,7 +1,6 @@
/* pngset.c - storage of image information into info struct
*
* Copyright (c) 2018-2024 Cosmin Truta
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
@ -134,6 +133,32 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
#endif /* cHRM */
#ifdef PNG_cICP_SUPPORTED
void PNGAPI
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)
{
png_debug1(1, "in %s storage function", "cICP");
if (png_ptr == NULL || info_ptr == NULL)
return;
info_ptr->cicp_colour_primaries = colour_primaries;
info_ptr->cicp_transfer_function = transfer_function;
info_ptr->cicp_matrix_coefficients = matrix_coefficients;
info_ptr->cicp_video_full_range_flag = video_full_range_flag;
if (info_ptr->cicp_matrix_coefficients != 0)
{
png_warning(png_ptr, "Invalid cICP matrix coefficients");
return;
}
info_ptr->valid |= PNG_INFO_cICP;
}
#endif /* cICP */
#ifdef PNG_eXIf_SUPPORTED
void PNGAPI
png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
@ -1395,6 +1420,7 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
static const png_byte chunks_to_ignore[] = {
98, 75, 71, 68, '\0', /* bKGD */
99, 72, 82, 77, '\0', /* cHRM */
99, 73, 67, 80, '\0', /* cICP */
101, 88, 73, 102, '\0', /* eXIf */
103, 65, 77, 65, '\0', /* gAMA */
104, 73, 83, 84, '\0', /* hIST */

View file

@ -1,4 +1,3 @@
/* pngstruct.h - header file for PNG reference library
*
* Copyright (c) 2018-2022 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
*
* Copyright (c) 2018-2024 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* pngwio.c - functions for data output
*
* Copyright (c) 2018 Cosmin Truta

View file

@ -1,7 +1,6 @@
/* pngwrite.c - general routines 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.
@ -128,29 +127,61 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
* the application continues writing the PNG. So check the 'invalid'
* flag here too.
*/
#ifdef PNG_GAMMA_SUPPORTED
# ifdef PNG_WRITE_gAMA_SUPPORTED
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
(info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 &&
(info_ptr->valid & PNG_INFO_gAMA) != 0)
png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
# endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
/* Write unknown chunks first; PNG v3 establishes a precedence order
* for colourspace chunks. It is certain therefore that new
* colourspace chunks will have a precedence and very likely it will be
* higher than all known so far. Writing the unknown chunks here is
* most likely to present the chunks in the most convenient order.
*
* FUTURE: maybe write chunks in the order the app calls png_set_chnk
* to give the app control.
*/
write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
#endif
#ifdef PNG_WRITE_sBIT_SUPPORTED
/* PNG v3: a streaming app will need to see this before cICP because
* the information is helpful in handling HLG encoding (which is
* natively 10 bits but gets expanded to 16 in PNG.)
*
* The app shouldn't care about the order ideally, but it might have
* no choice. In PNG v3, apps are allowed to reject PNGs where the
* APNG chunks are out of order so it behooves libpng to be nice here.
*/
if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
#endif
/* PNG v3: the July 2004 version of the TR introduced the concept of colour
* space priority. As above it therefore behooves libpng to write the colour
* space chunks in the priority order so that a streaming app need not buffer
* them.
*/
#ifdef PNG_COLORSPACE_SUPPORTED
/* Write only one of sRGB or an ICC profile. If a profile was supplied
* and it matches one of the known sRGB ones issue a warning.
# ifdef PNG_WRITE_cICP_SUPPORTED /* Priority 4 */
if ((info_ptr->valid & PNG_INFO_cICP) != 0)
{
png_write_cICP(png_ptr,
info_ptr->cicp_colour_primaries,
info_ptr->cicp_transfer_function,
info_ptr->cicp_matrix_coefficients,
info_ptr->cicp_video_full_range_flag);
}
# endif
/* 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
# ifdef PNG_WRITE_iCCP_SUPPORTED /* Priority 3 */
if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
(info_ptr->valid & PNG_INFO_iCCP) != 0)
{
# ifdef PNG_WRITE_sRGB_SUPPORTED
if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
png_app_warning(png_ptr,
"profile matches sRGB but writing iCCP instead");
# endif
png_write_iCCP(png_ptr, info_ptr->iccp_name,
info_ptr->iccp_profile);
}
@ -159,20 +190,24 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
# endif
# endif
# ifdef PNG_WRITE_sRGB_SUPPORTED
# 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);
# endif /* WRITE_sRGB */
#endif /* COLORSPACE */
#ifdef PNG_WRITE_sBIT_SUPPORTED
if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
#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);
# endif
#endif
#ifdef PNG_COLORSPACE_SUPPORTED
# ifdef PNG_WRITE_cHRM_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)
@ -180,10 +215,6 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
# endif
#endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
#endif
png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
}
}

View file

@ -1,4 +1,3 @@
/* pngwtran.c - transforms the data in a row for PNG writers
*
* Copyright (c) 2018 Cosmin Truta

View file

@ -1,4 +1,3 @@
/* pngwutil.c - utilities to write a PNG file
*
* Copyright (c) 2018-2024 Cosmin Truta
@ -9,12 +8,30 @@
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*
* This file contains routines that are only called from within
* libpng itself during the course of writing an image.
*/
#include "pngpriv.h"
#ifdef PNG_WRITE_SUPPORTED
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Arrays to facilitate interlacing - use pass (0 - 6) as index. */
/* Start of interlace block */
static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
/* TODO: Move these arrays to a common utility module to avoid duplication. */
#endif
#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
/* Place a 32-bit number into a buffer in PNG byte order. We work
* with unsigned numbers for convenience, although one supported
@ -1471,6 +1488,29 @@ png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
}
#endif
#ifdef PNG_WRITE_cICP_SUPPORTED
/* Write the cICP data */
void /* PRIVATE */
png_write_cICP(png_structrp png_ptr,
png_byte colour_primaries, png_byte transfer_function,
png_byte matrix_coefficients, png_byte video_full_range_flag)
{
png_byte buf[4];
png_debug(1, "in png_write_cICP");
png_write_chunk_header(png_ptr, png_cICP, 4);
buf[0] = colour_primaries;
buf[1] = transfer_function;
buf[2] = matrix_coefficients;
buf[3] = video_full_range_flag;
png_write_chunk_data(png_ptr, buf, 4);
png_write_chunk_end(png_ptr);
}
#endif
#ifdef PNG_WRITE_eXIf_SUPPORTED
/* Write the Exif data */
void /* PRIVATE */
@ -1889,22 +1929,6 @@ png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
void /* PRIVATE */
png_write_start_row(png_structrp png_ptr)
{
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
png_alloc_size_t buf_size;
int usr_pixel_depth;
@ -2004,22 +2028,6 @@ png_write_start_row(png_structrp png_ptr)
void /* PRIVATE */
png_write_finish_row(png_structrp png_ptr)
{
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
static const png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
static const png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
png_debug(1, "in png_write_finish_row");
/* Next row */
@ -2095,14 +2103,6 @@ png_write_finish_row(png_structrp png_ptr)
void /* PRIVATE */
png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
{
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
static const png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
static const png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
png_debug(1, "in png_do_write_interlace");
/* We don't have to do anything on the last pass (6) */

View file

@ -1,4 +1,3 @@
/* powerpc_init.c - POWERPC optimised filter functions
*
* Copyright (c) 2018 Cosmin Truta