[Bf-blender-cvs] [68b15fc3ad4] master: Cycles: support loading images from arbitrary OpenColorIO color space

Lukas Stockner noreply at git.blender.org
Fri May 3 15:43:35 CEST 2019


Commit: 68b15fc3ad4f74be192150d3a2fb35e7ef2d4edd
Author: Lukas Stockner
Date:   Thu May 2 15:45:31 2019 +0200
Branches: master
https://developer.blender.org/rB68b15fc3ad4f74be192150d3a2fb35e7ef2d4edd

Cycles: support loading images from arbitrary OpenColorIO color space

These are the internal changes to Cycles, for Blender integration there are no
functional changes in this commit.

Images are converted to scene linear color space on file load, and on reading
from the OpenImageIO texture cache. 8-bit images are compressed with the sRGB
transfer function to avoid precision loss while keeping memory usages low. This
also means that for common cases of 8-bit sRGB images no conversion happens at
all on image loading.

Initial patch by Lukas, completed by Brecht.

Differential Revision: https://developer.blender.org/D3491

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

M	intern/cycles/blender/blender_mesh.cpp
M	intern/cycles/blender/blender_session.cpp
M	intern/cycles/blender/blender_shader.cpp
M	intern/cycles/kernel/osl/osl_globals.h
M	intern/cycles/kernel/osl/osl_services.cpp
M	intern/cycles/kernel/svm/svm_types.h
M	intern/cycles/render/image.cpp
M	intern/cycles/render/image.h
M	intern/cycles/render/nodes.cpp
M	intern/cycles/render/nodes.h
M	intern/cycles/render/osl.cpp
M	intern/cycles/render/osl.h
M	intern/cycles/render/shader.cpp

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

diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp
index de594f4fb6c..1b47c4123e3 100644
--- a/intern/cycles/blender/blender_mesh.cpp
+++ b/intern/cycles/blender/blender_mesh.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "render/colorspace.h"
 #include "render/mesh.h"
 #include "render/object.h"
 #include "render/scene.h"
@@ -301,6 +302,7 @@ static void create_mesh_volume_attribute(
                                                INTERPOLATION_LINEAR,
                                                EXTENSION_CLIP,
                                                use_alpha,
+                                               u_colorspace_raw,
                                                metadata);
 }
 
diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp
index 3a7e5f02b1d..c50dbb6ba55 100644
--- a/intern/cycles/blender/blender_session.cpp
+++ b/intern/cycles/blender/blender_session.cpp
@@ -16,12 +16,13 @@
 
 #include <stdlib.h>
 
+#include "device/device.h"
 #include "render/background.h"
 #include "render/buffers.h"
 #include "render/camera.h"
-#include "device/device.h"
-#include "render/integrator.h"
+#include "render/colorspace.h"
 #include "render/film.h"
+#include "render/integrator.h"
 #include "render/light.h"
 #include "render/mesh.h"
 #include "render/object.h"
@@ -1158,6 +1159,12 @@ void BlenderSession::builtin_image_info(const string &builtin_name,
     metadata.height = b_image.size()[1];
     metadata.depth = 1;
     metadata.channels = b_image.channels();
+
+    if (metadata.is_float) {
+      /* Float images are already converted on the Blender side,
+       * no need to do anything in Cycles. */
+      metadata.colorspace = u_colorspace_raw;
+    }
   }
   else if (b_id.is_a(&RNA_Object)) {
     /* smoke volume data */
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index d1f823bc2b8..e6ec8b22d7a 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -15,6 +15,7 @@
  */
 
 #include "render/background.h"
+#include "render/colorspace.h"
 #include "render/graph.h"
 #include "render/light.h"
 #include "render/nodes.h"
@@ -665,7 +666,14 @@ static ShaderNode *add_node(Scene *scene,
       }
 #endif
     }
-    image->color_space = (NodeImageColorSpace)b_image_node.color_space();
+    switch (b_image_node.color_space()) {
+      case BL::ShaderNodeTexImage::color_space_NONE:
+        image->colorspace = u_colorspace_raw;
+        break;
+      case BL::ShaderNodeTexImage::color_space_COLOR:
+        image->colorspace = u_colorspace_auto;
+        break;
+    }
     image->projection = (NodeImageProjection)b_image_node.projection();
     image->interpolation = get_image_interpolation(b_image_node);
     image->extension = get_image_extension(b_image_node);
