Color management: Improve no-op color space detection

Make it so transform between color spaces which is a no-op does not
peroform any calculations.

This was initially found when working on #110941, but the issue can
be replicated easily by renaming "Linear" to "Linear Rec.709" and
adding alias as "Linear".

Doing so would result in a failure of the compositor_matte_test.
The reason for that is due to the image data-block still referring
to the "Linear" color space, the name-based comparison not detecting
that "Linear" and "Linear Rec.709" are the same spaces, and that the
cryptomatte requires bit-perfect floating point values.

Pull Request: https://projects.blender.org/blender/blender/pulls/110959
This commit is contained in:
Sergey Sharybin 2023-08-09 16:24:49 +02:00 committed by Sergey Sharybin
parent 5eef5b0d61
commit ba81908a2d
7 changed files with 49 additions and 3 deletions

View File

@ -77,6 +77,12 @@ struct FallbackTransform {
applyRGB(pixel);
}
bool isNoOp()
{
/* Rely on the short-circuiting based on name-space comparison in the IMB_colormanagement. */
return false;
}
TransformType type;
/* Scale transform. */
float scale;
@ -99,6 +105,11 @@ struct FallbackProcessor {
transform.applyRGBA(pixel);
}
bool isNoOp()
{
return transform.isNoOp();
}
FallbackTransform transform;
MEM_CXX_CLASS_ALLOC_FUNCS("FallbackProcessor");
@ -337,6 +348,11 @@ void FallbackImpl::processorRelease(OCIO_ConstProcessorRcPtr *processor)
delete (FallbackProcessor *)(processor);
}
bool FallbackImpl::cpuProcessorIsNoOp(OCIO_ConstCPUProcessorRcPtr *cpu_processor)
{
return ((FallbackProcessor *)cpu_processor)->isNoOp();
}
void FallbackImpl::cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img)
{

View File

@ -189,6 +189,11 @@ OCIO_ConstCPUProcessorRcPtr *OCIO_processorGetCPUProcessor(OCIO_ConstProcessorRc
return impl->processorGetCPUProcessor(processor);
}
bool OCIO_cpuProcessorIsNoOp(OCIO_ConstCPUProcessorRcPtr *cpu_processor)
{
return impl->cpuProcessorIsNoOp(cpu_processor);
}
void OCIO_cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img)
{
impl->cpuProcessorApply(cpu_processor, img);

View File

@ -151,6 +151,7 @@ OCIO_ConstProcessorRcPtr *OCIO_configGetProcessorWithNames(OCIO_ConstConfigRcPtr
void OCIO_processorRelease(OCIO_ConstProcessorRcPtr *cpu_processor);
OCIO_ConstCPUProcessorRcPtr *OCIO_processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor);
bool OCIO_cpuProcessorIsNoOp(OCIO_ConstCPUProcessorRcPtr *cpu_processor);
void OCIO_cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
struct OCIO_PackedImageDesc *img);
void OCIO_cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,

View File

@ -590,6 +590,11 @@ void OCIOImpl::cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_proc
}
}
bool OCIOImpl::cpuProcessorIsNoOp(OCIO_ConstCPUProcessorRcPtr *cpu_processor)
{
return (*(ConstCPUProcessorRcPtr *)cpu_processor)->isNoOp();
}
void OCIOImpl::cpuProcessorApplyRGB(OCIO_ConstCPUProcessorRcPtr *cpu_processor, float *pixel)
{
(*(ConstCPUProcessorRcPtr *)cpu_processor)->applyRGB(pixel);

View File

@ -63,6 +63,7 @@ class IOCIOImpl {
virtual void processorRelease(OCIO_ConstProcessorRcPtr *processor) = 0;
virtual OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *p) = 0;
virtual bool cpuProcessorIsNoOp(OCIO_ConstCPUProcessorRcPtr *cpu_processor) = 0;
virtual void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img) = 0;
virtual void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
@ -177,6 +178,7 @@ class FallbackImpl : public IOCIOImpl {
void processorRelease(OCIO_ConstProcessorRcPtr *processor);
OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor);
bool cpuProcessorIsNoOp(OCIO_ConstCPUProcessorRcPtr *cpu_processor);
void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img);
void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img);
@ -267,6 +269,7 @@ class OCIOImpl : public IOCIOImpl {
void processorRelease(OCIO_ConstProcessorRcPtr *processor);
OCIO_ConstCPUProcessorRcPtr *processorGetCPUProcessor(OCIO_ConstProcessorRcPtr *processor);
bool cpuProcessorIsNoOp(OCIO_ConstCPUProcessorRcPtr *cpu_processor);
void cpuProcessorApply(OCIO_ConstCPUProcessorRcPtr *cpu_processor, OCIO_PackedImageDesc *img);
void cpuProcessorApply_predivide(OCIO_ConstCPUProcessorRcPtr *cpu_processor,
OCIO_PackedImageDesc *img);

View File

@ -421,6 +421,7 @@ struct ColormanageProcessor *IMB_colormanagement_display_processor_new(
const struct ColorManagedDisplaySettings *display_settings);
struct ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(
const char *from_colorspace, const char *to_colorspace);
bool IMB_colormanagement_processor_is_noop(struct ColormanageProcessor *cm_processor);
void IMB_colormanagement_processor_apply_v4(struct ColormanageProcessor *cm_processor,
float pixel[4]);
void IMB_colormanagement_processor_apply_v4_predivide(struct ColormanageProcessor *cm_processor,

View File

@ -1930,8 +1930,6 @@ static void colormanagement_transform_ex(uchar *byte_buffer,
bool predivide,
bool do_threaded)
{
ColormanageProcessor *cm_processor;
if (from_colorspace[0] == '\0') {
return;
}
@ -1943,7 +1941,12 @@ static void colormanagement_transform_ex(uchar *byte_buffer,
return;
}
cm_processor = IMB_colormanagement_colorspace_processor_new(from_colorspace, to_colorspace);
ColormanageProcessor *cm_processor = IMB_colormanagement_colorspace_processor_new(
from_colorspace, to_colorspace);
if (IMB_colormanagement_processor_is_noop(cm_processor)) {
IMB_colormanagement_processor_free(cm_processor);
return;
}
if (do_threaded) {
processor_transform_apply_threaded(
@ -3851,6 +3854,18 @@ ColormanageProcessor *IMB_colormanagement_colorspace_processor_new(const char *f
return cm_processor;
}
bool IMB_colormanagement_processor_is_noop(ColormanageProcessor *cm_processor)
{
if (cm_processor->curve_mapping) {
/* Consider processor which has curve mapping as a non no-op.
* This is mainly for the simplicity of the check, since the current cases where this function
* is used the curve mapping is never assigned. */
return false;
}
return OCIO_cpuProcessorIsNoOp(cm_processor->cpu_processor);
}
void IMB_colormanagement_processor_apply_v4(ColormanageProcessor *cm_processor, float pixel[4])
{
if (cm_processor->curve_mapping) {