mirror of
https://github.com/glennrp/libpng.git
synced 2025-04-19 08:22:16 +03:00
api(PNGv3): Add support for mDCV and cLLI
This adds APIs to get/set the two remaining new PNG-v3 colour space chunks. The mDCV API matches that of cHRM. Both chunks support floating point APIs (all values in the two chunks are real numbers). Both chunks have a new encoded type, a four-digit-precision fixed-point number, which cannot be represented in the existing `png_fixed_point` type, so a `png_uint_32` is used. Test examples for cICP, cLLI and mDCV are now in pngtest.png, and a necessary change to the pngunknown.c test program has been made to accomodate the additions. Reviewed-by: Cosmin Truta <ctruta@gmail.com> Signed-off-by: John Bowler <jbowler@acm.org> Signed-off-by: Cosmin Truta <ctruta@gmail.com>
This commit is contained in:
parent
8ffc967e8a
commit
92e8581f12
@ -113,6 +113,8 @@ typedef png_byte *png_const_bytep;
|
||||
#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) /* PNGv3 */
|
||||
#define png_cLLI PNG_U32( 99, 76, 76, 73) /* PNGv3 */
|
||||
#define png_eXIf PNG_U32(101, 88, 73, 102) /* registered July 2017 */
|
||||
#define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */
|
||||
#define png_gAMA PNG_U32(103, 65, 77, 65)
|
||||
@ -122,6 +124,7 @@ typedef png_byte *png_const_bytep;
|
||||
#define png_hIST PNG_U32(104, 73, 83, 84)
|
||||
#define png_iCCP PNG_U32(105, 67, 67, 80)
|
||||
#define png_iTXt PNG_U32(105, 84, 88, 116)
|
||||
#define png_mDCV PNG_U32(109, 68, 67, 86) /* PNGv3 */
|
||||
#define png_oFFs PNG_U32(111, 70, 70, 115)
|
||||
#define png_pCAL PNG_U32(112, 67, 65, 76)
|
||||
#define png_pHYs PNG_U32(112, 72, 89, 115)
|
||||
@ -208,6 +211,20 @@ static struct
|
||||
0,
|
||||
# else
|
||||
1,
|
||||
# endif
|
||||
1, START, 0 },
|
||||
{ "cICP", PNG_INFO_cICP, png_cICP,
|
||||
# ifdef PNG_READ_cICP_SUPPORTED
|
||||
0,
|
||||
# else
|
||||
1,
|
||||
# endif
|
||||
1, START, 0 },
|
||||
{ "cLLI", PNG_INFO_cLLI, png_cLLI,
|
||||
# ifdef PNG_READ_cLLI_SUPPORTED
|
||||
0,
|
||||
# else
|
||||
1,
|
||||
# endif
|
||||
1, START, 0 },
|
||||
{ "eXIf", PNG_INFO_eXIf, png_eXIf,
|
||||
@ -245,6 +262,13 @@ static struct
|
||||
1,
|
||||
# endif
|
||||
1, ABSENT, 0 },
|
||||
{ "mDCV", PNG_INFO_mDCV, png_mDCV,
|
||||
# ifdef PNG_READ_mDCV_SUPPORTED
|
||||
0,
|
||||
# else
|
||||
1,
|
||||
# endif
|
||||
1, START, 0 },
|
||||
{ "oFFs", PNG_INFO_oFFs, png_oFFs,
|
||||
# ifdef PNG_READ_oFFs_SUPPORTED
|
||||
0,
|
||||
|
20
png.c
20
png.c
@ -3390,6 +3390,26 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
|
||||
!defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
|
||||
(defined(PNG_cLLI_SUPPORTED) || defined(PNG_mDCV_SUPPORTED))
|
||||
png_uint_32
|
||||
png_fixed_ITU(png_const_structrp png_ptr, double fp, png_const_charp text)
|
||||
{
|
||||
double r = floor(10000 * fp + .5);
|
||||
|
||||
if (r > 2147483647. || r < 0)
|
||||
png_fixed_error(png_ptr, text);
|
||||
|
||||
# ifndef PNG_ERROR_TEXT_SUPPORTED
|
||||
PNG_UNUSED(text)
|
||||
# endif
|
||||
|
||||
return (png_uint_32)r;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\
|
||||
defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
|
||||
/* muldiv functions */
|
||||
|
101
png.h
101
png.h
@ -744,7 +744,21 @@ typedef png_unknown_chunk * * png_unknown_chunkpp;
|
||||
#define PNG_INFO_sCAL 0x4000U /* ESR, 1.0.6 */
|
||||
#define PNG_INFO_IDAT 0x8000U /* ESR, 1.0.6 */
|
||||
#define PNG_INFO_eXIf 0x10000U /* GR-P, 1.6.31 */
|
||||
#define PNG_INFO_cICP 0x20000U
|
||||
#define PNG_INFO_cICP 0x20000U /* PNGv3: 1.6.45 */
|
||||
#define PNG_INFO_cLLI 0x40000U /* PNGv3: 1.6.45 */
|
||||
#define PNG_INFO_mDCV 0x80000U /* PNGv3: 1.6.45 */
|
||||
/* APNG: these chunks are stored as unknown, these flags are never set
|
||||
* however they are provided as a convenience for implementors of APNG and
|
||||
* avoids any merge conflicts.
|
||||
*
|
||||
* Private chunks: these chunk names violate the chunk name recommendations
|
||||
* because the chunk definitions have no signature and because the private
|
||||
* chunks with these names have been reserved. Private definitions should
|
||||
* avoid them.
|
||||
*/
|
||||
#define PNG_INFO_acTL 0x100000U /* PNGv3: 1.6.45: unknown */
|
||||
#define PNG_INFO_fcTL 0x200000U /* PNGv3: 1.6.45: unknown */
|
||||
#define PNG_INFO_fdAT 0x400000U /* PNGv3: 1.6.45: unknown */
|
||||
|
||||
/* This is used for the transformation routines, as some of them
|
||||
* change these values for the row. It also should enable using
|
||||
@ -1976,15 +1990,44 @@ PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
|
||||
|
||||
#ifdef PNG_cICP_SUPPORTED
|
||||
PNG_EXPORT(250, png_uint_32, png_get_cICP, (png_const_structrp png_ptr,
|
||||
png_inforp info_ptr, png_bytep colour_primaries,
|
||||
png_const_inforp info_ptr, png_bytep colour_primaries,
|
||||
png_bytep transfer_function, png_bytep matrix_coefficients,
|
||||
png_bytep video_full_range_flag));
|
||||
#endif
|
||||
|
||||
#ifdef PNG_cICP_SUPPORTED
|
||||
PNG_EXPORT(251, void, png_set_cICP, (png_const_structrp png_ptr,
|
||||
png_inforp info_ptr, png_byte colour_primaries,
|
||||
png_byte transfer_function, png_byte matrix_coefficients,
|
||||
png_byte video_full_range_flag));
|
||||
#endif
|
||||
|
||||
#ifdef PNG_cLLI_SUPPORTED
|
||||
PNG_FP_EXPORT(252, png_uint_32, png_get_cLLI, (png_const_structrp png_ptr,
|
||||
png_const_inforp info_ptr, double *maximum_content_light_level,
|
||||
double *maximum_frame_average_light_level));
|
||||
PNG_FIXED_EXPORT(253, png_uint_32, png_get_cLLI_fixed,
|
||||
(png_const_structrp png_ptr, png_const_inforp info_ptr,
|
||||
/* The values below are in cd/m2 (nits) and are scaled by 10,000; not
|
||||
* 100,000 as in the case of png_fixed_point.
|
||||
*/
|
||||
png_uint_32p maximum_content_light_level_scaled_by_10000,
|
||||
png_uint_32p maximum_frame_average_light_level_scaled_by_10000));
|
||||
#endif
|
||||
|
||||
#ifdef PNG_cLLI_SUPPORTED
|
||||
PNG_FP_EXPORT(254, void, png_set_cLLI, (png_const_structrp png_ptr,
|
||||
png_inforp info_ptr, double maximum_content_light_level,
|
||||
double maximum_frame_average_light_level));
|
||||
PNG_FIXED_EXPORT(255, void, png_set_cLLI_fixed, (png_const_structrp png_ptr,
|
||||
png_inforp info_ptr,
|
||||
/* The values below are in cd/m2 (nits) and are scaled by 10,000; not
|
||||
* 100,000 as in the case of png_fixed_point.
|
||||
*/
|
||||
png_uint_32 maximum_content_light_level_scaled_by_10000,
|
||||
png_uint_32 maximum_frame_average_light_level_scaled_by_10000));
|
||||
#endif
|
||||
|
||||
#ifdef PNG_eXIf_SUPPORTED
|
||||
PNG_EXPORT(246, png_uint_32, png_get_eXIf, (png_const_structrp png_ptr,
|
||||
png_inforp info_ptr, png_bytep *exif));
|
||||
@ -2029,6 +2072,60 @@ PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr,
|
||||
int color_type, int interlace_method, int compression_method,
|
||||
int filter_method));
|
||||
|
||||
#ifdef PNG_mDCV_SUPPORTED
|
||||
PNG_FP_EXPORT(256, png_uint_32, png_get_mDCV, (png_const_structrp png_ptr,
|
||||
png_const_inforp info_ptr,
|
||||
/* The chromaticities of the mastering display. As cHRM, but independent of
|
||||
* the encoding endpoints in cHRM, or cICP, or iCCP. These values will
|
||||
* always be in the range 0 to 1.3107.
|
||||
*/
|
||||
double *white_x, double *white_y, double *red_x, double *red_y,
|
||||
double *green_x, double *green_y, double *blue_x, double *blue_y,
|
||||
/* Mastering display luminance in cd/m2 (nits). */
|
||||
double *mastering_display_maximum_luminance,
|
||||
double *mastering_display_minimum_luminance));
|
||||
|
||||
PNG_FIXED_EXPORT(257, png_uint_32, png_get_mDCV_fixed,
|
||||
(png_const_structrp png_ptr, png_const_inforp info_ptr,
|
||||
png_fixed_point *int_white_x, png_fixed_point *int_white_y,
|
||||
png_fixed_point *int_red_x, png_fixed_point *int_red_y,
|
||||
png_fixed_point *int_green_x, png_fixed_point *int_green_y,
|
||||
png_fixed_point *int_blue_x, png_fixed_point *int_blue_y,
|
||||
/* Mastering display luminance in cd/m2 (nits) multiplied (scaled) by
|
||||
* 10,000.
|
||||
*/
|
||||
png_uint_32p mastering_display_maximum_luminance_scaled_by_10000,
|
||||
png_uint_32p mastering_display_minimum_luminance_scaled_by_10000));
|
||||
#endif
|
||||
|
||||
#ifdef PNG_mDCV_SUPPORTED
|
||||
PNG_FP_EXPORT(258, void, png_set_mDCV, (png_const_structrp png_ptr,
|
||||
png_inforp info_ptr,
|
||||
/* The chromaticities of the mastering display. As cHRM, but independent of
|
||||
* the encoding endpoints in cHRM, or cICP, or iCCP.
|
||||
*/
|
||||
double white_x, double white_y, double red_x, double red_y, double green_x,
|
||||
double green_y, double blue_x, double blue_y,
|
||||
/* Mastering display luminance in cd/m2 (nits). */
|
||||
double mastering_display_maximum_luminance,
|
||||
double mastering_display_minimum_luminance));
|
||||
|
||||
PNG_FIXED_EXPORT(259, void, png_set_mDCV_fixed, (png_const_structrp png_ptr,
|
||||
png_inforp info_ptr,
|
||||
/* The admissible range of these values is not the full range of a PNG
|
||||
* fixed point value. Negative values cannot be encoded and the maximum
|
||||
* value is about 1.3 */
|
||||
png_fixed_point int_white_x, png_fixed_point int_white_y,
|
||||
png_fixed_point int_red_x, png_fixed_point int_red_y,
|
||||
png_fixed_point int_green_x, png_fixed_point int_green_y,
|
||||
png_fixed_point int_blue_x, png_fixed_point int_blue_y,
|
||||
/* These are PNG unsigned 4 byte values: 31-bit unsigned values. The MSB
|
||||
* must be zero.
|
||||
*/
|
||||
png_uint_32 mastering_display_maximum_luminance_scaled_by_10000,
|
||||
png_uint_32 mastering_display_minimum_luminance_scaled_by_10000));
|
||||
#endif
|
||||
|
||||
#ifdef PNG_oFFs_SUPPORTED
|
||||
PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr,
|
||||
png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
|
||||
|
109
pngget.c
109
pngget.c
@ -787,7 +787,7 @@ png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
|
||||
#ifdef PNG_cICP_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_cICP(png_const_structrp png_ptr,
|
||||
png_inforp info_ptr, png_bytep colour_primaries,
|
||||
png_const_inforp info_ptr, png_bytep colour_primaries,
|
||||
png_bytep transfer_function, png_bytep matrix_coefficients,
|
||||
png_bytep video_full_range_flag)
|
||||
{
|
||||
@ -805,10 +805,115 @@ png_get_cICP(png_const_structrp png_ptr,
|
||||
return (PNG_INFO_cICP);
|
||||
}
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_cLLI_SUPPORTED
|
||||
# ifdef PNG_FIXED_POINT_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_cLLI_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
|
||||
png_uint_32p maxCLL,
|
||||
png_uint_32p maxFALL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function", "cLLI");
|
||||
|
||||
if (png_ptr != NULL && info_ptr != NULL &&
|
||||
(info_ptr->valid & PNG_INFO_cLLI) != 0)
|
||||
{
|
||||
if (maxCLL != NULL) *maxCLL = info_ptr->maxCLL;
|
||||
if (maxFALL != NULL) *maxFALL = info_ptr->maxFALL;
|
||||
return PNG_INFO_cLLI;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_cLLI(png_const_structrp png_ptr, png_const_inforp info_ptr,
|
||||
double *maxCLL, double *maxFALL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function", "cLLI(float)");
|
||||
|
||||
if (png_ptr != NULL && info_ptr != NULL &&
|
||||
(info_ptr->valid & PNG_INFO_cLLI) != 0)
|
||||
{
|
||||
if (maxCLL != NULL) *maxCLL = info_ptr->maxCLL * .0001;
|
||||
if (maxFALL != NULL) *maxFALL = info_ptr->maxFALL * .0001;
|
||||
return PNG_INFO_cLLI;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
#endif /* cLLI */
|
||||
|
||||
#ifdef PNG_mDCV_SUPPORTED
|
||||
# ifdef PNG_FIXED_POINT_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_mDCV_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
|
||||
png_fixed_point *white_x, png_fixed_point *white_y,
|
||||
png_fixed_point *red_x, png_fixed_point *red_y,
|
||||
png_fixed_point *green_x, png_fixed_point *green_y,
|
||||
png_fixed_point *blue_x, png_fixed_point *blue_y,
|
||||
png_uint_32p mastering_maxDL, png_uint_32p mastering_minDL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function", "mDCV");
|
||||
|
||||
if (png_ptr != NULL && info_ptr != NULL &&
|
||||
(info_ptr->valid & PNG_INFO_mDCV) != 0)
|
||||
{
|
||||
if (white_x != NULL) *white_x = info_ptr->mastering_white_x * 2;
|
||||
if (white_y != NULL) *white_y = info_ptr->mastering_white_y * 2;
|
||||
if (red_x != NULL) *red_x = info_ptr->mastering_red_x * 2;
|
||||
if (red_y != NULL) *red_y = info_ptr->mastering_red_y * 2;
|
||||
if (green_x != NULL) *green_x = info_ptr->mastering_green_x * 2;
|
||||
if (green_y != NULL) *green_y = info_ptr->mastering_green_y * 2;
|
||||
if (blue_x != NULL) *blue_x = info_ptr->mastering_blue_x * 2;
|
||||
if (blue_y != NULL) *blue_y = info_ptr->mastering_blue_y * 2;
|
||||
if (mastering_maxDL != NULL) *mastering_maxDL = info_ptr->mastering_maxDL;
|
||||
if (mastering_minDL != NULL) *mastering_minDL = info_ptr->mastering_minDL;
|
||||
return PNG_INFO_mDCV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
# endif
|
||||
|
||||
# ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_mDCV(png_const_structrp png_ptr, png_const_inforp info_ptr,
|
||||
double *white_x, double *white_y, double *red_x, double *red_y,
|
||||
double *green_x, double *green_y, double *blue_x, double *blue_y,
|
||||
double *mastering_maxDL, double *mastering_minDL)
|
||||
{
|
||||
png_debug1(1, "in %s retrieval function", "mDCV(float)");
|
||||
|
||||
if (png_ptr != NULL && info_ptr != NULL &&
|
||||
(info_ptr->valid & PNG_INFO_mDCV) != 0)
|
||||
{
|
||||
if (white_x != NULL) *white_x = info_ptr->mastering_white_x * .00002;
|
||||
if (white_y != NULL) *white_y = info_ptr->mastering_white_y * .00002;
|
||||
if (red_x != NULL) *red_x = info_ptr->mastering_red_x * .00002;
|
||||
if (red_y != NULL) *red_y = info_ptr->mastering_red_y * .00002;
|
||||
if (green_x != NULL) *green_x = info_ptr->mastering_green_x * .00002;
|
||||
if (green_y != NULL) *green_y = info_ptr->mastering_green_y * .00002;
|
||||
if (blue_x != NULL) *blue_x = info_ptr->mastering_blue_x * .00002;
|
||||
if (blue_y != NULL) *blue_y = info_ptr->mastering_blue_y * .00002;
|
||||
if (mastering_maxDL != NULL)
|
||||
*mastering_maxDL = info_ptr->mastering_maxDL * .0001;
|
||||
if (mastering_minDL != NULL)
|
||||
*mastering_minDL = info_ptr->mastering_minDL * .0001;
|
||||
return PNG_INFO_mDCV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
# endif /* FLOATING_POINT */
|
||||
#endif /* mDCV */
|
||||
|
||||
#ifdef PNG_eXIf_SUPPORTED
|
||||
png_uint_32 PNGAPI
|
||||
png_get_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
|
||||
|
18
pnginfo.h
18
pnginfo.h
@ -115,6 +115,24 @@ struct png_info_def
|
||||
png_uint_32 iccp_proflen; /* ICC profile data length */
|
||||
#endif
|
||||
|
||||
#ifdef PNG_cLLI_SUPPORTED
|
||||
png_uint_32 maxCLL; /* cd/m2 (nits) * 10,000 */
|
||||
png_uint_32 maxFALL;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_mDCV_SUPPORTED
|
||||
png_uint_16 mastering_red_x; /* CIE (xy) x * 50,000 */
|
||||
png_uint_16 mastering_red_y;
|
||||
png_uint_16 mastering_green_x;
|
||||
png_uint_16 mastering_green_y;
|
||||
png_uint_16 mastering_blue_x;
|
||||
png_uint_16 mastering_blue_y;
|
||||
png_uint_16 mastering_white_x;
|
||||
png_uint_16 mastering_white_y;
|
||||
png_uint_32 mastering_maxDL; /* cd/m2 (nits) * 10,000 */
|
||||
png_uint_32 mastering_minDL;
|
||||
#endif
|
||||
|
||||
#ifdef PNG_TEXT_SUPPORTED
|
||||
/* The tEXt, and zTXt chunks contain human-readable textual data in
|
||||
* uncompressed, compressed, and optionally compressed forms, respectively.
|
||||
|
16
pngpread.c
16
pngpread.c
@ -316,6 +316,22 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
|
||||
png_handle_cICP(png_ptr, info_ptr, png_ptr->push_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef PNG_READ_cLLI_SUPPORTED
|
||||
else if (png_ptr->chunk_name == png_cLLI)
|
||||
{
|
||||
PNG_PUSH_SAVE_BUFFER_IF_FULL
|
||||
png_handle_cLLI(png_ptr, info_ptr, png_ptr->push_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef PNG_READ_mDCV_SUPPORTED
|
||||
else if (png_ptr->chunk_name == png_mDCV)
|
||||
{
|
||||
PNG_PUSH_SAVE_BUFFER_IF_FULL
|
||||
png_handle_mDCV(png_ptr, info_ptr, png_ptr->push_length);
|
||||
}
|
||||
|
||||
#endif
|
||||
#ifdef PNG_READ_eXIf_SUPPORTED
|
||||
else if (png_ptr->chunk_name == png_eXIf)
|
||||
|
38
pngpriv.h
38
pngpriv.h
@ -782,6 +782,8 @@
|
||||
#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED
|
||||
#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\
|
||||
((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0))
|
||||
#define png_fixed_ITU(png_ptr, fp, s) ((fp) <= 214748 && (fp) >= 0 ?\
|
||||
((png_uint_32)(10000 * (fp))) : (png_fixed_error(png_ptr, s),0))
|
||||
#endif
|
||||
/* else the corresponding function is defined below, inside the scope of the
|
||||
* cplusplus test.
|
||||
@ -834,7 +836,8 @@
|
||||
#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_cICP PNG_U32( 99, 73, 67, 80) /* PNGv3 */
|
||||
#define png_cLLI PNG_U32( 99, 76, 76, 73) /* PNGv3 */
|
||||
#define png_eXIf PNG_U32(101, 88, 73, 102) /* registered July 2017 */
|
||||
#define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */
|
||||
#define png_gAMA PNG_U32(103, 65, 77, 65)
|
||||
@ -844,6 +847,7 @@
|
||||
#define png_hIST PNG_U32(104, 73, 83, 84)
|
||||
#define png_iCCP PNG_U32(105, 67, 67, 80)
|
||||
#define png_iTXt PNG_U32(105, 84, 88, 116)
|
||||
#define png_mDCV PNG_U32(109, 68, 67, 86) /* PNGv3 */
|
||||
#define png_oFFs PNG_U32(111, 70, 70, 115)
|
||||
#define png_pCAL PNG_U32(112, 67, 65, 76)
|
||||
#define png_pHYs PNG_U32(112, 72, 89, 115)
|
||||
@ -971,6 +975,7 @@ PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr,
|
||||
!defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
|
||||
(defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
|
||||
defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
|
||||
defined(PNG_mDCV_SUPPORTED) || \
|
||||
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
|
||||
(defined(PNG_sCAL_SUPPORTED) && \
|
||||
defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
|
||||
@ -978,6 +983,13 @@ PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr,
|
||||
double fp, png_const_charp text),PNG_EMPTY);
|
||||
#endif
|
||||
|
||||
#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
|
||||
!defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
|
||||
(defined(PNG_cLLI_SUPPORTED) || defined(PNG_mDCV_SUPPORTED))
|
||||
PNG_INTERNAL_FUNCTION(png_uint_32,png_fixed_ITU,(png_const_structrp png_ptr,
|
||||
double fp, png_const_charp text),PNG_EMPTY);
|
||||
#endif
|
||||
|
||||
/* Check the user version string for compatibility, returns false if the version
|
||||
* numbers aren't compatible.
|
||||
*/
|
||||
@ -1137,6 +1149,20 @@ PNG_INTERNAL_FUNCTION(void,png_write_cICP,(png_structrp png_ptr,
|
||||
png_byte matrix_coefficients, png_byte video_full_range_flag), PNG_EMPTY);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_cLLI_SUPPORTED
|
||||
PNG_INTERNAL_FUNCTION(void,png_write_cLLI_fixed,(png_structrp png_ptr,
|
||||
png_uint_32 maxCLL, png_uint_32 maxFALL), PNG_EMPTY);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_mDCV_SUPPORTED
|
||||
PNG_INTERNAL_FUNCTION(void,png_write_mDCV_fixed,(png_structrp png_ptr,
|
||||
png_uint_16 red_x, png_uint_16 red_y,
|
||||
png_uint_16 green_x, png_uint_16 green_y,
|
||||
png_uint_16 blue_x, png_uint_16 blue_y,
|
||||
png_uint_16 white_x, png_uint_16 white_y,
|
||||
png_uint_32 maxDL, png_uint_32 minDL), PNG_EMPTY);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_sRGB_SUPPORTED
|
||||
PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr,
|
||||
int intent),PNG_EMPTY);
|
||||
@ -1485,6 +1511,11 @@ 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_cLLI_SUPPORTED
|
||||
PNG_INTERNAL_FUNCTION(void,png_handle_cLLI,(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);
|
||||
@ -1510,6 +1541,11 @@ PNG_INTERNAL_FUNCTION(void,png_handle_iTXt,(png_structrp png_ptr,
|
||||
png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_mDCV_SUPPORTED
|
||||
PNG_INTERNAL_FUNCTION(void,png_handle_mDCV,(png_structrp png_ptr,
|
||||
png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_oFFs_SUPPORTED
|
||||
PNG_INTERNAL_FUNCTION(void,png_handle_oFFs,(png_structrp png_ptr,
|
||||
png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
|
||||
|
20
pngread.c
20
pngread.c
@ -179,6 +179,11 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
|
||||
png_handle_cICP(png_ptr, info_ptr, length);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_cLLI_SUPPORTED
|
||||
else if (chunk_name == png_cLLI)
|
||||
png_handle_cLLI(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);
|
||||
@ -194,6 +199,11 @@ png_read_info(png_structrp png_ptr, png_inforp info_ptr)
|
||||
png_handle_hIST(png_ptr, info_ptr, length);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_mDCV_SUPPORTED
|
||||
else if (chunk_name == png_mDCV)
|
||||
png_handle_mDCV(png_ptr, info_ptr, length);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_oFFs_SUPPORTED
|
||||
else if (chunk_name == png_oFFs)
|
||||
png_handle_oFFs(png_ptr, info_ptr, length);
|
||||
@ -861,6 +871,11 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
|
||||
png_handle_cICP(png_ptr, info_ptr, length);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_cLLI_SUPPORTED
|
||||
else if (chunk_name == png_cLLI)
|
||||
png_handle_cLLI(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);
|
||||
@ -876,6 +891,11 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
|
||||
png_handle_hIST(png_ptr, info_ptr, length);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_mDCV_SUPPORTED
|
||||
else if (chunk_name == png_mDCV)
|
||||
png_handle_mDCV(png_ptr, info_ptr, length);
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_oFFs_SUPPORTED
|
||||
else if (chunk_name == png_oFFs)
|
||||
png_handle_oFFs(png_ptr, info_ptr, length);
|
||||
|
105
pngrutil.c
105
pngrutil.c
@ -2087,6 +2087,111 @@ png_handle_cICP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_cLLI_SUPPORTED
|
||||
void /* PRIVATE */
|
||||
png_handle_cLLI(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
|
||||
{
|
||||
png_byte buf[8];
|
||||
|
||||
png_debug(1, "in png_handle_cLLI");
|
||||
|
||||
if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
|
||||
png_chunk_error(png_ptr, "missing IHDR");
|
||||
|
||||
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_cLLI) != 0)
|
||||
{
|
||||
png_crc_finish(png_ptr, length);
|
||||
png_chunk_benign_error(png_ptr, "duplicate");
|
||||
return;
|
||||
}
|
||||
|
||||
else if (length != 8)
|
||||
{
|
||||
png_crc_finish(png_ptr, length);
|
||||
png_chunk_benign_error(png_ptr, "invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
png_crc_read(png_ptr, buf, 8);
|
||||
|
||||
if (png_crc_finish(png_ptr, 0) != 0)
|
||||
return;
|
||||
|
||||
/* The error checking happens here, this puts it in just one place: */
|
||||
png_set_cLLI_fixed(png_ptr, info_ptr, png_get_uint_32(buf),
|
||||
png_get_uint_32(buf+4));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_mDCV_SUPPORTED
|
||||
void /* PRIVATE */
|
||||
png_handle_mDCV(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
|
||||
{
|
||||
png_byte buf[24];
|
||||
|
||||
png_debug(1, "in png_handle_mDCV");
|
||||
|
||||
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_mDCV) != 0)
|
||||
{
|
||||
png_crc_finish(png_ptr, length);
|
||||
png_chunk_benign_error(png_ptr, "duplicate");
|
||||
return;
|
||||
}
|
||||
|
||||
else if (length != 24)
|
||||
{
|
||||
png_crc_finish(png_ptr, length);
|
||||
png_chunk_benign_error(png_ptr, "invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
png_crc_read(png_ptr, buf, 24);
|
||||
|
||||
if (png_crc_finish(png_ptr, 0) != 0)
|
||||
return;
|
||||
|
||||
/* The error checking happens here, this puts it in just one place. The
|
||||
* odd /50000 scaling factor makes it more difficult but the (x.y) values are
|
||||
* only two bytes so a <<1 is safe.
|
||||
*
|
||||
* WARNING: the PNG specification defines the cHRM chunk to **start** with
|
||||
* the white point (x,y). The W3C PNG v3 specification puts the white point
|
||||
* **after* R,G,B. The x,y values in mDCV are also scaled by 50,000 and
|
||||
* stored in just two bytes, whereas those in cHRM are scaled by 100,000 and
|
||||
* stored in four bytes. This is very, very confusing. These APIs remove
|
||||
* the confusion by copying the existing, well established, API.
|
||||
*/
|
||||
png_set_mDCV_fixed(png_ptr, info_ptr,
|
||||
png_get_uint_16(buf+12U) << 1U, /* white x */
|
||||
png_get_uint_16(buf+14U) << 1U, /* white y */
|
||||
png_get_uint_16(buf+ 0U) << 1U, /* red x */
|
||||
png_get_uint_16(buf+ 2U) << 1U, /* red y */
|
||||
png_get_uint_16(buf+ 4U) << 1U, /* green x */
|
||||
png_get_uint_16(buf+ 6U) << 1U, /* green y */
|
||||
png_get_uint_16(buf+ 8U) << 1U, /* blue x */
|
||||
png_get_uint_16(buf+10U) << 1U, /* blue y */
|
||||
png_get_uint_32(buf+16U), /* peak luminance */
|
||||
png_get_uint_32(buf+20U));/* minimum perceivable luminance */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_READ_eXIf_SUPPORTED
|
||||
void /* PRIVATE */
|
||||
png_handle_eXIf(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
|
||||
|
154
pngset.c
154
pngset.c
@ -159,6 +159,158 @@ png_set_cICP(png_const_structrp png_ptr, png_inforp info_ptr,
|
||||
}
|
||||
#endif /* cICP */
|
||||
|
||||
#ifdef PNG_cLLI_SUPPORTED
|
||||
void PNGFAPI
|
||||
png_set_cLLI_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
|
||||
/* The values below are in cd/m2 (nits) and are scaled by 10,000; not
|
||||
* 100,000 as in the case of png_fixed_point.
|
||||
*/
|
||||
png_uint_32 maxCLL, png_uint_32 maxFALL)
|
||||
{
|
||||
png_debug1(1, "in %s storage function", "cLLI");
|
||||
|
||||
if (png_ptr == NULL || info_ptr == NULL)
|
||||
return;
|
||||
|
||||
/* Check the light level range: */
|
||||
if (maxCLL > 0x7FFFFFFFU || maxFALL > 0x7FFFFFFFU)
|
||||
{
|
||||
/* The limit is 200kcd/m2; somewhat bright but not inconceivable because
|
||||
* human vision is said to run up to 100Mcd/m2. The sun is about 2Gcd/m2.
|
||||
*
|
||||
* The reference sRGB monitor is 80cd/m2 and the limit of PQ encoding is
|
||||
* 2kcd/m2.
|
||||
*/
|
||||
png_chunk_report(png_ptr, "cLLI light level exceeds PNG limit",
|
||||
PNG_CHUNK_WRITE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
info_ptr->maxCLL = maxCLL;
|
||||
info_ptr->maxFALL = maxFALL;
|
||||
info_ptr->valid |= PNG_INFO_cLLI;
|
||||
}
|
||||
|
||||
# ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
void PNGAPI
|
||||
png_set_cLLI(png_const_structrp png_ptr, png_inforp info_ptr,
|
||||
double maxCLL, double maxFALL)
|
||||
{
|
||||
png_set_cLLI_fixed(png_ptr, info_ptr,
|
||||
png_fixed_ITU(png_ptr, maxCLL, "png_set_cLLI(maxCLL)"),
|
||||
png_fixed_ITU(png_ptr, maxFALL, "png_set_cLLI(maxFALL)"));
|
||||
}
|
||||
# endif /* FLOATING_POINT */
|
||||
#endif /* cLLI */
|
||||
|
||||
#ifdef PNG_mDCV_SUPPORTED
|
||||
static png_uint_16
|
||||
png_ITU_fixed_16(png_const_structrp png_ptr, png_fixed_point v,
|
||||
png_const_charp text)
|
||||
{
|
||||
/* Return a safe uint16_t value scaled according to the ITU H273 rules for
|
||||
* 16-bit display chromaticities. Functions like the corresponding
|
||||
* png_fixed() internal function with regard to errors: it's an error on
|
||||
* write, a chunk_benign_error on read: See the definition of
|
||||
* png_chunk_report in pngpriv.h.
|
||||
*/
|
||||
v /= 2; /* rounds to 0 in C: avoids insignificant arithmetic errors */
|
||||
if (v > 65535 || v < 0)
|
||||
png_fixed_error(png_ptr, text);
|
||||
|
||||
# ifndef PNG_ERROR_TEXT_SUPPORTED
|
||||
PNG_UNUSED(text)
|
||||
# endif
|
||||
|
||||
return (png_uint_16)/*SAFE*/v;
|
||||
}
|
||||
|
||||
void PNGAPI
|
||||
png_set_mDCV_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
|
||||
png_fixed_point white_x, png_fixed_point white_y,
|
||||
png_fixed_point red_x, png_fixed_point red_y,
|
||||
png_fixed_point green_x, png_fixed_point green_y,
|
||||
png_fixed_point blue_x, png_fixed_point blue_y,
|
||||
png_uint_32 maxDL,
|
||||
png_uint_32 minDL)
|
||||
{
|
||||
png_uint_16 rx, ry, gx, gy, bx, by, wx, wy;
|
||||
|
||||
png_debug1(1, "in %s storage function", "mDCV");
|
||||
|
||||
if (png_ptr == NULL || info_ptr == NULL)
|
||||
return;
|
||||
|
||||
/* Check the input values to ensure they are in the expected range: */
|
||||
rx = png_ITU_fixed_16(png_ptr, red_x, "png_set_mDCV(red(x))");
|
||||
ry = png_ITU_fixed_16(png_ptr, red_y, "png_set_mDCV(red(y))");
|
||||
gx = png_ITU_fixed_16(png_ptr, green_x, "png_set_mDCV(green(x))");
|
||||
gy = png_ITU_fixed_16(png_ptr, green_y, "png_set_mDCV(green(y))");
|
||||
bx = png_ITU_fixed_16(png_ptr, blue_x, "png_set_mDCV(blue(x))");
|
||||
by = png_ITU_fixed_16(png_ptr, blue_y, "png_set_mDCV(blue(y))");
|
||||
wx = png_ITU_fixed_16(png_ptr, white_x, "png_set_mDCV(white(x))");
|
||||
wy = png_ITU_fixed_16(png_ptr, white_y, "png_set_mDCV(white(y))");
|
||||
|
||||
/* Check the light level range: */
|
||||
if (maxDL > 0x7FFFFFFFU || minDL > 0x7FFFFFFFU)
|
||||
{
|
||||
/* The limit is 200kcd/m2; somewhat bright but not inconceivable because
|
||||
* human vision is said to run up to 100Mcd/m2. The sun is about 2Gcd/m2.
|
||||
*
|
||||
* The reference sRGB monitor is 80cd/m2 and the limit of PQ encoding is
|
||||
* 2kcd/m2.
|
||||
*/
|
||||
png_chunk_report(png_ptr, "mDCV display light level exceeds PNG limit",
|
||||
PNG_CHUNK_WRITE_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
/* All values are safe, the settings are accepted.
|
||||
*
|
||||
* IMPLEMENTATION NOTE: in practice the values can be checked and assigned
|
||||
* but the result is confusing if a writing app calls png_set_mDCV more than
|
||||
* once, the second time with an invalid value. This approach is more
|
||||
* obviously correct at the cost of typing and a very slight machine
|
||||
* overhead.
|
||||
*/
|
||||
info_ptr->mastering_red_x = rx;
|
||||
info_ptr->mastering_red_y = ry;
|
||||
info_ptr->mastering_green_x = gx;
|
||||
info_ptr->mastering_green_y = gy;
|
||||
info_ptr->mastering_blue_x = bx;
|
||||
info_ptr->mastering_blue_y = by;
|
||||
info_ptr->mastering_white_x = wx;
|
||||
info_ptr->mastering_white_y = wy;
|
||||
info_ptr->mastering_maxDL = maxDL;
|
||||
info_ptr->mastering_minDL = minDL;
|
||||
info_ptr->valid |= PNG_INFO_mDCV;
|
||||
}
|
||||
|
||||
# ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
void PNGAPI
|
||||
png_set_mDCV(png_const_structrp png_ptr, png_inforp info_ptr,
|
||||
double white_x, double white_y, double red_x, double red_y, double green_x,
|
||||
double green_y, double blue_x, double blue_y,
|
||||
double maxDL, double minDL)
|
||||
{
|
||||
png_set_mDCV_fixed(png_ptr, info_ptr,
|
||||
/* The ITU approach is to scale by 50,000, not 100,000 so just divide
|
||||
* the input values by 2 and use png_fixed:
|
||||
*/
|
||||
png_fixed(png_ptr, white_x / 2, "png_set_mDCV(white(x))"),
|
||||
png_fixed(png_ptr, white_y / 2, "png_set_mDCV(white(y))"),
|
||||
png_fixed(png_ptr, red_x / 2, "png_set_mDCV(red(x))"),
|
||||
png_fixed(png_ptr, red_y / 2, "png_set_mDCV(red(y))"),
|
||||
png_fixed(png_ptr, green_x / 2, "png_set_mDCV(green(x))"),
|
||||
png_fixed(png_ptr, green_y / 2, "png_set_mDCV(green(y))"),
|
||||
png_fixed(png_ptr, blue_x / 2, "png_set_mDCV(blue(x))"),
|
||||
png_fixed(png_ptr, blue_y / 2, "png_set_mDCV(blue(y))"),
|
||||
png_fixed_ITU(png_ptr, maxDL, "png_set_mDCV(maxDL)"),
|
||||
png_fixed_ITU(png_ptr, minDL, "png_set_mDCV(minDL)"));
|
||||
}
|
||||
# endif /* FLOATING_POINT */
|
||||
#endif /* mDCV */
|
||||
|
||||
#ifdef PNG_eXIf_SUPPORTED
|
||||
void PNGAPI
|
||||
png_set_eXIf(png_const_structrp png_ptr, png_inforp info_ptr,
|
||||
@ -1421,11 +1573,13 @@ png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
|
||||
98, 75, 71, 68, '\0', /* bKGD */
|
||||
99, 72, 82, 77, '\0', /* cHRM */
|
||||
99, 73, 67, 80, '\0', /* cICP */
|
||||
99, 76, 76, 73, '\0', /* cLLI */
|
||||
101, 88, 73, 102, '\0', /* eXIf */
|
||||
103, 65, 77, 65, '\0', /* gAMA */
|
||||
104, 73, 83, 84, '\0', /* hIST */
|
||||
105, 67, 67, 80, '\0', /* iCCP */
|
||||
105, 84, 88, 116, '\0', /* iTXt */
|
||||
109, 68, 67, 86, '\0', /* mDCV */
|
||||
111, 70, 70, 115, '\0', /* oFFs */
|
||||
112, 67, 65, 76, '\0', /* pCAL */
|
||||
112, 72, 89, 115, '\0', /* pHYs */
|
||||
|
47
pngtest.c
47
pngtest.c
@ -1142,6 +1142,30 @@ test_one_file(const char *inname, const char *outname)
|
||||
png_set_gAMA_fixed(write_ptr, write_info_ptr, gamma);
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_cLLI_SUPPORTED
|
||||
{
|
||||
png_uint_32 maxCLL;
|
||||
png_uint_32 maxFALL;
|
||||
|
||||
if (png_get_cLLI_fixed(read_ptr, read_info_ptr, &maxCLL, &maxFALL) != 0)
|
||||
png_set_cLLI_fixed(write_ptr, write_info_ptr, maxCLL, maxFALL);
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_mDCV_SUPPORTED
|
||||
{
|
||||
png_fixed_point white_x, white_y, red_x, red_y, green_x, green_y, blue_x,
|
||||
blue_y;
|
||||
png_uint_32 maxDL;
|
||||
png_uint_32 minDL;
|
||||
|
||||
if (png_get_mDCV_fixed(read_ptr, read_info_ptr, &white_x, &white_y,
|
||||
&red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y,
|
||||
&maxDL, &minDL) != 0)
|
||||
png_set_mDCV_fixed(write_ptr, write_info_ptr, white_x, white_y,
|
||||
red_x, red_y, green_x, green_y, blue_x, blue_y,
|
||||
maxDL, minDL);
|
||||
}
|
||||
#endif
|
||||
#else /* Use floating point versions */
|
||||
#ifdef PNG_FLOATING_POINT_SUPPORTED
|
||||
#ifdef PNG_cHRM_SUPPORTED
|
||||
@ -1165,6 +1189,29 @@ test_one_file(const char *inname, const char *outname)
|
||||
png_set_gAMA(write_ptr, write_info_ptr, gamma);
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_cLLI_SUPPORTED
|
||||
{
|
||||
double maxCLL;
|
||||
double maxFALL;
|
||||
|
||||
if (png_get_cLLI(read_ptr, read_info_ptr, &maxCLL, &maxFALL) != 0)
|
||||
png_set_cLLI(write_ptr, write_info_ptr, maxCLL, maxFALL);
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_mDCV_SUPPORTED
|
||||
{
|
||||
double white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
|
||||
double maxDL;
|
||||
double minDL;
|
||||
|
||||
if (png_get_mDCV(read_ptr, read_info_ptr, &white_x, &white_y,
|
||||
&red_x, &red_y, &green_x, &green_y, &blue_x, &blue_y,
|
||||
&maxDL, &minDL) != 0)
|
||||
png_set_mDCV(write_ptr, write_info_ptr, white_x, white_y,
|
||||
red_x, red_y, green_x, green_y, blue_x, blue_y,
|
||||
maxDL, minDL);
|
||||
}
|
||||
#endif
|
||||
#endif /* Floating point */
|
||||
#endif /* Fixed point */
|
||||
#ifdef PNG_cICP_SUPPORTED
|
||||
|
BIN
pngtest.png
BIN
pngtest.png
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
23
pngwrite.c
23
pngwrite.c
@ -157,7 +157,30 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
|
||||
* space priority. As above it therefore behooves libpng to write the colour
|
||||
* space chunks in the priority order so that a streaming app need not buffer
|
||||
* them.
|
||||
*
|
||||
* PNG v3: Chunks mDCV and cLLI provide ancillary information for the
|
||||
* interpretation of the colourspace chunkgs but do not require support for
|
||||
* those chunks so are outside the "COLORSPACE" check but before the write of
|
||||
* the colourspace chunks themselves.
|
||||
*/
|
||||
#ifdef PNG_WRITE_cLLI_SUPPORTED
|
||||
if ((info_ptr->valid & PNG_INFO_cLLI) != 0)
|
||||
{
|
||||
png_write_cLLI_fixed(png_ptr, info_ptr->maxCLL, info_ptr->maxFALL);
|
||||
}
|
||||
#endif
|
||||
#ifdef PNG_WRITE_mDCV_SUPPORTED
|
||||
if ((info_ptr->valid & PNG_INFO_mDCV) != 0)
|
||||
{
|
||||
png_write_mDCV_fixed(png_ptr,
|
||||
info_ptr->mastering_red_x, info_ptr->mastering_red_y,
|
||||
info_ptr->mastering_green_x, info_ptr->mastering_green_y,
|
||||
info_ptr->mastering_blue_x, info_ptr->mastering_blue_y,
|
||||
info_ptr->mastering_white_x, info_ptr->mastering_white_y,
|
||||
info_ptr->mastering_maxDL, info_ptr->mastering_minDL);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_COLORSPACE_SUPPORTED
|
||||
# ifdef PNG_WRITE_cICP_SUPPORTED /* Priority 4 */
|
||||
if ((info_ptr->valid & PNG_INFO_cICP) != 0)
|
||||
|
44
pngwutil.c
44
pngwutil.c
@ -1511,6 +1511,50 @@ png_write_cICP(png_structrp png_ptr,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_cLLI_SUPPORTED
|
||||
void /* PRIVATE */
|
||||
png_write_cLLI_fixed(png_structrp png_ptr, png_uint_32 maxCLL,
|
||||
png_uint_32 maxFALL)
|
||||
{
|
||||
png_byte buf[8];
|
||||
|
||||
png_debug(1, "in png_write_cLLI_fixed");
|
||||
|
||||
png_save_uint_32(buf, maxCLL);
|
||||
png_save_uint_32(buf + 4, maxFALL);
|
||||
|
||||
png_write_complete_chunk(png_ptr, png_cLLI, buf, 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_mDCV_SUPPORTED
|
||||
void /* PRIVATE */
|
||||
png_write_mDCV_fixed(png_structrp png_ptr,
|
||||
png_uint_16 red_x, png_uint_16 red_y,
|
||||
png_uint_16 green_x, png_uint_16 green_y,
|
||||
png_uint_16 blue_x, png_uint_16 blue_y,
|
||||
png_uint_16 white_x, png_uint_16 white_y,
|
||||
png_uint_32 maxDL, png_uint_32 minDL)
|
||||
{
|
||||
png_byte buf[24];
|
||||
|
||||
png_debug(1, "in png_write_mDCV_fixed");
|
||||
|
||||
png_save_uint_16(buf + 0, red_x);
|
||||
png_save_uint_16(buf + 2, red_y);
|
||||
png_save_uint_16(buf + 4, green_x);
|
||||
png_save_uint_16(buf + 6, green_y);
|
||||
png_save_uint_16(buf + 8, blue_x);
|
||||
png_save_uint_16(buf + 10, blue_y);
|
||||
png_save_uint_16(buf + 12, white_x);
|
||||
png_save_uint_16(buf + 14, white_y);
|
||||
png_save_uint_32(buf + 16, maxDL);
|
||||
png_save_uint_32(buf + 20, minDL);
|
||||
|
||||
png_write_complete_chunk(png_ptr, png_mDCV, buf, 24);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_eXIf_SUPPORTED
|
||||
/* Write the Exif data */
|
||||
void /* PRIVATE */
|
||||
|
@ -847,11 +847,13 @@ setting IDAT_READ_SIZE default PNG_ZBUF_SIZE
|
||||
chunk bKGD
|
||||
chunk cHRM enables COLORSPACE
|
||||
chunk cICP enables COLORSPACE, GAMMA
|
||||
chunk cLLI
|
||||
chunk eXIf
|
||||
chunk gAMA enables GAMMA
|
||||
chunk hIST
|
||||
chunk iCCP enables COLORSPACE, GAMMA
|
||||
chunk iTXt enables TEXT
|
||||
chunk mDCV
|
||||
chunk oFFs
|
||||
chunk pCAL
|
||||
chunk pHYs
|
||||
|
Loading…
x
Reference in New Issue
Block a user