mirror of
https://github.com/glennrp/libpng.git
synced 2025-04-19 08:22:16 +03:00
[libpng16] Add support for reading and writing the cICP chunk
This chunk was added in the third edition of the PNG specification and contains Coding Independent Code Points (related to color space description). It is fairly simple as it only contains four fields of one byte each: Colour Primaries, Transfer Function, Matrix Coefficients, Video Full Range Flag. The test file originally comes from the related WPT test case: https://github.com/web-platform-tests/wpt/blob/master/png/support/cicp-display-p3.png Note that I reencoded the file to make it match libpng's default encoding parameters (it only modifies the IDAT chunk). This is a cherry-pick of commit 65925ad4b2cbed934d5d850fe764dc46c4becbcb from branch 'libpng18'. Reviewed-by: John Bowler <jbowler@acm.org> Reviewed-by: Chris Blume <ProgramMax@gmail.com> Reviewed-by: Cosmin Truta <ctruta@gmail.com> Signed-off-by: Cosmin Truta <ctruta@gmail.com>
This commit is contained in:
parent
6f786ff0f6
commit
75748d93ce
1
AUTHORS
1
AUTHORS
@ -17,6 +17,7 @@ Authors, for copyright and licensing purposes.
|
||||
* James Yu
|
||||
* John Bowler
|
||||
* Kevin Bracey
|
||||
* Lucas Chollet
|
||||
* Magnus Holmgren
|
||||
* Mandar Sahastrabuddhe
|
||||
* Mans Rullgard
|
||||
|
@ -814,6 +814,10 @@ if(PNG_TESTS AND PNG_SHARED)
|
||||
COMMAND pngtest
|
||||
FILES "${PNGTEST_PNG}")
|
||||
|
||||
png_add_test(NAME pngtest-cicp
|
||||
COMMAND pngtest
|
||||
FILES "${CMAKE_CURRENT_SOURCE_DIR}/cicp-display-p3_reencoded.png")
|
||||
|
||||
add_executable(pngvalid ${pngvalid_sources})
|
||||
target_link_libraries(pngvalid PRIVATE png_shared)
|
||||
|
||||
|
BIN
cicp-display-p3_reencoded.png
Normal file
BIN
cicp-display-p3_reencoded.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 142 B |
14
png.h
14
png.h
@ -744,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
|
||||
@ -1973,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));
|
||||
@ -3237,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
|
||||
|
25
pngget.c
25
pngget.c
@ -784,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,
|
||||
|
@ -100,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 */
|
||||
|
@ -308,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)
|
||||
|
12
pngpriv.h
12
pngpriv.h
@ -834,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)
|
||||
@ -1130,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);
|
||||
@ -1473,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);
|
||||
|
@ -173,6 +173,10 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
|
||||
else if (chunk_name == png_cHRM)
|
||||
png_handle_cHRM(png_ptr, info_ptr, length);
|
||||
#endif
|
||||
#ifdef PNG_READ_cICP_SUPPORTED
|
||||
else if (chunk_name == png_cICP)
|
||||
png_handle_cICP(png_ptr, info_ptr, length);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_eXIf_SUPPORTED
|
||||
else if (chunk_name == png_eXIf)
|
||||
|
37
pngrutil.c
37
pngrutil.c
@ -2046,6 +2046,43 @@ 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 (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cICP) != 0)
|
||||
{
|
||||
png_crc_finish(png_ptr, length);
|
||||
png_chunk_benign_error(png_ptr, "duplicate");
|
||||
return;
|
||||
}
|
||||
|
||||
if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
|
||||
png_ptr->mode |= PNG_AFTER_IDAT;
|
||||
|
||||
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)
|
||||
|
20
pngset.c
20
pngset.c
@ -133,6 +133,26 @@ 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;
|
||||
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,
|
||||
|
17
pngtest.c
17
pngtest.c
@ -1205,6 +1205,23 @@ test_one_file(const char *inname, const char *outname)
|
||||
png_set_bKGD(write_ptr, write_info_ptr, background);
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_cICP_SUPPORTED
|
||||
{
|
||||
png_byte colour_primaries;
|
||||
png_byte transfer_function;
|
||||
png_byte matrix_coefficients;
|
||||
png_byte video_full_range_flag;
|
||||
|
||||
if (png_get_cICP(read_ptr, read_info_ptr, &colour_primaries,
|
||||
&transfer_function, &matrix_coefficients,
|
||||
&video_full_range_flag) != 0)
|
||||
#ifdef PNG_WRITE_cICP_SUPPORTED
|
||||
png_set_cICP(write_ptr, write_info_ptr, colour_primaries,
|
||||
transfer_function, matrix_coefficients,
|
||||
video_full_range_flag);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_READ_eXIf_SUPPORTED
|
||||
{
|
||||
png_bytep exif = NULL;
|
||||
|
10
pngwrite.c
10
pngwrite.c
@ -236,6 +236,16 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
|
||||
png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_cICP_SUPPORTED
|
||||
if ((info_ptr->valid & PNG_INFO_cICP) != 0)
|
||||
{
|
||||
png_write_cICP(png_ptr, info_ptr->cicp_colour_primaries,
|
||||
info_ptr->cicp_transfer_function,
|
||||
info_ptr->cicp_matrix_coefficients,
|
||||
info_ptr->cicp_video_full_range_flag);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_eXIf_SUPPORTED
|
||||
if ((info_ptr->valid & PNG_INFO_eXIf) != 0)
|
||||
{
|
||||
|
20
pngwutil.c
20
pngwutil.c
@ -1488,6 +1488,26 @@ 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_debug(1, "in png_write_cICP");
|
||||
|
||||
png_write_chunk_header(png_ptr, png_cICP, 4);
|
||||
|
||||
png_write_chunk_data(png_ptr, &colour_primaries, 1);
|
||||
png_write_chunk_data(png_ptr, &transfer_function, 1);
|
||||
png_write_chunk_data(png_ptr, &matrix_coefficients, 1);
|
||||
png_write_chunk_data(png_ptr, &video_full_range_flag, 1);
|
||||
|
||||
png_write_chunk_end(png_ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_eXIf_SUPPORTED
|
||||
/* Write the Exif data */
|
||||
void /* PRIVATE */
|
||||
|
@ -846,6 +846,7 @@ setting IDAT_READ_SIZE default PNG_ZBUF_SIZE
|
||||
# Ancillary chunks
|
||||
chunk bKGD
|
||||
chunk cHRM enables COLORSPACE
|
||||
chunk cICP
|
||||
chunk eXIf
|
||||
chunk gAMA enables GAMMA
|
||||
chunk hIST
|
||||
|
@ -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
|
||||
|
@ -253,3 +253,5 @@ EXPORTS
|
||||
png_set_eXIf @247
|
||||
png_get_eXIf_1 @248
|
||||
png_set_eXIf_1 @249
|
||||
png_get_cICP @250
|
||||
png_set_cICP @251
|
||||
|
Loading…
x
Reference in New Issue
Block a user