[eog/gnome-3-32] EogMetadataReaderPng: Use built-in SRGB profile for matching cHRM/gAMA
- From: Felix Riemann <friemann src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [eog/gnome-3-32] EogMetadataReaderPng: Use built-in SRGB profile for matching cHRM/gAMA
- Date: Fri, 3 May 2019 13:59:47 +0000 (UTC)
commit 305ab5254eb0f95a7b00c6fef32bad1504db28ff
Author: Felix Riemann <friemann gnome org>
Date: Fri May 3 15:53:25 2019 +0200
EogMetadataReaderPng: 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.
Fixes #51.
src/eog-metadata-reader-png.c | 45 ++++++++++++++++++++++++++++++++++++++-----
1 file changed, 40 insertions(+), 5 deletions(-)
---
diff --git a/src/eog-metadata-reader-png.c b/src/eog-metadata-reader-png.c
index deadab5f..6d96f4ca 100644
--- a/src/eog-metadata-reader-png.c
+++ b/src/eog-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 @@ eog_metadata_reader_png_get_xmp_data (EogMetadataReaderPng *emr )
* A maximum output buffer of 5MB should be enough. */
#define EOG_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
eog_metadata_reader_png_get_icc_profile (EogMetadataReaderPng *emr)
{
@@ -600,11 +626,20 @@ eog_metadata_reader_png_get_icc_profile (EogMetadataReaderPng *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]);
+ eog_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)) {
+ eog_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;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]