[Bf-blender-cvs] [2c0da4a3db9] master: Color management: add functions to detect scene linear and sRGB color spaces

Brecht Van Lommel noreply at git.blender.org
Mon May 6 12:08:17 CEST 2019


Commit: 2c0da4a3db96d4aeeeec1cfba4a0a9f5bf0fa970
Author: Brecht Van Lommel
Date:   Sun May 5 13:14:37 2019 +0200
Branches: master
https://developer.blender.org/rB2c0da4a3db96d4aeeeec1cfba4a0a9f5bf0fa970

Color management: add functions to detect scene linear and sRGB color spaces

Same as the ones in Cycles, but intended for GPU textures.

===================================================================

M	intern/cycles/render/colorspace.cpp
M	intern/opencolorio/fallback_impl.cc
M	intern/opencolorio/ocio_capi.cc
M	intern/opencolorio/ocio_capi.h
M	intern/opencolorio/ocio_impl.cc
M	intern/opencolorio/ocio_impl.h

===================================================================

diff --git a/intern/cycles/render/colorspace.cpp b/intern/cycles/render/colorspace.cpp
index cbfcf774a15..265a0d90b2a 100644
--- a/intern/cycles/render/colorspace.cpp
+++ b/intern/cycles/render/colorspace.cpp
@@ -114,11 +114,11 @@ ustring ColorSpaceManager::detect_known_colorspace(ustring colorspace,
     }
 
     /* Detect if it matches a simple builtin colorspace. */
-    bool is_no_op, is_srgb;
-    is_builtin_colorspace(colorspace, is_no_op, is_srgb);
+    bool is_scene_linear, is_srgb;
+    is_builtin_colorspace(colorspace, is_scene_linear, is_srgb);
 
     thread_scoped_lock cache_lock(cache_mutex);
-    if (is_no_op) {
+    if (is_scene_linear) {
       VLOG(1) << "Colorspace " << colorspace.string() << " is no-op";
       cached_colorspaces[colorspace] = u_colorspace_raw;
       return u_colorspace_raw;
@@ -154,17 +154,19 @@ ustring ColorSpaceManager::detect_known_colorspace(ustring colorspace,
   }
 }
 
-void ColorSpaceManager::is_builtin_colorspace(ustring colorspace, bool &is_no_op, bool &is_srgb)
+void ColorSpaceManager::is_builtin_colorspace(ustring colorspace,
+                                              bool &is_scene_linear,
+                                              bool &is_srgb)
 {
 #ifdef WITH_OCIO
   const OCIO::Processor *processor = (const OCIO::Processor *)get_processor(colorspace);
   if (!processor) {
-    is_no_op = false;
+    is_scene_linear = false;
     is_srgb = false;
     return;
   }
 
-  is_no_op = true;
+  is_scene_linear = true;
   is_srgb = true;
   for (int i = 0; i < 256; i++) {
     float v = i / 255.0f;
@@ -181,27 +183,27 @@ void ColorSpaceManager::is_builtin_colorspace(ustring colorspace, bool &is_no_op
     /* Make sure that there is no channel crosstalk. */
     if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
         fabsf(cG[2]) > 1e-5f || fabsf(cB[0]) > 1e-5f || fabsf(cB[1]) > 1e-5f) {
-      is_no_op = false;
+      is_scene_linear = false;
       is_srgb = false;
       break;
     }
     /* Make sure that the three primaries combine linearly. */
     if (!compare_floats(cR[0], cW[0], 1e-6f, 64) || !compare_floats(cG[1], cW[1], 1e-6f, 64) ||
         !compare_floats(cB[2], cW[2], 1e-6f, 64)) {
-      is_no_op = false;
+      is_scene_linear = false;
       is_srgb = false;
       break;
     }
     /* Make sure that the three channels behave identically. */
     if (!compare_floats(cW[0], cW[1], 1e-6f, 64) || !compare_floats(cW[1], cW[2], 1e-6f, 64)) {
-      is_no_op = false;
+      is_scene_linear = false;
       is_srgb = false;
       break;
     }
 
     float out_v = average(make_float3(cW[0], cW[1], cW[2]));
     if (!compare_floats(v, out_v, 1e-6f, 64)) {
-      is_no_op = false;
+      is_scene_linear = false;
     }
     if (!compare_floats(color_srgb_to_linear(v), out_v, 1e-6f, 64)) {
       is_srgb = false;
@@ -209,7 +211,7 @@ void ColorSpaceManager::is_builtin_colorspace(ustring colorspace, bool &is_no_op
   }
 #else
   (void)colorspace;
-  is_no_op = false;
+  is_scene_linear = false;
   is_srgb = false;
 #endif
 }
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc
index 91f009b3b57..dbf56136d8a 100644
--- a/intern/opencolorio/fallback_impl.cc
+++ b/intern/opencolorio/fallback_impl.cc
@@ -363,6 +363,25 @@ int FallbackImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr * /*cs*/)
   return 0;
 }
 
+void FallbackImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr * /*config*/,
+                                       OCIO_ConstColorSpaceRcPtr *cs,
+                                       bool &is_scene_linear,
+                                       bool &is_srgb)
+{
+  if (cs == COLORSPACE_LINEAR) {
+    is_scene_linear = true;
+    is_srgb = false;
+  }
+  else if (cs == COLORSPACE_SRGB) {
+    is_scene_linear = false;
+    is_srgb = true;
+  }
+  else {
+    is_scene_linear = false;
+    is_srgb = false;
+  }
+}
+
 void FallbackImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr * /*cs*/)
 {
 }
diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc
index 530d1fb8a27..d259ba73e45 100644
--- a/intern/opencolorio/ocio_capi.cc
+++ b/intern/opencolorio/ocio_capi.cc
@@ -174,6 +174,14 @@ int OCIO_colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
   return impl->colorSpaceIsData(cs);
 }
 
+void OCIO_colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config,
+                              OCIO_ConstColorSpaceRcPtr *cs,
+                              bool *is_scene_linear,
+                              bool *is_srgb)
+{
+  impl->colorSpaceIsBuiltin(config, cs, *is_scene_linear, *is_srgb);
+}
+
 void OCIO_colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
 {
   impl->colorSpaceRelease(cs);
diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h
index 9af302647a3..f4d7717ba46 100644
--- a/intern/opencolorio/ocio_capi.h
+++ b/intern/opencolorio/ocio_capi.h
@@ -130,6 +130,10 @@ int OCIO_configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *
 
 int OCIO_colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs);
 int OCIO_colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs);
+void OCIO_colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config,
+                              OCIO_ConstColorSpaceRcPtr *cs,
+                              bool *is_scene_linear,
+                              bool *is_srgb);
 
 void OCIO_colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs);
 
diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc
index 1b2207bfb53..644117e0000 100644
--- a/intern/opencolorio/ocio_impl.cc
+++ b/intern/opencolorio/ocio_impl.cc
@@ -18,6 +18,7 @@
  */
 
 #include <iostream>
+#include <math.h>
 #include <sstream>
 #include <string.h>
 
@@ -34,6 +35,8 @@ using namespace OCIO_NAMESPACE;
 
 #include "MEM_guardedalloc.h"
 
+#include "BLI_math_color.h"
+
 #include "ocio_impl.h"
 
 #if !defined(WITH_ASSERT_ABORT)
@@ -520,6 +523,86 @@ int OCIOImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
   return (*(ConstColorSpaceRcPtr *)cs)->isData();
 }
 
