summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVictor Kareh <[email protected]>2019-07-08 17:10:18 -0400
committerraveit65 <[email protected]>2019-09-12 15:59:44 +0200
commit1c705581c5d344a178f938a4beb868314cb0b2db (patch)
treecf52f95eeb6e9db82451b791d67d1eeafaf5b9d6
parent3bdabe92391f3dbc72b3cdafdd6b7caddb7311e6 (diff)
downloadeom-1c705581c5d344a178f938a4beb868314cb0b2db.tar.bz2
eom-1c705581c5d344a178f938a4beb868314cb0b2db.tar.xz
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
-rw-r--r--src/eom-metadata-reader-png.c45
1 files changed, 40 insertions, 5 deletions
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 <config.h>
#endif
+#include <math.h>
#include <string.h>
#include <zlib.h>
@@ -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;