Merge pull request #27741 from dkurt:libpng_1.6.45

libpng upgrade to 1.6.45 and cICP metadata support for PNG imwrite #27741

### Pull Request Readiness Checklist

resolves #24185

libpng docs: https://www.w3.org/TR/png-3/#cICP-chunk
similar code from ffmpeg: a700f0f72d/libavcodec/pngenc.c (L452-L456)

So issue #24185 can be solved by replacing `cv.imwrite` in user's code to `cv.imwriteWithMetadata`:
```python
cv.imwriteWithMetadata("frame.png", frame, [cv.IMAGE_METADATA_CICP], np.array([[9, 18, 0, 1]], np.uint8))
```
```
$ exiftool /home/d.kurtaev/opencv_build/frames_pr/image_38.png
ExifTool Version Number         : 12.76
File Name                       : image_38.png
Directory                       : /home/d.kurtaev/opencv_build/frames_pr
File Size                       : 3.8 MB
File Modification Date/Time     : 2025:09:02 20:48:22+03:00
File Access Date/Time           : 2025:09:02 20:48:22+03:00
File Inode Change Date/Time     : 2025:09:02 20:48:22+03:00
File Permissions                : -rw-r--r--
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 1080
Image Height                    : 1920
Bit Depth                       : 8
Color Type                      : RGB
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
Color Primaries                 : BT.2020, BT.2100
Transfer Characteristics        : BT.2100 HLG, ARIB STD-B67
Matrix Coefficients             : Identity matrix
Video Full Range Flag           : 1
Image Size                      : 1080x1920
Megapixels                      : 2.1
```

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [x] I agree to contribute to the project under Apache 2 License.
- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [x] The PR is proposed to the proper branch
- [x] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
Dmitry Kurtaev 2025-09-08 09:49:26 +03:00 committed by GitHub
parent e22c1065ec
commit 65cb3fd86c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
37 changed files with 615 additions and 565 deletions

View File

@ -6196,6 +6196,39 @@ Version 1.6.43 [February 23, 2024]
consistency verification and text linting.
Added version consistency verification to pngtest.c also.
Version 1.6.44 [September 12, 2024]
Hardened calculations in chroma handling to prevent overflows, and
relaxed a constraint in cHRM validation to accomodate the standard
ACES AP1 set of color primaries.
(Contributed by John Bowler)
Removed the ASM implementation of ARM Neon optimizations and updated
the build accordingly. Only the remaining C implementation shall be
used from now on, thus ensuring the support of the PAC/BTI security
features on ARM64.
(Contributed by Ross Burton and John Bowler)
Fixed the pickup of the PNG_HARDWARE_OPTIMIZATIONS option in the
CMake build on FreeBSD/amd64. This is an important performance fix
on this platform.
Applied various fixes and improvements to the CMake build.
(Contributed by Eric Riff, Benjamin Buch and Erik Scholz)
Added fuzzing targets for the simplified read API.
(Contributed by Mikhail Khachayants)
Fixed a build error involving pngtest.c under a custom config.
This was a regression introduced in a code cleanup in libpng-1.6.43.
(Contributed by Ben Wagner)
Fixed and improved the config files for AppVeyor CI and Travis CI.
Version 1.6.45 [January 7, 2025]
Added support for the cICP chunk.
(Contributed by Lucas Chollet and John Bowler)
Adjusted and improved various checks in colorspace calculations.
(Contributed by John Bowler)
Rearranged the write order of colorspace chunks for better conformance
with the PNG v3 draft specification.
(Contributed by John Bowler)
Raised the minimum required CMake version from 3.6 to 3.14.
Forked off a development branch for libpng version 1.8.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
Subscription is required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement

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,4 @@
README for libpng version 1.6.43
README for libpng version 1.6.45
================================
See the note about version numbers near the top of `png.h`.
@ -157,8 +157,6 @@ Files included in this distribution
"PNG: The Definitive Guide" by Greg Roelofs,
O'Reilly, 1999
libtests/ => Test programs
oss-fuzz/ => Files used by the OSS-Fuzz project for fuzz-testing
libpng
pngexif/ => Program to inspect the EXIF information in PNG files
pngminim/ => Minimal decoder, encoder, and progressive decoder
programs demonstrating the use of pngusr.dfa