@@ -710,7 +718,14 @@ static ShaderNode *add_node(Scene *scene,
       }
 #endif
     }
-    env->color_space = (NodeImageColorSpace)b_env_node.color_space();
+    switch (b_env_node.color_space()) {
+      case BL::ShaderNodeTexEnvironment::color_space_NONE:
+        env->colorspace = u_colorspace_raw;
+        break;
+      case BL::ShaderNodeTexEnvironment::color_space_COLOR:
+        env->colorspace = u_colorspace_auto;
+        break;
+    }
     env->interpolation = get_image_interpolation(b_env_node);
     env->projection = (NodeEnvironmentProjection)b_env_node.projection();
     BL::TexMapping b_texture_mapping(b_env_node.texture_mapping());
@@ -861,7 +876,8 @@ static ShaderNode *add_node(Scene *scene,
                                              point_density->builtin_data,
                                              point_density->interpolation,
                                              EXTENSION_CLIP,
-                                             true);
+                                             true,
+                                             u_colorspace_raw);
     }
     node = point_density;
 
diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h
index 414aaf891db..51bc5cf81a9 100644
--- a/intern/cycles/kernel/osl/osl_globals.h
+++ b/intern/cycles/kernel/osl/osl_globals.h
@@ -37,6 +37,7 @@ using std::isfinite;
 CCL_NAMESPACE_BEGIN
 
 class OSLRenderServices;
+class ColorSpaceProcessor;
 
 /* OSL Texture Handle
  *
@@ -53,21 +54,15 @@ class OSLRenderServices;
 struct OSLTextureHandle : public OIIO::RefCnt {
   enum Type { OIIO, SVM, IES, BEVEL, AO };
 
-  OSLTextureHandle() : type(OIIO), svm_slot(-1), oiio_handle(NULL)
-  {
-  }
-
-  OSLTextureHandle(Type type) : type(type), svm_slot(-1), oiio_handle(NULL)
-  {
-  }
-
-  OSLTextureHandle(Type type, int svm_slot) : type(type), svm_slot(svm_slot), oiio_handle(NULL)
+  OSLTextureHandle(Type type = OIIO, int svm_slot = -1)
+      : type(type), svm_slot(svm_slot), oiio_handle(NULL), processor(NULL)
   {
   }
 
   Type type;
   int svm_slot;
   OSL::TextureSystem::TextureHandle *oiio_handle;
+  ColorSpaceProcessor *processor;
 };
 
 typedef OIIO::intrusive_ptr<OSLTextureHandle> OSLTextureHandleRef;
diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp
index 7de596a2c30..0257f569f4a 100644
--- a/intern/cycles/kernel/osl/osl_services.cpp
+++ b/intern/cycles/kernel/osl/osl_services.cpp
@@ -25,6 +25,7 @@
 
 #include <string.h>
 
+#include "render/colorspace.h"
 #include "render/mesh.h"
 #include "render/object.h"
 #include "render/scene.h"
@@ -1116,6 +1117,9 @@ bool OSLRenderServices::texture(ustring filename,
          * other nasty stuff happening. */
         ts->geterror();
       }
+      else if (handle && handle->processor) {
+        ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels);
+      }
       break;
     }
   }
@@ -1213,6 +1217,9 @@ bool OSLRenderServices::texture3d(ustring filename,
          * other nasty stuff happening. */
         ts->geterror();
       }
+      else if (handle && handle->processor) {
+        ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels);
+      }
       break;
     }
     case OSLTextureHandle::IES:
@@ -1287,6 +1294,9 @@ bool OSLRenderServices::environment(ustring filename,
         result[3] = 1.0f;
     }
   }
+  else if (handle && handle->processor) {
+    ColorSpaceManager::to_scene_linear(handle->processor, result, nchannels);
+  }
 
   return status;
 }
diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h
index d31e4f93696..2e4d0c81b95 100644
--- a/intern/cycles/kernel/svm/svm_types.h
+++ b/intern/cycles/kernel/svm/svm_types.h
@@ -373,11 +373,6 @@ typedef enum NodeNormalMapSpace {
   NODE_NORMAL_MAP_BLENDER_WORLD,
 } NodeNormalMapSpace;
 
-typedef enum NodeImageColorSpace {
-  NODE_COLOR_SPACE_NONE = 0,
-  NODE_COLOR_SPACE_COLOR = 1,
-} NodeImageColorSpace;
-
 typedef enum NodeImageProjection {
   NODE_IMAGE_PROJ_FLAT = 0,
   NODE_IMAGE_PROJ_BOX = 1,
diff --git a/intern/cycles/render/image.cpp b/intern/cycles/render/image.cpp
index ae219e912e0..dc75dca2d19 100644
--- a/intern/cycles/render/image.cpp
+++ b/intern/cycles/render/image.cpp
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
-#include "device/device.h"
 #include "render/image.h"
+#include "device/device.h"
+#include "render/colorspace.h"
 #include "render/scene.h"
 #include "render/stats.h"
 
 #include "util/util_foreach.h"
+#include "util/util_image_impl.h"
 #include "util/util_logging.h"
 #include "util/util_path.h"
 #include "util/util_progress.h"
@@ -164,11 +166,36 @@ bool ImageManager::get_image_metadata(int flat_slot, ImageMetaData &metadata)
   return false;
 }
 
+void ImageManager::metadata_detect_colorspace(ImageMetaData &metadata, const char *file_format)
+{
+  /* Convert used specified color spaces to one we know how to handle. */
+  metadata.colorspace = ColorSpaceManager::detect_known_colorspace(
+      metadata.colorspace, file_format, metadata.is_float || metadata.is_half);
+
+  if (metadata.colorspace == u_colorspace_raw) {
+    /* Nothing to do. */
+  }
+  else if (metadata.colorspace == u_colorspace_srgb) {
+    /* Keep sRGB colorspace stored as sRGB, to save memory and/or loading time
+     * for the common case of 8bit sRGB images like PNG. */
+    metadata.compress_as_srgb = true;
+  }
+  else {
+    /* Always compress non-raw 8bit images as scene linear + sRGB, as a
+     * heuristic to keep memory usage the same without too much data loss
+     * due to quantization in common cases. */
+    metadata.compress_as_srgb = (metadata.type == IMAGE_DATA_TYPE_BYTE ||
+                                 metadata.type == IMAGE_DATA_TYPE_BYTE4);
+  }
+}
+
 bool ImageManager::get_image_metadata(const string &filename,
                                       void *builtin_data,
+                                      ustring colorspace,
                                       ImageMetaData &metadata)
 {
   memset(&metadata, 0, sizeof(metadata));
+  metadata.colorspace = colorspace;
 
   if (builtin_data) {
     if (builtin_image_info_cb) {
@@ -179,13 +206,14 @@ bool ImageManager::get_image_metadata(const string &filename,
     }
 
     if (metadata.is_float) {
-      metadata.is_linear = true;
       metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_FLOAT4 : IMAGE_DATA_TYPE_FLOAT;
     }
     else {
       metadata.type = (metadata.channels > 1) ? IMAGE_DATA_TYPE_BYTE4 : IMAGE_DATA_TYPE_BYTE;
     }
 
+    metadata_detect_colorspace(metadata, "");
+
     return true;
   }
 
@@ -213,20 +241,19 @@ bool ImageManager::get_image_metadata(const string &filename,
   metadata.width = spec.width;
   metadata.height = spec.height;
   metadata.depth = spec.depth;
+  metadata.compress_as_srgb = false;
 
   /* Check the main format, and channel formats. */
   size_t channel_size = spec.format.basesize();
 
   if (spec.format.is_floating_point()) {
     metadata.is_float = true;
-    metadata.is_linear = true;
   }
 
   for (size_t channel = 0; channel < spec.channelformats.size(); channel++) {
     channel_size = max(channel_size, spec.channelformats[channel].basesize());
     if (spec.channelformats[channel].is_floating_point()

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list