Skip to content

Commit a8242dd

Browse files
committed
PNGv3 colourspace precedence rules conformance
This is a major change required by the new PNGv3 colour chunk precedence rules. It **does not** change the libpng API (png.h) however it changes the following handling of PNG files: IFF the PNG file contains colour space information it changes from the libpng v3 behaviour to the now compulsory PNG v3 behaviour: 1) libpng no longer invalidates colour space chunks because they are inconsistent. 2) libpng no longer responds to the "png_get_" APIs positively if they are not present in the PNG but can be deduced from the colour space chunks that are present.
1 parent 171bdd3 commit a8242dd

File tree

12 files changed

+1737
-2863
lines changed

12 files changed

+1737
-2863
lines changed

png.c

Lines changed: 233 additions & 886 deletions
Large diffs are not rendered by default.

pngget.c

Lines changed: 76 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,13 @@ png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns)
380380
* Notice that this can overflow - a warning is output and 0 is
381381
* returned.
382382
*/
383-
return png_muldiv_warn(png_ptr, microns, 500, 127);
383+
png_fixed_point result;
384+
385+
if (png_muldiv(&result, microns, 500, 127) != 0)
386+
return result;
387+
388+
png_warning(png_ptr, "fixed point overflow ignored");
389+
return 0;
384390
}
385391

386392
png_fixed_point PNGAPI
@@ -390,7 +396,7 @@ png_get_x_offset_inches_fixed(png_const_structrp png_ptr,
390396
return png_fixed_inches_from_microns(png_ptr,
391397
png_get_x_offset_microns(png_ptr, info_ptr));
392398
}
393-
#endif
399+
#endif /* FIXED_POINT */
394400

