diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml index d5a4454aef..2be4d92f6e 100644 --- a/.github/workflows/analysis.yml +++ b/.github/workflows/analysis.yml @@ -40,7 +40,7 @@ jobs: fail-fast: false matrix: include: - - desc: sonar gcc9/C++14 py39 boost1.76 exr3.1 ocio2.1 + - desc: sonar gcc9/C++14 py39 boost1.76 exr3.1 ocio2.2 nametag: static-analysis-sonar os: ubuntu-latest vfxyear: 2022 @@ -62,6 +62,7 @@ jobs: CODECOV=1 CTEST_TEST_TIMEOUT=1200 OIIO_CMAKE_FLAGS="-DOIIO_TEX_IMPLEMENT_VARYINGREF=OFF" + OPENCOLORIO_VERSION=v2.2.0 runs-on: ${{ matrix.os }} container: diff --git a/src/build-scripts/ci-startup.bash b/src/build-scripts/ci-startup.bash index 8b2d544307..49089e5b7a 100755 --- a/src/build-scripts/ci-startup.bash +++ b/src/build-scripts/ci-startup.bash @@ -46,7 +46,7 @@ export LD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib64:$LD_LIBRARY_PATH export DYLD_LIBRARY_PATH=${LOCAL_DEPS_DIR}/dist/lib:$DYLD_LIBRARY_PATH -export OCIO="$PWD/testsuite/common/OpenColorIO/nuke-default/config.ocio" +# export OCIO="$PWD/testsuite/common/OpenColorIO/nuke-default/config.ocio" export TESTSUITE_CLEANUP_ON_SUCCESS=${TESTSUITE_CLEANUP_ON_SUCCESS:=1} mkdir -p build dist diff --git a/src/build-scripts/ci-test.bash b/src/build-scripts/ci-test.bash index 1ed20c7c50..8d0e1325f8 100755 --- a/src/build-scripts/ci-test.bash +++ b/src/build-scripts/ci-test.bash @@ -15,6 +15,8 @@ echo ; echo "Results of oiiotool --version:" $OpenImageIO_ROOT/bin/oiiotool --version || true echo ; echo "Results of oiiotool --help:" $OpenImageIO_ROOT/bin/oiiotool --help || true +echo ; echo "Results of oiiotool --colorconfiginfo:" +$OpenImageIO_ROOT/bin/oiiotool --colorconfiginfo echo ; echo "Results of oiiotool with no args (should get short help message):" $OpenImageIO_ROOT/bin/oiiotool || true echo ; echo "Run unit tests and simple stats:" diff --git a/src/cmake/externalpackages.cmake b/src/cmake/externalpackages.cmake index 48e871418a..526da81de7 100644 --- a/src/cmake/externalpackages.cmake +++ b/src/cmake/externalpackages.cmake @@ -178,9 +178,16 @@ checked_find_package (OpenColorIO DEFINITIONS -DUSE_OCIO=1 -DUSE_OPENCOLORIO=1 # PREFER_CONFIG ) -if (NOT OpenColorIO_FOUND) +if (OpenColorIO_FOUND) + option (OIIO_DISABLE_BUILTIN_OCIO_CONFIGS + "For deveoper debugging/testing ONLY! Disable OCIO 2.2 builtin configs." OFF) + if (OIIO_DISABLE_BUILTIN_OCIO_CONFIGS OR "$ENV{OIIO_DISABLE_BUILTIN_OCIO_CONFIGS}") + add_compile_definitions(OIIO_DISABLE_BUILTIN_OCIO_CONFIGS) + endif () +else () set (OpenColorIO_FOUND 0) endif () + checked_find_package (OpenCV 3.0 DEFINITIONS -DUSE_OPENCV=1) diff --git a/src/cmake/testing.cmake b/src/cmake/testing.cmake index ac2520692a..c8ca9dab4e 100644 --- a/src/cmake/testing.cmake +++ b/src/cmake/testing.cmake @@ -69,7 +69,8 @@ macro (oiio_add_tests) set (_test_disabled 1) endif () endforeach () - if (0 AND OpenColorIO_VERSION VERSION_GREATER_EQUAL 2.2) + if (OpenColorIO_VERSION VERSION_GREATER_EQUAL 2.2 + AND NOT (OIIO_DISABLE_BUILTIN_OCIO_CONFIGS OR "$ENV{OIIO_DISABLE_BUILTIN_OCIO_CONFIGS}")) # For OCIO 2.2+, have the testsuite use the default built-in config list (APPEND _ats_ENVIRONMENT "OCIO=ocio://default" "OIIO_TESTSUITE_OCIOCONFIG=ocio://default") diff --git a/src/doc/builtinplugins.rst b/src/doc/builtinplugins.rst index 91c15cc031..86ff154590 100644 --- a/src/doc/builtinplugins.rst +++ b/src/doc/builtinplugins.rst @@ -676,7 +676,8 @@ preferred except when legacy file access is required. - encodes the orientation (see Section :ref:`sec-metadata-orientation`) * - ``oiio:ColorSpace`` - string - - Color space (see Section :ref:`sec-metadata-color`). + - Color space (see Section :ref:`sec-metadata-color`). We currently + assume that any RGBE files encountered are linear with sRGB primaries. * - ``oiio:Gamma`` - float - the gamma correction specified in the RGBE header (if it's gamma corrected). diff --git a/src/doc/imageoutput.rst b/src/doc/imageoutput.rst index ffbd464472..2d1e7dface 100644 --- a/src/doc/imageoutput.rst +++ b/src/doc/imageoutput.rst @@ -906,25 +906,26 @@ The color space hints only describe color channels. You should always pass alpha, depth, or other non-color channels with linear values. Here is a simple example of setting up the ``ImageSpec`` when you know that -the pixel values you are writing are linear: +the pixel values you are writing are in your default linear scene-referred +color space: .. tabs:: .. code-tab:: c++ ImageSpec spec (width, length, channels, format); - spec.attribute ("oiio:ColorSpace", "Linear"); + spec.attribute ("oiio:ColorSpace", "scene_linear"); .. code-tab:: py spec = ImageSpec(width, length, channels, format) - spec.attribute ("oiio:ColorSpace", "Linear") + spec.attribute ("oiio:ColorSpace", "scene_linear") If a particular ``ImageOutput`` implementation is required (by the rules of -the file format it writes) to have pixels in a particular color space, +the file format it writes) to have pixels in a fixed color space, then it should try to convert the color values of your image to the right color space if it is not already in that space. For example, JPEG images -must be in sRGB space, so if you declare your pixels to be ``"Linear"``, +must be in sRGB space, so if you declare your pixels to be ``"scene_linear"``, the JPEG ``ImageOutput`` will convert to sRGB. If you leave the ``"oiio:ColorSpace"`` unset, the values will not be diff --git a/src/doc/oiiotool.rst b/src/doc/oiiotool.rst index 4fde8aa5f3..ac0d8eb218 100644 --- a/src/doc/oiiotool.rst +++ b/src/doc/oiiotool.rst @@ -4004,14 +4004,17 @@ versa). If you ask for :program:`oiiotool` help (`oiiotool --help`), at the very bottom you will see the list of all color spaces, looks, and displays that -:program:`oiiotool` knows about. +:program:`oiiotool` knows about. That information (including even more detail) +will be printed with the command `oiiotool --colorconfiginfo`. -.. option:: --iscolorspace +.. option:: --colorconfiginfo - Alter the metadata of the current image so that it thinks its pixels are - in the named color space. This does not alter the pixels of the image, - it only changes :program:`oiiotool`'s understanding of what color space - those those pixels are in. + Print to the console extensive information about the color management + configuration, including the list of all known color spaces (and their + aliases), looks, displays (and their views), as well as which version + of OpenColorIO is being used, and the path to the configuration file. + + This command was added in OIIO 2.4.6. .. option:: --colorconfig @@ -4019,6 +4022,13 @@ bottom you will see the list of all color spaces, looks, and displays that location. Without this, the default is to use the `$OCIO` environment variable as a guide for the location of the configuration file. +.. option:: --iscolorspace + + Alter the metadata of the current image so that it thinks its pixels are + in the named color space. This does not alter the pixels of the image, + it only changes :program:`oiiotool`'s understanding of what color space + those those pixels are in. + .. option:: --colorconvert Replace the current image with a new image whose pixels are transformed diff --git a/src/doc/pythonbindings.rst b/src/doc/pythonbindings.rst index 55e8aaddca..b91ea6b058 100644 --- a/src/doc/pythonbindings.rst +++ b/src/doc/pythonbindings.rst @@ -3532,7 +3532,7 @@ Color manipulation .. code-block:: python Src = ImageBuf ("tahoe.jpg") - Dst = ImageBufAlgo.colorconvert (Src, "sRGB", "linear") + Dst = ImageBufAlgo.colorconvert (Src, "sRGB", "scene_linear") diff --git a/src/doc/stdmetadata.rst b/src/doc/stdmetadata.rst index 7ec1d36e2b..0da00b176e 100644 --- a/src/doc/stdmetadata.rst +++ b/src/doc/stdmetadata.rst @@ -136,12 +136,18 @@ Color information The name of the color space of the color channels. Values include: - - `"Linear"` : Color pixel values are known to be scene-linear and - using facility-default color primaries (presumed sRGB/Rec709 color - primaries if otherwise unknown. + - `"scene_linear"` : Color pixel values are known to be scene-linear and + using facility-default color primaries as defined by the OpenColorIO + configuration. Note that `"linear"` is treated as a synonym. (Note: when + no color config is found, this are presumed to use sRGB/Rec709 color + primaries when built against OpenColorIO 2.1 or earlier, or when no OCIO + support is available, but is presumed to be ACEScg when built against + OCIO 2.2 or higher and using its built-in config.) + - `"lin_srgb"` : Color pixel values are known to be linear and + using sRGB/Rec709 color primaries. - `"sRGB"` : Using standard sRGB response and primaries. - `"Rec709"` : Using standard Rec709 response and primaries. - - `"ACES"` : ACES color space encoding. + - `"ACEScg"` : ACEScg color space encoding. - `"AdobeRGB"` : Adobe RGB color space. - `"KodakLog"` : Kodak logarithmic color space. - `"GammaX.Y"` : Color values have been gamma corrected diff --git a/src/hdr.imageio/hdrinput.cpp b/src/hdr.imageio/hdrinput.cpp index 8bab0d8421..500d3e776b 100644 --- a/src/hdr.imageio/hdrinput.cpp +++ b/src/hdr.imageio/hdrinput.cpp @@ -277,7 +277,10 @@ HdrInput::RGBE_ReadHeader() if (!line.size()) return false; - m_spec.attribute("oiio:ColorSpace", "linear"); // presume linear + m_spec.attribute("oiio:ColorSpace", "lin_srgb"); + // presume linear w/ srgb primaries -- seems like the safest assumption + // for this old file format. + bool found_FORMAT_line = false; for (int nlines = 0; nlines < 100 /* safety */; ++nlines) { if (line.size() == 0 || line[0] == '\n') // stop at blank line diff --git a/src/include/OpenImageIO/color.h b/src/include/OpenImageIO/color.h index 113a1715f8..a88897bacf 100644 --- a/src/include/OpenImageIO/color.h +++ b/src/include/OpenImageIO/color.h @@ -94,7 +94,7 @@ class OIIO_API ColorConfig { /// This routine will return the error string (and by default, clear any /// error flags). If no error has occurred since the last time /// geterror() was called, it will return an empty string. - std::string geterror(bool clear = true); + std::string geterror(bool clear = true) const; /// Get the number of ColorSpace(s) defined in this configuration int getNumColorSpaces() const; @@ -309,6 +309,15 @@ class OIIO_API ColorConfig { /// is found. string_view parseColorSpaceFromString(string_view str) const; + /// Turn the name, which could be a color space, an alias, a role, or + /// an OIIO-understood universal name (like "sRGB") into a canonical + /// color space name. If the name is not recognized, return "". + string_view resolve(string_view name) const; + + /// Are the two color space names/aliases/roles equivalent? + bool equivalent(string_view color_space, + string_view other_color_space) const; + /// Return a filename or other identifier for the config we're using. std::string configname() const; @@ -325,6 +334,13 @@ class OIIO_API ColorConfig { /// OCIO support is available. static int OpenColorIO_version_hex(); + /// Return a default ColorConfig, which is a singleton that will be + /// created the first time it is needed. It will be initialized with the + /// OCIO environment variable, if it exists, or the OCIO built-in config + /// (for OCIO >= 2.2). If neither of those is possible, it will be + /// initialized with a built-in minimal config. + static const ColorConfig& default_colorconfig(); + private: ColorConfig(const ColorConfig&) = delete; ColorConfig& operator=(const ColorConfig&) = delete; @@ -336,7 +352,8 @@ class OIIO_API ColorConfig { -/// Utility -- convert sRGB value to linear +/// Utility -- convert sRGB value to linear transfer function, without +/// any change in color primaries. /// http://en.wikipedia.org/wiki/SRGB inline float sRGB_to_linear(float x) @@ -356,7 +373,8 @@ sRGB_to_linear(const simd::vfloat4& x) } #endif -/// Utility -- convert linear value to sRGB +/// Utility -- convert linear value to sRGB transfer function, without +/// any change in color primaries. inline float linear_to_sRGB(float x) { @@ -366,7 +384,8 @@ linear_to_sRGB(float x) #ifndef __CUDA_ARCH__ -/// Utility -- convert linear value to sRGB +/// Utility -- convert linear value to sRGB transfer function, without +/// any change in color primaries. inline simd::vfloat4 linear_to_sRGB(const simd::vfloat4& x) { @@ -377,7 +396,8 @@ linear_to_sRGB(const simd::vfloat4& x) #endif -/// Utility -- convert Rec709 value to linear +/// Utility -- convert Rec709 value to linear transfer function, without +/// any change in color primaries. /// http://en.wikipedia.org/wiki/Rec._709 inline float Rec709_to_linear(float x) @@ -388,7 +408,8 @@ Rec709_to_linear(float x) return powf((x + 0.099f) * (1.0f / 1.099f), (1.0f / 0.45f)); } -/// Utility -- convert linear value to Rec709 +/// Utility -- convert linear value to Rec709 transfer function, without +/// any change in color primaries. inline float linear_to_Rec709(float x) { diff --git a/src/include/OpenImageIO/imagebufalgo.h b/src/include/OpenImageIO/imagebufalgo.h index 2bc8a153f7..246de744c8 100644 --- a/src/include/OpenImageIO/imagebufalgo.h +++ b/src/include/OpenImageIO/imagebufalgo.h @@ -1824,7 +1824,7 @@ bool OIIO_API erode (ImageBuf &dst, const ImageBuf &src, ImageBuf OIIO_API colorconvert (const ImageBuf &src, string_view fromspace, string_view tospace, bool unpremult=true, string_view context_key="", string_view context_value="", - ColorConfig *colorconfig=nullptr, + const ColorConfig* colorconfig = nullptr, ROI roi={}, int nthreads=0); /// Transform using a ColorProcessor, returning an ImageBuf result. @@ -1835,7 +1835,7 @@ ImageBuf OIIO_API colorconvert (const ImageBuf &src, bool OIIO_API colorconvert (ImageBuf &dst, const ImageBuf &src, string_view fromspace, string_view tospace, bool unpremult=true, string_view context_key="", string_view context_value="", - ColorConfig *colorconfig=nullptr, + const ColorConfig* colorconfig = nullptr, ROI roi={}, int nthreads=0); /// Transform using a ColorProcessor, storing reults into an existing ImageBuf. @@ -1925,14 +1925,14 @@ ImageBuf OIIO_API ociolook (const ImageBuf &src, string_view looks, string_view fromspace, string_view tospace, bool unpremult=true, bool inverse=false, string_view context_key="", string_view context_value="", - ColorConfig *colorconfig=nullptr, + const ColorConfig* colorconfig = nullptr, ROI roi={}, int nthreads=0); /// Write to an existing image `dst` (allocating if it is uninitialized). bool OIIO_API ociolook (ImageBuf &dst, const ImageBuf &src, string_view looks, string_view fromspace, string_view tospace, bool unpremult=true, bool inverse=false, string_view context_key="", string_view context_value="", - ColorConfig *colorconfig=nullptr, + const ColorConfig* colorconfig = nullptr, ROI roi={}, int nthreads=0); @@ -1982,7 +1982,7 @@ ImageBuf OIIO_API ociodisplay (const ImageBuf &src, string_view fromspace="", string_view looks="", bool unpremult=true, bool inverse=false, string_view context_key="", string_view context_value="", - ColorConfig *colorconfig=nullptr, + const ColorConfig* colorconfig = nullptr, ROI roi={}, int nthreads=0); /// Write to an existing image `dst` (allocating if it is uninitialized). bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src, @@ -1990,7 +1990,7 @@ bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src, string_view fromspace="", string_view looks="", bool unpremult=true, bool inverse=false, string_view context_key="", string_view context_value="", - ColorConfig *colorconfig=nullptr, + const ColorConfig* colorconfig = nullptr, ROI roi={}, int nthreads=0); #ifndef OIIO_DOXYGEN @@ -2000,7 +2000,7 @@ ImageBuf OIIO_API ociodisplay (const ImageBuf &src, string_view fromspace, string_view looks, bool unpremult, string_view context_key, string_view context_value="", - ColorConfig *colorconfig=nullptr, + const ColorConfig* colorconfig = nullptr, ROI roi={}, int nthreads=0); // OIIO_DEPRECATED("prefer the kind that takes an `inverse` parameter (2.5)") bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src, @@ -2008,7 +2008,7 @@ bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src, string_view fromspace, string_view looks, bool unpremult, string_view context_key, string_view context_value="", - ColorConfig *colorconfig=nullptr, + const ColorConfig* colorconfig = nullptr, ROI roi={}, int nthreads=0); #endif @@ -2039,13 +2039,13 @@ bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src, ImageBuf OIIO_API ociofiletransform (const ImageBuf &src, string_view name, bool unpremult=true, bool inverse=false, - ColorConfig *colorconfig=nullptr, + const ColorConfig* colorconfig = nullptr, ROI roi={}, int nthreads=0); /// Write to an existing image `dst` (allocating if it is uninitialized). bool OIIO_API ociofiletransform (ImageBuf &dst, const ImageBuf &src, string_view name, bool unpremult=true, bool inverse=false, - ColorConfig *colorconfig=nullptr, + const ColorConfig* colorconfig = nullptr, ROI roi={}, int nthreads=0); diff --git a/src/libOpenImageIO/color_ocio.cpp b/src/libOpenImageIO/color_ocio.cpp index a45bb4967a..2080d48f41 100644 --- a/src/libOpenImageIO/color_ocio.cpp +++ b/src/libOpenImageIO/color_ocio.cpp @@ -29,7 +29,8 @@ # if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 0, 0) # define OCIO_v2 1 # endif -# if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 2, 0) +# if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 2, 0) \ + && !defined(OIIO_DISABLE_BUILTIN_OCIO_CONFIGS) # define OCIO_HAS_BUILTIN_CONFIGS 1 # endif namespace OCIO = OCIO_NAMESPACE; @@ -51,14 +52,24 @@ static bool colordebug = Strutil::stoi(Sysutil::getenv("OIIO_COLOR_DEBUG")); #endif -static std::shared_ptr default_colorconfig; // default color config -static spin_mutex colorconfig_mutex; +static int disable_ocio = Strutil::stoi(Sysutil::getenv("OIIO_DISABLE_OCIO")); +static int disable_builtin_configs = Strutil::stoi( + Sysutil::getenv("OIIO_DISABLE_BUILTIN_OCIO_CONFIGS")); #ifdef USE_OCIO static OCIO::ConstConfigRcPtr ocio_current_config; #endif +const ColorConfig& +ColorConfig::default_colorconfig() +{ + static ColorConfig config; + return config; +} + + + // Class used as the key to index color processors in the cache. class ColorProcCacheKey { public: @@ -118,7 +129,7 @@ bool ColorConfig::supportsOpenColorIO() { #ifdef USE_OCIO - return true; + return (disable_ocio == 0); #else return false; #endif @@ -133,6 +144,32 @@ ColorConfig::OpenColorIO_version_hex() } +struct CSInfo { + std::string name; + int index; // More than one can have the same index -- aliases + enum Flags { + none = 0, + is_linear_response = 1, + is_scene_linear = 2, + is_srgb = 4, + is_lin_srgb = 8, + is_ACEScg = 16, + // is_Rec709 = 32, + }; + int flags = 0; +#ifdef USE_OCIO + OCIO::ConstColorSpaceRcPtr ocio_cs; +#endif + + CSInfo(string_view name_, int index_, int flags_ = none) + : name(name_) + , index(index_) + , flags(flags_) + { + } +}; + + // Hidden implementation of ColorConfig class ColorConfig::Impl { @@ -140,8 +177,13 @@ class ColorConfig::Impl { #ifdef USE_OCIO OCIO::ConstConfigRcPtr config_; #endif - std::vector> colorspaces; - std::string linear_alias; // Alias for a scene-linear color space + std::vector colorspaces; + std::string scene_linear_alias; // Alias for a scene-linear color space + std::string lin_srgb_alias; + std::string srgb_alias; + std::string ACEScg_alias; + // std::string Rec709_alias; + private: mutable spin_rw_mutex m_mutex; mutable std::string m_error; @@ -171,6 +213,8 @@ class ColorConfig::Impl { colorspaces.emplace_back(name, index); } + void classify(CSInfo& cs); + // Search for a matching ColorProcessor, return it if found (otherwise // return an empty handle). ColorProcessorHandle findproc(const ColorProcCacheKey& key) @@ -211,7 +255,7 @@ class ColorConfig::Impl { spin_rw_write_lock lock(m_mutex); m_error = Strutil::fmt::format(fmt, args...); } - std::string geterror(bool clear = true) + std::string geterror(bool clear = true) const { std::string err; spin_rw_write_lock lock(m_mutex); @@ -235,18 +279,26 @@ class ColorConfig::Impl { const std::string& configname() const { return m_configname; } void configname(string_view name) { m_configname = name; } + +#if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 2, 0) + OCIO::ConstCPUProcessorRcPtr + get_to_builtin_cpu_proc(const char* my_from, const char* builtin_to) const; +#endif + bool check_same_as_builtin_transform(const char* my_from, + const char* builtin_to) const; }; // ColorConfig utility to take inventory of the color spaces available. -// It sets up knowledge of "linear", "sRGB", "Rec709", +// It sets up knowledge of "linear", "sRGB", "Rec709", etc, // even if the underlying OCIO configuration lacks them. void ColorConfig::Impl::inventory() { + DBG("inventorying config {}\n", configname()); #ifdef USE_OCIO - if (config_) { + if (config_ && !disable_ocio) { bool nonraw = false; for (int i = 0, e = config_->getNumColorSpaces(); i < e; ++i) nonraw |= !Strutil::iequals(config_->getColorSpaceNameByIndex(i), @@ -254,10 +306,12 @@ ColorConfig::Impl::inventory() if (nonraw) { for (int i = 0, e = config_->getNumColorSpaces(); i < e; ++i) add(config_->getColorSpaceNameByIndex(i), i); + for (auto&& cs : colorspaces) + classify(cs); OCIO::ConstColorSpaceRcPtr lin = config_->getColorSpace( "scene_linear"); if (lin) - linear_alias = lin->getName(); + scene_linear_alias = lin->getName(); return; // If any non-"raw" spaces were defined, we're done } } @@ -270,11 +324,131 @@ ColorConfig::Impl::inventory() // If there was no configuration, or we didn't compile with OCIO // support at all, register a few basic names we know about. add("linear", 0); + add("scene_linear", 0); add("default", 0); add("rgb", 0); add("RGB", 0); + add("lin_srgb", 0); add("sRGB", 1); add("Rec709", 2); + for (auto&& cs : colorspaces) + classify(cs); +} + + + +inline bool +close_colors(cspan a, cspan b) +{ + OIIO_DASSERT(a.size() == b.size()); + for (size_t i = 0, e = a.size(); i < e; ++i) + if (std::abs(a[i].x - b[i].x) > 1.0e-3f + || std::abs(a[i].y - b[i].y) > 1.0e-3f + || std::abs(a[i].z - b[i].z) > 1.0e-3f) + return false; + return true; +} + + + +#if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 2, 0) + +OCIO::ConstCPUProcessorRcPtr +ColorConfig::Impl::get_to_builtin_cpu_proc(const char* my_from, + const char* builtin_to) const +{ + auto proc = OCIO::Config::GetProcessorToBuiltinColorSpace(config_, my_from, + builtin_to); + return proc ? proc->getDefaultCPUProcessor() + : OCIO::ConstCPUProcessorRcPtr(); +} + +#endif + + + +// Is this config's `my_from` color space equivalent to the built-in +// `builtin_to` color space? Find out by transforming the primaries, white, +// and half white and see if the results indicate that it was the identity +// transform (or close enough). +bool +ColorConfig::Impl::check_same_as_builtin_transform(const char* my_from, + const char* builtin_to) const +{ + if (disable_builtin_configs) + return false; +#if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 2, 0) + const int n_test_colors = 5; + static const Imath::C3f test_colors[n_test_colors] = { + { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 }, { 1, 1, 1 }, { 0.5, 0.5, 0.5 } + }; + auto proc = get_to_builtin_cpu_proc(my_from, builtin_to); + if (proc) { + Imath::C3f colors[n_test_colors]; + std::copy(test_colors, test_colors + n_test_colors, colors); + proc->apply(OCIO::PackedImageDesc(colors, n_test_colors, 1, 3)); + // DBG("Color space {} to sRGB: {} / {} / {} / {} / {} \n", + // cs.name, colors[0], colors[1], colors[2], colors[3], + // colors[4]); + if (close_colors(colors, test_colors)) + return true; + } +#endif + return false; +} + + + +void +ColorConfig::Impl::classify(CSInfo& cs) +{ +#ifdef USE_OCIO + if (config_ && !disable_ocio) { + cs.ocio_cs = config_->getColorSpace(cs.name.c_str()); +# if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 2, 0) + if (!disable_builtin_configs) { + if (config_->isColorSpaceLinear(cs.name.c_str(), + OCIO::REFERENCE_SPACE_SCENE) + || config_->isColorSpaceLinear(cs.name.c_str(), + OCIO::REFERENCE_SPACE_DISPLAY)) { + cs.flags |= CSInfo::is_linear_response; + } + } +# endif + if (check_same_as_builtin_transform(cs.name.c_str(), "srgb_tx")) { + cs.flags |= CSInfo::is_srgb; + if (srgb_alias.empty()) + srgb_alias = cs.name; + } else if (check_same_as_builtin_transform(cs.name.c_str(), + "lin_srgb")) { + cs.flags |= CSInfo::is_lin_srgb; + cs.flags |= CSInfo::is_linear_response; + if (lin_srgb_alias.empty()) + lin_srgb_alias = cs.name; + } else if (check_same_as_builtin_transform(cs.name.c_str(), "ACEScg")) { + cs.flags |= CSInfo::is_ACEScg; + cs.flags |= CSInfo::is_linear_response; + if (ACEScg_alias.empty()) + ACEScg_alias = cs.name; + } + } +#endif + // General heuristics + +#if 1 + if (cs.flags & CSInfo::is_linear_response) + DBG("'{}' is linear\n", cs.name); + if (cs.flags & CSInfo::is_srgb) + DBG("'{}' is srgb\n", cs.name); + if (cs.flags & CSInfo::is_lin_srgb) + DBG("'{}' is lin_srgb\n", cs.name); + if (cs.flags & CSInfo::is_ACEScg) + DBG("'{}' is ACEScg\n", cs.name); + if (cs.flags & CSInfo::is_scene_linear) + DBG("'{}' is scene_linear\n", cs.name); + if (cs.flags) + DBG("\n"); +#endif } @@ -306,6 +480,10 @@ ColorConfig::reset(string_view filename) // If no filename was specified, use env $OCIO if (filename.empty()) filename = Sysutil::getenv("OCIO"); +# ifdef OCIO_HAS_BUILTIN_CONFIGS + if (filename.empty() && !disable_builtin_configs) + filename = "ocio://default"; +# endif if (filename.size() && !Filesystem::exists(filename) # ifdef OCIO_HAS_BUILTIN_CONFIGS && !Strutil::istarts_with(filename, "ocio://") @@ -353,7 +531,7 @@ ColorConfig::error() const std::string -ColorConfig::geterror(bool clear) +ColorConfig::geterror(bool clear) const { return getImpl()->geterror(clear); } @@ -371,7 +549,7 @@ ColorConfig::getNumColorSpaces() const const char* ColorConfig::getColorSpaceNameByIndex(int index) const { - return getImpl()->colorspaces[index].first.c_str(); + return getImpl()->colorspaces[index].name.c_str(); } @@ -380,7 +558,7 @@ const char* ColorConfig::getColorSpaceFamilyByName(string_view name) const { #ifdef USE_OCIO - if (getImpl()->config_) { + if (getImpl()->config_ && !disable_ocio) { OCIO::ConstColorSpaceRcPtr c = getImpl()->config_->getColorSpace( std::string(name).c_str()); if (c) @@ -398,7 +576,7 @@ ColorConfig::getColorSpaceNames() const std::vector result; result.reserve(getImpl()->colorspaces.size()); for (auto& c : getImpl()->colorspaces) - result.push_back(c.first); + result.push_back(c.name); return result; } @@ -406,7 +584,7 @@ int ColorConfig::getNumRoles() const { #ifdef USE_OCIO - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) return getImpl()->config_->getNumRoles(); #endif return 0; @@ -416,10 +594,10 @@ const char* ColorConfig::getRoleByIndex(int index) const { #ifdef USE_OCIO - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) return getImpl()->config_->getRoleName(index); #endif - return NULL; + return nullptr; } @@ -438,7 +616,7 @@ int ColorConfig::getNumLooks() const { #ifdef USE_OCIO - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) return getImpl()->config_->getNumLooks(); #endif return 0; @@ -450,10 +628,10 @@ const char* ColorConfig::getLookNameByIndex(int index) const { #ifdef USE_OCIO - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) return getImpl()->config_->getLookNameByIndex(index); #endif - return NULL; + return nullptr; } @@ -473,7 +651,7 @@ bool ColorConfig::isColorSpaceLinear(string_view name) const { #if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 2, 0) - if (getImpl()->config_) { + if (getImpl()->config_ && !disable_ocio) { return getImpl()->config_->isColorSpaceLinear( c_str(name), OCIO::REFERENCE_SPACE_SCENE) || getImpl()->config_->isColorSpaceLinear( @@ -481,7 +659,10 @@ ColorConfig::isColorSpaceLinear(string_view name) const } #endif return Strutil::iequals(name, "linear") - || Strutil::iequals(name, "scene_linear"); + || Strutil::istarts_with(name, "linear_") + || Strutil::istarts_with(name, "lin_") + || Strutil::iends_with(name, "_linear") + || Strutil::iends_with(name, "_lin"); } @@ -509,9 +690,12 @@ const char* ColorConfig::getColorSpaceNameByRole(string_view role) const { #ifdef USE_OCIO - if (getImpl()->config_) { + if (getImpl()->config_ && !disable_ocio) { + using Strutil::print; OCIO::ConstColorSpaceRcPtr c = getImpl()->config_->getColorSpace( std::string(role).c_str()); + // print("looking first for named color space {} -> {}\n", role, + // c ? c->getName() : "not found"); // Catch special case of obvious name synonyms if (!c && (Strutil::iequals(role, "RGB") @@ -521,8 +705,19 @@ ColorConfig::getColorSpaceNameByRole(string_view role) const c = getImpl()->config_->getColorSpace("scene_linear"); if (!c && Strutil::iequals(role, "scene_linear")) c = getImpl()->config_->getColorSpace("linear"); - if (c) +# ifdef OCIO_HAS_BUILTIN_CONFIGS + if (!c && Strutil::iequals(role, "srgb")) { + c = getImpl()->config_->getColorSpace("sRGB - Texture"); + // DBG("Unilaterally substituting {} -> '{}'\n", role, + // c->getName()); + } +# endif + + if (c) { + // DBG("found color space {} for role {}\n", c->getName(), + // role); return c->getName(); + } } #endif @@ -540,7 +735,7 @@ TypeDesc ColorConfig::getColorSpaceDataType(string_view name, int* bits) const { #ifdef USE_OCIO - if (getImpl()->config_) { + if (getImpl()->config_ && !disable_ocio) { OCIO::ConstColorSpaceRcPtr c = getImpl()->config_->getColorSpace( std::string(name).c_str()); if (c) { @@ -568,7 +763,7 @@ int ColorConfig::getNumDisplays() const { #ifdef USE_OCIO - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) return getImpl()->config_->getNumDisplays(); #endif return 0; @@ -580,10 +775,10 @@ const char* ColorConfig::getDisplayNameByIndex(int index) const { #ifdef USE_OCIO - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) return getImpl()->config_->getDisplay(index); #endif - return NULL; + return nullptr; } @@ -605,7 +800,7 @@ ColorConfig::getNumViews(string_view display) const #ifdef USE_OCIO if (display.empty()) display = getDefaultDisplayName(); - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) return getImpl()->config_->getNumViews(std::string(display).c_str()); #endif return 0; @@ -619,10 +814,10 @@ ColorConfig::getViewNameByIndex(string_view display, int index) const #ifdef USE_OCIO if (display.empty()) display = getDefaultDisplayName(); - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) return getImpl()->config_->getView(std::string(display).c_str(), index); #endif - return NULL; + return nullptr; } @@ -644,10 +839,10 @@ const char* ColorConfig::getDefaultDisplayName() const { #ifdef USE_OCIO - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) return getImpl()->config_->getDefaultDisplay(); #endif - return NULL; + return nullptr; } @@ -656,10 +851,12 @@ const char* ColorConfig::getDefaultViewName(string_view display) const { #ifdef USE_OCIO - if (getImpl()->config_) - return getImpl()->config_->getDefaultView(std::string(display).c_str()); + if (display.empty() || display == "default") + display = getDefaultDisplayName(); + if (getImpl()->config_ && !disable_ocio) + return getImpl()->config_->getDefaultView(c_str(display)); #endif - return NULL; + return nullptr; } @@ -669,7 +866,7 @@ ColorConfig::getDisplayViewColorSpaceName(const std::string& display, const std::string& view) const { #ifdef USE_OCIO - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) # if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 0, 0) return getImpl()->config_->getDisplayViewColorSpaceName(display.c_str(), view.c_str()); @@ -688,7 +885,7 @@ ColorConfig::getDisplayViewLooks(const std::string& display, const std::string& view) const { #ifdef USE_OCIO - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) # if OCIO_VERSION_HEX >= MAKE_OCIO_VERSION_HEX(2, 0, 0) return getImpl()->config_->getDisplayViewLooks(display.c_str(), view.c_str()); @@ -706,7 +903,7 @@ std::string ColorConfig::configname() const { #ifdef USE_OCIO - if (getImpl()->config_) + if (getImpl()->config_ && !disable_ocio) return getImpl()->configname(); #endif return "built-in"; @@ -714,6 +911,68 @@ ColorConfig::configname() const +string_view +ColorConfig::resolve(string_view name) const +{ +#ifdef USE_OCIO + OCIO::ConstConfigRcPtr config = getImpl()->config_; + if (config && !disable_ocio) { + const char* namestr = c_str(name); + OCIO::ConstColorSpaceRcPtr cs = config->getColorSpace(namestr); + if (cs) + return cs->getName(); + } + // OCIO did not know this name as a color space, role, or alias. +#endif + // Maybe it's an informal alias of common names? + if (Strutil::iequals(name, "sRGB") && !getImpl()->srgb_alias.empty()) { + return getImpl()->srgb_alias; + } + if (Strutil::iequals(name, "lin_srgb") + && getImpl()->lin_srgb_alias.size()) { + return getImpl()->lin_srgb_alias; + } + if (Strutil::iequals(name, "ACEScg") && !getImpl()->ACEScg_alias.empty()) { + return getImpl()->ACEScg_alias; + } + if (Strutil::iequals(name, "linear") + && !getImpl()->scene_linear_alias.empty()) { + return getImpl()->scene_linear_alias; + } + + // if (Strutil::iequals(name, "Rec709") && getImpl()->Rec709_alias.size()) { + // return getImpl()->Rec709_alias; + // } + return name; +} + + + +bool +ColorConfig::equivalent(string_view color_space1, + string_view color_space2) const +{ + // Empty color spaces never match + if (color_space1.empty() || color_space2.empty()) + return false; + // Easy case: matching names are the same! + if (Strutil::iequals(color_space1, color_space2)) + return true; + + // If "resolved" names (after converting aliases and roles to color + // spaces) match, they are equivalent. + color_space1 = resolve(color_space1); + color_space2 = resolve(color_space2); + if (color_space1.empty() || color_space2.empty()) + return false; + if (Strutil::iequals(color_space1, color_space2)) + return true; + + return false; +} + + + #ifdef USE_OCIO # if OCIO_VERSION_HEX >= 0x02000000 @@ -780,6 +1039,11 @@ class ColorProcessor_OCIO final : public ColorProcessor { +#if OCIO_VERSION_HEX < MAKE_OCIO_VERSION_HEX(2, 2, 0) +// For version 2.2 and later, missing OCIO config will always fall back on +// built-in configs, so we don't need any of these secondary fallback +// heuristics. + // ColorProcessor that hard-codes sRGB-to-linear class ColorProcessor_sRGB_to_linear final : public ColorProcessor { public: @@ -962,6 +1226,7 @@ class ColorProcessor_Ident final : public ColorProcessor { { } }; +#endif @@ -1043,7 +1308,6 @@ ColorConfig::createColorProcessor(ustring inputColorSpace, ustring outputColorSpace, ustring context_key, ustring context_value) const { - ustring inputrole, outputrole; std::string pending_error; // First, look up the requested processor in the cache. If it already @@ -1055,23 +1319,17 @@ ColorConfig::createColorProcessor(ustring inputColorSpace, return handle; #ifdef USE_OCIO + // DBG("createColorProcessor {} -> {}\n", inputColorSpace, + // outputColorSpace); // Ask OCIO to make a Processor that can handle the requested // transformation. OCIO::ConstProcessorRcPtr p; - if (getImpl()->config_) { - // If the names are roles, convert them to color space names - string_view name; - name = getColorSpaceNameByRole(inputColorSpace); - if (!name.empty()) { - inputrole = inputColorSpace; - inputColorSpace = name; - } - name = getColorSpaceNameByRole(outputColorSpace); - if (!name.empty()) { - outputrole = outputColorSpace; - outputColorSpace = name; - } - + if (getImpl()->config_ && !disable_ocio) { + // Canonicalize the names + inputColorSpace = ustring(resolve(inputColorSpace)); + outputColorSpace = ustring(resolve(outputColorSpace)); + // DBG("after role substitution, {} -> {}\n", inputColorSpace, + // outputColorSpace); auto config = getImpl()->config_; auto context = config->getCurrentContext(); auto keys = Strutil::splits(context_key, ","); @@ -1089,11 +1347,15 @@ ColorConfig::createColorProcessor(ustring inputColorSpace, inputColorSpace.c_str(), outputColorSpace.c_str()); getImpl()->clear_error(); + // DBG("Created OCIO processor '{}' -> '{}'\n", + // inputColorSpace, outputColorSpace); } catch (OCIO::Exception& e) { // Don't quit yet, remember the error and see if any of our // built-in knowledge of some generic spaces will save us. p.reset(); pending_error = e.what(); + // DBG("FAILED to create OCIO processor '{}' -> '{}'\n", + // inputColorSpace, outputColorSpace); } catch (...) { p.reset(); getImpl()->error( @@ -1105,10 +1367,16 @@ ColorConfig::createColorProcessor(ustring inputColorSpace, // return it now. If it boils down to a no-op, give a second // chance below to recognize it as a special case. handle = ColorProcessorHandle(new ColorProcessor_OCIO(p)); + // DBG("OCIO processor '{}' -> '{}' is NOT NoOp, handle = {}\n", + // inputColorSpace, outputColorSpace, (bool)handle); } } #endif +#if OCIO_VERSION_HEX < MAKE_OCIO_VERSION_HEX(2, 2, 0) + // For version 2.2 and later, missing OCIO config will always fall back on + // built-in configs, so we don't need any of these secondary fallback + // heuristics. if (!handle) { // Either not compiled with OCIO support, or no OCIO configuration // was found at all. There are a few color conversions we know @@ -1117,31 +1385,36 @@ ColorConfig::createColorProcessor(ustring inputColorSpace, if (iequals(inputColorSpace, outputColorSpace)) { handle = ColorProcessorHandle(new ColorProcessor_Ident); } else if ((iequals(inputColorSpace, "linear") - || iequals(inputrole, "linear") + || iequals(inputColorSpace, "scene_linear") + || iequals(inputColorSpace, "lin_srgb") || iequals(inputColorSpace, "lnf") || iequals(inputColorSpace, "lnh")) && iequals(outputColorSpace, "sRGB")) { handle = ColorProcessorHandle(new ColorProcessor_linear_to_sRGB); } else if (iequals(inputColorSpace, "sRGB") && (iequals(outputColorSpace, "linear") - || iequals(outputrole, "linear") + || iequals(outputColorSpace, "scene_linear") + || iequals(outputColorSpace, "lin_srgb") || iequals(outputColorSpace, "lnf") || iequals(outputColorSpace, "lnh"))) { handle = ColorProcessorHandle(new ColorProcessor_sRGB_to_linear); } else if ((iequals(inputColorSpace, "linear") - || iequals(inputrole, "linear") + || iequals(inputColorSpace, "scene_linear") + || iequals(inputColorSpace, "lin_srgb") || iequals(inputColorSpace, "lnf") || iequals(inputColorSpace, "lnh")) && iequals(outputColorSpace, "Rec709")) { handle = ColorProcessorHandle(new ColorProcessor_linear_to_Rec709); } else if (iequals(inputColorSpace, "Rec709") && (iequals(outputColorSpace, "linear") - || iequals(outputrole, "linear") + || iequals(outputColorSpace, "scene_linear") + || iequals(outputColorSpace, "lin_srgb") || iequals(outputColorSpace, "lnf") || iequals(outputColorSpace, "lnh"))) { handle = ColorProcessorHandle(new ColorProcessor_Rec709_to_linear); } else if ((iequals(inputColorSpace, "linear") - || iequals(inputrole, "linear") + || iequals(inputColorSpace, "scene_linear") + || iequals(inputColorSpace, "lin_srgb") || iequals(inputColorSpace, "lnf") || iequals(inputColorSpace, "lnh")) && istarts_with(outputColorSpace, "Gamma")) { @@ -1151,7 +1424,8 @@ ColorConfig::createColorProcessor(ustring inputColorSpace, handle = ColorProcessorHandle(new ColorProcessor_gamma(1.0f / g)); } else if (istarts_with(inputColorSpace, "Gamma") && (iequals(outputColorSpace, "linear") - || iequals(outputrole, "linear") + || iequals(outputColorSpace, "scene_linear") + || iequals(outputColorSpace, "lin_srgb") || iequals(outputColorSpace, "lnf") || iequals(outputColorSpace, "lnh"))) { string_view gamstr = inputColorSpace; @@ -1160,6 +1434,7 @@ ColorConfig::createColorProcessor(ustring inputColorSpace, handle = ColorProcessorHandle(new ColorProcessor_gamma(g)); } } +#endif #ifdef USE_OCIO if (!handle && p) { @@ -1208,7 +1483,7 @@ ColorConfig::createLookTransform(ustring looks, ustring inputColorSpace, #ifdef USE_OCIO // Ask OCIO to make a Processor that can handle the requested // transformation. - if (getImpl()->config_) { + if (getImpl()->config_ && !disable_ocio) { OCIO::ConstConfigRcPtr config = getImpl()->config_; OCIO::LookTransformRcPtr transform = OCIO::LookTransform::Create(); transform->setLooks(looks.c_str()); @@ -1219,12 +1494,12 @@ ColorConfig::createLookTransform(ustring looks, ustring inputColorSpace, // look -> src. This is an unintuitive result for the // artist (who would expect in, out to remain unchanged), so // we account for that here by flipping src/dst - transform->setSrc(outputColorSpace.c_str()); - transform->setDst(inputColorSpace.c_str()); + transform->setSrc(c_str(resolve(outputColorSpace))); + transform->setDst(c_str(resolve(inputColorSpace))); dir = OCIO::TRANSFORM_DIR_INVERSE; } else { // forward - transform->setSrc(inputColorSpace.c_str()); - transform->setDst(outputColorSpace.c_str()); + transform->setSrc(c_str(resolve(inputColorSpace))); + transform->setDst(c_str(resolve(outputColorSpace))); dir = OCIO::TRANSFORM_DIR_FORWARD; } auto context = config->getCurrentContext(); @@ -1278,10 +1553,10 @@ ColorConfig::createDisplayTransform(ustring display, ustring view, bool inverse, ustring context_key, ustring context_value) const { - if (display.empty()) + if (display.empty() || display == "default") display = getDefaultDisplayName(); - if (view.empty()) - view = getDefaultViewName(); + if (view.empty() || view == "default") + view = getDefaultViewName(display); // First, look up the requested processor in the cache. If it already // exists, just return it. ColorProcCacheKey prockey(inputColorSpace, ustring() /*outputColorSpace*/, @@ -1294,7 +1569,7 @@ ColorConfig::createDisplayTransform(ustring display, ustring view, #ifdef USE_OCIO // Ask OCIO to make a Processor that can handle the requested // transformation. - if (getImpl()->config_) { + if (getImpl()->config_ && !disable_ocio) { OCIO::ConstConfigRcPtr config = getImpl()->config_; # ifdef OCIO_v2 auto transform = OCIO::DisplayViewTransform::Create(); @@ -1330,7 +1605,7 @@ ColorConfig::createDisplayTransform(ustring display, ustring view, OCIO::ConstProcessorRcPtr p; try { // Get the processor corresponding to this transform. - p = getImpl()->config_->getProcessor(context, transform, dir); + p = config->getProcessor(context, transform, dir); getImpl()->clear_error(); handle = ColorProcessorHandle(new ColorProcessor_OCIO(p)); } catch (OCIO::Exception& e) { @@ -1515,11 +1790,12 @@ bool ImageBufAlgo::colorconvert(ImageBuf& dst, const ImageBuf& src, string_view from, string_view to, bool unpremult, string_view context_key, string_view context_value, - ColorConfig* colorconfig, ROI roi, int nthreads) + const ColorConfig* colorconfig, ROI roi, + int nthreads) { pvt::LoggedTimer logtime("IBA::colorconvert"); if (from.empty() || from == "current") { - from = src.spec().get_string_attribute("oiio:Colorspace", "Linear"); + from = src.spec().get_string_attribute("oiio:Colorspace", "linear"); } if (from.empty() || to.empty()) { dst.errorfmt("Unknown color space name"); @@ -1527,13 +1803,12 @@ ImageBufAlgo::colorconvert(ImageBuf& dst, const ImageBuf& src, string_view from, } ColorProcessorHandle processor; { - spin_lock lock(colorconfig_mutex); - if (!colorconfig) - colorconfig = default_colorconfig.get(); if (!colorconfig) - default_colorconfig.reset(colorconfig = new ColorConfig); - processor = colorconfig->createColorProcessor(from, to, context_key, - context_value); + colorconfig = &ColorConfig::default_colorconfig(); + processor + = colorconfig->createColorProcessor(colorconfig->resolve(from), + colorconfig->resolve(to), + context_key, context_value); if (!processor) { if (colorconfig->error()) dst.errorfmt("{}", colorconfig->geterror()); @@ -1546,8 +1821,10 @@ ImageBufAlgo::colorconvert(ImageBuf& dst, const ImageBuf& src, string_view from, logtime.stop(); // transition to other colorconvert bool ok = colorconvert(dst, src, processor.get(), unpremult, roi, nthreads); - if (ok) + if (ok) { + // DBG("done, setting output colorspace to {}\n", to); dst.specmod().attribute("oiio:ColorSpace", to); + } return ok; } @@ -1557,7 +1834,8 @@ ImageBuf ImageBufAlgo::colorconvert(const ImageBuf& src, string_view from, string_view to, bool unpremult, string_view context_key, string_view context_value, - ColorConfig* colorconfig, ROI roi, int nthreads) + const ColorConfig* colorconfig, ROI roi, + int nthreads) { ImageBuf result; bool ok = colorconvert(result, src, from, to, unpremult, context_key, @@ -1575,15 +1853,8 @@ ImageBufAlgo::colormatrixtransform(ImageBuf& dst, const ImageBuf& src, int nthreads) { pvt::LoggedTimer logtime("IBA::colormatrixtransform"); - ColorProcessorHandle processor; - { - spin_lock lock(colorconfig_mutex); - auto colorconfig = default_colorconfig.get(); - if (!colorconfig) - default_colorconfig.reset(colorconfig = new ColorConfig); - processor = colorconfig->createMatrixTransform(M); - } - + ColorProcessorHandle processor + = ColorConfig::default_colorconfig().createMatrixTransform(M); logtime.stop(); // transition to other colorconvert bool ok = colorconvert(dst, src, processor.get(), unpremult, roi, nthreads); return ok; @@ -1826,14 +2097,16 @@ bool ImageBufAlgo::ociolook(ImageBuf& dst, const ImageBuf& src, string_view looks, string_view from, string_view to, bool unpremult, bool inverse, string_view key, string_view value, - ColorConfig* colorconfig, ROI roi, int nthreads) + const ColorConfig* colorconfig, ROI roi, int nthreads) { pvt::LoggedTimer logtime("IBA::ociolook"); if (from.empty() || from == "current") { - from = src.spec().get_string_attribute("oiio:Colorspace", "Linear"); + auto linearspace = colorconfig->resolve("linear"); + from = src.spec().get_string_attribute("oiio:Colorspace", linearspace); } if (to.empty() || to == "current") { - to = src.spec().get_string_attribute("oiio:Colorspace", "Linear"); + auto linearspace = colorconfig->resolve("linear"); + to = src.spec().get_string_attribute("oiio:Colorspace", linearspace); } if (from.empty() || to.empty()) { dst.errorfmt("Unknown color space name"); @@ -1841,13 +2114,12 @@ ImageBufAlgo::ociolook(ImageBuf& dst, const ImageBuf& src, string_view looks, } ColorProcessorHandle processor; { - spin_lock lock(colorconfig_mutex); - if (!colorconfig) - colorconfig = default_colorconfig.get(); if (!colorconfig) - default_colorconfig.reset(colorconfig = new ColorConfig); - processor = colorconfig->createLookTransform(looks, from, to, inverse, - key, value); + colorconfig = &ColorConfig::default_colorconfig(); + processor = colorconfig->createLookTransform(looks, + colorconfig->resolve(from), + colorconfig->resolve(to), + inverse, key, value); if (!processor) { if (colorconfig->error()) dst.errorfmt("{}", colorconfig->geterror()); @@ -1870,7 +2142,7 @@ ImageBuf ImageBufAlgo::ociolook(const ImageBuf& src, string_view looks, string_view from, string_view to, bool unpremult, bool inverse, string_view key, string_view value, - ColorConfig* colorconfig, ROI roi, int nthreads) + const ColorConfig* colorconfig, ROI roi, int nthreads) { ImageBuf result; bool ok = ociolook(result, src, looks, from, to, unpremult, inverse, key, @@ -1887,18 +2159,15 @@ ImageBufAlgo::ociodisplay(ImageBuf& dst, const ImageBuf& src, string_view display, string_view view, string_view from, string_view looks, bool unpremult, bool inverse, string_view key, string_view value, - ColorConfig* colorconfig, ROI roi, int nthreads) + const ColorConfig* colorconfig, ROI roi, int nthreads) { pvt::LoggedTimer logtime("IBA::ociodisplay"); ColorProcessorHandle processor; { - spin_lock lock(colorconfig_mutex); if (!colorconfig) - colorconfig = default_colorconfig.get(); - if (!colorconfig) - default_colorconfig.reset(colorconfig = new ColorConfig); + colorconfig = &ColorConfig::default_colorconfig(); if (from.empty() || from == "current") { - auto linearspace = colorconfig->getColorSpaceNameByRole("linear"); + auto linearspace = colorconfig->resolve("linear"); from = src.spec().get_string_attribute("oiio:Colorspace", linearspace); } @@ -1906,9 +2175,10 @@ ImageBufAlgo::ociodisplay(ImageBuf& dst, const ImageBuf& src, dst.errorfmt("Unknown color space name"); return false; } - processor = colorconfig->createDisplayTransform(display, view, from, - looks, inverse, key, - value); + processor + = colorconfig->createDisplayTransform(display, view, + colorconfig->resolve(from), + looks, inverse, key, value); if (!processor) { if (colorconfig->error()) dst.errorfmt("{}", colorconfig->geterror()); @@ -1929,8 +2199,8 @@ ImageBuf ImageBufAlgo::ociodisplay(const ImageBuf& src, string_view display, string_view view, string_view from, string_view looks, bool unpremult, bool inverse, string_view key, - string_view value, ColorConfig* colorconfig, ROI roi, - int nthreads) + string_view value, const ColorConfig* colorconfig, + ROI roi, int nthreads) { ImageBuf result; bool ok = ociodisplay(result, src, display, view, from, looks, unpremult, @@ -1948,7 +2218,7 @@ ImageBufAlgo::ociodisplay(ImageBuf& dst, const ImageBuf& src, string_view display, string_view view, string_view from, string_view looks, bool unpremult, string_view key, string_view value, - ColorConfig* colorconfig, ROI roi, int nthreads) + const ColorConfig* colorconfig, ROI roi, int nthreads) { return ociodisplay(dst, src, display, view, from, looks, unpremult, false, key, value, colorconfig, roi, nthreads); @@ -1961,7 +2231,7 @@ ImageBuf ImageBufAlgo::ociodisplay(const ImageBuf& src, string_view display, string_view view, string_view from, string_view looks, bool unpremult, string_view key, string_view value, - ColorConfig* colorconfig, ROI roi, int nthreads) + const ColorConfig* colorconfig, ROI roi, int nthreads) { return ociodisplay(src, display, view, from, looks, unpremult, false, key, value, colorconfig, roi, nthreads); @@ -1972,7 +2242,8 @@ ImageBufAlgo::ociodisplay(const ImageBuf& src, string_view display, bool ImageBufAlgo::ociofiletransform(ImageBuf& dst, const ImageBuf& src, string_view name, bool unpremult, bool inverse, - ColorConfig* colorconfig, ROI roi, int nthreads) + const ColorConfig* colorconfig, ROI roi, + int nthreads) { pvt::LoggedTimer logtime("IBA::ociofiletransform"); if (name.empty()) { @@ -1981,11 +2252,8 @@ ImageBufAlgo::ociofiletransform(ImageBuf& dst, const ImageBuf& src, } ColorProcessorHandle processor; { - spin_lock lock(colorconfig_mutex); - if (!colorconfig) - colorconfig = default_colorconfig.get(); if (!colorconfig) - default_colorconfig.reset(colorconfig = new ColorConfig); + colorconfig = &ColorConfig::default_colorconfig(); processor = colorconfig->createFileTransform(name, inverse); if (!processor) { if (colorconfig->error()) @@ -2008,7 +2276,8 @@ ImageBufAlgo::ociofiletransform(ImageBuf& dst, const ImageBuf& src, ImageBuf ImageBufAlgo::ociofiletransform(const ImageBuf& src, string_view name, bool unpremult, bool inverse, - ColorConfig* colorconfig, ROI roi, int nthreads) + const ColorConfig* colorconfig, ROI roi, + int nthreads) { ImageBuf result; bool ok = ociofiletransform(result, src, name, unpremult, inverse, diff --git a/src/libOpenImageIO/imagebufalgo_test.cpp b/src/libOpenImageIO/imagebufalgo_test.cpp index b4321df9c1..316757bfe3 100644 --- a/src/libOpenImageIO/imagebufalgo_test.cpp +++ b/src/libOpenImageIO/imagebufalgo_test.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -1019,6 +1020,28 @@ test_opencv() +void +test_color_management() +{ + ColorConfig config; + + // Test the IBA::colorconvert version that works on a color at a time + { + auto processor = config.createColorProcessor("lin_srgb", "srgb"); + float rgb[3] = { 0.5f, 0.5f, 0.5f }; + ImageBufAlgo::colorconvert(rgb, processor.get(), false); + OIIO_CHECK_EQUAL_THRESH(rgb[1], 0.735356983052449f, 1.0e-5); + } + { + auto processor = config.createColorProcessor("lin_srgb", "srgb"); + float rgb[4] = { 0.5f, 0.5f, 0.5f, 1.0f }; + ImageBufAlgo::colorconvert(rgb, processor.get(), true); + OIIO_CHECK_EQUAL_THRESH(rgb[1], 0.735356983052449f, 1.0e-5); + } +} + + + int main(int argc, char** argv) { @@ -1053,6 +1076,7 @@ main(int argc, char** argv) test_IBAprep(); test_validate_st_warp_checks(); test_opencv(); + test_color_management(); benchmark_parallel_image(64, iterations * 64); benchmark_parallel_image(512, iterations * 16); diff --git a/src/libOpenImageIO/imagespec_test.cpp b/src/libOpenImageIO/imagespec_test.cpp index 49a3c3c546..1a69ed292d 100644 --- a/src/libOpenImageIO/imagespec_test.cpp +++ b/src/libOpenImageIO/imagespec_test.cpp @@ -37,7 +37,7 @@ const char* imagespec_xml_string = R"EOF( 3 -1 0 -Linear +scene_linear none 1 0.7347, 0.2653, 0, 1, 0.0001, -0.077, 0.32168, 0.33767 @@ -322,7 +322,8 @@ test_imagespec_from_xml() OIIO_CHECK_EQUAL(spec.full_height, 1080); OIIO_CHECK_EQUAL(spec.full_depth, 1); OIIO_CHECK_EQUAL(spec.format, TypeFloat); - OIIO_CHECK_EQUAL(spec.get_string_attribute("oiio:ColorSpace"), "Linear"); + OIIO_CHECK_EQUAL(spec.get_string_attribute("oiio:ColorSpace"), + "scene_linear"); } diff --git a/src/oiiotool/oiiotool.cpp b/src/oiiotool/oiiotool.cpp index 3a2a332b4c..55a3c21fda 100644 --- a/src/oiiotool/oiiotool.cpp +++ b/src/oiiotool/oiiotool.cpp @@ -2763,11 +2763,9 @@ OIIOTOOL_OP(ociolook, 1, [](OiiotoolOp& op, span img) { bool inverse = op.options().get_int("inverse"); bool unpremult = op.options().get_int("unpremult"); if (fromspace == "current" || fromspace == "") - fromspace = img[1]->spec().get_string_attribute("oiio:Colorspace", - "Linear"); + fromspace = img[1]->spec().get_string_attribute("oiio:Colorspace"); if (tospace == "current" || tospace == "") - tospace = img[1]->spec().get_string_attribute("oiio:Colorspace", - "Linear"); + tospace = img[1]->spec().get_string_attribute("oiio:Colorspace"); return ImageBufAlgo::ociolook(*img[0], *img[1], lookname, fromspace, tospace, unpremult, inverse, contextkey, contextvalue, &ot.colorconfig); @@ -2786,8 +2784,7 @@ OIIOTOOL_OP(ociodisplay, 1, [](OiiotoolOp& op, span img) { bool unpremult = op.options().get_int("unpremult"); bool inverse = op.options().get_int("inverse"); if (fromspace == "current" || fromspace == "") - fromspace = img[1]->spec().get_string_attribute("oiio:Colorspace", - "Linear"); + fromspace = img[1]->spec().get_string_attribute("oiio:Colorspace"); return ImageBufAlgo::ociodisplay(*img[0], *img[1], displayname, viewname, fromspace, looks, unpremult, inverse, contextkey, contextvalue, &ot.colorconfig); @@ -5275,12 +5272,9 @@ input_file(int argc, const char* argv[]) << " indicates color space \"" << colorspace << "\"\n"; } - std::string linearspace = ot.colorconfig.getColorSpaceNameByRole( - "linear"); - if (linearspace.empty()) - linearspace = string_view("Linear"); + std::string linearspace = ot.colorconfig.resolve("linear"); if (colorspace.size() - && !Strutil::iequals(colorspace, linearspace)) { + && ot.colorconfig.equivalent(colorspace, linearspace)) { std::string cmd = "colorconvert:strict=0"; if (autoccunpremult) cmd += ":unpremult=1"; @@ -5566,10 +5560,7 @@ output_file(int /*argc*/, const char* argv[]) } } if (autocc) { - string_view linearspace = ot.colorconfig.getColorSpaceNameByRole( - "linear"); - if (linearspace.empty()) - linearspace = string_view("Linear"); + string_view linearspace = ot.colorconfig.resolve("linear"); std::string currentspace = ir->spec()->get_string_attribute("oiio:ColorSpace", linearspace); // Special cases where we know formats should be particular color @@ -6023,103 +6014,160 @@ print_usage_tips() -static void -print_help_end(std::ostream& out) +inline bool +has_space(string_view s) { - out << "\n"; - int columns = Sysutil::terminal_columns() - 2; + return s.find(' ') != string_view::npos; +} - out << formatted_format_list("Input", "input_format_list") << "\n"; - out << formatted_format_list("Output", "output_format_list") << "\n"; - // debugging color space names + +inline std::string +quote_if_spaces(string_view s) +{ + return has_space(s) ? Strutil::fmt::format("\"{}\"", s) : std::string(s); +} + + + +template +inline std::string +join_with_quotes(const Sequence& seq, string_view sep = "") +{ + std::ostringstream out; + out.imbue(std::locale::classic()); // Force "C" locale + bool first = true; + for (auto&& s : seq) { + if (!first && sep.size()) + out << sep; + out << quote_if_spaces(s); + first = false; + } + return out.str(); +} + + +static void +print_ocio_info(std::ostream& out) +{ + using Strutil::print; + int columns = Sysutil::terminal_columns() - 1; + int ociover = ot.colorconfig.OpenColorIO_version_hex(); if (ociover) out << "OpenColorIO " << (ociover >> 24) << '.' << ((ociover >> 16) & 0xff) << '.' << ((ociover >> 8) & 0xff); else out << "No OpenColorIO"; - out << ", color config: " << ot.colorconfig.configname() << "\n"; - std::stringstream s; - s << "Known color spaces: "; + out << "\nColor config: " << ot.colorconfig.configname() << "\n"; + out << "Known color spaces: \n"; const char* linear = ot.colorconfig.getColorSpaceNameByRole("linear"); for (int i = 0, e = ot.colorconfig.getNumColorSpaces(); i < e; ++i) { const char* n = ot.colorconfig.getColorSpaceNameByIndex(i); - s << "\"" << n << "\""; - if (linear && !Strutil::iequals(n, "linear") - && Strutil::iequals(n, linear)) - s << " (linear)"; - if (i < e - 1) - s << ", "; + out << " - " << quote_if_spaces(n); + if ((linear && !ot.colorconfig.equivalent(n, "linear") + && ot.colorconfig.equivalent(n, linear)) + || ot.colorconfig.isColorSpaceLinear(n)) + out << " (linear)"; + out << "\n"; + auto aliases = ot.colorconfig.getAliases(n); + if (aliases.size()) { + std::stringstream s; + s << " aliases: " << join_with_quotes(aliases, ", "); + out << Strutil::wordwrap(s.str(), columns, 6) << "\n"; + } + } + + int roles = ot.colorconfig.getNumRoles(); + if (roles) { + print(out, "Known roles:\n"); + for (int i = 0; i < roles; ++i) { + const char* r = ot.colorconfig.getRoleByIndex(i); + print(out, " - {} -> {}\n", quote_if_spaces(r), + quote_if_spaces(ot.colorconfig.getColorSpaceNameByRole(r))); + } } - out << Strutil::wordwrap(s.str(), columns, 4) << "\n"; int nlooks = ot.colorconfig.getNumLooks(); if (nlooks) { - std::stringstream s; - s << "Known looks: "; - for (int i = 0; i < nlooks; ++i) { - const char* n = ot.colorconfig.getLookNameByIndex(i); - s << "\"" << n << "\""; - if (i < nlooks - 1) - s << ", "; - } - out << Strutil::wordwrap(s.str(), columns, 4) << "\n"; + print(out, "Known looks:\n"); + for (int i = 0; i < nlooks; ++i) + print(out, " - {}\n", + quote_if_spaces(ot.colorconfig.getLookNameByIndex(i))); } const char* default_display = ot.colorconfig.getDefaultDisplayName(); int ndisplays = ot.colorconfig.getNumDisplays(); if (ndisplays) { - std::stringstream s; - s << "Known displays: "; + out << "Known displays: (* indicates default)\n"; for (int i = 0; i < ndisplays; ++i) { const char* d = ot.colorconfig.getDisplayNameByIndex(i); - s << "\"" << d << "\""; + out << " - " << quote_if_spaces(d); if (!strcmp(d, default_display)) - s << "*"; + out << " (*)"; const char* default_view = ot.colorconfig.getDefaultViewName(d); int nviews = ot.colorconfig.getNumViews(d); if (nviews) { - s << " (views: "; + out << "\n "; + std::stringstream s; + s << "views: "; for (int i = 0; i < nviews; ++i) { const char* v = ot.colorconfig.getViewNameByIndex(d, i); - s << "\"" << v << "\""; + s << quote_if_spaces(v); if (!strcmp(v, default_view)) - s << "*"; + s << " (*)"; if (i < nviews - 1) s << ", "; } - s << ")"; + out << Strutil::wordwrap(s.str(), columns, 6, " ") /*<< "\n"*/; } - if (i < ndisplays - 1) - s << ", "; + out << "\n"; } - s << " (* = default)"; - out << Strutil::wordwrap(s.str(), columns, 4) << "\n"; } if (!ot.colorconfig.supportsOpenColorIO()) out << "No OpenColorIO support was enabled at build time.\n"; +} + + + +static void +print_help_end(std::ostream& out) +{ + using Strutil::print; + print(out, "\n"); + int columns = Sysutil::terminal_columns() - 2; + + out << formatted_format_list("Input", "input_format_list") << "\n"; + out << formatted_format_list("Output", "output_format_list") << "\n"; + + if (int ociover = ot.colorconfig.OpenColorIO_version_hex()) + print(out, "OpenColorIO {}.{}.{}\n", (ociover >> 24), + ((ociover >> 16) & 0xff), ((ociover >> 8) & 0xff)); + else + print(out, "No OpenColorIO\n"); + print(out, " Color config: {}\n", ot.colorconfig.configname()); + print(out, " Run `oiiotool --colorconfiginfo` for a " + "full color management inventory.\n"); std::vector filternames; for (int i = 0, e = Filter2D::num_filters(); i < e; ++i) filternames.emplace_back(Filter2D::get_filterdesc(i).name); - out << Strutil::wordwrap("Filters available: " - + Strutil::join(filternames, ", "), - columns, 4) - << "\n"; + print(out, "{}\n", + Strutil::wordwrap("Filters available: " + + Strutil::join(filternames, ", "), + columns, 4)); std::string libs = OIIO::get_string_attribute("library_list"); if (libs.size()) { - std::vector libvec; - Strutil::split(libs, libvec, ";"); + auto libvec = Strutil::splitsv(libs, ";"); for (auto& lib : libvec) { size_t pos = lib.find(':'); lib.remove_prefix(pos + 1); } - out << Strutil::wordwrap("Dependent libraries: " - + Strutil::join(libvec, ", "), - columns, 4) - << std::endl; + print(out, "{}\n", + Strutil::wordwrap("Dependent libraries: " + + Strutil::join(libvec, ", "), + columns, 4)); } // Print the HW info @@ -6130,19 +6178,19 @@ print_help_end(std::ostream& out) OIIO_VERSION_STRING, OIIO_CPLUSPLUS_VERSION, __cplusplus, buildsimd); - out << Strutil::wordwrap(buildinfo, columns, 4) << std::endl; + print("{}\n", Strutil::wordwrap(buildinfo, columns, 4)); auto hwinfo = Strutil::fmt::format("Running on {} cores {:.1f}GB {}", Sysutil::hardware_concurrency(), Sysutil::physical_memory() / float(1 << 30), OIIO::get_string_attribute("hw:simd")); - out << Strutil::wordwrap(hwinfo, columns, 4) << std::endl; + print(out, "{}\n", Strutil::wordwrap(hwinfo, columns, 4)); // Print the path to the docs. If found, use the one installed in the // same area is this executable, otherwise just point to the copy on // GitHub corresponding to our version of the softare. - out << "Full OIIO documentation can be found at\n"; - out << " https://openimageio.readthedocs.io\n"; + print(out, "Full OIIO documentation can be found at\n"); + print(out, " https://openimageio.readthedocs.io\n"); } @@ -6797,6 +6845,12 @@ Oiiotool::getargs(int argc, char* argv[]) .action(action_label); ap.separator("Color management:"); + ap.arg("--colorconfiginfo") + .help("Print extensive details about the color management configuration") + .action([](cspan){ + print_ocio_info(std::cout); + ot.printed_info = true; + }); ap.arg("--colorconfig %s:FILENAME") .help("Explicitly specify an OCIO configuration file") .action(set_colorconfig); diff --git a/src/python/py_colorconfig.cpp b/src/python/py_colorconfig.cpp index 5437606953..91bf36da39 100644 --- a/src/python/py_colorconfig.cpp +++ b/src/python/py_colorconfig.cpp @@ -110,6 +110,19 @@ declare_colorconfig(py::module& m) [](const ColorConfig& self, const std::string& str) { return std::string(self.parseColorSpaceFromString(str)); }) + .def( + "resolve", + [](const ColorConfig& self, const std::string& name) { + return std::string(self.resolve(name)); + }, + "name"_a) + .def( + "equivalent", + [](const ColorConfig& self, const std::string& color_space, + const std::string& other_color_space) { + return self.equivalent(color_space, other_color_space); + }, + "color_space"_a, "other_color_space"_a) .def("configname", &ColorConfig::configname); m.attr("supportsOpenColorIO") = ColorConfig::supportsOpenColorIO(); diff --git a/src/targa.imageio/targainput.cpp b/src/targa.imageio/targainput.cpp index 8748a93ed5..e89326b9dd 100644 --- a/src/targa.imageio/targainput.cpp +++ b/src/targa.imageio/targainput.cpp @@ -427,7 +427,8 @@ TGAInput::read_tga2_header() // 2.2, not 2.19998. gamma = roundf(100.0 * gamma) / 100.0f; if (gamma == 1.f) { - m_spec.attribute("oiio:ColorSpace", "linear"); + m_spec.attribute("oiio:ColorSpace", "lin_srgb"); + // Presume that Targa files are sRGB primaries } else { m_spec.attribute("oiio:ColorSpace", Strutil::fmt::format("Gamma{:.2g}", gamma)); diff --git a/testsuite/hdr/ref/out.txt b/testsuite/hdr/ref/out.txt index 8fbd2ebdbb..7f1b7b95f4 100644 --- a/testsuite/hdr/ref/out.txt +++ b/testsuite/hdr/ref/out.txt @@ -2,7 +2,7 @@ Reading MtTamWest.hdr MtTamWest.hdr : 1214 x 732, 3 channel, float hdr channel list: R, G, B Orientation: 1 (normal) - oiio:ColorSpace: "linear" + oiio:ColorSpace: "lin_srgb" Stats Min: 0.000183 0.000240 0.000000 (float) Stats Max: 3.875000 3.875000 4.875000 (float) Stats Avg: 0.220837 0.352995 0.493945 (float) diff --git a/testsuite/oiiotool-color/ref/grey_sRGB.tif b/testsuite/oiiotool-color/ref/grey_sRGB.tif new file mode 100644 index 0000000000..23aabc9624 Binary files /dev/null and b/testsuite/oiiotool-color/ref/grey_sRGB.tif differ diff --git a/testsuite/oiiotool-color/ref/grey_sRGB_un.tif b/testsuite/oiiotool-color/ref/grey_sRGB_un.tif new file mode 100644 index 0000000000..1c7d27bad9 Binary files /dev/null and b/testsuite/oiiotool-color/ref/grey_sRGB_un.tif differ diff --git a/testsuite/oiiotool-color/ref/greyalpha_sRGB_un-ocio22.tif b/testsuite/oiiotool-color/ref/greyalpha_sRGB_un-ocio22.tif new file mode 100644 index 0000000000..6a0ed14ab8 Binary files /dev/null and b/testsuite/oiiotool-color/ref/greyalpha_sRGB_un-ocio22.tif differ diff --git a/testsuite/oiiotool-color/ref/look-default.tif b/testsuite/oiiotool-color/ref/look-default.tif new file mode 100644 index 0000000000..4f33db3dea Binary files /dev/null and b/testsuite/oiiotool-color/ref/look-default.tif differ diff --git a/testsuite/oiiotool-color/ref/out-ocio1.1.0.txt b/testsuite/oiiotool-color/ref/out-ocio1.1.0.txt index 4ea60c3e9e..e3c88a470f 100644 --- a/testsuite/oiiotool-color/ref/out-ocio1.1.0.txt +++ b/testsuite/oiiotool-color/ref/out-ocio1.1.0.txt @@ -28,11 +28,11 @@ Comparing "rgbfromtga.png" and "ref/rgbfromtga.png" PASS Comparing "greyalpha_sRGB.tif" and "ref/greyalpha_sRGB.tif" PASS -Comparing "greyalpha_Cineon.tif" and "ref/greyalpha_Cineon.tif" -PASS Comparing "greyalpha_sRGB_un.tif" and "ref/greyalpha_sRGB_un.tif" PASS -Comparing "greyalpha_Cineon_un.tif" and "ref/greyalpha_Cineon_un.tif" +Comparing "grey_sRGB.tif" and "ref/grey_sRGB.tif" +PASS +Comparing "grey_sRGB_un.tif" and "ref/grey_sRGB_un.tif" PASS Comparing "tahoe-ccmatrix.tif" and "ref/tahoe-ccmatrix.tif" PASS @@ -40,3 +40,7 @@ Comparing "tahoe-sat0.tif" and "ref/tahoe-sat0.tif" PASS Comparing "tahoe-sat2.tif" and "ref/tahoe-sat2.tif" PASS +Comparing "greyalpha_Cineon.tif" and "ref/greyalpha_Cineon.tif" +PASS +Comparing "greyalpha_Cineon_un.tif" and "ref/greyalpha_Cineon_un.tif" +PASS diff --git a/testsuite/oiiotool-color/ref/out-ocio1.1.0b.txt b/testsuite/oiiotool-color/ref/out-ocio1.1.0b.txt index 6f933dd320..e3b6898c4e 100644 --- a/testsuite/oiiotool-color/ref/out-ocio1.1.0b.txt +++ b/testsuite/oiiotool-color/ref/out-ocio1.1.0b.txt @@ -28,11 +28,11 @@ Comparing "rgbfromtga.png" and "ref/rgbfromtga.png" PASS Comparing "greyalpha_sRGB.tif" and "ref/greyalpha_sRGB.tif" PASS -Comparing "greyalpha_Cineon.tif" and "ref/greyalpha_Cineon.tif" -PASS Comparing "greyalpha_sRGB_un.tif" and "ref/greyalpha_sRGB_un.tif" PASS -Comparing "greyalpha_Cineon_un.tif" and "ref/greyalpha_Cineon_un.tif" +Comparing "grey_sRGB.tif" and "ref/grey_sRGB.tif" +PASS +Comparing "grey_sRGB_un.tif" and "ref/grey_sRGB_un.tif" PASS Comparing "tahoe-ccmatrix.tif" and "ref/tahoe-ccmatrix.tif" PASS @@ -40,3 +40,7 @@ Comparing "tahoe-sat0.tif" and "ref/tahoe-sat0.tif" PASS Comparing "tahoe-sat2.tif" and "ref/tahoe-sat2.tif" PASS +Comparing "greyalpha_Cineon.tif" and "ref/greyalpha_Cineon.tif" +PASS +Comparing "greyalpha_Cineon_un.tif" and "ref/greyalpha_Cineon_un.tif" +PASS diff --git a/testsuite/oiiotool-color/ref/out-ocio22.txt b/testsuite/oiiotool-color/ref/out-ocio22.txt new file mode 100644 index 0000000000..e25768e4a0 --- /dev/null +++ b/testsuite/oiiotool-color/ref/out-ocio22.txt @@ -0,0 +1,42 @@ +oiiotool ERROR: --colorconfig : Requested non-existent OCIO config "missing.ocio" +Full command line was: +> oiiotool --nostderr --colorconfig missing.ocio -echo "Nonexistent config" +OCIOv2 config Ok +Comparing "colormap-inferno.tif" and "ref/colormap-inferno.tif" +PASS +Comparing "colormap-custom.tif" and "ref/colormap-custom.tif" +PASS +Comparing "unpremult.exr" and "ref/unpremult.exr" +PASS +Comparing "premult.exr" and "ref/premult.exr" +PASS +Comparing "contrast-stretch.tif" and "ref/contrast-stretch.tif" +PASS +Comparing "contrast-shrink.tif" and "ref/contrast-shrink.tif" +PASS +Comparing "contrast-inverse.tif" and "ref/contrast-inverse.tif" +PASS +Comparing "contrast-threshold.tif" and "ref/contrast-threshold.tif" +PASS +Comparing "contrast-sigmoid5.tif" and "ref/contrast-sigmoid5.tif" +PASS +Comparing "display-sRGB.tif" and "ref/display-sRGB.tif" +PASS +Comparing "rgbfromtga.png" and "ref/rgbfromtga.png" +PASS +Comparing "greyalpha_sRGB.tif" and "ref/greyalpha_sRGB.tif" +PASS +Comparing "greyalpha_sRGB_un.tif" and "ref/greyalpha_sRGB_un-ocio22.tif" +PASS +Comparing "grey_sRGB.tif" and "ref/grey_sRGB.tif" +PASS +Comparing "grey_sRGB_un.tif" and "ref/grey_sRGB_un.tif" +PASS +Comparing "tahoe-ccmatrix.tif" and "ref/tahoe-ccmatrix.tif" +PASS +Comparing "tahoe-sat0.tif" and "ref/tahoe-sat0.tif" +PASS +Comparing "tahoe-sat2.tif" and "ref/tahoe-sat2.tif" +PASS +Comparing "look-default.tif" and "ref/look-default.tif" +PASS diff --git a/testsuite/oiiotool-color/ref/out.txt b/testsuite/oiiotool-color/ref/out.txt index 7d7b0d33cb..f1eb5c2b77 100644 --- a/testsuite/oiiotool-color/ref/out.txt +++ b/testsuite/oiiotool-color/ref/out.txt @@ -26,11 +26,11 @@ Comparing "rgbfromtga.png" and "ref/rgbfromtga.png" PASS Comparing "greyalpha_sRGB.tif" and "ref/greyalpha_sRGB.tif" PASS -Comparing "greyalpha_Cineon.tif" and "ref/greyalpha_Cineon.tif" -PASS Comparing "greyalpha_sRGB_un.tif" and "ref/greyalpha_sRGB_un.tif" PASS -Comparing "greyalpha_Cineon_un.tif" and "ref/greyalpha_Cineon_un.tif" +Comparing "grey_sRGB.tif" and "ref/grey_sRGB.tif" +PASS +Comparing "grey_sRGB_un.tif" and "ref/grey_sRGB_un.tif" PASS Comparing "tahoe-ccmatrix.tif" and "ref/tahoe-ccmatrix.tif" PASS @@ -38,3 +38,7 @@ Comparing "tahoe-sat0.tif" and "ref/tahoe-sat0.tif" PASS Comparing "tahoe-sat2.tif" and "ref/tahoe-sat2.tif" PASS +Comparing "greyalpha_Cineon.tif" and "ref/greyalpha_Cineon.tif" +PASS +Comparing "greyalpha_Cineon_un.tif" and "ref/greyalpha_Cineon_un.tif" +PASS diff --git a/testsuite/oiiotool-color/run.py b/testsuite/oiiotool-color/run.py index ea40207085..65ae390d3b 100644 --- a/testsuite/oiiotool-color/run.py +++ b/testsuite/oiiotool-color/run.py @@ -3,12 +3,15 @@ from __future__ import absolute_import import os +# print("ociover =", ociover) # Make test pattern with increasing intensity left to right, decreasing # alpha going down. Carefully done so that the first pixel is 0.0, last # pixel is 1.0 (correcting for the half pixel offset). command += oiiotool ("-pattern fill:topleft=0,0,0,1:topright=1,1,1,1:bottomleft=0,0,0,0:bottomright=1,1,1,0 256x256 4 " - + " -d uint8 -o greyalpha_linear.tif") + + " -d uint8 -o greyalpha_lin_srgb.tif") +command += oiiotool ("-pattern fill:topleft=0,0,0:topright=1,1,1:bottomleft=0,0,0:bottomright=1,1,1 256x256 3 " + + " -d uint8 -o grey_lin_srgb.tif") # test --colormap @@ -54,13 +57,19 @@ # # colorconvert without unpremult -command += oiiotool ("greyalpha_linear.tif --colorconvert:unpremult=0 linear sRGB -o greyalpha_sRGB.tif") -command += oiiotool ("greyalpha_linear.tif --colorconvert:unpremult=0 linear Cineon -o greyalpha_Cineon.tif") - -# colorconvert with unpremult -command += oiiotool ("greyalpha_linear.tif --colorconvert:unpremult=1 linear sRGB -o greyalpha_sRGB_un.tif") -command += oiiotool ("greyalpha_linear.tif --colorconvert:unpremult=1 linear Cineon -o greyalpha_Cineon_un.tif") - +if float(ociover) >= 2.2 : + command += oiiotool ("greyalpha_lin_srgb.tif --colorconvert:unpremult=0 lin_srgb sRGB -o greyalpha_sRGB.tif") + command += oiiotool ("greyalpha_lin_srgb.tif --colorconvert:unpremult=1 lin_srgb sRGB -o greyalpha_sRGB_un.tif") + command += oiiotool ("grey_lin_srgb.tif --colorconvert:unpremult=0 lin_srgb sRGB -o grey_sRGB.tif") + command += oiiotool ("grey_lin_srgb.tif --colorconvert:unpremult=1 lin_srgb sRGB -o grey_sRGB_un.tif") +else: + command += oiiotool ("greyalpha_lin_srgb.tif --colorconvert:unpremult=0 linear sRGB -o greyalpha_sRGB.tif") + command += oiiotool ("greyalpha_lin_srgb.tif --colorconvert:unpremult=0 linear Cineon -o greyalpha_Cineon.tif") + command += oiiotool ("greyalpha_lin_srgb.tif --colorconvert:unpremult=1 linear sRGB -o greyalpha_sRGB_un.tif") + command += oiiotool ("greyalpha_lin_srgb.tif --colorconvert:unpremult=1 linear Cineon -o greyalpha_Cineon_un.tif") + command += oiiotool ("grey_lin_srgb.tif --colorconvert:unpremult=0 linear sRGB -o grey_sRGB.tif") + command += oiiotool ("grey_lin_srgb.tif --colorconvert:unpremult=1 linear sRGB -o grey_sRGB_un.tif") + # test color convert by matrix command += oiiotool ("--autocc " + "../common/tahoe-tiny.tif"+ " " @@ -68,9 +77,15 @@ + "-d uint8 -o tahoe-ccmatrix.tif") # Apply a display -command += oiiotool ("greyalpha_linear.tif --ociodisplay default sRGB -o display-sRGB.tif") +if float(ociover) >= 2.2 : + command += oiiotool ("greyalpha_lin_srgb.tif --iscolorspace lin_srgb --ociodisplay \"sRGB - Display\" Un-tone-mapped -o display-sRGB.tif") +else : + command += oiiotool ("greyalpha_lin_srgb.tif --ociodisplay default sRGB -o display-sRGB.tif") + +# Applying a look +if float(ociover) >= 2.2 : + command += oiiotool ("--autocc ../common/tahoe-tiny.tif --ociolook \"ACES 1.3 Reference Gamut Compression\" -o look-default.tif") -# TODO: should test applying a look # TODO: should test applying a file transform # test various behaviors and misbehaviors related to OCIO configs. @@ -99,10 +114,18 @@ "display-sRGB.tif", "rgbfromtga.png", "greyalpha_sRGB.tif", - "greyalpha_Cineon.tif", "greyalpha_sRGB_un.tif", - "greyalpha_Cineon_un.tif", + "grey_sRGB.tif", + "grey_sRGB_un.tif", "tahoe-ccmatrix.tif", "tahoe-sat0.tif", - "tahoe-sat2.tif", - "out.txt" ] + "tahoe-sat2.tif" + ] +if float(ociover) >= 2.2 : + outputs += [ "look-default.tif" ] +else : + outputs += [ + "greyalpha_Cineon.tif", + "greyalpha_Cineon_un.tif", + ] +outputs += [ "out.txt" ] diff --git a/testsuite/python-colorconfig/ref/out-noocio-python27.txt b/testsuite/python-colorconfig/ref/out-noocio-python27.txt index b51d6a28fb..f18cb06248 100644 --- a/testsuite/python-colorconfig/ref/out-noocio-python27.txt +++ b/testsuite/python-colorconfig/ref/out-noocio-python27.txt @@ -1,5 +1,5 @@ -getNumColorSpaces = 6 -getColorSpaceNames = ['linear', 'default', 'rgb', 'RGB', 'sRGB', 'Rec709'] +getNumColorSpaces = 8 +getColorSpaceNames = [u'linear', u'scene_linear', u'default', u'rgb', u'RGB', u'lin_srgb', u'sRGB', u'Rec709'] getNumLooks = 0 getLookNames = [] getNumDisplays = 0 @@ -10,5 +10,16 @@ getViewNames = [] getDefaultViewName = None getNumRoles = 0 getRoles = [] +aliases of 'scene_linear' are [] +resolve('foo'): foo +resolve('linear'): linear +resolve('scene_linear'): scene_linear +resolve('lin_srgb'): lin_srgb +resolve('srgb'): srgb +equivalent('lin_srgb', 'srgb'): False +equivalent('scene_linear', 'srgb'): False +equivalent('scene_linear', 'lin_srgb'): False +equivalent('ACEScg', 'scene_linear'): False +equivalent('lnf', 'scene_linear'): False Done. diff --git a/testsuite/python-colorconfig/ref/out-noocio-python3.txt b/testsuite/python-colorconfig/ref/out-noocio-python3.txt new file mode 100644 index 0000000000..d52e53583b --- /dev/null +++ b/testsuite/python-colorconfig/ref/out-noocio-python3.txt @@ -0,0 +1,25 @@ +getNumColorSpaces = 8 +getColorSpaceNames = ['linear', 'scene_linear', 'default', 'rgb', 'RGB', 'lin_srgb', 'sRGB', 'Rec709'] +getNumLooks = 0 +getLookNames = [] +getNumDisplays = 0 +getDisplayNames = [] +getDefaultDisplayName = None +getNumViews = 0 +getViewNames = [] +getDefaultViewName = None +getNumRoles = 0 +getRoles = [] +aliases of 'scene_linear' are [] +resolve('foo'): foo +resolve('linear'): linear +resolve('scene_linear'): scene_linear +resolve('lin_srgb'): lin_srgb +resolve('srgb'): srgb +equivalent('lin_srgb', 'srgb'): False +equivalent('scene_linear', 'srgb'): False +equivalent('scene_linear', 'lin_srgb'): False +equivalent('ACEScg', 'scene_linear'): False +equivalent('lnf', 'scene_linear'): False + +Done. diff --git a/testsuite/python-colorconfig/ref/out-noocio.txt b/testsuite/python-colorconfig/ref/out-noocio.txt deleted file mode 100644 index 58ff918c88..0000000000 --- a/testsuite/python-colorconfig/ref/out-noocio.txt +++ /dev/null @@ -1,14 +0,0 @@ -getNumColorSpaces = 6 -getColorSpaceNames = [u'linear', u'default', u'rgb', u'RGB', u'sRGB', u'Rec709'] -getNumLooks = 0 -getLookNames = [] -getNumDisplays = 0 -getDisplayNames = [] -getDefaultDisplayName = None -getNumViews = 0 -getViewNames = [] -getDefaultViewName = None -getNumRoles = 0 -getRoles = [] - -Done. diff --git a/testsuite/python-colorconfig/ref/out-ocio11-python27.txt b/testsuite/python-colorconfig/ref/out-ocio11-python27.txt new file mode 100644 index 0000000000..b0ae8853e7 --- /dev/null +++ b/testsuite/python-colorconfig/ref/out-ocio11-python27.txt @@ -0,0 +1,25 @@ +getNumColorSpaces = 14 +getColorSpaceNames = [u'linear', u'sRGB', u'sRGBf', u'rec709', u'Cineon', u'Gamma1.8', u'Gamma2.2', u'Panalog', u'REDLog', u'ViperLog', u'AlexaV3LogC', u'PLogLin', u'SLog', u'raw'] +getNumLooks = 0 +getLookNames = [] +getNumDisplays = 1 +getDisplayNames = [u'default'] +getDefaultDisplayName = default +getNumViews = 3 +getViewNames = [u'None', u'sRGB', u'rec709'] +getDefaultViewName = None +getNumRoles = 9 +getRoles = [u'color_picking', u'color_timing', u'compositing_log', u'data', u'default', u'matte_paint', u'reference', u'scene_linear', u'texture_paint'] +aliases of 'scene_linear' are [] +resolve('foo'): foo +resolve('linear'): linear +resolve('scene_linear'): linear +resolve('lin_srgb'): lin_srgb +resolve('srgb'): sRGB +equivalent('lin_srgb', 'srgb'): False +equivalent('scene_linear', 'srgb'): False +equivalent('scene_linear', 'lin_srgb'): False +equivalent('ACEScg', 'scene_linear'): False +equivalent('lnf', 'scene_linear'): False + +Done. diff --git a/testsuite/python-colorconfig/ref/out-ocio11-python3.txt b/testsuite/python-colorconfig/ref/out-ocio11-python3.txt new file mode 100644 index 0000000000..001d7fc199 --- /dev/null +++ b/testsuite/python-colorconfig/ref/out-ocio11-python3.txt @@ -0,0 +1,25 @@ +getNumColorSpaces = 14 +getColorSpaceNames = ['linear', 'sRGB', 'sRGBf', 'rec709', 'Cineon', 'Gamma1.8', 'Gamma2.2', 'Panalog', 'REDLog', 'ViperLog', 'AlexaV3LogC', 'PLogLin', 'SLog', 'raw'] +getNumLooks = 0 +getLookNames = [] +getNumDisplays = 1 +getDisplayNames = ['default'] +getDefaultDisplayName = default +getNumViews = 3 +getViewNames = ['None', 'sRGB', 'rec709'] +getDefaultViewName = sRGB +getNumRoles = 9 +getRoles = ['color_picking', 'color_timing', 'compositing_log', 'data', 'default', 'matte_paint', 'reference', 'scene_linear', 'texture_paint'] +aliases of 'scene_linear' are [] +resolve('foo'): foo +resolve('linear'): linear +resolve('scene_linear'): linear +resolve('lin_srgb'): lin_srgb +resolve('srgb'): sRGB +equivalent('lin_srgb', 'srgb'): False +equivalent('scene_linear', 'srgb'): False +equivalent('scene_linear', 'lin_srgb'): False +equivalent('ACEScg', 'scene_linear'): False +equivalent('lnf', 'scene_linear'): False + +Done. diff --git a/testsuite/python-colorconfig/ref/out-ocio2-python27.txt b/testsuite/python-colorconfig/ref/out-ocio21-python27.txt similarity index 54% rename from testsuite/python-colorconfig/ref/out-ocio2-python27.txt rename to testsuite/python-colorconfig/ref/out-ocio21-python27.txt index 72addba55d..3b81b3751f 100644 --- a/testsuite/python-colorconfig/ref/out-ocio2-python27.txt +++ b/testsuite/python-colorconfig/ref/out-ocio21-python27.txt @@ -5,10 +5,21 @@ getLookNames = [] getNumDisplays = 1 getDisplayNames = [u'default'] getDefaultDisplayName = default -getNumViews = 1 -getViewNames = [u'sRGB'] +getNumViews = 3 +getViewNames = [u'None', u'sRGB', u'rec709'] getDefaultViewName = getNumRoles = 9 getRoles = [u'color_picking', u'color_timing', u'compositing_log', u'data', u'default', u'matte_paint', u'reference', u'scene_linear', u'texture_paint'] +aliases of 'scene_linear' are [] +resolve('foo'): foo +resolve('linear'): linear +resolve('scene_linear'): linear +resolve('lin_srgb'): lin_srgb +resolve('srgb'): sRGB +equivalent('lin_srgb', 'srgb'): False +equivalent('scene_linear', 'srgb'): False +equivalent('scene_linear', 'lin_srgb'): False +equivalent('ACEScg', 'scene_linear'): False +equivalent('lnf', 'scene_linear'): False Done. diff --git a/testsuite/python-colorconfig/ref/out-ocio2.txt b/testsuite/python-colorconfig/ref/out-ocio21-python3.txt similarity index 56% rename from testsuite/python-colorconfig/ref/out-ocio2.txt rename to testsuite/python-colorconfig/ref/out-ocio21-python3.txt index 8f20165a46..4e6ee22c89 100644 --- a/testsuite/python-colorconfig/ref/out-ocio2.txt +++ b/testsuite/python-colorconfig/ref/out-ocio21-python3.txt @@ -7,8 +7,19 @@ getDisplayNames = ['default'] getDefaultDisplayName = default getNumViews = 1 getViewNames = ['sRGB'] -getDefaultViewName = +getDefaultViewName = sRGB getNumRoles = 9 getRoles = ['color_picking', 'color_timing', 'compositing_log', 'data', 'default', 'matte_paint', 'reference', 'scene_linear', 'texture_paint'] +aliases of 'scene_linear' are [] +resolve('foo'): foo +resolve('linear'): linear +resolve('scene_linear'): linear +resolve('lin_srgb'): lin_srgb +resolve('srgb'): sRGB +equivalent('lin_srgb', 'srgb'): False +equivalent('scene_linear', 'srgb'): False +equivalent('scene_linear', 'lin_srgb'): False +equivalent('ACEScg', 'scene_linear'): False +equivalent('lnf', 'scene_linear'): False Done. diff --git a/testsuite/python-colorconfig/ref/out-ocio22.txt b/testsuite/python-colorconfig/ref/out-ocio22.txt new file mode 100644 index 0000000000..8176f2ec98 --- /dev/null +++ b/testsuite/python-colorconfig/ref/out-ocio22.txt @@ -0,0 +1,25 @@ +getNumColorSpaces = 14 +getColorSpaceNames = ['ACES2065-1', 'ACEScc', 'ACEScct', 'ACEScg', 'Linear P3-D65', 'Linear Rec.2020', 'Linear Rec.709 (sRGB)', 'Gamma 1.8 Rec.709 - Texture', 'Gamma 2.2 AP1 - Texture', 'Gamma 2.2 Rec.709 - Texture', 'Gamma 2.4 Rec.709 - Texture', 'sRGB Encoded AP1 - Texture', 'sRGB - Texture', 'Raw'] +getNumLooks = 1 +getLookNames = ['ACES 1.3 Reference Gamut Compression'] +getNumDisplays = 5 +getDisplayNames = ['sRGB - Display', 'Rec.1886 Rec.709 - Display', 'Rec.2100-PQ - Display', 'ST2084-P3-D65 - Display', 'P3-D65 - Display'] +getDefaultDisplayName = sRGB - Display +getNumViews = 3 +getViewNames = ['ACES 1.0 - SDR Video', 'Un-tone-mapped', 'Raw'] +getDefaultViewName = ACES 1.0 - SDR Video +getNumRoles = 9 +getRoles = ['aces_interchange', 'cie_xyz_d65_interchange', 'color_picking', 'color_timing', 'compositing_log', 'data', 'matte_paint', 'scene_linear', 'texture_paint'] +aliases of 'scene_linear' are ['ACES - ACEScg', 'lin_ap1'] +resolve('foo'): foo +resolve('linear'): ACEScg +resolve('scene_linear'): ACEScg +resolve('lin_srgb'): Linear Rec.709 (sRGB) +resolve('srgb'): sRGB - Texture +equivalent('lin_srgb', 'srgb'): False +equivalent('scene_linear', 'srgb'): False +equivalent('scene_linear', 'lin_srgb'): False +equivalent('ACEScg', 'scene_linear'): True +equivalent('lnf', 'scene_linear'): False + +Done. diff --git a/testsuite/python-colorconfig/ref/out-python27.txt b/testsuite/python-colorconfig/ref/out-python27.txt index fa25565fd5..21c6d8f059 100644 --- a/testsuite/python-colorconfig/ref/out-python27.txt +++ b/testsuite/python-colorconfig/ref/out-python27.txt @@ -10,5 +10,16 @@ getViewNames = [u'None', u'sRGB', u'rec709'] getDefaultViewName = getNumRoles = 9 getRoles = [u'color_picking', u'color_timing', u'compositing_log', u'data', u'default', u'matte_paint', u'reference', u'scene_linear', u'texture_paint'] +aliases of 'scene_linear' are [] +resolve('foo'): foo +resolve('linear'): linear +resolve('scene_linear'): linear +resolve('lin_srgb'): linear +resolve('srgb'): sRGB +equivalent('lin_srgb', 'srgb'): False +equivalent('scene_linear', 'srgb'): False +equivalent('scene_linear', 'lin_srgb'): True +equivalent('ACEScg', 'scene_linear'): False +equivalent('lnf', 'scene_linear'): False Done. diff --git a/testsuite/python-colorconfig/ref/out.txt b/testsuite/python-colorconfig/ref/out.txt index b2bcbd96c3..bc30ac9f14 100644 --- a/testsuite/python-colorconfig/ref/out.txt +++ b/testsuite/python-colorconfig/ref/out.txt @@ -10,5 +10,16 @@ getViewNames = ['None', 'sRGB', 'rec709'] getDefaultViewName = getNumRoles = 9 getRoles = ['color_picking', 'color_timing', 'compositing_log', 'data', 'default', 'matte_paint', 'reference', 'scene_linear', 'texture_paint'] +aliases of 'scene_linear' are [] +resolve('foo'): foo +resolve('linear'): linear +resolve('scene_linear'): linear +resolve('lin_srgb'): linear +resolve('srgb'): sRGB +equivalent('lin_srgb', 'srgb'): False +equivalent('scene_linear', 'srgb'): False +equivalent('scene_linear', 'lin_srgb'): True +equivalent('ACEScg', 'scene_linear'): False +equivalent('lnf', 'scene_linear'): False Done. diff --git a/testsuite/python-colorconfig/src/test_colorconfig.py b/testsuite/python-colorconfig/src/test_colorconfig.py index 8b1c0f3c79..de1e114aee 100755 --- a/testsuite/python-colorconfig/src/test_colorconfig.py +++ b/testsuite/python-colorconfig/src/test_colorconfig.py @@ -25,6 +25,18 @@ print ("getNumRoles =", config.getNumRoles()) print ("getRoles =", config.getRoles()) + print ("aliases of 'scene_linear' are", config.getAliases("scene_linear")) + + print ("resolve('foo'):", config.resolve("foo")) + print ("resolve('linear'):", config.resolve("linear")) + print ("resolve('scene_linear'):", config.resolve("scene_linear")) + print ("resolve('lin_srgb'):", config.resolve("lin_srgb")) + print ("resolve('srgb'):", config.resolve("srgb")) + print ("equivalent('lin_srgb', 'srgb'):", config.equivalent("lin_srgb", "srgb")) + print ("equivalent('scene_linear', 'srgb'):", config.equivalent("scene_linear", "srgb")) + print ("equivalent('scene_linear', 'lin_srgb'):", config.equivalent("scene_linear", "lin_srgb")) + print ("equivalent('ACEScg', 'scene_linear'):", config.equivalent("ACEScg", "scene_linear")) + print ("equivalent('lnf', 'scene_linear'):", config.equivalent("lnf", "scene_linear")) print ("") print ("Done.") diff --git a/testsuite/runtest.py b/testsuite/runtest.py index b889723715..d3d0a15397 100755 --- a/testsuite/runtest.py +++ b/testsuite/runtest.py @@ -90,7 +90,7 @@ def oiio_app (app): return cmd -# Ask oiiotool what version of OpenColorIO it has emedded +# Ask oiiotool what version of OpenColorIO it has embedded ociover = subprocess.check_output([oiio_app('oiiotool').strip(), '--echo', '{getattribute(opencolorio_version)}']) ociover = ociover.strip().decode('utf-8')[0:3] @@ -99,7 +99,7 @@ def oiio_app (app): OCIO_env = os.getenv('OCIO') if OCIO_env is None: - os.environ['OCIO'] = 'ocio:://default' + os.environ['OCIO'] = 'ocio://default' if ociover == '2.2' or ociover == '2.3' : colorconfig_file = os.getenv('OIIO_TESTSUITE_OCIOCONFIG', 'ocio://default') else :