diff --git a/src/doc/oiiotool.rst b/src/doc/oiiotool.rst index e68a8fe66c..4fde8aa5f3 100644 --- a/src/doc/oiiotool.rst +++ b/src/doc/oiiotool.rst @@ -4188,6 +4188,10 @@ bottom you will see the list of all color spaces, looks, and displays that is 0, meaning the color transformation not will be automatically bracketed by divide-by-alpha / mult-by-alpha operations. + `inverse=` *val* : + + If *val* is nonzero, inverts the color transformation. + `:subimages=` *indices-or-names* Include/exclude subimages (see :ref:`sec-oiiotool-subimage-modifier`). diff --git a/src/doc/pythonbindings.rst b/src/doc/pythonbindings.rst index e20a1654ae..55e8aaddca 100644 --- a/src/doc/pythonbindings.rst +++ b/src/doc/pythonbindings.rst @@ -3572,8 +3572,8 @@ Color manipulation -.. py:method:: ImageBuf ImageBufAlgo.ociodisplay (src, display, view, fromspace="", looks="", unpremult=True, context_key="", context_value="", colorconfig="", roi=ROI.All, nthreads=0) - bool ImageBufAlgo.ociodisplay (dst, src, display, view, fromspace="", looks="", unpremult=True, context_key="", context_value="", colorconfig="", roi=ROI.All, nthreads=0) +.. py:method:: ImageBuf ImageBufAlgo.ociodisplay (src, display, view, fromspace="", looks="", unpremult=True, inverse=False, context_key="", context_value="", colorconfig="", roi=ROI.All, nthreads=0) + bool ImageBufAlgo.ociodisplay (dst, src, display, view, fromspace="", looks="", unpremult=True, inverse=False, context_key="", context_value="", colorconfig="", roi=ROI.All, nthreads=0) Apply an OpenColorIO "display" transform to the pixel values. diff --git a/src/include/OpenImageIO/color.h b/src/include/OpenImageIO/color.h index d29667f767..5155419606 100644 --- a/src/include/OpenImageIO/color.h +++ b/src/include/OpenImageIO/color.h @@ -161,7 +161,7 @@ class OIIO_API ColorConfig { /// inverse==true, request the inverse transformation. The /// context_key and context_value can optionally be used to establish /// extra key/value pairs in the OCIO context if they are comma- - /// separated lists of ontext keys and values, respectively. + /// separated lists of context keys and values, respectively. /// /// The handle is actually a shared_ptr, so when you're done with a /// ColorProcess, just discard it. ColorProcessor(s) remain valid even @@ -245,14 +245,26 @@ class OIIO_API ColorConfig { ColorProcessorHandle createDisplayTransform(string_view display, string_view view, string_view inputColorSpace, string_view looks = "", - string_view context_key = "", + bool inverse = false, string_view context_key = "", string_view context_value = "") const; ColorProcessorHandle createDisplayTransform(ustring display, ustring view, ustring inputColorSpace, ustring looks = ustring(), + bool inverse = false, ustring context_key = ustring(), ustring context_value = ustring()) const; + // OIIO_DEPRECATED("prefer the kind that takes an `inverse` parameter (2.5)") + ColorProcessorHandle + createDisplayTransform(string_view display, string_view view, + string_view inputColorSpace, string_view looks, + string_view context_key, + string_view context_value = "") const; + // OIIO_DEPRECATED("prefer the kind that takes an `inverse` parameter (2.5)") + ColorProcessorHandle createDisplayTransform( + ustring display, ustring view, ustring inputColorSpace, ustring looks, + ustring context_key, ustring context_value = ustring()) const; + /// Construct a processor to perform color transforms determined by an /// OpenColorIO FileTransform. It is possible that this will return an /// empty handle if the FileTransform doesn't exist or is not allowed. diff --git a/src/include/OpenImageIO/imagebufalgo.h b/src/include/OpenImageIO/imagebufalgo.h index 92cc91ef1f..2bc8a153f7 100644 --- a/src/include/OpenImageIO/imagebufalgo.h +++ b/src/include/OpenImageIO/imagebufalgo.h @@ -1980,7 +1980,7 @@ bool OIIO_API ociolook (ImageBuf &dst, const ImageBuf &src, string_view looks, ImageBuf OIIO_API ociodisplay (const ImageBuf &src, string_view display, string_view view, string_view fromspace="", string_view looks="", - bool unpremult=true, + bool unpremult=true, bool inverse=false, string_view context_key="", string_view context_value="", ColorConfig *colorconfig=nullptr, ROI roi={}, int nthreads=0); @@ -1988,11 +1988,30 @@ ImageBuf OIIO_API ociodisplay (const ImageBuf &src, bool OIIO_API ociodisplay (ImageBuf &dst, const ImageBuf &src, string_view display, string_view view, string_view fromspace="", string_view looks="", - bool unpremult=true, + bool unpremult=true, bool inverse=false, string_view context_key="", string_view context_value="", ColorConfig *colorconfig=nullptr, ROI roi={}, int nthreads=0); +#ifndef OIIO_DOXYGEN +// OIIO_DEPRECATED("prefer the kind that takes an `inverse` parameter (2.5)") +ImageBuf OIIO_API ociodisplay (const ImageBuf &src, + string_view display, string_view view, + string_view fromspace, string_view looks, + bool unpremult, + string_view context_key, string_view context_value="", + 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, + string_view display, string_view view, + string_view fromspace, string_view looks, + bool unpremult, + string_view context_key, string_view context_value="", + ColorConfig *colorconfig=nullptr, + ROI roi={}, int nthreads=0); +#endif + /// Return the pixels of `src` within the ROI, applying an OpenColorIO /// "file" transform. In-place operations (`dst` == `src`) are supported. diff --git a/src/libOpenImageIO/color_ocio.cpp b/src/libOpenImageIO/color_ocio.cpp index 394bcf4322..f671782698 100644 --- a/src/libOpenImageIO/color_ocio.cpp +++ b/src/libOpenImageIO/color_ocio.cpp @@ -1250,12 +1250,14 @@ ColorConfig::createLookTransform(ustring looks, ustring inputColorSpace, ColorProcessorHandle ColorConfig::createDisplayTransform(string_view display, string_view view, string_view inputColorSpace, - string_view looks, string_view context_key, + string_view looks, bool inverse, + string_view context_key, string_view context_value) const { return createDisplayTransform(ustring(display), ustring(view), ustring(inputColorSpace), ustring(looks), - ustring(context_key), ustring(context_value)); + inverse, ustring(context_key), + ustring(context_value)); } @@ -1263,7 +1265,7 @@ ColorConfig::createDisplayTransform(string_view display, string_view view, ColorProcessorHandle ColorConfig::createDisplayTransform(ustring display, ustring view, ustring inputColorSpace, ustring looks, - ustring context_key, + bool inverse, ustring context_key, ustring context_value) const { if (display.empty()) @@ -1273,7 +1275,8 @@ ColorConfig::createDisplayTransform(ustring display, ustring view, // First, look up the requested processor in the cache. If it already // exists, just return it. ColorProcCacheKey prockey(inputColorSpace, ustring() /*outputColorSpace*/, - context_key, context_value, looks, display, view); + context_key, context_value, looks, display, view, + ustring() /*file*/, inverse); ColorProcessorHandle handle = getImpl()->findproc(prockey); if (handle) return handle; @@ -1300,6 +1303,8 @@ ColorConfig::createDisplayTransform(ustring display, ustring view, transform->setLooksOverrideEnabled(false); } # endif + OCIO::TransformDirection dir = inverse ? OCIO::TRANSFORM_DIR_INVERSE + : OCIO::TRANSFORM_DIR_FORWARD; transform->setDisplay(display.c_str()); transform->setView(view.c_str()); auto context = config->getCurrentContext(); @@ -1315,8 +1320,7 @@ ColorConfig::createDisplayTransform(ustring display, ustring view, OCIO::ConstProcessorRcPtr p; try { // Get the processor corresponding to this transform. - p = getImpl()->config_->getProcessor(context, transform, - OCIO::TRANSFORM_DIR_FORWARD); + p = getImpl()->config_->getProcessor(context, transform, dir); getImpl()->clear_error(); handle = ColorProcessorHandle(new ColorProcessor_OCIO(p)); } catch (OCIO::Exception& e) { @@ -1333,6 +1337,30 @@ ColorConfig::createDisplayTransform(ustring display, ustring view, +ColorProcessorHandle +ColorConfig::createDisplayTransform(string_view display, string_view view, + string_view inputColorSpace, + string_view looks, string_view context_key, + string_view context_value) const +{ + return createDisplayTransform(ustring(display), ustring(view), + ustring(inputColorSpace), ustring(looks), + false, ustring(context_key), + ustring(context_value)); +} + +ColorProcessorHandle +ColorConfig::createDisplayTransform(ustring display, ustring view, + ustring inputColorSpace, ustring looks, + ustring context_key, + ustring context_value) const +{ + return createDisplayTransform(display, view, inputColorSpace, looks, false, + context_key, context_value); +} + + + ColorProcessorHandle ColorConfig::createFileTransform(string_view name, bool inverse) const { @@ -1848,7 +1876,7 @@ bool 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, + bool inverse, string_view key, string_view value, ColorConfig* colorconfig, ROI roi, int nthreads) { pvt::LoggedTimer logtime("IBA::ociodisplay"); @@ -1889,12 +1917,13 @@ ImageBufAlgo::ociodisplay(ImageBuf& dst, const ImageBuf& src, 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) + bool unpremult, bool inverse, string_view key, + string_view value, ColorConfig* colorconfig, ROI roi, + int nthreads) { ImageBuf result; bool ok = ociodisplay(result, src, display, view, from, looks, unpremult, - key, value, colorconfig, roi, nthreads); + unpremult, key, value, colorconfig, roi, nthreads); if (!ok && !result.has_error()) result.errorfmt("ImageBufAlgo::ociodisplay() error"); return result; @@ -1902,6 +1931,33 @@ ImageBufAlgo::ociodisplay(const ImageBuf& src, string_view display, +// DEPRECATED(2.5) +bool +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) +{ + return ociodisplay(dst, src, display, view, from, looks, unpremult, false, + key, value, colorconfig, roi, nthreads); +} + + + +// DEPRECATED(2.5) +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) +{ + return ociodisplay(src, display, view, from, looks, unpremult, false, key, + value, colorconfig, roi, nthreads); +} + + + bool ImageBufAlgo::ociofiletransform(ImageBuf& dst, const ImageBuf& src, string_view name, bool unpremult, bool inverse, diff --git a/src/oiiotool/oiiotool.cpp b/src/oiiotool/oiiotool.cpp index c803fe88dc..74192dd3e0 100644 --- a/src/oiiotool/oiiotool.cpp +++ b/src/oiiotool/oiiotool.cpp @@ -2777,12 +2777,13 @@ OIIOTOOL_OP(ociodisplay, 1, [](OiiotoolOp& op, span img) { std::string contextvalue = op.options()["value"]; std::string looks = op.options()["looks"]; 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"); return ImageBufAlgo::ociodisplay(*img[0], *img[1], displayname, viewname, - fromspace, looks, unpremult, contextkey, - contextvalue, &ot.colorconfig); + fromspace, looks, unpremult, inverse, + contextkey, contextvalue, &ot.colorconfig); }); @@ -6801,7 +6802,7 @@ Oiiotool::getargs(int argc, char* argv[]) .help("Apply the named OCIO look (options: from=, to=, inverse=, key=, value=, unpremult=)") .action(action_ociolook); ap.arg("--ociodisplay %s:DISPLAY %s:VIEW") - .help("Apply the named OCIO display and view (options: from=, looks=, key=, value=, unpremult=)") + .help("Apply the named OCIO display and view (options: from=, looks=, key=, value=, unpremult=, inverse=)") .action(action_ociodisplay); ap.arg("--ociofiletransform %s:FILENAME") .help("Apply the named OCIO filetransform (options: inverse=, unpremult=)") diff --git a/src/python/py_imagebufalgo.cpp b/src/python/py_imagebufalgo.cpp index bcef33b98f..6e3464e080 100644 --- a/src/python/py_imagebufalgo.cpp +++ b/src/python/py_imagebufalgo.cpp @@ -1983,15 +1983,15 @@ IBA_ociolook_colorconfig_ret(const ImageBuf& src, const std::string& looks, bool IBA_ociodisplay(ImageBuf& dst, const ImageBuf& src, const std::string& display, const std::string& view, const std::string& from, - const std::string& looks, bool unpremult, + const std::string& looks, bool unpremult, bool inverse, const std::string& context_key, const std::string& context_value, ROI roi = ROI::All(), int nthreads = 0) { py::gil_scoped_release gil; return ImageBufAlgo::ociodisplay(dst, src, display, view, from, looks, - unpremult, context_key, context_value, - NULL, roi, nthreads); + unpremult, inverse, context_key, + context_value, NULL, roi, nthreads); } @@ -1999,7 +1999,8 @@ bool IBA_ociodisplay_colorconfig(ImageBuf& dst, const ImageBuf& src, const std::string& display, const std::string& view, const std::string& from, const std::string& looks, - bool unpremult, const std::string& context_key, + bool unpremult, bool inverse, + const std::string& context_key, const std::string& context_value, const std::string& colorconfig = "", ROI roi = ROI::All(), int nthreads = 0) @@ -2007,8 +2008,8 @@ IBA_ociodisplay_colorconfig(ImageBuf& dst, const ImageBuf& src, ColorConfig config(colorconfig); py::gil_scoped_release gil; return ImageBufAlgo::ociodisplay(dst, src, display, view, from, looks, - unpremult, context_key, context_value, - &config, roi, nthreads); + unpremult, inverse, context_key, + context_value, &config, roi, nthreads); } @@ -2016,20 +2017,86 @@ IBA_ociodisplay_colorconfig(ImageBuf& dst, const ImageBuf& src, ImageBuf IBA_ociodisplay_ret(const ImageBuf& src, const std::string& display, const std::string& view, const std::string& from, - const std::string& looks, bool unpremult, + const std::string& looks, bool unpremult, bool inverse, const std::string& context_key, const std::string& context_value, ROI roi = ROI::All(), int nthreads = 0) { py::gil_scoped_release gil; return ImageBufAlgo::ociodisplay(src, display, view, from, looks, unpremult, - context_key, context_value, NULL, roi, - nthreads); + inverse, context_key, context_value, NULL, + roi, nthreads); } ImageBuf -IBA_ociodisplay_colorconfig_ret( +IBA_ociodisplay_colorconfig_ret(const ImageBuf& src, const std::string& display, + const std::string& view, + const std::string& from, + const std::string& looks, bool unpremult, + bool inverse, const std::string& context_key, + const std::string& context_value, + const std::string& colorconfig = "", + ROI roi = ROI::All(), int nthreads = 0) +{ + ColorConfig config(colorconfig); + py::gil_scoped_release gil; + return ImageBufAlgo::ociodisplay(src, display, view, from, looks, unpremult, + inverse, context_key, context_value, + &config, roi, nthreads); +} + + + +bool +IBA_ociodisplay_dep(ImageBuf& dst, const ImageBuf& src, + const std::string& display, const std::string& view, + const std::string& from, const std::string& looks, + bool unpremult, const std::string& context_key, + const std::string& context_value, ROI roi = ROI::All(), + int nthreads = 0) +{ + py::gil_scoped_release gil; + return ImageBufAlgo::ociodisplay(dst, src, display, view, from, looks, + unpremult, false, context_key, + context_value, NULL, roi, nthreads); +} + + +bool +IBA_ociodisplay_dep_colorconfig( + ImageBuf& dst, const ImageBuf& src, const std::string& display, + const std::string& view, const std::string& from, const std::string& looks, + bool unpremult, const std::string& context_key, + const std::string& context_value, const std::string& colorconfig = "", + ROI roi = ROI::All(), int nthreads = 0) +{ + ColorConfig config(colorconfig); + py::gil_scoped_release gil; + return ImageBufAlgo::ociodisplay(dst, src, display, view, from, looks, + unpremult, false, context_key, + context_value, &config, roi, nthreads); +} + + + +ImageBuf +IBA_ociodisplay_dep_ret(const ImageBuf& src, const std::string& display, + const std::string& view, const std::string& from, + const std::string& looks, bool unpremult, + const std::string& context_key, + const std::string& context_value, ROI roi = ROI::All(), + int nthreads = 0) +{ + py::gil_scoped_release gil; + return ImageBufAlgo::ociodisplay(src, display, view, from, looks, unpremult, + false, context_key, context_value, NULL, + roi, nthreads); +} + + +ImageBuf +IBA_ociodisplay_dep_colorconfig_ret( const ImageBuf& src, const std::string& display, const std::string& view, const std::string& from, const std::string& looks, bool unpremult, const std::string& context_key, const std::string& context_value, @@ -2038,8 +2105,8 @@ IBA_ociodisplay_colorconfig_ret( ColorConfig config(colorconfig); py::gil_scoped_release gil; return ImageBufAlgo::ociodisplay(src, display, view, from, looks, unpremult, - context_key, context_value, &config, roi, - nthreads); + false, context_key, context_value, &config, + roi, nthreads); } @@ -2737,24 +2804,46 @@ declare_imagebufalgo(py::module& m) .def_static("ociodisplay", &IBA_ociodisplay, "dst"_a, "src"_a, "display"_a, "view"_a, "fromspace"_a = "", "looks"_a = "", - "unpremult"_a = true, "context_key"_a = "", - "context_value"_a = "", "roi"_a = ROI::All(), - "nthreads"_a = 0) + "unpremult"_a = true, "inverse"_a = false, + "context_key"_a = "", "context_value"_a = "", + "roi"_a = ROI::All(), "nthreads"_a = 0) .def_static("ociodisplay", &IBA_ociodisplay_colorconfig, "dst"_a, "src"_a, "display"_a, "view"_a, "fromspace"_a = "", - "looks"_a = "", "unpremult"_a = true, "context_key"_a = "", - "context_value"_a = "", "colorconfig"_a = "", - "roi"_a = ROI::All(), "nthreads"_a = 0) + "looks"_a = "", "unpremult"_a = true, "inverse"_a = false, + "context_key"_a = "", "context_value"_a = "", + "colorconfig"_a = "", "roi"_a = ROI::All(), + "nthreads"_a = 0) .def_static("ociodisplay", &IBA_ociodisplay_ret, "src"_a, "display"_a, "view"_a, "fromspace"_a = "", "looks"_a = "", - "unpremult"_a = true, "context_key"_a = "", - "context_value"_a = "", "roi"_a = ROI::All(), - "nthreads"_a = 0) + "unpremult"_a = true, "inverse"_a = false, + "context_key"_a = "", "context_value"_a = "", + "roi"_a = ROI::All(), "nthreads"_a = 0) .def_static("ociodisplay", &IBA_ociodisplay_colorconfig_ret, "src"_a, "display"_a, "view"_a, "fromspace"_a = "", "looks"_a = "", - "unpremult"_a = true, "context_key"_a = "", - "context_value"_a = "", "colorconfig"_a = "", + "unpremult"_a = true, "inverse"_a = false, + "context_key"_a = "", "context_value"_a = "", + "colorconfig"_a = "", "roi"_a = ROI::All(), + "nthreads"_a = 0) + + // DEPRECATED + .def_static("ociodisplay", &IBA_ociodisplay_dep, "dst"_a, "src"_a, + "display"_a, "view"_a, "fromspace"_a, "looks"_a, + "unpremult"_a, "context_key"_a, "context_value"_a = "", "roi"_a = ROI::All(), "nthreads"_a = 0) + .def_static("ociodisplay", &IBA_ociodisplay_dep_colorconfig, "dst"_a, + "src"_a, "display"_a, "view"_a, "fromspace"_a, "looks"_a, + "unpremult"_a, "context_key"_a, "context_value"_a, + "colorconfig"_a = "", "roi"_a = ROI::All(), + "nthreads"_a = 0) + .def_static("ociodisplay", &IBA_ociodisplay_dep_ret, "src"_a, + "display"_a, "view"_a, "fromspace"_a, "looks"_a, + "unpremult"_a, "context_key"_a, "context_value"_a = "", + "roi"_a = ROI::All(), "nthreads"_a = 0) + .def_static("ociodisplay", &IBA_ociodisplay_dep_colorconfig_ret, + "src"_a, "display"_a, "view"_a, "fromspace"_a, "looks"_a, + "unpremult"_a, "context_key"_a, "context_value"_a = "", + "colorconfig"_a = "", "roi"_a = ROI::All(), + "nthreads"_a = 0) .def_static("ociofiletransform", &IBA_ociofiletransform, "dst"_a, "src"_a, "name"_a, "unpremult"_a = true,