View File

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

View File

@ -1,253 +1,60 @@
/* filter_neon.S - NEON optimised filter functions
/* filter_neon.S - placeholder file
*
* Copyright (c) 2018 Cosmin Truta
* Copyright (c) 2014,2017 Glenn Randers-Pehrson
* Written by Mans Rullgard, 2011.
* Copyright (c) 2024 Cosmin Truta
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* IMPORTANT NOTE:
*
* Historically, the hand-coded assembler implementation of Neon optimizations
* in this module had not been in sync with the intrinsics-based implementation
* in filter_neon_intrinsics.c and palette_neon_intrinsics.c, at least since
* the introduction of riffled palette optimizations. Moreover, the assembler
* code used to work on 32-bit ARM only, and it caused problems, even if empty,
* on 64-bit ARM.
*
* All references to this module from our internal build scripts and projects
* have been removed.
*
* For the external projects that might still expect this module to be present,
* we leave this stub in place, for the remaining lifetime of libpng-1.6.x.
* Everything should continue to function normally, as long as there are no
* deliberate attempts to use the old hand-made assembler code. A build error
* will be raised otherwise.
*/
/* This is required to get the symbol renames, which are #defines, and the
* definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION.
*/
#define PNG_VERSION_INFO_ONLY
#include "../pngpriv.h"
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */
#endif
#ifdef PNG_READ_SUPPORTED
/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for
* ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it
* only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h
* for the logic which sets PNG_USE_ARM_NEON_ASM:
*/
#if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */
#if PNG_ARM_NEON_OPT > 0
#ifdef __ELF__
# define ELF
#if defined(__clang__)
#define GNUC_VERSION 0 /* not gcc, although it might pretend to be */
#elif defined(__GNUC__)
#define GNUC_MAJOR (__GNUC__ + 0)
#define GNUC_MINOR (__GNUC_MINOR__ + 0)
#define GNUC_PATCHLEVEL (__GNUC_PATCHLEVEL__ + 0)
#define GNUC_VERSION (GNUC_MAJOR * 10000 + GNUC_MINOR * 100 + GNUC_PATCHLEVEL)
#else
# define ELF @
#define GNUC_VERSION 0 /* not gcc */
#endif
.arch armv7-a
.fpu neon
#if (GNUC_VERSION > 0) && (GNUC_VERSION < 40300)
#error "PNG_ARM_NEON is not supported with gcc versions earlier than 4.3.0"
#elif GNUC_VERSION == 40504
#error "PNG_ARM_NEON is not supported with gcc version 4.5.4"
#else
#error "Please use 'arm/*_neon_intrinsics.c' for PNG_ARM_NEON support"
#endif
.macro func name, export=0
.macro endfunc
ELF .size \name, . - \name
.endfunc
.purgem endfunc
.endm
.text
/* Explicitly specifying alignment here because some versions of
* GAS don't align code correctly. This is harmless in correctly
* written versions of GAS.
*/
.align 2
.if \export
.global \name
.endif
ELF .type \name, STT_FUNC
.func \name
\name:
.endm
func png_read_filter_row_sub4_neon, export=1
ldr r3, [r0, #4] @ rowbytes
vmov.i8 d3, #0
1:
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
vadd.u8 d0, d3, d4
vadd.u8 d1, d0, d5
vadd.u8 d2, d1, d6
vadd.u8 d3, d2, d7
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
subs r3, r3, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_sub3_neon, export=1
ldr r3, [r0, #4] @ rowbytes
vmov.i8 d3, #0
mov r0, r1
mov r2, #3
mov r12, #12
vld1.8 {q11}, [r0], r12
1:
vext.8 d5, d22, d23, #3
vadd.u8 d0, d3, d22
vext.8 d6, d22, d23, #6
vadd.u8 d1, d0, d5
vext.8 d7, d23, d23, #1
vld1.8 {q11}, [r0], r12
vst1.32 {d0[0]}, [r1,:32], r2
vadd.u8 d2, d1, d6
vst1.32 {d1[0]}, [r1], r2
vadd.u8 d3, d2, d7
vst1.32 {d2[0]}, [r1], r2
vst1.32 {d3[0]}, [r1], r2
subs r3, r3, #12
bgt 1b
bx lr
endfunc
func png_read_filter_row_up_neon, export=1
ldr r3, [r0, #4] @ rowbytes
1:
vld1.8 {q0}, [r1,:128]
vld1.8 {q1}, [r2,:128]!
vadd.u8 q0, q0, q1
vst1.8 {q0}, [r1,:128]!
subs r3, r3, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_avg4_neon, export=1
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
1:
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
vhadd.u8 d0, d3, d16
vadd.u8 d0, d0, d4
vhadd.u8 d1, d0, d17
vadd.u8 d1, d1, d5
vhadd.u8 d2, d1, d18
vadd.u8 d2, d2, d6
vhadd.u8 d3, d2, d19
vadd.u8 d3, d3, d7
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
subs r12, r12, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_avg3_neon, export=1
push {r4,lr}
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
mov r0, r1
mov r4, #3
mov lr, #12
vld1.8 {q11}, [r0], lr
1:
vld1.8 {q10}, [r2], lr
vext.8 d5, d22, d23, #3
vhadd.u8 d0, d3, d20
vext.8 d17, d20, d21, #3
vadd.u8 d0, d0, d22
vext.8 d6, d22, d23, #6
vhadd.u8 d1, d0, d17
vext.8 d18, d20, d21, #6
vadd.u8 d1, d1, d5
vext.8 d7, d23, d23, #1
vld1.8 {q11}, [r0], lr
vst1.32 {d0[0]}, [r1,:32], r4
vhadd.u8 d2, d1, d18
vst1.32 {d1[0]}, [r1], r4
vext.8 d19, d21, d21, #1
vadd.u8 d2, d2, d6
vhadd.u8 d3, d2, d19
vst1.32 {d2[0]}, [r1], r4
vadd.u8 d3, d3, d7
vst1.32 {d3[0]}, [r1], r4
subs r12, r12, #12
bgt 1b
pop {r4,pc}
endfunc
.macro paeth rx, ra, rb, rc
vaddl.u8 q12, \ra, \rb @ a + b
vaddl.u8 q15, \rc, \rc @ 2*c
vabdl.u8 q13, \rb, \rc @ pa
vabdl.u8 q14, \ra, \rc @ pb
vabd.u16 q15, q12, q15 @ pc
vcle.u16 q12, q13, q14 @ pa <= pb
vcle.u16 q13, q13, q15 @ pa <= pc
vcle.u16 q14, q14, q15 @ pb <= pc
vand q12, q12, q13 @ pa <= pb && pa <= pc
vmovn.u16 d28, q14
vmovn.u16 \rx, q12
vbsl d28, \rb, \rc
vbsl \rx, \ra, d28
.endm
func png_read_filter_row_paeth4_neon, export=1
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
vmov.i8 d20, #0
1:
vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128]
vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]!
paeth d0, d3, d16, d20
vadd.u8 d0, d0, d4
paeth d1, d0, d17, d16
vadd.u8 d1, d1, d5
paeth d2, d1, d18, d17
vadd.u8 d2, d2, d6
paeth d3, d2, d19, d18
vmov d20, d19
vadd.u8 d3, d3, d7
vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]!
subs r12, r12, #16
bgt 1b
bx lr
endfunc
func png_read_filter_row_paeth3_neon, export=1
push {r4,lr}
ldr r12, [r0, #4] @ rowbytes
vmov.i8 d3, #0
vmov.i8 d4, #0
mov r0, r1
mov r4, #3
mov lr, #12
vld1.8 {q11}, [r0], lr
1:
vld1.8 {q10}, [r2], lr
paeth d0, d3, d20, d4
vext.8 d5, d22, d23, #3
vadd.u8 d0, d0, d22
vext.8 d17, d20, d21, #3
paeth d1, d0, d17, d20
vst1.32 {d0[0]}, [r1,:32], r4
vext.8 d6, d22, d23, #6
vadd.u8 d1, d1, d5
vext.8 d18, d20, d21, #6
paeth d2, d1, d18, d17
vext.8 d7, d23, d23, #1
vld1.8 {q11}, [r0], lr
vst1.32 {d1[0]}, [r1], r4
vadd.u8 d2, d2, d6
vext.8 d19, d21, d21, #1
paeth d3, d2, d19, d18
vst1.32 {d2[0]}, [r1], r4
vmov d4, d19
vadd.u8 d3, d3, d7
vst1.32 {d3[0]}, [r1], r4
subs r12, r12, #12
bgt 1b
pop {r4,pc}
endfunc
#endif /* PNG_ARM_NEON_OPT > 0 */
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */
#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 */
#endif /* READ */

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

@ -1,4 +1,3 @@
/* filter_msa_intrinsics.c - MSA optimised filter functions
*
* Copyright (c) 2018-2024 Cosmin Truta
@ -47,7 +46,7 @@
uint8_t *psrc_lw_m = (uint8_t *) (psrc); \
uint32_t val_m; \
\
asm volatile ( \
__asm__ volatile ( \
"lw %[val_m], %[psrc_lw_m] \n\t" \
\
: [val_m] "=r" (val_m) \
@ -62,7 +61,7 @@
uint8_t *pdst_sh_m = (uint8_t *) (pdst); \
uint16_t val_m = (val); \
\
asm volatile ( \
__asm__ volatile ( \
"sh %[val_m], %[pdst_sh_m] \n\t" \
\
: [pdst_sh_m] "=m" (*pdst_sh_m) \
@ -75,7 +74,7 @@
uint8_t *pdst_sw_m = (uint8_t *) (pdst); \
uint32_t val_m = (val); \
\
asm volatile ( \
__asm__ volatile ( \
"sw %[val_m], %[pdst_sw_m] \n\t" \
\
: [pdst_sw_m] "=m" (*pdst_sw_m) \
@ -83,20 +82,20 @@
); \
}
#if (__mips == 64)
#if __mips == 64
#define SD(val, pdst) \
{ \
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
uint64_t val_m = (val); \
\
asm volatile ( \
__asm__ volatile ( \
"sd %[val_m], %[pdst_sd_m] \n\t" \
\
: [pdst_sd_m] "=m" (*pdst_sd_m) \
: [val_m] "r" (val_m) \
); \
}
#else
#else
#define SD(val, pdst) \
{ \
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
@ -108,17 +107,17 @@
SW(val0_m, pdst_sd_m); \
SW(val1_m, pdst_sd_m + 4); \
}
#endif
#endif /* __mips == 64 */
#else
#define MSA_SRLI_B(a, b) (a >> b)
#if (__mips_isa_rev >= 6)
#if __mips_isa_rev >= 6
#define LW(psrc) \
( { \
uint8_t *psrc_lw_m = (uint8_t *) (psrc); \
uint32_t val_m; \
\
asm volatile ( \
__asm__ volatile ( \
"lw %[val_m], %[psrc_lw_m] \n\t" \
\
: [val_m] "=r" (val_m) \
@ -133,7 +132,7 @@
uint8_t *pdst_sh_m = (uint8_t *) (pdst); \
uint16_t val_m = (val); \
\
asm volatile ( \
__asm__ volatile ( \
"sh %[val_m], %[pdst_sh_m] \n\t" \
\
: [pdst_sh_m] "=m" (*pdst_sh_m) \
@ -146,7 +145,7 @@
uint8_t *pdst_sw_m = (uint8_t *) (pdst); \
uint32_t val_m = (val); \
\
asm volatile ( \
__asm__ volatile ( \
"sw %[val_m], %[pdst_sw_m] \n\t" \
\
: [pdst_sw_m] "=m" (*pdst_sw_m) \
@ -154,20 +153,20 @@
); \
}
#if (__mips == 64)
#if __mips == 64
#define SD(val, pdst) \
{ \
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
uint64_t val_m = (val); \
\
asm volatile ( \
__asm__ volatile ( \
"sd %[val_m], %[pdst_sd_m] \n\t" \
\
: [pdst_sd_m] "=m" (*pdst_sd_m) \
: [val_m] "r" (val_m) \
); \
}
#else
#else
#define SD(val, pdst) \
{ \
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
@ -179,14 +178,14 @@
SW(val0_m, pdst_sd_m); \
SW(val1_m, pdst_sd_m + 4); \
}
#endif
#else // !(__mips_isa_rev >= 6)
#endif /* __mips == 64 */
#else
#define LW(psrc) \
( { \
uint8_t *psrc_lw_m = (uint8_t *) (psrc); \
uint32_t val_m; \
\
asm volatile ( \
__asm__ volatile ( \
"ulw %[val_m], %[psrc_lw_m] \n\t" \
\
: [val_m] "=r" (val_m) \
@ -201,7 +200,7 @@
uint8_t *pdst_sh_m = (uint8_t *) (pdst); \
uint16_t val_m = (val); \
\
asm volatile ( \
__asm__ volatile ( \
"ush %[val_m], %[pdst_sh_m] \n\t" \
\
: [pdst_sh_m] "=m" (*pdst_sh_m) \
@ -214,7 +213,7 @@
uint8_t *pdst_sw_m = (uint8_t *) (pdst); \
uint32_t val_m = (val); \
\
asm volatile ( \
__asm__ volatile ( \
"usw %[val_m], %[pdst_sw_m] \n\t" \
\
: [pdst_sw_m] "=m" (*pdst_sw_m) \
@ -222,7 +221,7 @@
); \
}
#define SD(val, pdst) \
#define SD(val, pdst) \
{ \
uint8_t *pdst_sd_m = (uint8_t *) (pdst); \
uint32_t val0_m, val1_m; \
@ -238,14 +237,14 @@
{ \
uint8_t *pdst_m = (uint8_t *) (pdst); \
\
asm volatile ( \
__asm__ volatile ( \
"usw $0, %[pdst_m] \n\t" \
\
: [pdst_m] "=m" (*pdst_m) \
: \
); \
}
#endif // (__mips_isa_rev >= 6)
#endif /* __mips_isa_rev >= 6 */
#endif
#define LD_B(RTYPE, psrc) *((RTYPE *) (psrc))

View File

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

268
3rdparty/libpng/png.c vendored
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_43 Your_png_h_is_not_version_1_6_43;
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.43" 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,6 +1202,68 @@ png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
#endif /* GAMMA */
#ifdef PNG_COLORSPACE_SUPPORTED
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.
*/
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
* cHRM, as opposed to using chromaticities. These internal APIs return
* non-zero on a parameter error. The X, Y and Z values are required to be
@ -1211,38 +1272,60 @@ png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
static int
png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
{
png_int_32 d, dwhite, whiteX, whiteY;
png_int_32 d, dred, dgreen, dblue, dwhite, whiteX, whiteY;
d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
/* 'd' in each of the blocks below is just X+Y+Z for each component,
* x, y and z are X,Y,Z/(X+Y+Z).
*/
d = XYZ->red_X;
if (png_safe_add(&d, XYZ->red_Y, XYZ->red_Z))
return 1;
if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
dred = d;
if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, dred) == 0)
return 1;
if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, dred) == 0)
return 1;
d = XYZ->green_X;
if (png_safe_add(&d, XYZ->green_Y, XYZ->green_Z))
return 1;
dgreen = d;
if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, dgreen) == 0)
return 1;
if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, dgreen) == 0)
return 1;
d = XYZ->blue_X;
if (png_safe_add(&d, XYZ->blue_Y, XYZ->blue_Z))
return 1;
dblue = d;
if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, dblue) == 0)
return 1;
if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, dblue) == 0)
return 1;
/* 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;
whiteX = XYZ->red_X;
whiteY = XYZ->red_Y;
d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
return 1;
if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
return 1;
dwhite += d;
whiteX += XYZ->green_X;
whiteY += XYZ->green_Y;
d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
return 1;
if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
return 1;
dwhite += d;
whiteX += XYZ->blue_X;
whiteY += XYZ->blue_Y;
/* The reference white is simply the sum of the end-point (X,Y,Z) vectors,
* thus:
/* 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)
@ -1261,15 +1344,24 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
* have end points with 0 tristimulus values (these are impossible end
* points, but they are used to cover the possible colors). We check
* xy->whitey against 5, not 0, to avoid a possible integer overflow.
*
* The limits here will *not* accept ACES AP0, where bluey is -7700
* (-0.0770) because the PNG spec itself requires the xy values to be
* unsigned. whitey is also required to be 5 or more to avoid overflow.
*
* Instead the upper limits have been relaxed to 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.
*/
if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1;
if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1;
if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
const png_fixed_point fpLimit = PNG_FP_1+(PNG_FP_1/10);
if (xy->redx < 0 || xy->redx > fpLimit) return 1;
if (xy->redy < 0 || xy->redy > fpLimit-xy->redx) return 1;
if (xy->greenx < 0 || xy->greenx > fpLimit) return 1;
if (xy->greeny < 0 || xy->greeny > fpLimit-xy->greenx) return 1;
if (xy->bluex < 0 || xy->bluex > fpLimit) return 1;
if (xy->bluey < 0 || xy->bluey > fpLimit-xy->bluex) return 1;
if (xy->whitex < 0 || xy->whitex > fpLimit) return 1;
if (xy->whitey < 5 || xy->whitey > fpLimit-xy->whitex) return 1;
/* The reverse calculation is more difficult because the original tristimulus
* value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
@ -1414,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
@ -1447,49 +1544,61 @@ 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)
return 2;
if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
return 2;
denominator = left - right;
if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 8) == 0)
return 1;
if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 8) == 0)
return 1;
denominator = png_fp_sub(left, right, &error);
if (error) return 1;
/* Now find the red numerator. */
if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
return 2;
if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
return 2;
if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 8) == 0)
return 1;
if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 8) == 0)
return 1;
/* Overflow is possible here and it indicates an extreme set of PNG cHRM
* chunk values. This calculation actually returns the reciprocal of the
* scale value because this allows us to delay the multiplication of white-y
* into the denominator, which tends to produce a small number.
*/
if (png_muldiv(&red_inverse, xy->whitey, denominator, 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)
return 2;
if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
return 2;
if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 8) == 0)
return 1;
if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 8) == 0)
return 1;
if (png_muldiv(&green_inverse, xy->whitey, denominator,
png_fp_sub(left, right, &error)) == 0 || error ||
green_inverse <= xy->whitey)
return 1;
/* And the blue scale, the checks above guarantee this can't overflow but it
* can still produce 0 for extreme cHRM values.
*/
blue_scale = png_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)
@ -1520,25 +1629,14 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
static int
png_XYZ_normalize(png_XYZ *XYZ)
{
png_int_32 Y;
png_int_32 Y, Ytemp;
if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
/* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. */
Ytemp = XYZ->red_Y;
if (png_safe_add(&Ytemp, XYZ->green_Y, XYZ->blue_Y))
return 1;
/* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
* IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
* relying on addition of two positive values producing a negative one is not
* safe.
*/
Y = XYZ->red_Y;
if (0x7fffffff - Y < XYZ->green_X)
return 1;
Y += XYZ->green_Y;
if (0x7fffffff - Y < XYZ->blue_X)
return 1;
Y += XYZ->blue_Y;
Y = Ytemp;
if (Y != PNG_FP_1)
{

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

@ -1,9 +1,8 @@
/* png.h - header file for PNG reference library
*
* libpng version 1.6.43
* 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.43, February 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.43 16 10643 16.so.16.43[.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.43"
#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,18 +285,18 @@
/* 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 43
#define PNG_LIBPNG_VER_RELEASE 45
/* This should be zero for a public release, or non-zero for a
* development version.
*/
#define PNG_LIBPNG_VER_BUILD 0
#define PNG_LIBPNG_VER_BUILD 0
/* Release Status */
#define PNG_LIBPNG_BUILD_ALPHA 1
#define PNG_LIBPNG_BUILD_BETA 2
#define PNG_LIBPNG_BUILD_RC 3
#define PNG_LIBPNG_BUILD_STABLE 4
#define PNG_LIBPNG_BUILD_ALPHA 1
#define PNG_LIBPNG_BUILD_BETA 2
#define PNG_LIBPNG_BUILD_RC 3
#define PNG_LIBPNG_BUILD_STABLE 4
#define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7
/* Release-Specific Flags */
@ -317,7 +316,7 @@
* From version 1.0.1 it is:
* XXYYZZ, where XX=major, YY=minor, ZZ=release
*/
#define PNG_LIBPNG_VER 10643 /* 1.6.43 */
#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_43;
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
@ -824,7 +824,7 @@ typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp,
* your compiler. This may be very difficult - try using a different compiler
* to build the library!
*/
PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef);
PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), (jmp_buf, int), typedef);
#endif
/* Transform masks for the high-level interface */
@ -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.43
* 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.
@ -88,7 +87,7 @@
/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect
* against legacy (pre ISOC90) compilers that did not understand function
* prototypes. It is not required for modern C compilers.
* prototypes. [Deprecated.]
*/
#ifndef PNGARG
# define PNGARG(arglist) arglist
@ -298,7 +297,7 @@
#ifndef PNG_EXPORTA
# define PNG_EXPORTA(ordinal, type, name, args, attributes) \
PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \
PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), args, \
PNG_LINKAGE_API attributes)
#endif
@ -316,7 +315,7 @@
#endif
#ifndef PNG_CALLBACK
# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args)
# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) args
#endif
/* Support for compiler specific function attributes. These are used

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
@ -20,13 +19,14 @@
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr,
png_const_charp error_message)),PNG_NORETURN);
static PNG_FUNCTION(void /* PRIVATE */,
png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN);
#ifdef PNG_WARNINGS_SUPPORTED
static void /* PRIVATE */
png_default_warning PNGARG((png_const_structrp png_ptr,
png_const_charp warning_message));
png_default_warning(png_const_structrp png_ptr,
png_const_charp warning_message);
#endif /* WARNINGS */
/* This function is called whenever there is a fatal error. This function

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.37 */
/* libpng version 1.6.45 */
/* Copyright (c) 2018-2019 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. */
@ -27,6 +27,7 @@
#define PNG_COLORSPACE_SUPPORTED
#define PNG_CONSOLE_IO_SUPPORTED
#define PNG_CONVERT_tIME_SUPPORTED
/*#undef PNG_DISABLE_ADLER32_CHECK_SUPPORTED*/
#define PNG_EASY_ACCESS_SUPPORTED
/*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
#define PNG_ERROR_TEXT_SUPPORTED
@ -41,6 +42,10 @@
#define PNG_INCH_CONVERSIONS_SUPPORTED
#define PNG_INFO_IMAGE_SUPPORTED
#define PNG_IO_STATE_SUPPORTED
/*#undef PNG_MIPS_MMI_API_SUPPORTED*/
/*#undef PNG_MIPS_MMI_CHECK_SUPPORTED*/
/*#undef PNG_MIPS_MSA_API_SUPPORTED*/
/*#undef PNG_MIPS_MSA_CHECK_SUPPORTED*/
#define PNG_MNG_FEATURES_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED
/*#undef PNG_POWERPC_VSX_API_SUPPORTED*/
@ -83,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
@ -153,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
@ -171,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
@ -140,47 +139,6 @@
* callbacks to do this.
*/
# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon
/* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used
* if possible - if __ARM_NEON__ is set and the compiler version is not known
* to be broken. This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can
* be:
*
* 1 The intrinsics code (the default with __ARM_NEON__)
* 2 The hand coded assembler (the default without __ARM_NEON__)
*
* It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however
* this is *NOT* supported and may cease to work even after a minor revision
* to libpng. It *is* valid to do this for testing purposes, e.g. speed
* testing or a new compiler, but the results should be communicated to the
* libpng implementation list for incorporation in the next minor release.
*/
# ifndef PNG_ARM_NEON_IMPLEMENTATION
# if defined(__ARM_NEON__) || defined(__ARM_NEON)
# if defined(__clang__)
/* At present it is unknown by the libpng developers which versions
* of clang support the intrinsics, however some or perhaps all
* versions do not work with the assembler so this may be
* irrelevant, so just use the default (do nothing here.)
*/
# elif defined(__GNUC__)
/* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to
* work, so if this *is* GCC, or G++, look for a version >4.5
*/
# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
# define PNG_ARM_NEON_IMPLEMENTATION 2
# endif /* no GNUC support */
# endif /* __GNUC__ */
# else /* !defined __ARM_NEON__ */
/* The 'intrinsics' code simply won't compile without this -mfpu=neon:
*/
# if !defined(__aarch64__) && !defined(_M_ARM64)
/* The assembler code currently does not work on ARM64 */
# define PNG_ARM_NEON_IMPLEMENTATION 2
# endif /* __aarch64__ */
# endif /* __ARM_NEON__ */
# endif /* !PNG_ARM_NEON_IMPLEMENTATION */
# ifndef PNG_ARM_NEON_IMPLEMENTATION
/* Use the intrinsics code by default. */
# define PNG_ARM_NEON_IMPLEMENTATION 1
@ -876,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)
@ -1172,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);
@ -1515,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

