From 7d829e58d375cc7ab79a107fe3c97a589c115a6b Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Tue, 2 Sep 2025 11:40:23 +0200 Subject: [PATCH] Refactor: Move linear color space matrices from imbuf to blenlib We want to be able to use them in BLI_color.hh. Pull Request: https://projects.blender.org/blender/blender/pulls/145755 --- source/blender/blenlib/BLI_colorspace.hh | 38 +++++++++++++ source/blender/blenlib/CMakeLists.txt | 2 + .../blender/blenlib/intern/BLI_colorspace.cc | 35 ++++++++++++ .../intern/IMB_colormanagement_intern.hh | 13 ----- .../blender/imbuf/intern/colormanagement.cc | 57 +++++++++---------- .../imbuf/intern/colormanagement_inline.h | 39 ++++++------- 6 files changed, 121 insertions(+), 63 deletions(-) create mode 100644 source/blender/blenlib/BLI_colorspace.hh create mode 100644 source/blender/blenlib/intern/BLI_colorspace.cc diff --git a/source/blender/blenlib/BLI_colorspace.hh b/source/blender/blenlib/BLI_colorspace.hh new file mode 100644 index 00000000000..033be6fc08b --- /dev/null +++ b/source/blender/blenlib/BLI_colorspace.hh @@ -0,0 +1,38 @@ +/* SPDX-FileCopyrightText: 2025 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup bli + */ + +#pragma once + +#include "BLI_math_matrix_types.hh" +#include "BLI_math_vector_types.hh" + +namespace blender { + +namespace colorspace { + +/* Coefficients to compute luma from RGB. */ +extern float3 luma_coefficients; + +/* Conversion between scene linear and common linear spaces. */ +extern float3x3 scene_linear_to_xyz; +extern float3x3 xyz_to_scene_linear; +extern float3x3 scene_linear_to_aces; +extern float3x3 aces_to_scene_linear; +extern float3x3 scene_linear_to_acescg; +extern float3x3 acescg_to_scene_linear; +extern float3x3 scene_linear_to_rec709; +extern float3x3 rec709_to_scene_linear; +extern float3x3 scene_linear_to_rec2020; +extern float3x3 rec2020_to_scene_linear; + +/* For fast path when converting to/from sRGB. */ +extern bool scene_linear_is_rec709; + +}; // namespace colorspace + +} // namespace blender diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 6cc82531d0a..e35d42a510d 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -22,6 +22,7 @@ set(INC_SYS set(SRC intern/BLI_assert.cc intern/BLI_color.cc + intern/BLI_colorspace.cc intern/BLI_dial_2d.cc intern/BLI_dynstr.cc intern/BLI_filelist.cc @@ -204,6 +205,7 @@ set(SRC BLI_cache_mutex.hh BLI_color.hh BLI_color_mix.hh + BLI_colorspace.hh BLI_compiler_attrs.h BLI_compiler_compat.h BLI_compiler_typecheck.h diff --git a/source/blender/blenlib/intern/BLI_colorspace.cc b/source/blender/blenlib/intern/BLI_colorspace.cc new file mode 100644 index 00000000000..a843f19b6aa --- /dev/null +++ b/source/blender/blenlib/intern/BLI_colorspace.cc @@ -0,0 +1,35 @@ +/* SPDX-FileCopyrightText: 2025 Blender Authors + * + * SPDX-License-Identifier: GPL-2.0-or-later */ + +/** \file + * \ingroup bli + */ + +#include "BLI_colorspace.hh" + +namespace blender { + +namespace colorspace { + +/* These are initialized in colormanagement.cc based on the OpenColorIO config, + * but until then default to Rec.709 scene linear. */ + +float3 luma_coefficients(0.2126f, 0.7152f, 0.0722f); + +float3x3 scene_linear_to_rec709 = float3x3::identity(); +float3x3 rec709_to_scene_linear = float3x3::identity(); +bool scene_linear_is_rec709 = true; + +float3x3 scene_linear_to_xyz = float3x3::zero(); +float3x3 xyz_to_scene_linear = float3x3::zero(); +float3x3 scene_linear_to_rec2020 = float3x3::zero(); +float3x3 rec2020_to_scene_linear = float3x3::zero(); +float3x3 scene_linear_to_aces = float3x3::zero(); +float3x3 aces_to_scene_linear = float3x3::zero(); +float3x3 scene_linear_to_acescg = float3x3::zero(); +float3x3 acescg_to_scene_linear = float3x3::zero(); + +}; // namespace colorspace + +} // namespace blender diff --git a/source/blender/imbuf/intern/IMB_colormanagement_intern.hh b/source/blender/imbuf/intern/IMB_colormanagement_intern.hh index 0f0f005840f..178a2a7dd0c 100644 --- a/source/blender/imbuf/intern/IMB_colormanagement_intern.hh +++ b/source/blender/imbuf/intern/IMB_colormanagement_intern.hh @@ -21,19 +21,6 @@ using ColorSpace = blender::ocio::ColorSpace; struct ImBuf; -extern blender::float3 imbuf_luma_coefficients; -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 /* ** Initialization / De-initialization ** */ diff --git a/source/blender/imbuf/intern/colormanagement.cc b/source/blender/imbuf/intern/colormanagement.cc index 695a4948d6d..c8ff3a05880 100644 --- a/source/blender/imbuf/intern/colormanagement.cc +++ b/source/blender/imbuf/intern/colormanagement.cc @@ -6,7 +6,6 @@ * \ingroup imbuf */ -#include "BLI_string_ref.hh" #include "IMB_colormanagement.hh" #include "IMB_colormanagement_intern.hh" @@ -30,6 +29,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_colorspace.hh" #include "BLI_fileops.hh" #include "BLI_listbase.h" #include "BLI_math_color.h" @@ -39,6 +39,7 @@ #include "BLI_math_vector_types.hh" #include "BLI_path_utils.hh" #include "BLI_rect.h" +#include "BLI_string_ref.hh" #include "BLI_string_utf8.h" #include "BLI_task.hh" #include "BLI_threads.h" @@ -91,21 +92,6 @@ static char global_role_default_float[MAX_COLORSPACE_NAME]; static char global_role_default_sequencer[MAX_COLORSPACE_NAME]; static char global_role_aces_interchange[MAX_COLORSPACE_NAME]; -/* Luma coefficients and XYZ to RGB to be initialized by OCIO. */ - -float3 imbuf_luma_coefficients(0.0f); -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 * be created several times * LOCK_COLORMANAGE can not be used since this mutex could be needed to @@ -521,26 +507,35 @@ static bool colormanage_role_color_space_name_get(ocio::Config &config, static void colormanage_update_matrices() { /* Load luminance coefficients. */ - imbuf_luma_coefficients = g_config->get_default_luma_coefs(); + blender::colorspace::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); + blender::colorspace::xyz_to_scene_linear = g_config->get_xyz_to_scene_linear_matrix(); + blender::colorspace::scene_linear_to_xyz = math::invert( + blender::colorspace::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); + blender::colorspace::scene_linear_to_rec709 = ocio::XYZ_TO_REC709 * + blender::colorspace::scene_linear_to_xyz; + blender::colorspace::rec709_to_scene_linear = math::invert( + blender::colorspace::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); + blender::colorspace::scene_linear_to_rec2020 = ocio::XYZ_TO_REC2020 * + blender::colorspace::scene_linear_to_xyz; + blender::colorspace::rec2020_to_scene_linear = math::invert( + blender::colorspace::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); + blender::colorspace::aces_to_scene_linear = blender::colorspace::xyz_to_scene_linear * + ocio::ACES_TO_XYZ; + blender::colorspace::scene_linear_to_aces = math::invert( + blender::colorspace::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); + blender::colorspace::acescg_to_scene_linear = blender::colorspace::xyz_to_scene_linear * + ocio::ACESCG_TO_XYZ; + blender::colorspace::scene_linear_to_acescg = math::invert( + blender::colorspace::acescg_to_scene_linear); - imbuf_scene_linear_is_rec709 = math::is_equal( - imbuf_scene_linear_to_rec709, float3x3::identity(), 0.0001f); + blender::colorspace::scene_linear_is_rec709 = math::is_equal( + blender::colorspace::scene_linear_to_rec709, float3x3::identity(), 0.0001f); } static bool colormanage_load_config(ocio::Config &config) @@ -1372,12 +1367,12 @@ const ColorSpace *IMB_colormanagement_space_from_interop_id(StringRefNull intero blender::float3x3 IMB_colormanagement_get_xyz_to_scene_linear() { - return blender::float3x3(imbuf_xyz_to_scene_linear); + return blender::float3x3(blender::colorspace::xyz_to_scene_linear); } blender::float3x3 IMB_colormanagement_get_scene_linear_to_xyz() { - return blender::float3x3(imbuf_scene_linear_to_xyz); + return blender::float3x3(blender::colorspace::scene_linear_to_xyz); } /** \} */ diff --git a/source/blender/imbuf/intern/colormanagement_inline.h b/source/blender/imbuf/intern/colormanagement_inline.h index 0fc83e965e6..8177b3f9020 100644 --- a/source/blender/imbuf/intern/colormanagement_inline.h +++ b/source/blender/imbuf/intern/colormanagement_inline.h @@ -9,6 +9,7 @@ #ifndef __IMB_COLORMANAGEMENT_INLINE_C__ #define __IMB_COLORMANAGEMENT_INLINE_C__ +#include "BLI_colorspace.hh" #include "BLI_math_color.h" #include "BLI_math_matrix.h" #include "BLI_math_vector.h" @@ -16,12 +17,12 @@ void IMB_colormanagement_get_luminance_coefficients(float r_rgb[3]) { - copy_v3_v3(r_rgb, imbuf_luma_coefficients); + copy_v3_v3(r_rgb, blender::colorspace::luma_coefficients); } float IMB_colormanagement_get_luminance(const float rgb[3]) { - return dot_v3v3(imbuf_luma_coefficients, rgb); + return dot_v3v3(blender::colorspace::luma_coefficients, rgb); } uchar IMB_colormanagement_get_luminance_byte(const uchar rgb[3]) @@ -30,48 +31,48 @@ uchar IMB_colormanagement_get_luminance_byte(const uchar rgb[3]) float val; rgb_uchar_to_float(rgbf, rgb); - val = dot_v3v3(imbuf_luma_coefficients, rgbf); + val = dot_v3v3(blender::colorspace::luma_coefficients, rgbf); return unit_float_to_uchar_clamp(val); } void IMB_colormanagement_xyz_to_scene_linear(float scene_linear[3], const float xyz[3]) { - mul_v3_m3v3(scene_linear, imbuf_xyz_to_scene_linear.ptr(), xyz); + mul_v3_m3v3(scene_linear, blender::colorspace::xyz_to_scene_linear.ptr(), xyz); } void IMB_colormanagement_scene_linear_to_xyz(float xyz[3], const float scene_linear[3]) { - mul_v3_m3v3(xyz, imbuf_scene_linear_to_xyz.ptr(), scene_linear); + mul_v3_m3v3(xyz, blender::colorspace::scene_linear_to_xyz.ptr(), scene_linear); } void IMB_colormanagement_rec709_to_scene_linear(float scene_linear[3], const float rec709[3]) { - if (imbuf_scene_linear_is_rec709) { + if (blender::colorspace::scene_linear_is_rec709) { copy_v3_v3(scene_linear, rec709); } else { - mul_v3_m3v3(scene_linear, imbuf_rec709_to_scene_linear.ptr(), rec709); + mul_v3_m3v3(scene_linear, blender::colorspace::rec709_to_scene_linear.ptr(), rec709); } } void IMB_colormanagement_scene_linear_to_rec709(float rec709[3], const float scene_linear[3]) { - if (imbuf_scene_linear_is_rec709) { + if (blender::colorspace::scene_linear_is_rec709) { copy_v3_v3(rec709, scene_linear); } else { - mul_v3_m3v3(rec709, imbuf_scene_linear_to_rec709.ptr(), scene_linear); + mul_v3_m3v3(rec709, blender::colorspace::scene_linear_to_rec709.ptr(), scene_linear); } } void IMB_colormanagement_scene_linear_to_srgb_v3(float srgb[3], const float scene_linear[3]) { - if (imbuf_scene_linear_is_rec709) { + if (blender::colorspace::scene_linear_is_rec709) { copy_v3_v3(srgb, scene_linear); } else { - mul_v3_m3v3(srgb, imbuf_scene_linear_to_rec709.ptr(), scene_linear); + mul_v3_m3v3(srgb, blender::colorspace::scene_linear_to_rec709.ptr(), scene_linear); } linearrgb_to_srgb_v3_v3(srgb, srgb); } @@ -79,39 +80,39 @@ void IMB_colormanagement_scene_linear_to_srgb_v3(float srgb[3], const float scen void IMB_colormanagement_srgb_to_scene_linear_v3(float scene_linear[3], const float srgb[3]) { srgb_to_linearrgb_v3_v3(scene_linear, srgb); - if (!imbuf_scene_linear_is_rec709) { - mul_m3_v3(imbuf_rec709_to_scene_linear.ptr(), scene_linear); + if (!blender::colorspace::scene_linear_is_rec709) { + mul_m3_v3(blender::colorspace::rec709_to_scene_linear.ptr(), scene_linear); } } void IMB_colormanagement_aces_to_scene_linear(float scene_linear[3], const float aces[3]) { - mul_v3_m3v3(scene_linear, imbuf_aces_to_scene_linear.ptr(), aces); + mul_v3_m3v3(scene_linear, blender::colorspace::aces_to_scene_linear.ptr(), aces); } void IMB_colormanagement_scene_linear_to_aces(float aces[3], const float scene_linear[3]) { - mul_v3_m3v3(aces, imbuf_scene_linear_to_aces.ptr(), scene_linear); + mul_v3_m3v3(aces, blender::colorspace::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); + mul_v3_m3v3(scene_linear, blender::colorspace::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); + mul_v3_m3v3(acescg, blender::colorspace::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); + mul_v3_m3v3(scene_linear, blender::colorspace::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); + mul_v3_m3v3(rec2020, blender::colorspace::scene_linear_to_rec2020.ptr(), scene_linear); } #endif /* __IMB_COLORMANAGEMENT_INLINE_H__ */