+static float compare_floats(float a, float b, float abs_diff, int ulp_diff)
+{
+  /* Returns true if the absolute difference is smaller than abs_diff (for numbers near zero)
+   * or their relative difference is less than ulp_diff ULPs. Based on:
+   * https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ */
+  if (fabsf(a - b) < abs_diff) {
+    return true;
+  }
+
+  if ((a < 0.0f) != (b < 0.0f)) {
+    return false;
+  }
+
+  return (abs((*(int *)&a) - (*(int *)&b)) < ulp_diff);
+}
+
+void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_,
+                                   OCIO_ConstColorSpaceRcPtr *cs_,
+                                   bool &is_scene_linear,
+                                   bool &is_srgb)
+{
+  ConstConfigRcPtr *config = (ConstConfigRcPtr *)config_;
+  ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *)cs_;
+  ConstProcessorRcPtr processor;
+
+  try {
+    processor = (*config)->getProcessor((*cs)->getName(), "scene_linear");
+  }
+  catch (Exception &exception) {
+    OCIO_reportException(exception);
+    is_scene_linear = false;
+    is_srgb = false;
+    return;
+  }
+
+  is_scene_linear = true;
+  is_srgb = true;
+  for (int i = 0; i < 256; i++) {
+    float v = i / 255.0f;
+
+    float cR[3] = {v, 0, 0};
+    float cG[3] = {0, v, 0};
+    float cB[3] = {0, 0, v};
+    float cW[3] = {v, v, v};
+    processor->applyRGB(cR);
+    processor->applyRGB(cG);
+    processor->applyRGB(cB);
+    processor->applyRGB(cW);
+
+    /* Make sure that there is no channel crosstalk. */
+    if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
+        fabsf(cG[2]) > 1e-5f || fabsf(cB[0]) > 1e-5f || fabsf(cB[1]) > 1e-5f) {
+      is_scene_linear = false;
+      is_srgb = false;
+      break;
+    }
+    /* Make sure that the three primaries combine linearly. */
+    if (!compare_floats(cR[0], cW[0], 1e-6f, 64) || !compare_floats(cG[1], cW[1], 1e-6f, 64) ||
+        !compare_floats(cB[2], cW[2], 1e-6f, 64)) {
+      is_scene_linear = false;
+      is_srgb = false;
+      break;
+    }
+    /* Make sure that the three channels behave identically. */
+    if (!compare_floats(cW[0], cW[1], 1e-6f, 64) || !compare_floats(cW[1], cW[2], 1e-6f, 64)) {
+      is_scene_linear = false;
+      is_srgb = false;
+      break;
+    }
+
+    float out_v = (cW[0] + cW[1] + cW[2]) * (1.0f / 3.0f);
+    if (!compare_floats(v, out_v, 1e-6f, 64)) {
+      is_scene_linear = false;
+    }
+    if (!compare_floats(srgb_to_linearrgb(v), out_v, 1e-6f, 64)) {
+      is_srgb = false;
+    }
+  }
+}
+
 void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
 {
   OBJECT_GUARDED_DELETE((ConstColorSpaceRcPtr *)cs, ConstColorSpaceRcPtr);
diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h
index 0952e7e16d0..082aa4a091e 100644
--- a/intern/opencolorio/ocio_impl.h
+++ b/intern/opencolorio/ocio_impl.h
@@ -44,6 +44,10 @@ class IOCIOImpl {
 
   virtual int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs) = 0;
   virtual int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs) = 0;
+  virtual void colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config,
+                                   OCIO_ConstColorSpaceRcPtr *cs,
+                                   bool &is_scene_linear,
+                                   bool &is_srgb) = 0;
 
   virtual void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs) = 0;
 
@@ -160,6 +164,10 @@ class FallbackImpl : public IOCIOImpl {
 
   int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs);
   int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs);
+  void colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config,
+                           OCIO_ConstColorSpaceRcPtr *cs,
+                           bool &is_scene_linear,
+                           bool &is_srgb);
 
   void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs);
 
@@ -266,6 +274,10 @@ class OCIOImpl : public IOCIOImpl {
 
   int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs);
   int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs);
+  void colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config,
+                           OCIO_ConstColorSpaceRcPtr *cs,
+                       

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list