View File

@ -264,8 +264,9 @@ enum ImageMetadataType
IMAGE_METADATA_EXIF = 0, // EXIF metadata (e.g., camera info, GPS, orientation)
IMAGE_METADATA_XMP = 1, // XMP metadata (eXtensible Metadata Platform - Adobe format)
IMAGE_METADATA_ICCP = 2, // ICC Profile (color profile for color management)
IMAGE_METADATA_CICP = 3, // cICP Profile (video signal type)
IMAGE_METADATA_MAX = 2 // Highest valid index (usually used for bounds checking)
IMAGE_METADATA_MAX = 3 // Highest valid index (usually used for bounds checking)
};
//! @} imgcodecs_flags

View File

@ -901,6 +901,7 @@ PngEncoder::PngEncoder()
m_support_metadata[IMAGE_METADATA_EXIF] = true;
m_support_metadata[IMAGE_METADATA_XMP] = true;
m_support_metadata[IMAGE_METADATA_ICCP] = true;
m_support_metadata[IMAGE_METADATA_CICP] = true;
op_zstream1.zalloc = NULL;
op_zstream2.zalloc = NULL;
next_seq_num = 0;
@ -1116,6 +1117,16 @@ bool PngEncoder::write( const Mat& img, const std::vector<int>& params )
#endif
static_cast<png_uint_32>(iccp.size()));
}
std::vector<uchar>& cicp = m_metadata[IMAGE_METADATA_CICP];
if (!cicp.empty()) {
#ifdef PNG_cICP_SUPPORTED
CV_CheckEQ((size_t)4, cicp.size(), "The cICP chunk consists of four 1-byte unsigned integers");
png_set_cICP(png_ptr, info_ptr, cicp[0], cicp[1], cicp[2], cicp[3]);
#else
CV_LOG_WARNING(NULL, "Libpng is too old and does not support cICP.");
#endif
}
}
png_write_info( png_ptr, info_ptr );

