Color Management: Builtin support for ACEScg and Rec.2020 linear spaces
With new functions to convert to/from scene linear in the Python API. ACEScg in particular is common in USD and MaterialX files. Pull Request: https://projects.blender.org/blender/blender/pulls/145755
This commit is contained in:
@@ -110,6 +110,14 @@ BLI_INLINE void IMB_colormanagement_aces_to_scene_linear(float scene_linear[3],
|
||||
const float aces[3]);
|
||||
BLI_INLINE void IMB_colormanagement_scene_linear_to_aces(float aces[3],
|
||||
const float scene_linear[3]);
|
||||
BLI_INLINE void IMB_colormanagement_acescg_to_scene_linear(float scene_linear[3],
|
||||
const float acescg[3]);
|
||||
BLI_INLINE void IMB_colormanagement_scene_linear_to_acescg(float acescg[3],
|
||||
const float scene_linear[3]);
|
||||
BLI_INLINE void IMB_colormanagement_rec2020_to_scene_linear(float scene_linear[3],
|
||||
const float rec2020[3]);
|
||||
BLI_INLINE void IMB_colormanagement_scene_linear_to_rec2020(float rec2020[3],
|
||||
const float scene_linear[3]);
|
||||
blender::float3x3 IMB_colormanagement_get_xyz_to_scene_linear();
|
||||
blender::float3x3 IMB_colormanagement_get_scene_linear_to_xyz();
|
||||
|
||||
|
||||
@@ -26,8 +26,12 @@ extern blender::float3x3 imbuf_scene_linear_to_xyz;
|
||||
extern blender::float3x3 imbuf_xyz_to_scene_linear;
|
||||
extern blender::float3x3 imbuf_scene_linear_to_aces;
|
||||
extern blender::float3x3 imbuf_aces_to_scene_linear;
|
||||
extern blender::float3x3 imbuf_scene_linear_to_acescg;
|
||||
extern blender::float3x3 imbuf_acescg_to_scene_linear;
|
||||
extern blender::float3x3 imbuf_scene_linear_to_rec709;
|
||||
extern blender::float3x3 imbuf_rec709_to_scene_linear;
|
||||
extern blender::float3x3 imbuf_scene_linear_to_rec2020;
|
||||
extern blender::float3x3 imbuf_rec2020_to_scene_linear;
|
||||
extern bool imbuf_scene_linear_is_rec709;
|
||||
|
||||
#define MAX_COLORSPACE_NAME 64
|
||||
|
||||
@@ -98,8 +98,12 @@ float3x3 imbuf_scene_linear_to_xyz = float3x3::zero();
|
||||
float3x3 imbuf_xyz_to_scene_linear = float3x3::zero();
|
||||
float3x3 imbuf_scene_linear_to_rec709 = float3x3::zero();
|
||||
float3x3 imbuf_rec709_to_scene_linear = float3x3::zero();
|
||||
float3x3 imbuf_scene_linear_to_rec2020 = float3x3::zero();
|
||||
float3x3 imbuf_rec2020_to_scene_linear = float3x3::zero();
|
||||
float3x3 imbuf_scene_linear_to_aces = float3x3::zero();
|
||||
float3x3 imbuf_aces_to_scene_linear = float3x3::zero();
|
||||
float3x3 imbuf_scene_linear_to_acescg = float3x3::zero();
|
||||
float3x3 imbuf_acescg_to_scene_linear = float3x3::zero();
|
||||
bool imbuf_scene_linear_is_rec709 = false;
|
||||
|
||||
/* lock used by pre-cached processors getters, so processor wouldn't
|
||||
@@ -514,6 +518,31 @@ static bool colormanage_role_color_space_name_get(ocio::Config &config,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void colormanage_update_matrices()
|
||||
{
|
||||
/* Load luminance coefficients. */
|
||||
imbuf_luma_coefficients = g_config->get_default_luma_coefs();
|
||||
|
||||
/* Load standard color spaces. */
|
||||
imbuf_xyz_to_scene_linear = g_config->get_xyz_to_scene_linear_matrix();
|
||||
imbuf_scene_linear_to_xyz = math::invert(imbuf_xyz_to_scene_linear);
|
||||
|
||||
imbuf_scene_linear_to_rec709 = ocio::XYZ_TO_REC709 * imbuf_scene_linear_to_xyz;
|
||||
imbuf_rec709_to_scene_linear = math::invert(imbuf_scene_linear_to_rec709);
|
||||
|
||||
imbuf_scene_linear_to_rec2020 = ocio::XYZ_TO_REC2020 * imbuf_scene_linear_to_xyz;
|
||||
imbuf_rec2020_to_scene_linear = math::invert(imbuf_scene_linear_to_rec2020);
|
||||
|
||||
imbuf_aces_to_scene_linear = imbuf_xyz_to_scene_linear * ocio::ACES_TO_XYZ;
|
||||
imbuf_scene_linear_to_aces = math::invert(imbuf_aces_to_scene_linear);
|
||||
|
||||
imbuf_acescg_to_scene_linear = imbuf_xyz_to_scene_linear * ocio::ACESCG_TO_XYZ;
|
||||
imbuf_scene_linear_to_acescg = math::invert(imbuf_acescg_to_scene_linear);
|
||||
|
||||
imbuf_scene_linear_is_rec709 = math::is_equal(
|
||||
imbuf_scene_linear_to_rec709, float3x3::identity(), 0.0001f);
|
||||
}
|
||||
|
||||
static bool colormanage_load_config(ocio::Config &config)
|
||||
{
|
||||
bool ok = true;
|
||||
@@ -561,21 +590,7 @@ static bool colormanage_load_config(ocio::Config &config)
|
||||
}
|
||||
}
|
||||
|
||||
/* Load luminance coefficients. */
|
||||
imbuf_luma_coefficients = config.get_default_luma_coefs();
|
||||
|
||||
/* Load standard color spaces. */
|
||||
imbuf_xyz_to_scene_linear = config.get_xyz_to_scene_linear_matrix();
|
||||
imbuf_scene_linear_to_xyz = math::invert(imbuf_xyz_to_scene_linear);
|
||||
|
||||
imbuf_scene_linear_to_rec709 = ocio::XYZ_TO_REC709 * imbuf_scene_linear_to_xyz;
|
||||
imbuf_rec709_to_scene_linear = math::invert(imbuf_scene_linear_to_rec709);
|
||||
|
||||
imbuf_aces_to_scene_linear = imbuf_xyz_to_scene_linear * ocio::ACES_TO_XYZ;
|
||||
imbuf_scene_linear_to_aces = math::invert(imbuf_aces_to_scene_linear);
|
||||
|
||||
imbuf_scene_linear_is_rec709 = math::is_equal(
|
||||
imbuf_scene_linear_to_rec709, float3x3::identity(), 0.0001f);
|
||||
colormanage_update_matrices();
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -94,4 +94,24 @@ void IMB_colormanagement_scene_linear_to_aces(float aces[3], const float scene_l
|
||||
mul_v3_m3v3(aces, imbuf_scene_linear_to_aces.ptr(), scene_linear);
|
||||
}
|
||||
|
||||
void IMB_colormanagement_acescg_to_scene_linear(float scene_linear[3], const float acescg[3])
|
||||
{
|
||||
mul_v3_m3v3(scene_linear, imbuf_acescg_to_scene_linear.ptr(), acescg);
|
||||
}
|
||||
|
||||
void IMB_colormanagement_scene_linear_to_acescg(float acescg[3], const float scene_linear[3])
|
||||
{
|
||||
mul_v3_m3v3(acescg, imbuf_scene_linear_to_acescg.ptr(), scene_linear);
|
||||
}
|
||||
|
||||
void IMB_colormanagement_rec2020_to_scene_linear(float scene_linear[3], const float rec2020[3])
|
||||
{
|
||||
mul_v3_m3v3(scene_linear, imbuf_rec2020_to_scene_linear.ptr(), rec2020);
|
||||
}
|
||||
|
||||
void IMB_colormanagement_scene_linear_to_rec2020(float rec2020[3], const float scene_linear[3])
|
||||
{
|
||||
mul_v3_m3v3(rec2020, imbuf_scene_linear_to_rec2020.ptr(), scene_linear);
|
||||
}
|
||||
|
||||
#endif /* __IMB_COLORMANAGEMENT_INLINE_H__ */
|
||||
|
||||
@@ -15,10 +15,23 @@ static const float3x3 XYZ_TO_REC709{{3.2409699f, -0.9692436f, 0.0556301f},
|
||||
{-1.5373832f, 1.8759675f, -0.2039770f},
|
||||
{-0.4986108f, 0.0415551f, 1.0569715f}};
|
||||
|
||||
/* Standard XYZ (D65) to linear Rec.2020 transform. */
|
||||
/* Use four-digit constants instead of higher precisions to match sRGB and Rec.2020 standards.
|
||||
* See PR #141027 for details. */
|
||||
static const float3x3 XYZ_TO_REC2020{{1.7166512f, -0.6666844, 0.0176399f},
|
||||
{-0.3556708f, 1.6164812f, -0.0427706f},
|
||||
{-0.2533663f, 0.0157685f, 0.9421031f}};
|
||||
|
||||
/* Standard ACES to XYZ (D65) transform.
|
||||
* Matches OpenColorIO builtin transform: UTILITY - ACES-AP0_to_CIE-XYZ-D65_BFD. */
|
||||
static const float3x3 ACES_TO_XYZ = {{0.938280f, 0.337369f, 0.001174f},
|
||||
{-0.004451f, 0.729522f, -0.003711f},
|
||||
{0.016628f, -0.066890f, 1.091595f}};
|
||||
|
||||
/* Standard ACEScg to XYZ (D65) transform.
|
||||
* Matches OpenColorIO builtin transform: UTILITY - ACES-AP1_to_CIE-XYZ-D65_BFD. */
|
||||
static const float3x3 ACESCG_TO_XYZ = {{0.652238f, 0.267672f, -0.005382f},
|
||||
{0.128237f, 0.674340f, 0.001369f},
|
||||
{0.169983f, 0.057988f, 1.093071f}};
|
||||
|
||||
} // namespace blender::ocio
|
||||
|
||||
@@ -195,6 +195,38 @@ static PyObject *Color_from_aces_to_scene_linear(ColorObject *self)
|
||||
return Color_CreatePyObject(col, Py_TYPE(self));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(
|
||||
/* Wrap. */
|
||||
Color_from_scene_linear_to_acescg_doc,
|
||||
".. function:: from_scene_linear_to_acescg()\n"
|
||||
"\n"
|
||||
" Convert from scene linear to ACEScg linear color space.\n"
|
||||
"\n"
|
||||
" :return: A color in ACEScg linear color space.\n"
|
||||
" :rtype: :class:`Color`\n");
|
||||
static PyObject *Color_from_scene_linear_to_acescg(ColorObject *self)
|
||||
{
|
||||
float col[3];
|
||||
IMB_colormanagement_scene_linear_to_acescg(col, self->col);
|
||||
return Color_CreatePyObject(col, Py_TYPE(self));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(
|
||||
/* Wrap. */
|
||||
Color_from_acescg_to_scene_linear_doc,
|
||||
".. function:: from_acescg_to_scene_linear()\n"
|
||||
"\n"
|
||||
" Convert from ACEScg 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_acescg_to_scene_linear(ColorObject *self)
|
||||
{
|
||||
float col[3];
|
||||
IMB_colormanagement_acescg_to_scene_linear(col, self->col);
|
||||
return Color_CreatePyObject(col, Py_TYPE(self));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(
|
||||
/* Wrap. */
|
||||
Color_from_scene_linear_to_rec709_linear_doc,
|
||||
@@ -227,6 +259,38 @@ static PyObject *Color_from_rec709_linear_to_scene_linear(ColorObject *self)
|
||||
return Color_CreatePyObject(col, Py_TYPE(self));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(
|
||||
/* Wrap. */
|
||||
Color_from_scene_linear_to_rec2020_linear_doc,
|
||||
".. function:: from_scene_linear_to_rec2020_linear()\n"
|
||||
"\n"
|
||||
" Convert from scene linear to Rec.2020 linear color space.\n"
|
||||
"\n"
|
||||
" :return: A color in Rec.2020 linear color space.\n"
|
||||
" :rtype: :class:`Color`\n");
|
||||
static PyObject *Color_from_scene_linear_to_rec2020_linear(ColorObject *self)
|
||||
{
|
||||
float col[3];
|
||||
IMB_colormanagement_scene_linear_to_rec2020(col, self->col);
|
||||
return Color_CreatePyObject(col, Py_TYPE(self));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(
|
||||
/* Wrap. */
|
||||
Color_from_rec2020_linear_to_scene_linear_doc,
|
||||
".. function:: from_rec2020_linear_to_scene_linear()\n"
|
||||
"\n"
|
||||
" Convert from Rec.2020 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_rec2020_linear_to_scene_linear(ColorObject *self)
|
||||
{
|
||||
float col[3];
|
||||
IMB_colormanagement_rec2020_to_scene_linear(col, self->col);
|
||||
return Color_CreatePyObject(col, Py_TYPE(self));
|
||||
}
|
||||
|
||||
#endif /* !MATH_STANDALONE */
|
||||
|
||||
/** \} */
|
||||
@@ -1220,6 +1284,14 @@ static PyMethodDef Color_methods[] = {
|
||||
(PyCFunction)Color_from_aces_to_scene_linear,
|
||||
METH_NOARGS,
|
||||
Color_from_aces_to_scene_linear_doc},
|
||||
{"from_scene_linear_to_acescg",
|
||||
(PyCFunction)Color_from_scene_linear_to_acescg,
|
||||
METH_NOARGS,
|
||||
Color_from_scene_linear_to_acescg_doc},
|
||||
{"from_acescg_to_scene_linear",
|
||||
(PyCFunction)Color_from_acescg_to_scene_linear,
|
||||
METH_NOARGS,
|
||||
Color_from_acescg_to_scene_linear_doc},
|
||||
{"from_scene_linear_to_rec709_linear",
|
||||
(PyCFunction)Color_from_scene_linear_to_rec709_linear,
|
||||
METH_NOARGS,
|
||||
@@ -1228,6 +1300,14 @@ static PyMethodDef Color_methods[] = {
|
||||
(PyCFunction)Color_from_rec709_linear_to_scene_linear,
|
||||
METH_NOARGS,
|
||||
Color_from_rec709_linear_to_scene_linear_doc},
|
||||
{"from_scene_linear_to_rec2020_linear",
|
||||
(PyCFunction)Color_from_scene_linear_to_rec2020_linear,
|
||||
METH_NOARGS,
|
||||
Color_from_scene_linear_to_rec2020_linear_doc},
|
||||
{"from_rec2020_linear_to_scene_linear",
|
||||
(PyCFunction)Color_from_rec2020_linear_to_scene_linear,
|
||||
METH_NOARGS,
|
||||
Color_from_rec2020_linear_to_scene_linear_doc},
|
||||
#endif /* !MATH_STANDALONE */
|
||||
|
||||
{nullptr, nullptr, 0, nullptr},
|
||||
|
||||
Reference in New Issue
Block a user