[mutter] color-profile: Add gamma LUT generators



commit 3e1a3faa28c63cffc8b424911b8251e5c20c1877
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Sat Dec 4 00:37:20 2021 +0100

    color-profile: Add gamma LUT generators
    
    More or less copied from gnome-settings-daemon. The look up tables are
    either calculated based on the VCGT (Video Card Gamma Table) and the
    blackbody color for a given temperature, or the blackbody color for a
    given temperature alone, if no VCGT is available.
    
    Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2165>

 src/backends/meta-color-profile.c | 122 ++++++++++++++++++++++++++++++++++++++
 src/backends/meta-color-profile.h |   4 ++
 2 files changed, 126 insertions(+)
---
diff --git a/src/backends/meta-color-profile.c b/src/backends/meta-color-profile.c
index f759f26876..b844c45776 100644
--- a/src/backends/meta-color-profile.c
+++ b/src/backends/meta-color-profile.c
@@ -24,6 +24,7 @@
 
 #include <colord.h>
 #include <gio/gio.h>
+#include <lcms2.h>
 
 #include "backends/meta-color-manager-private.h"
 
@@ -380,3 +381,124 @@ meta_color_profile_get_brightness_profile (MetaColorProfile *color_profile)
   return cd_profile_get_metadata_item (color_profile->cd_profile,
                                        CD_PROFILE_METADATA_SCREEN_BRIGHTNESS);
 }
+
+static void
+set_blackbody_color_for_temperature (CdColorRGB   *blackbody_color,
+                                     unsigned int  temperature)
+{
+  if (!cd_color_get_blackbody_rgb_full (temperature,
+                                        blackbody_color,
+                                        CD_COLOR_BLACKBODY_FLAG_USE_PLANCKIAN))
+    {
+      g_warning ("Failed to get blackbody for %uK", temperature);
+      cd_color_rgb_set (blackbody_color, 1.0, 1.0, 1.0);
+    }
+  else
+    {
+      meta_topic (META_DEBUG_COLOR,
+                  "Using blackbody color from %uK: %.1f, %.1f, %.1f",
+                  temperature,
+                  blackbody_color->R,
+                  blackbody_color->G,
+                  blackbody_color->B);
+    }
+}
+
+static MetaGammaLut *
+generate_gamma_lut_from_vcgt (MetaColorProfile    *color_profile,
+                              const cmsToneCurve **vcgt,
+                              unsigned int         temperature,
+                              size_t               lut_size)
+{
+  CdColorRGB blackbody_color;
+  MetaGammaLut *lut;
+  size_t i;
+
+  meta_topic (META_DEBUG_COLOR,
+              "Generating %zu sized GAMMA LUT using temperature %uK and VCGT",
+              lut_size, temperature);
+
+  set_blackbody_color_for_temperature (&blackbody_color, temperature);
+
+  lut = g_new0 (MetaGammaLut, 1);
+  lut->size = lut_size;
+  lut->red = g_new0 (uint16_t, lut_size);
+  lut->green = g_new0 (uint16_t, lut_size);
+  lut->blue = g_new0 (uint16_t, lut_size);
+
+  for (i = 0; i < lut_size; i++)
+    {
+      cmsFloat32Number in;
+
+      in = (double) i / (double) (lut_size - 1);
+      lut->red[i] =
+        cmsEvalToneCurveFloat (vcgt[0], in) *
+        blackbody_color.R * (double) 0xffff;
+      lut->green[i] =
+        cmsEvalToneCurveFloat (vcgt[1], in) *
+        blackbody_color.G * (double) 0xffff;
+      lut->blue[i] =
+        cmsEvalToneCurveFloat (vcgt[2], in) *
+        blackbody_color.B * (gdouble) 0xffff;
+    }
+
+  return lut;
+}
+
+static MetaGammaLut *
+generate_gamma_lut (MetaColorProfile *color_profile,
+                    unsigned int      temperature,
+                    size_t            lut_size)
+{
+  CdColorRGB blackbody_color;
+  MetaGammaLut *lut;
+  size_t i;
+
+  meta_topic (META_DEBUG_COLOR,
+              "Generating %zu sized GAMMA LUT using temperature %uK",
+              lut_size, temperature);
+
+  set_blackbody_color_for_temperature (&blackbody_color, temperature);
+
+  lut = g_new0 (MetaGammaLut, 1);
+  lut->size = lut_size;
+  lut->red = g_new0 (uint16_t, lut_size);
+  lut->green = g_new0 (uint16_t, lut_size);
+  lut->blue = g_new0 (uint16_t, lut_size);
+
+  for (i = 0; i < lut_size; i++)
+    {
+      uint16_t in;
+
+      in = (i * 0xffff) / (lut->size - 1);
+      lut->red[i] = in * blackbody_color.R;
+      lut->green[i] = in * blackbody_color.G;
+      lut->blue[i] = in * blackbody_color.B;
+    }
+
+  return lut;
+}
+
+MetaGammaLut *
+meta_color_profile_generate_gamma_lut (MetaColorProfile *color_profile,
+                                       unsigned int      temperature,
+                                       size_t            lut_size)
+{
+  cmsHPROFILE lcms_profile;
+  const cmsToneCurve **vcgt;
+
+  g_return_val_if_fail (lut_size > 0, NULL);
+
+  lcms_profile = cd_icc_get_handle (color_profile->cd_icc);
+  vcgt = cmsReadTag (lcms_profile, cmsSigVcgtTag);
+
+  if (vcgt && *vcgt)
+    {
+      return generate_gamma_lut_from_vcgt (color_profile, vcgt,
+                                           temperature, lut_size);
+    }
+  else
+    {
+      return generate_gamma_lut (color_profile, temperature, lut_size);
+    }
+}
diff --git a/src/backends/meta-color-profile.h b/src/backends/meta-color-profile.h
index 72c894aabf..53f2400296 100644
--- a/src/backends/meta-color-profile.h
+++ b/src/backends/meta-color-profile.h
@@ -60,4 +60,8 @@ const char * meta_color_profile_get_file_path (MetaColorProfile *color_profile);
 
 const char * meta_color_profile_get_brightness_profile (MetaColorProfile *color_profile);
 
+MetaGammaLut * meta_color_profile_generate_gamma_lut (MetaColorProfile *color_profile,
+                                                      unsigned int      temperature,
+                                                      size_t            lut_size);
+
 #endif /* META_COLOR_PROFILE_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]