Color management: add functions to detect scene linear and sRGB color spaces
Same as the ones in Cycles, but intended for GPU textures.
This commit is contained in:
@@ -114,11 +114,11 @@ ustring ColorSpaceManager::detect_known_colorspace(ustring colorspace,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Detect if it matches a simple builtin colorspace. */
|
/* Detect if it matches a simple builtin colorspace. */
|
||||||
bool is_no_op, is_srgb;
|
bool is_scene_linear, is_srgb;
|
||||||
is_builtin_colorspace(colorspace, is_no_op, is_srgb);
|
is_builtin_colorspace(colorspace, is_scene_linear, is_srgb);
|
||||||
|
|
||||||
thread_scoped_lock cache_lock(cache_mutex);
|
thread_scoped_lock cache_lock(cache_mutex);
|
||||||
if (is_no_op) {
|
if (is_scene_linear) {
|
||||||
VLOG(1) << "Colorspace " << colorspace.string() << " is no-op";
|
VLOG(1) << "Colorspace " << colorspace.string() << " is no-op";
|
||||||
cached_colorspaces[colorspace] = u_colorspace_raw;
|
cached_colorspaces[colorspace] = u_colorspace_raw;
|
||||||
return u_colorspace_raw;
|
return u_colorspace_raw;
|
||||||
@@ -154,17 +154,19 @@ ustring ColorSpaceManager::detect_known_colorspace(ustring colorspace,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ColorSpaceManager::is_builtin_colorspace(ustring colorspace, bool &is_no_op, bool &is_srgb)
|
void ColorSpaceManager::is_builtin_colorspace(ustring colorspace,
|
||||||
|
bool &is_scene_linear,
|
||||||
|
bool &is_srgb)
|
||||||
{
|
{
|
||||||
#ifdef WITH_OCIO
|
#ifdef WITH_OCIO
|
||||||
const OCIO::Processor *processor = (const OCIO::Processor *)get_processor(colorspace);
|
const OCIO::Processor *processor = (const OCIO::Processor *)get_processor(colorspace);
|
||||||
if (!processor) {
|
if (!processor) {
|
||||||
is_no_op = false;
|
is_scene_linear = false;
|
||||||
is_srgb = false;
|
is_srgb = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_no_op = true;
|
is_scene_linear = true;
|
||||||
is_srgb = true;
|
is_srgb = true;
|
||||||
for (int i = 0; i < 256; i++) {
|
for (int i = 0; i < 256; i++) {
|
||||||
float v = i / 255.0f;
|
float v = i / 255.0f;
|
||||||
@@ -181,27 +183,27 @@ void ColorSpaceManager::is_builtin_colorspace(ustring colorspace, bool &is_no_op
|
|||||||
/* Make sure that there is no channel crosstalk. */
|
/* Make sure that there is no channel crosstalk. */
|
||||||
if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
|
if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
|
||||||
fabsf(cG[2]) > 1e-5f || fabsf(cB[0]) > 1e-5f || fabsf(cB[1]) > 1e-5f) {
|
fabsf(cG[2]) > 1e-5f || fabsf(cB[0]) > 1e-5f || fabsf(cB[1]) > 1e-5f) {
|
||||||
is_no_op = false;
|
is_scene_linear = false;
|
||||||
is_srgb = false;
|
is_srgb = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Make sure that the three primaries combine linearly. */
|
/* Make sure that the three primaries combine linearly. */
|
||||||
if (!compare_floats(cR[0], cW[0], 1e-6f, 64) || !compare_floats(cG[1], cW[1], 1e-6f, 64) ||
|
if (!compare_floats(cR[0], cW[0], 1e-6f, 64) || !compare_floats(cG[1], cW[1], 1e-6f, 64) ||
|
||||||
!compare_floats(cB[2], cW[2], 1e-6f, 64)) {
|
!compare_floats(cB[2], cW[2], 1e-6f, 64)) {
|
||||||
is_no_op = false;
|
is_scene_linear = false;
|
||||||
is_srgb = false;
|
is_srgb = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Make sure that the three channels behave identically. */
|
/* Make sure that the three channels behave identically. */
|
||||||
if (!compare_floats(cW[0], cW[1], 1e-6f, 64) || !compare_floats(cW[1], cW[2], 1e-6f, 64)) {
|
if (!compare_floats(cW[0], cW[1], 1e-6f, 64) || !compare_floats(cW[1], cW[2], 1e-6f, 64)) {
|
||||||
is_no_op = false;
|
is_scene_linear = false;
|
||||||
is_srgb = false;
|
is_srgb = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
float out_v = average(make_float3(cW[0], cW[1], cW[2]));
|
float out_v = average(make_float3(cW[0], cW[1], cW[2]));
|
||||||
if (!compare_floats(v, out_v, 1e-6f, 64)) {
|
if (!compare_floats(v, out_v, 1e-6f, 64)) {
|
||||||
is_no_op = false;
|
is_scene_linear = false;
|
||||||
}
|
}
|
||||||
if (!compare_floats(color_srgb_to_linear(v), out_v, 1e-6f, 64)) {
|
if (!compare_floats(color_srgb_to_linear(v), out_v, 1e-6f, 64)) {
|
||||||
is_srgb = false;
|
is_srgb = false;
|
||||||
@@ -209,7 +211,7 @@ void ColorSpaceManager::is_builtin_colorspace(ustring colorspace, bool &is_no_op
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void)colorspace;
|
(void)colorspace;
|
||||||
is_no_op = false;
|
is_scene_linear = false;
|
||||||
is_srgb = false;
|
is_srgb = false;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@@ -363,6 +363,25 @@ int FallbackImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr * /*cs*/)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FallbackImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr * /*config*/,
|
||||||
|
OCIO_ConstColorSpaceRcPtr *cs,
|
||||||
|
bool &is_scene_linear,
|
||||||
|
bool &is_srgb)
|
||||||
|
{
|
||||||
|
if (cs == COLORSPACE_LINEAR) {
|
||||||
|
is_scene_linear = true;
|
||||||
|
is_srgb = false;
|
||||||
|
}
|
||||||
|
else if (cs == COLORSPACE_SRGB) {
|
||||||
|
is_scene_linear = false;
|
||||||
|
is_srgb = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
is_scene_linear = false;
|
||||||
|
is_srgb = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void FallbackImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr * /*cs*/)
|
void FallbackImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr * /*cs*/)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@@ -174,6 +174,14 @@ int OCIO_colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
|
|||||||
return impl->colorSpaceIsData(cs);
|
return impl->colorSpaceIsData(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OCIO_colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config,
|
||||||
|
OCIO_ConstColorSpaceRcPtr *cs,
|
||||||
|
bool *is_scene_linear,
|
||||||
|
bool *is_srgb)
|
||||||
|
{
|
||||||
|
impl->colorSpaceIsBuiltin(config, cs, *is_scene_linear, *is_srgb);
|
||||||
|
}
|
||||||
|
|
||||||
void OCIO_colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
|
void OCIO_colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
|
||||||
{
|
{
|
||||||
impl->colorSpaceRelease(cs);
|
impl->colorSpaceRelease(cs);
|
||||||
|
@@ -130,6 +130,10 @@ int OCIO_configGetIndexForColorSpace(OCIO_ConstConfigRcPtr *config, const char *
|
|||||||
|
|
||||||
int OCIO_colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs);
|
int OCIO_colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs);
|
||||||
int OCIO_colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs);
|
int OCIO_colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs);
|
||||||
|
void OCIO_colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config,
|
||||||
|
OCIO_ConstColorSpaceRcPtr *cs,
|
||||||
|
bool *is_scene_linear,
|
||||||
|
bool *is_srgb);
|
||||||
|
|
||||||
void OCIO_colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs);
|
void OCIO_colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs);
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <math.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -34,6 +35,8 @@ using namespace OCIO_NAMESPACE;
|
|||||||
|
|
||||||
#include "MEM_guardedalloc.h"
|
#include "MEM_guardedalloc.h"
|
||||||
|
|
||||||
|
#include "BLI_math_color.h"
|
||||||
|
|
||||||
#include "ocio_impl.h"
|
#include "ocio_impl.h"
|
||||||
|
|
||||||
#if !defined(WITH_ASSERT_ABORT)
|
#if !defined(WITH_ASSERT_ABORT)
|
||||||
@@ -520,6 +523,86 @@ int OCIOImpl::colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs)
|
|||||||
return (*(ConstColorSpaceRcPtr *)cs)->isData();
|
return (*(ConstColorSpaceRcPtr *)cs)->isData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static float compare_floats(float a, float b, float abs_diff, int ulp_diff)
|
||||||
|
{
|
||||||
|
/* Returns true if the absolute difference is smaller than abs_diff (for numbers near zero)
|
||||||
|
* or their relative difference is less than ulp_diff ULPs. Based on:
|
||||||
|
* https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ */
|
||||||
|
if (fabsf(a - b) < abs_diff) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((a < 0.0f) != (b < 0.0f)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (abs((*(int *)&a) - (*(int *)&b)) < ulp_diff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OCIOImpl::colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config_,
|
||||||
|
OCIO_ConstColorSpaceRcPtr *cs_,
|
||||||
|
bool &is_scene_linear,
|
||||||
|
bool &is_srgb)
|
||||||
|
{
|
||||||
|
ConstConfigRcPtr *config = (ConstConfigRcPtr *)config_;
|
||||||
|
ConstColorSpaceRcPtr *cs = (ConstColorSpaceRcPtr *)cs_;
|
||||||
|
ConstProcessorRcPtr processor;
|
||||||
|
|
||||||
|
try {
|
||||||
|
processor = (*config)->getProcessor((*cs)->getName(), "scene_linear");
|
||||||
|
}
|
||||||
|
catch (Exception &exception) {
|
||||||
|
OCIO_reportException(exception);
|
||||||
|
is_scene_linear = false;
|
||||||
|
is_srgb = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_scene_linear = true;
|
||||||
|
is_srgb = true;
|
||||||
|
for (int i = 0; i < 256; i++) {
|
||||||
|
float v = i / 255.0f;
|
||||||
|
|
||||||
|
float cR[3] = {v, 0, 0};
|
||||||
|
float cG[3] = {0, v, 0};
|
||||||
|
float cB[3] = {0, 0, v};
|
||||||
|
float cW[3] = {v, v, v};
|
||||||
|
processor->applyRGB(cR);
|
||||||
|
processor->applyRGB(cG);
|
||||||
|
processor->applyRGB(cB);
|
||||||
|
processor->applyRGB(cW);
|
||||||
|
|
||||||
|
/* Make sure that there is no channel crosstalk. */
|
||||||
|
if (fabsf(cR[1]) > 1e-5f || fabsf(cR[2]) > 1e-5f || fabsf(cG[0]) > 1e-5f ||
|
||||||
|
fabsf(cG[2]) > 1e-5f || fabsf(cB[0]) > 1e-5f || fabsf(cB[1]) > 1e-5f) {
|
||||||
|
is_scene_linear = false;
|
||||||
|
is_srgb = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Make sure that the three primaries combine linearly. */
|
||||||
|
if (!compare_floats(cR[0], cW[0], 1e-6f, 64) || !compare_floats(cG[1], cW[1], 1e-6f, 64) ||
|
||||||
|
!compare_floats(cB[2], cW[2], 1e-6f, 64)) {
|
||||||
|
is_scene_linear = false;
|
||||||
|
is_srgb = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Make sure that the three channels behave identically. */
|
||||||
|
if (!compare_floats(cW[0], cW[1], 1e-6f, 64) || !compare_floats(cW[1], cW[2], 1e-6f, 64)) {
|
||||||
|
is_scene_linear = false;
|
||||||
|
is_srgb = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
float out_v = (cW[0] + cW[1] + cW[2]) * (1.0f / 3.0f);
|
||||||
|
if (!compare_floats(v, out_v, 1e-6f, 64)) {
|
||||||
|
is_scene_linear = false;
|
||||||
|
}
|
||||||
|
if (!compare_floats(srgb_to_linearrgb(v), out_v, 1e-6f, 64)) {
|
||||||
|
is_srgb = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
|
void OCIOImpl::colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs)
|
||||||
{
|
{
|
||||||
OBJECT_GUARDED_DELETE((ConstColorSpaceRcPtr *)cs, ConstColorSpaceRcPtr);
|
OBJECT_GUARDED_DELETE((ConstColorSpaceRcPtr *)cs, ConstColorSpaceRcPtr);
|
||||||
|
@@ -44,6 +44,10 @@ class IOCIOImpl {
|
|||||||
|
|
||||||
virtual int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs) = 0;
|
virtual int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs) = 0;
|
||||||
virtual int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs) = 0;
|
virtual int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs) = 0;
|
||||||
|
virtual void colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config,
|
||||||
|
OCIO_ConstColorSpaceRcPtr *cs,
|
||||||
|
bool &is_scene_linear,
|
||||||
|
bool &is_srgb) = 0;
|
||||||
|
|
||||||
virtual void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs) = 0;
|
virtual void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs) = 0;
|
||||||
|
|
||||||
@@ -160,6 +164,10 @@ class FallbackImpl : public IOCIOImpl {
|
|||||||
|
|
||||||
int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs);
|
int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs);
|
||||||
int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs);
|
int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs);
|
||||||
|
void colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config,
|
||||||
|
OCIO_ConstColorSpaceRcPtr *cs,
|
||||||
|
bool &is_scene_linear,
|
||||||
|
bool &is_srgb);
|
||||||
|
|
||||||
void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs);
|
void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs);
|
||||||
|
|
||||||
@@ -266,6 +274,10 @@ class OCIOImpl : public IOCIOImpl {
|
|||||||
|
|
||||||
int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs);
|
int colorSpaceIsInvertible(OCIO_ConstColorSpaceRcPtr *cs);
|
||||||
int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs);
|
int colorSpaceIsData(OCIO_ConstColorSpaceRcPtr *cs);
|
||||||
|
void colorSpaceIsBuiltin(OCIO_ConstConfigRcPtr *config,
|
||||||
|
OCIO_ConstColorSpaceRcPtr *cs,
|
||||||
|
bool &is_scene_linear,
|
||||||
|
bool &is_srgb);
|
||||||
|
|
||||||
void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs);
|
void colorSpaceRelease(OCIO_ConstColorSpaceRcPtr *cs);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user