395401
#ifdef PNG_FIXED_POINT_SUPPORTED
396402
png_fixed_point PNGAPI
@@ -518,44 +524,31 @@ png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
518524
# ifdef PNG_FLOATING_POINT_SUPPORTED
519525
png_uint_32 PNGAPI
520526
png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
521-
double *white_x, double *white_y, double *red_x, double *red_y,
522-
double *green_x, double *green_y, double *blue_x, double *blue_y)
527+
double *whitex, double *whitey, double *redx, double *redy,
528+
double *greenx, double *greeny, double *bluex, double *bluey)
523529
{
524530
png_debug1(1, "in %s retrieval function", "cHRM");
525531

526-
/* Quiet API change: this code used to only return the end points if a cHRM
527-
* chunk was present, but the end points can also come from iCCP or sRGB
528-
* chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
529-
* the png_set_ APIs merely check that set end points are mutually
530-
* consistent.
531-
*/
532+
/* PNGv3: this just returns the values store from the cHRM, if any. */
532533
if (png_ptr != NULL && info_ptr != NULL &&
533-
(info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
534+
(info_ptr->valid & PNG_INFO_cHRM) != 0)
534535
{
535-
if (white_x != NULL)
536-
*white_x = png_float(png_ptr,
537-
info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
538-
if (white_y != NULL)
539-
*white_y = png_float(png_ptr,
540-
info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y");
541-
if (red_x != NULL)
542-
*red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx,
543-
"cHRM red X");
544-
if (red_y != NULL)
545-
*red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy,
546-
"cHRM red Y");
547-
if (green_x != NULL)
548-
*green_x = png_float(png_ptr,
549-
info_ptr->colorspace.end_points_xy.greenx, "cHRM green X");
550-
if (green_y != NULL)
551-
*green_y = png_float(png_ptr,
552-
info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y");
553-
if (blue_x != NULL)
554-
*blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex,
555-
"cHRM blue X");
556-
if (blue_y != NULL)
557-
*blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
558-
"cHRM blue Y");
536+
if (whitex != NULL)
537+
*whitex = png_float(png_ptr, info_ptr->cHRM.whitex, "cHRM wx");
538+
if (whitey != NULL)
539+
*whitey = png_float(png_ptr, info_ptr->cHRM.whitey, "cHRM wy");
540+
if (redx != NULL)
541+
*redx = png_float(png_ptr, info_ptr->cHRM.redx, "cHRM rx");
542+
if (redy != NULL)
543+
*redy = png_float(png_ptr, info_ptr->cHRM.redy, "cHRM ry");
544+
if (greenx != NULL)
545+
*greenx = png_float(png_ptr, info_ptr->cHRM.greenx, "cHRM gx");
546+
if (greeny != NULL)
547+
*greeny = png_float(png_ptr, info_ptr->cHRM.greeny, "cHRM gy");
548+
if (bluex != NULL)
549+
*bluex = png_float(png_ptr, info_ptr->cHRM.bluex, "cHRM bx");
550+
if (bluey != NULL)
551+
*bluey = png_float(png_ptr, info_ptr->cHRM.bluey, "cHRM by");
559552
return PNG_INFO_cHRM;
560553
}
561554

@@ -568,38 +561,31 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
568561
double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
569562
double *blue_Z)
570563
{
564+
png_XYZ XYZ;
571565
png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
572566

573567
if (png_ptr != NULL && info_ptr != NULL &&
574-
(info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
568+
(info_ptr->valid & PNG_INFO_cHRM) != 0 &&
569+
png_XYZ_from_xy(&XYZ, &info_ptr->cHRM) == 0)
575570
{
576571
if (red_X != NULL)
577-
*red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
578-
"cHRM red X");
572+
*red_X = png_float(png_ptr, XYZ.red_X, "cHRM red X");
579573
if (red_Y != NULL)
580-
*red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y,
581-
"cHRM red Y");
574+
*red_Y = png_float(png_ptr, XYZ.red_Y, "cHRM red Y");
582575
if (red_Z != NULL)
583-
*red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z,
584-
"cHRM red Z");
576+
*red_Z = png_float(png_ptr, XYZ.red_Z, "cHRM red Z");
585577
if (green_X != NULL)
586-
*green_X = png_float(png_ptr,
587-
info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X");
578+
*green_X = png_float(png_ptr, XYZ.green_X, "cHRM green X");
588579
if (green_Y != NULL)
589-
*green_Y = png_float(png_ptr,
590-
info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y");
580+
*green_Y = png_float(png_ptr, XYZ.green_Y, "cHRM green Y");
591581
if (green_Z != NULL)
592-
*green_Z = png_float(png_ptr,
593-
info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z");
582+
*green_Z = png_float(png_ptr, XYZ.green_Z, "cHRM green Z");
594583
if (blue_X != NULL)
595-
*blue_X = png_float(png_ptr,
596-
info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X");
584+
*blue_X = png_float(png_ptr, XYZ.blue_X, "cHRM blue X");
597585
if (blue_Y != NULL)
598-
*blue_Y = png_float(png_ptr,
599-
info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y");
586+
*blue_Y = png_float(png_ptr, XYZ.blue_Y, "cHRM blue Y");
600587
if (blue_Z != NULL)
601-
*blue_Z = png_float(png_ptr,
602-
info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
588+
*blue_Z = png_float(png_ptr, XYZ.blue_Z, "cHRM blue Z");
603589
return PNG_INFO_cHRM;
604590
}
605591

@@ -616,29 +602,22 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
616602
png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
617603
png_fixed_point *int_blue_Z)
618604
{
605+
png_XYZ XYZ;
619606
png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
620607

621608
if (png_ptr != NULL && info_ptr != NULL &&
622-
(info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
609+
(info_ptr->valid & PNG_INFO_cHRM) != 0U &&
610+
png_XYZ_from_xy(&XYZ, &info_ptr->cHRM) == 0)
623611
{
624-
if (int_red_X != NULL)
625-
*int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
626-
if (int_red_Y != NULL)
627-
*int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y;
628-
if (int_red_Z != NULL)
629-
*int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z;
630-
if (int_green_X != NULL)
631-
*int_green_X = info_ptr->colorspace.end_points_XYZ.green_X;
632-
if (int_green_Y != NULL)
633-
*int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y;
634-
if (int_green_Z != NULL)
635-
*int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z;
636-
if (int_blue_X != NULL)
637-
*int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X;
638-
if (int_blue_Y != NULL)
639-
*int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
640-
if (int_blue_Z != NULL)
641-
*int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
612+
if (int_red_X != NULL) *int_red_X = XYZ.red_X;
613+
if (int_red_Y != NULL) *int_red_Y = XYZ.red_Y;
614+
if (int_red_Z != NULL) *int_red_Z = XYZ.red_Z;
615+
if (int_green_X != NULL) *int_green_X = XYZ.green_X;
616+
if (int_green_Y != NULL) *int_green_Y = XYZ.green_Y;
617+
if (int_green_Z != NULL) *int_green_Z = XYZ.green_Z;
618+
if (int_blue_X != NULL) *int_blue_X = XYZ.blue_X;
619+
if (int_blue_Y != NULL) *int_blue_Y = XYZ.blue_Y;
620+
if (int_blue_Z != NULL) *int_blue_Z = XYZ.blue_Z;
642621
return PNG_INFO_cHRM;
643622
}
644623

@@ -647,31 +626,24 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
647626

648627
png_uint_32 PNGAPI
649628
png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
650-
png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
651-
png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
652-
png_fixed_point *blue_x, png_fixed_point *blue_y)
629+
png_fixed_point *whitex, png_fixed_point *whitey, png_fixed_point *redx,
630+
png_fixed_point *redy, png_fixed_point *greenx, png_fixed_point *greeny,
631+
png_fixed_point *bluex, png_fixed_point *bluey)
653632
{
654633
png_debug1(1, "in %s retrieval function", "cHRM");
655634

635+
/* PNGv3: this just returns the values store from the cHRM, if any. */
656636
if (png_ptr != NULL && info_ptr != NULL &&
657-
(info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
637+
(info_ptr->valid & PNG_INFO_cHRM) != 0)
658638
{
659-
if (white_x != NULL)
660-
*white_x = info_ptr->colorspace.end_points_xy.whitex;
661-
if (white_y != NULL)
662-
*white_y = info_ptr->colorspace.end_points_xy.whitey;
663-
if (red_x != NULL)
664-
*red_x = info_ptr->colorspace.end_points_xy.redx;
665-
if (red_y != NULL)
666-
*red_y = info_ptr->colorspace.end_points_xy.redy;
667-
if (green_x != NULL)
668-
*green_x = info_ptr->colorspace.end_points_xy.greenx;
669-
if (green_y != NULL)
670-
*green_y = info_ptr->colorspace.end_points_xy.greeny;
671-
if (blue_x != NULL)
672-
*blue_x = info_ptr->colorspace.end_points_xy.bluex;
673-
if (blue_y != NULL)
674-
*blue_y = info_ptr->colorspace.end_points_xy.bluey;
639+
if (whitex != NULL) *whitex = info_ptr->cHRM.whitex;
640+
if (whitey != NULL) *whitey = info_ptr->cHRM.whitey;
641+
if (redx != NULL) *redx = info_ptr->cHRM.redx;
642+
if (redy != NULL) *redy = info_ptr->cHRM.redy;
643+
if (greenx != NULL) *greenx = info_ptr->cHRM.greenx;
644+
if (greeny != NULL) *greeny = info_ptr->cHRM.greeny;
645+
if (bluex != NULL) *bluex = info_ptr->cHRM.bluex;
646+
if (bluey != NULL) *bluey = info_ptr->cHRM.bluey;
675647
return PNG_INFO_cHRM;
676648
}
677649

@@ -688,11 +660,11 @@ png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
688660
{
689661
png_debug1(1, "in %s retrieval function", "gAMA");
690662

663+
/* PNGv3 compatibility: only report gAMA if it is really present. */
691664
if (png_ptr != NULL && info_ptr != NULL &&
692-
(info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
693-
file_gamma != NULL)
665+
(info_ptr->valid & PNG_INFO_gAMA) != 0)
694666
{
695-
*file_gamma = info_ptr->colorspace.gamma;
667+
if (file_gamma != NULL) *file_gamma = info_ptr->gamma;
696668
return PNG_INFO_gAMA;
697669
}
698670

@@ -707,12 +679,13 @@ png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
707679
{
708680
png_debug1(1, "in %s retrieval function", "gAMA(float)");
709681

682+
/* PNGv3 compatibility: only report gAMA if it is really present. */
710683
if (png_ptr != NULL && info_ptr != NULL &&
711-
(info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
712-
file_gamma != NULL)
684+
(info_ptr->valid & PNG_INFO_gAMA) != 0)
713685
{
714-
*file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
715-
"png_get_gAMA");
686+
if (file_gamma != NULL)
687+
*file_gamma = png_float(png_ptr, info_ptr->gamma, "gAMA");
688+
716689
return PNG_INFO_gAMA;
717690
}
718691

@@ -729,9 +702,10 @@ png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
729702
png_debug1(1, "in %s retrieval function", "sRGB");
730703

731704
if (png_ptr != NULL && info_ptr != NULL &&
732-
(info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
705+
(info_ptr->valid & PNG_INFO_sRGB) != 0)
733706
{
734-
*file_srgb_intent = info_ptr->colorspace.rendering_intent;
707+
if (file_srgb_intent != NULL)
708+
*file_srgb_intent = info_ptr->rendering_intent;
735709
return PNG_INFO_sRGB;
736710
}
737711

pnginfo.h

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,6 @@ struct png_info_def
8686
* and initialize the appropriate fields below.
8787
*/
8888

89-
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
90-
/* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
91-
* defined. When COLORSPACE is switched on all the colorspace-defining
92-
* chunks should be enabled, when GAMMA is switched on all the gamma-defining
93-
* chunks should be enabled. If this is not done it becomes possible to read
94-
* inconsistent PNG files and assign a probably incorrect interpretation to
95-
* the information. (In other words, by carefully choosing which chunks to
96-
* recognize the system configuration can select an interpretation for PNG
97-
* files containing ambiguous data and this will result in inconsistent
98-
* behavior between different libpng builds!)
99-
*/
100-
png_colorspace colorspace;
101-
#endif
102-
10389
#ifdef PNG_cICP_SUPPORTED
10490
/* cICP chunk data */
10591
png_byte cicp_colour_primaries;
@@ -211,11 +197,8 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
211197
#endif
212198

213199
#ifdef PNG_eXIf_SUPPORTED
214-
int num_exif; /* Added at libpng-1.6.31 */
200+
png_uint_32 num_exif; /* Added at libpng-1.6.31 */
215201
png_bytep exif;
216-
# ifdef PNG_READ_eXIf_SUPPORTED
217-
png_bytep eXIf_buf; /* Added at libpng-1.6.32 */
218-
# endif
219202
#endif
220203

221204
#ifdef PNG_hIST_SUPPORTED
@@ -288,5 +271,16 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
288271
png_bytepp row_pointers; /* the image bits */
289272
#endif
290273

274+
#ifdef PNG_cHRM_SUPPORTED
275+
png_xy cHRM;
276+
#endif
277+
278+
#ifdef PNG_gAMA_SUPPORTED
279+
png_fixed_point gamma;
280+
#endif
281+
282+
#ifdef PNG_sRGB_SUPPORTED
283+
int rendering_intent;
284+
#endif
291285
};
292286
#endif /* PNGINFO_H */

0 commit comments

Comments
 (0)