View File

@ -686,7 +686,7 @@ void CvCapture_FFMPEG::close()
{
#ifdef CV_FFMPEG_CODECPAR
// avcodec_close removed in FFmpeg release 8.0
# if (LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(62, 11, 100))
# if (LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(61, 9, 108))
avcodec_close( context );
# endif
#endif
@ -1719,7 +1719,16 @@ bool CvCapture_FFMPEG::retrieveFrame(int flag, unsigned char** data, int* step,
if (!sw_picture || !sw_picture->data[0])
return false;
CV_LOG_DEBUG(NULL, "Input picture format: " << av_get_pix_fmt_name((AVPixelFormat)sw_picture->format));
CV_LOG_DEBUG(NULL, "Input picture format: " << av_get_pix_fmt_name((AVPixelFormat)sw_picture->format) << ", colorspace: "
#if LIBAVUTIL_BUILD >= CALC_FFMPEG_VERSION(56, 72, 0)
<< av_color_space_name(sw_picture->colorspace)
#else
<< av_get_colorspace_name(sw_picture->colorspace)
#endif
<< ", range: " << av_color_range_name(sw_picture->color_range)
<< ", primaries: " << av_color_primaries_name(sw_picture->color_primaries)
<< ", transfer: " << av_color_transfer_name(sw_picture->color_trc)
);
const AVPixelFormat result_format = convertRGB ? AV_PIX_FMT_BGR24 : (AVPixelFormat)sw_picture->format;
switch (result_format)
{
@ -2009,7 +2018,7 @@ void CvCapture_FFMPEG::get_rotation_angle()
#if LIBAVFORMAT_BUILD >= CALC_FFMPEG_VERSION(57, 68, 100)
const uint8_t *data = 0;
// av_stream_get_side_data removed in FFmpeg release 8.0
# if (LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(62, 11, 100))
# if (LIBAVCODEC_BUILD < CALC_FFMPEG_VERSION(61, 9, 108))
data = av_stream_get_side_data(video_st, AV_PKT_DATA_DISPLAYMATRIX, NULL);
# else
AVPacketSideData* sd = video_st->codecpar->coded_side_data;