diff options
author | Brecht Van Lommel <brecht@blender.org> | 2022-05-19 21:31:58 +0300 |
---|---|---|
committer | Brecht Van Lommel <brecht@blender.org> | 2022-05-23 16:34:50 +0300 |
commit | 469ee7ff1529a1b28ce0b300835ebc42d5c5362f (patch) | |
tree | 9be3874673f222ac3c3773fe726f0158287ac1e6 /source/blender/python | |
parent | 2f2d13b8c664b90a7d3249d6ad71bac3d519026d (diff) |
Python API: add mathutils.Color functions to convert color spaces
Between scene linear and sRGB, XYZ, linear Rec.709 and ACES2065-1.
And add some clarifications about color spaces in the docs.
Fixes T98267
Ref T68926
Differential Revision: https://developer.blender.org/D14989
Diffstat (limited to 'source/blender/python')
-rw-r--r-- | source/blender/python/mathutils/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/python/mathutils/mathutils_Color.c | 169 |
2 files changed, 164 insertions, 7 deletions
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 */ |