diff options
-rw-r--r-- | intern/opencolorio/fallback_impl.cc | 2 | ||||
-rw-r--r-- | intern/opencolorio/ocio_capi.h | 13 | ||||
-rw-r--r-- | intern/opencolorio/ocio_impl.cc | 9 | ||||
-rw-r--r-- | source/blender/imbuf/IMB_colormanagement.h | 8 | ||||
-rw-r--r-- | source/blender/imbuf/intern/IMB_colormanagement_intern.h | 4 | ||||
-rw-r--r-- | source/blender/imbuf/intern/colormanagement.c | 18 | ||||
-rw-r--r-- | source/blender/imbuf/intern/colormanagement_inline.c | 24 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_mesh.c | 10 | ||||
-rw-r--r-- | source/blender/python/mathutils/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Color.c | 169 |
10 files changed, 231 insertions, 28 deletions
diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index d78b34d3c92..71b5ab9def2 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -244,7 +244,7 @@ void FallbackImpl::configGetDefaultLumaCoefs(OCIO_ConstConfigRcPtr * /*config*/, void FallbackImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr * /*config*/, float xyz_to_rgb[3][3]) { /* Default to ITU-BT.709. */ - memcpy(xyz_to_rgb, OCIO_XYZ_TO_LINEAR_SRGB, sizeof(OCIO_XYZ_TO_LINEAR_SRGB)); + memcpy(xyz_to_rgb, OCIO_XYZ_TO_REC709, sizeof(OCIO_XYZ_TO_REC709)); } int FallbackImpl::configGetNumLooks(OCIO_ConstConfigRcPtr * /*config*/) diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 9bd4ec374e2..4be838a218d 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -31,10 +31,15 @@ OCIO_DECLARE_HANDLE(OCIO_ConstContextRcPtr); OCIO_DECLARE_HANDLE(OCIO_PackedImageDesc); OCIO_DECLARE_HANDLE(OCIO_ConstLookRcPtr); -/* Standard XYZ to linear sRGB transform, for fallback. */ -static const float OCIO_XYZ_TO_LINEAR_SRGB[3][3] = {{3.2404542f, -0.9692660f, 0.0556434f}, - {-1.5371385f, 1.8760108f, -0.2040259f}, - {-0.4985314f, 0.0415560f, 1.0572252f}}; +/* Standard XYZ (D65) to linear Rec.709 transform. */ +static const float OCIO_XYZ_TO_REC709[3][3] = {{3.2404542f, -0.9692660f, 0.0556434f}, + {-1.5371385f, 1.8760108f, -0.2040259f}, + {-0.4985314f, 0.0415560f, 1.0572252f}}; +/* Standard ACES to XYZ (D65) transform. + * Matches OpenColorIO builtin transform: UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD. */ +static const float OCIO_ACES_TO_XYZ[3][3] = {{0.938280f, 0.337369f, 0.001174f}, + {-0.004451f, 0.729522f, -0.003711f}, + {0.016628f, -0.066890f, 1.091595f}}; /* This structure is used to pass curve mapping settings from * blender's DNA structure stored in view transform settings diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc index 8d9c5dd2d49..a352c54da86 100644 --- a/intern/opencolorio/ocio_impl.cc +++ b/intern/opencolorio/ocio_impl.cc @@ -317,7 +317,7 @@ void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rg /* Default to ITU-BT.709 in case no appropriate transform found. * Note XYZ is defined here as having a D65 white point. */ - memcpy(xyz_to_rgb, OCIO_XYZ_TO_LINEAR_SRGB, sizeof(OCIO_XYZ_TO_LINEAR_SRGB)); + memcpy(xyz_to_rgb, OCIO_XYZ_TO_REC709, sizeof(OCIO_XYZ_TO_REC709)); /* Get from OpenColorO config if it has the required roles. */ if (!config->hasRole(ROLE_SCENE_LINEAR)) { @@ -328,13 +328,8 @@ void OCIOImpl::configGetXYZtoRGB(OCIO_ConstConfigRcPtr *config_, float xyz_to_rg /* Standard OpenColorIO role, defined as ACES AP0 (ACES2065-1). */ float aces_to_rgb[3][3]; if (to_scene_linear_matrix(config, "aces_interchange", aces_to_rgb)) { - /* This is the OpenColorIO builtin transform: - * UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD. */ - const float ACES_AP0_to_xyz_D65[3][3] = {{0.938280f, 0.337369f, 0.001174f}, - {-0.004451f, 0.729522f, -0.003711f}, - {0.016628f, -0.066890f, 1.091595f}}; float xyz_to_aces[3][3]; - invert_m3_m3(xyz_to_aces, ACES_AP0_to_xyz_D65); + invert_m3_m3(xyz_to_aces, OCIO_ACES_TO_XYZ); mul_m3_m3m3(xyz_to_rgb, aces_to_rgb, xyz_to_aces); } diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 1f0ed4cafbe..94036da9d22 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -72,8 +72,16 @@ BLI_INLINE float IMB_colormanagement_get_luminance(const float rgb[3]); * Byte equivalent of #IMB_colormanagement_get_luminance(). */ BLI_INLINE unsigned char IMB_colormanagement_get_luminance_byte(const unsigned char[3]); + +/** + * Conversion between scene linear and other color spaces. + */ BLI_INLINE void IMB_colormanagement_xyz_to_rgb(float rgb[3], const float xyz[3]); BLI_INLINE void IMB_colormanagement_rgb_to_xyz(float xyz[3], const float rgb[3]); +BLI_INLINE void IMB_colormanagement_rec709_to_rgb(float rgb[3], const float rec709[3]); +BLI_INLINE void IMB_colormanagement_rgb_to_rec709(float rec709[3], const float rgb[3]); +BLI_INLINE void IMB_colormanagement_aces_to_rgb(float rgb[3], const float aces[3]); +BLI_INLINE void IMB_colormanagement_rgb_to_aces(float aces[3], const float rgb[3]); const float *IMB_colormanagement_get_xyz_to_rgb(void); /** \} */ diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.h b/source/blender/imbuf/intern/IMB_colormanagement_intern.h index c89b15480a2..fd70c633f83 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.h +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.h @@ -20,6 +20,10 @@ struct OCIO_ConstCPUProcessorRcPtr; extern float imbuf_luma_coefficients[3]; extern float imbuf_xyz_to_rgb[3][3]; extern float imbuf_rgb_to_xyz[3][3]; +extern float imbuf_xyz_to_aces[3][3]; +extern float imbuf_aces_to_xyz[3][3]; +extern float imbuf_xyz_to_rec709[3][3]; +extern float imbuf_rec709_to_xyz[3][3]; #define MAX_COLORSPACE_NAME 64 #define MAX_COLORSPACE_DESCRIPTION 512 diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 95e2d36891a..f189614e61c 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -75,8 +75,10 @@ static int global_tot_looks = 0; float imbuf_luma_coefficients[3] = {0.0f}; float imbuf_xyz_to_rgb[3][3] = {{0.0f}}; float imbuf_rgb_to_xyz[3][3] = {{0.0f}}; -static float imbuf_xyz_to_linear_srgb[3][3] = {{0.0f}}; -static float imbuf_linear_srgb_to_xyz[3][3] = {{0.0f}}; +float imbuf_xyz_to_rec709[3][3] = {{0.0f}}; +float imbuf_rec709_to_xyz[3][3] = {{0.0f}}; +float imbuf_xyz_to_aces[3][3] = {{0.0f}}; +float imbuf_aces_to_xyz[3][3] = {{0.0f}}; /* lock used by pre-cached processors getters, so processor wouldn't * be created several times @@ -573,10 +575,14 @@ static void colormanage_load_config(OCIO_ConstConfigRcPtr *config) /* Load luminance coefficients. */ OCIO_configGetDefaultLumaCoefs(config, imbuf_luma_coefficients); + + /* Load standard color spaces. */ OCIO_configGetXYZtoRGB(config, imbuf_xyz_to_rgb); invert_m3_m3(imbuf_rgb_to_xyz, imbuf_xyz_to_rgb); - copy_m3_m3(imbuf_xyz_to_linear_srgb, OCIO_XYZ_TO_LINEAR_SRGB); - invert_m3_m3(imbuf_linear_srgb_to_xyz, imbuf_xyz_to_linear_srgb); + copy_m3_m3(imbuf_xyz_to_rec709, OCIO_XYZ_TO_REC709); + invert_m3_m3(imbuf_rec709_to_xyz, imbuf_xyz_to_rec709); + copy_m3_m3(imbuf_aces_to_xyz, OCIO_ACES_TO_XYZ); + invert_m3_m3(imbuf_xyz_to_aces, imbuf_aces_to_xyz); } static void colormanage_free_config(void) @@ -2370,14 +2376,14 @@ void IMB_colormanagement_color_picking_to_scene_linear_v3(float pixel[3]) void IMB_colormanagement_scene_linear_to_srgb_v3(float pixel[3]) { mul_m3_v3(imbuf_rgb_to_xyz, pixel); - mul_m3_v3(imbuf_xyz_to_linear_srgb, pixel); + mul_m3_v3(imbuf_xyz_to_rec709, pixel); linearrgb_to_srgb_v3_v3(pixel, pixel); } void IMB_colormanagement_srgb_to_scene_linear_v3(float pixel[3]) { srgb_to_linearrgb_v3_v3(pixel, pixel); - mul_m3_v3(imbuf_linear_srgb_to_xyz, pixel); + mul_m3_v3(imbuf_rec709_to_xyz, pixel); mul_m3_v3(imbuf_xyz_to_rgb, pixel); } diff --git a/source/blender/imbuf/intern/colormanagement_inline.c b/source/blender/imbuf/intern/colormanagement_inline.c index 411cf9af802..4c632da1520 100644 --- a/source/blender/imbuf/intern/colormanagement_inline.c +++ b/source/blender/imbuf/intern/colormanagement_inline.c @@ -37,4 +37,28 @@ void IMB_colormanagement_rgb_to_xyz(float xyz[3], const float rgb[3]) mul_v3_m3v3(xyz, imbuf_rgb_to_xyz, rgb); } +void IMB_colormanagement_rec709_to_rgb(float rgb[3], const float rec709[3]) +{ + mul_v3_m3v3(rgb, imbuf_rec709_to_xyz, rec709); + mul_v3_m3v3(rgb, imbuf_xyz_to_rgb, rgb); +} + +void IMB_colormanagement_rgb_to_rec709(float rec709[3], const float rgb[3]) +{ + mul_v3_m3v3(rec709, imbuf_rgb_to_xyz, rgb); + mul_v3_m3v3(rec709, imbuf_xyz_to_rec709, rec709); +} + +void IMB_colormanagement_aces_to_rgb(float rgb[3], const float aces[3]) +{ + mul_v3_m3v3(rgb, imbuf_aces_to_xyz, aces); + mul_v3_m3v3(rgb, imbuf_xyz_to_rgb, rgb); +} + +void IMB_colormanagement_rgb_to_aces(float aces[3], const float rgb[3]) +{ + mul_v3_m3v3(aces, imbuf_rgb_to_xyz, rgb); + mul_v3_m3v3(aces, imbuf_xyz_to_aces, aces); +} + #endif /* __IMB_COLORMANAGEMENT_INLINE_H__ */ diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 38d473f04dd..ec0a182e338 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -2195,7 +2195,7 @@ static void rna_def_mloopcol(BlenderRNA *brna) RNA_def_property_range(prop, 0.0f, 1.0f); RNA_def_property_float_funcs( prop, "rna_MeshLoopColor_color_get", "rna_MeshLoopColor_color_set", NULL); - RNA_def_property_ui_text(prop, "Color", ""); + RNA_def_property_ui_text(prop, "Color", "Color in sRGB color space"); RNA_def_property_update(prop, 0, "rna_Mesh_update_data_legacy_deg_tag_all"); } @@ -3210,7 +3210,9 @@ static void rna_def_mesh(BlenderRNA *brna) NULL); RNA_def_property_struct_type(prop, "MeshLoopColorLayer"); RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE); - RNA_def_property_ui_text(prop, "Vertex Colors", "All vertex colors"); + RNA_def_property_ui_text(prop, + "Vertex Colors", + "Legacy vertex color layers. Deprecated, use color attributes instead"); rna_def_loop_colors(brna, prop); /* Sculpt Vertex colors */ @@ -3228,7 +3230,9 @@ static void rna_def_mesh(BlenderRNA *brna) NULL); RNA_def_property_struct_type(prop, "MeshVertColorLayer"); RNA_def_property_override_flag(prop, PROPOVERRIDE_IGNORE); - RNA_def_property_ui_text(prop, "Sculpt Vertex Colors", "All vertex colors"); + RNA_def_property_ui_text(prop, + "Sculpt Vertex Colors", + "Sculpt vertex color layers. Deprecated, use color attributes instead"); rna_def_vert_colors(brna, prop); /* TODO: edge customdata layers (bmesh py api can access already). */ diff --git a/source/blender/python/mathutils/CMakeLists.txt b/source/blender/python/mathutils/CMakeLists.txt index 1be9b568626..747d6c0e8f8 100644 --- a/source/blender/python/mathutils/CMakeLists.txt +++ b/source/blender/python/mathutils/CMakeLists.txt @@ -4,6 +4,7 @@ set(INC . ../../blenkernel ../../blenlib + ../../imbuf ../../bmesh ../../depsgraph ../../makesdna @@ -42,6 +43,7 @@ set(SRC set(LIB bf_blenlib + bf_imbuf bf_python_ext ${PYTHON_LINKFLAGS} diff --git a/source/blender/python/mathutils/mathutils_Color.c b/source/blender/python/mathutils/mathutils_Color.c index 8b126639f10..1495a465432 100644 --- a/source/blender/python/mathutils/mathutils_Color.c +++ b/source/blender/python/mathutils/mathutils_Color.c @@ -14,6 +14,8 @@ #include "../generic/py_capi_utils.h" #include "../generic/python_utildefines.h" +#include "IMB_colormanagement.h" + #ifndef MATH_STANDALONE # include "BLI_dynstr.h" #endif @@ -76,6 +78,120 @@ static PyObject *Color_ToTupleExt(ColorObject *self, int ndigits) return ret; } +PyDoc_STRVAR(Color_from_scene_linear_to_srgb_doc, + ".. function:: from_scene_linear_to_srgb()\n" + "\n" + " Convert from scene linear to sRGB color space.\n" + "\n" + " :return: A color in sRGB color space.\n" + " :rtype: :class:`Color`\n"); +static PyObject *Color_from_scene_linear_to_srgb(ColorObject *self) +{ + float col[3] = {self->col[0], self->col[1], self->col[2]}; + IMB_colormanagement_scene_linear_to_srgb_v3(col); + return Color_CreatePyObject(col, Py_TYPE(self)); +} + +PyDoc_STRVAR(Color_from_srgb_to_scene_linear_doc, + ".. function:: from_srgb_to_scene_linear()\n" + "\n" + " Convert from sRGB to scene linear color space.\n" + "\n" + " :return: A color in scene linear color space.\n" + " :rtype: :class:`Color`\n"); +static PyObject *Color_from_srgb_to_scene_linear(ColorObject *self) +{ + float col[3] = {self->col[0], self->col[1], self->col[2]}; + IMB_colormanagement_srgb_to_scene_linear_v3(col); + return Color_CreatePyObject(col, Py_TYPE(self)); +} + +PyDoc_STRVAR(Color_from_scene_linear_to_xyz_d65_doc, + ".. function:: from_scene_linear_to_xyz_d65()\n" + "\n" + " Convert from scene linear to CIE XYZ (Illuminant D65) color space.\n" + "\n" + " :return: A color in XYZ color space.\n" + " :rtype: :class:`Color`\n"); +static PyObject *Color_from_scene_linear_to_xyz_d65(ColorObject *self) +{ + float col[3]; + IMB_colormanagement_rgb_to_xyz(col, self->col); + return Color_CreatePyObject(col, Py_TYPE(self)); +} + +PyDoc_STRVAR(Color_from_xyz_d65_to_scene_linear_doc, + ".. function:: from_xyz_d65_to_scene_linear()\n" + "\n" + " Convert from CIE XYZ (Illuminant D65) to scene linear color space.\n" + "\n" + " :return: A color in scene linear color space.\n" + " :rtype: :class:`Color`\n"); +static PyObject *Color_from_xyz_d65_to_scene_linear(ColorObject *self) +{ + float col[3]; + IMB_colormanagement_xyz_to_rgb(col, self->col); + return Color_CreatePyObject(col, Py_TYPE(self)); +} + +PyDoc_STRVAR(Color_from_scene_linear_to_aces_doc, + ".. function:: from_scene_linear_to_aces()\n" + "\n" + " Convert from scene linear to ACES2065-1 linear color space.\n" + "\n" + " :return: A color in ACES2065-1 linear color space.\n" + " :rtype: :class:`Color`\n"); +static PyObject *Color_from_scene_linear_to_aces(ColorObject *self) +{ + float col[3]; + IMB_colormanagement_rgb_to_aces(col, self->col); + return Color_CreatePyObject(col, Py_TYPE(self)); +} + +PyDoc_STRVAR(Color_from_aces_to_scene_linear_doc, + ".. function:: from_aces_to_scene_linear()\n" + "\n" + " Convert from ACES2065-1 linear to scene linear color space.\n" + "\n" + " :return: A color in scene linear color space.\n" + " :rtype: :class:`Color`\n"); +static PyObject *Color_from_aces_to_scene_linear(ColorObject *self) +{ + float col[3]; + IMB_colormanagement_aces_to_rgb(col, self->col); + return Color_CreatePyObject(col, Py_TYPE(self)); +} + +PyDoc_STRVAR(Color_from_scene_linear_to_rec709_linear_doc, + ".. function:: from_scene_linear_to_rec709_linear()\n" + "\n" + " Convert from scene linear to Rec.709 linear color space.\n" + "\n" + " :return: A color in Rec.709 linear color space.\n" + " :rtype: :class:`Color`\n"); +static PyObject *Color_from_scene_linear_to_rec709_linear(ColorObject *self) +{ + float col[3]; + IMB_colormanagement_rgb_to_rec709(col, self->col); + return Color_CreatePyObject(col, Py_TYPE(self)); +} + +PyDoc_STRVAR(Color_from_rec709_linear_to_scene_linear_doc, + ".. function:: from_rec709_linear_to_scene_linear()\n" + "\n" + " Convert from Rec.709 linear color space to scene linear color space.\n" + "\n" + " :return: A color in scene linear color space.\n" + " :rtype: :class:`Color`\n"); +static PyObject *Color_from_rec709_linear_to_scene_linear(ColorObject *self) +{ + float col[3]; + IMB_colormanagement_rec709_to_rgb(col, self->col); + return Color_CreatePyObject(col, Py_TYPE(self)); +} + +/* ---------------------------- Colorspace conversion -------------- */ + PyDoc_STRVAR(Color_copy_doc, ".. function:: copy()\n" "\n" @@ -869,17 +985,56 @@ static struct PyMethodDef Color_methods[] = { /* base-math methods */ {"freeze", (PyCFunction)BaseMathObject_freeze, METH_NOARGS, BaseMathObject_freeze_doc}, + + /* Colorspace methods. */ + {"from_scene_linear_to_srgb", + (PyCFunction)Color_from_scene_linear_to_srgb, + METH_NOARGS, + Color_from_scene_linear_to_srgb_doc}, + {"from_srgb_to_scene_linear", + (PyCFunction)Color_from_srgb_to_scene_linear, + METH_NOARGS, + Color_from_srgb_to_scene_linear_doc}, + {"from_scene_linear_to_xyz_d65", + (PyCFunction)Color_from_scene_linear_to_xyz_d65, + METH_NOARGS, + Color_from_scene_linear_to_xyz_d65_doc}, + {"from_xyz_d65_to_scene_linear", + (PyCFunction)Color_from_xyz_d65_to_scene_linear, + METH_NOARGS, + Color_from_xyz_d65_to_scene_linear_doc}, + {"from_scene_linear_to_aces", + (PyCFunction)Color_from_scene_linear_to_aces, + METH_NOARGS, + Color_from_scene_linear_to_aces_doc}, + {"from_aces_to_scene_linear", + (PyCFunction)Color_from_aces_to_scene_linear, + METH_NOARGS, + Color_from_aces_to_scene_linear_doc}, + {"from_scene_linear_to_rec709_linear", + (PyCFunction)Color_from_scene_linear_to_rec709_linear, + METH_NOARGS, + Color_from_scene_linear_to_rec709_linear_doc}, + {"from_rec709_linear_to_scene_linear", + (PyCFunction)Color_from_rec709_linear_to_scene_linear, + METH_NOARGS, + Color_from_rec709_linear_to_scene_linear_doc}, {NULL, NULL, 0, NULL}, }; /* ------------------PY_OBECT DEFINITION-------------------------- */ -PyDoc_STRVAR(color_doc, - ".. class:: Color(rgb)\n" - "\n" - " This object gives access to Colors in Blender.\n" - "\n" - " :param rgb: (r, g, b) color values\n" - " :type rgb: 3d vector\n"); +PyDoc_STRVAR( + color_doc, + ".. class:: Color(rgb)\n" + "\n" + " This object gives access to Colors in Blender.\n" + "\n" + " Most colors returned by Blender APIs are in scene linear color space, as defined by " + " the OpenColorIO configuration. The notable exception is user interface theming colors, " + " which are in sRGB color space.\n" + "\n" + " :param rgb: (r, g, b) color values\n" + " :type rgb: 3d vector\n"); PyTypeObject color_Type = { PyVarObject_HEAD_INIT(NULL, 0) "Color", /* tp_name */ sizeof(ColorObject), /* tp_basicsize */ |