From f7d104e7379b3915c2d9557da64f34d09f7c142a Mon Sep 17 00:00:00 2001 From: Victor Kareh Date: Mon, 8 Jul 2019 17:10:18 -0400 Subject: EomMetadataReaderPng: Use built-in SRGB profile for matching cHRM/gAMA The values used for sRGB in cHRM and gAMA chunks do not compute to a profile that exactly matches the built-in profile. Catch this case and use the built-in profile instead to avoid color differences. upstream commit: https://gitlab.gnome.org/GNOME/eog/commit/9589430c --- src/eom-metadata-reader-png.c | 45 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/eom-metadata-reader-png.c b/src/eom-metadata-reader-png.c index ebf2ddf..eadf036 100644 --- a/src/eom-metadata-reader-png.c +++ b/src/eom-metadata-reader-png.c @@ -25,6 +25,7 @@ #include #endif +#include #include #include @@ -489,6 +490,31 @@ eom_metadata_reader_png_get_xmp_data (EomMetadataReaderPng *emr ) * A maximum output buffer of 5MB should be enough. */ #define EOM_ICC_INFLATE_BUFFER_LIMIT (1024*1024*5) +/* Apparently an sRGB profile saved in cHRM and gAMA chunks does not compute + * a profile that exactly matches the built-in sRGB profile and thus could + * cause a slight color deviation. Try catching this case to allow fallback + * to the built-in profile instead. + */ +static gboolean +_chrm_matches_srgb(const cmsCIExyY *whitepoint, + const cmsCIExyYTRIPLE *primaries, + gdouble gammaValue) +{ + /* PNGs gAMA value for 2.2 is only accurate to the 4th decimal point */ +#define DOUBLE_EQUAL_MAX_DIFF 1e-4 +#define DOUBLE_EQUAL(a,b) (fabs (a - b) < DOUBLE_EQUAL_MAX_DIFF) + + return (DOUBLE_EQUAL(gammaValue, 2.2) + && DOUBLE_EQUAL(whitepoint->x, 0.3127) + && DOUBLE_EQUAL(whitepoint->y, 0.329) + && DOUBLE_EQUAL(primaries->Red.x, 0.64) + && DOUBLE_EQUAL(primaries->Red.y, 0.33) + && DOUBLE_EQUAL(primaries->Green.x, 0.3) + && DOUBLE_EQUAL(primaries->Green.y, 0.6) + && DOUBLE_EQUAL(primaries->Blue.x, 0.15) + && DOUBLE_EQUAL(primaries->Blue.y, 0.06)); +} + static gpointer eom_metadata_reader_png_get_icc_profile (EomMetadataReaderPng *emr) { @@ -600,11 +626,20 @@ eom_metadata_reader_png_get_icc_profile (EomMetadataReaderPng *emr) whitepoint.Y = primaries.Red.Y = primaries.Green.Y = primaries.Blue.Y = 1.0; gammaValue = (double) 1.0/EXTRACT_DOUBLE_UINT_BLOCK_OFFSET (priv->gAMA_chunk, 0, 100000); - gamma[0] = gamma[1] = gamma[2] = cmsBuildGamma (NULL, gammaValue); - - profile = cmsCreateRGBProfile (&whitepoint, &primaries, gamma); - - cmsFreeToneCurve(gamma[0]); + eom_debug_message (DEBUG_LCMS, "Gamma %.5lf", gammaValue); + + /* Catch SRGB in cHRM/gAMA chunks and use accurate built-in + * profile instead of computing one that "gets close". */ + if(_chrm_matches_srgb (&whitepoint, &primaries, gammaValue)) { + eom_debug_message (DEBUG_LCMS, "gAMA and cHRM match sRGB"); + profile = cmsCreate_sRGBProfile (); + } else { + gamma[0] = gamma[1] = gamma[2] = + cmsBuildGamma (NULL, gammaValue); + profile = cmsCreateRGBProfile (&whitepoint, &primaries, + gamma); + cmsFreeToneCurve(gamma[0]); + } } return profile; -- cgit v1.2.1