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
This commit is contained in:
Brecht Van Lommel
2025-09-02 11:40:23 +02:00
parent ea0fab21d4
commit 7d829e58d3
6 changed files with 121 additions and 63 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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 ** */

View File

@@ -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);
}
/** \} */

View File

@@ -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__ */