Skip to content

Commit

Permalink
feat: implement support for OCIO NamedTransforms
Browse files Browse the repository at this point in the history
- ColorConfig: add NamedTransform convenience functions: `getNumNamedTransforms`, `getNamedTransformNameByIndex`, `getNamedTransformNames`, `getNamedTransformAliases`

- ColorConfig: add `createNamedTransform` function returning ColorProcessorHandle

- ColorProcCacheKey: Update definition (and usage) to account for new `namedtransform` variable.

- Add `ImageBufAlgo::ocionamedtransform` functions

- oiiotool: add `--ocionamedtransform` operator

- python: add NamedTransform convenience function bindings

- python: add `ImageBufAlgo.ocionamedtransform(...)` bindings

- Update `oiiotool` and `python` documentation with examples
  • Loading branch information
zachlewis committed Aug 14, 2024
1 parent 80545a9 commit 544150a
Show file tree
Hide file tree
Showing 8 changed files with 413 additions and 13 deletions.
33 changes: 33 additions & 0 deletions src/doc/oiiotool.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4439,6 +4439,39 @@ will be printed with the command `oiiotool --colorconfiginfo`.

oiiotool in.jpg --ociofiletransform footransform.csp -o out.jpg


.. option:: --ocionamedtransform <name>

Replace the current image with a new image whose pixels are transformed
using the named OpenColorIO named transform. Optional appended arguments
include:

- `key=` *name*, `value=` *str*

Adds a key/value pair to the "context" that OpenColorIO will used
when applying the look. Multiple key/value pairs may be specified by
making each one a comma-separated list.

- `inverse=` *val* :

If *val* is nonzero, inverts the color transformation.

- `unpremult=` *val* :

If the numeric *val* is nonzero, the pixel values will be
"un-premultipled" (divided by alpha) prior to the actual color
conversion, and then re-multipled by alpha afterwards. The default is
0, meaning the color transformation not will be automatically
bracketed by divide-by-alpha / mult-by-alpha operations.

`:subimages=` *indices-or-names*
Include/exclude subimages (see :ref:`sec-oiiotool-subimage-modifier`).

Examples::

oiiotool in.exr --ocionamedtransform:inverse=1 srgb_crv -o out.jpg


.. option:: --unpremult

Divide all color channels (those not alpha or z) of the current image by
Expand Down
13 changes: 13 additions & 0 deletions src/doc/pythonbindings.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3623,6 +3623,19 @@ Color manipulation
Dst = ImageBufAlgo.ociofiletransform (Src, "foottransform.csp")
.. py:method:: ImageBuf ImageBufAlgo.ocionamedtransform (src, name, unpremult=True, inverse=False, context_key="", context_value="", colorconfig="", roi=ROI.All, nthreads=0)
bool ImageBufAlgo.ocionamedtransform (dst, src, name, unpremult=True, inverse=False, context_key="", context_value="", colorconfig="", roi=ROI.All, nthreads=0)
Apply an OpenColorIO "named" transform to the pixel values.
Example:
.. code-block:: python
Src = ImageBuf ("tahoe.dpx")
Dst = ImageBufAlgo.ocionamedtransform (Src, "log_to_lin",
context_key="SHOT", context_value="pe0012")
.. py:method:: ImageBuf ImageBufAlgo.unpremult (src, roi=ROI.All, nthreads=0)
bool ImageBufAlgo.unpremult (dst, src, roi=ROI.All, nthreads=0)
Expand Down
32 changes: 32 additions & 0 deletions src/include/OpenImageIO/color.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,19 @@ class OIIO_API ColorConfig {
/// Retrieve the full list of known look names, as a vector of strings.
std::vector<std::string> getLookNames() const;

/// Get the number of NamedTransforms defined in this configuration
int getNumNamedTransforms() const;

/// Query the name of the specified NamedTransform.
const char* getNamedTransformNameByIndex(int index) const;

/// Retrieve the full list of known NamedTransforms, as a vector of strings
std::vector<std::string> getNamedTransformNames() const;

/// Retrieve the full list of aliases for the named NamedTransform.
std::vector<std::string>
getNamedTransformAliases(string_view named_transform) const;

/// Is the color space known to be linear? This is very conservative, and
/// will return false if it's not sure.
bool isColorSpaceLinear(string_view name) const;
Expand Down Expand Up @@ -305,6 +318,25 @@ class OIIO_API ColorConfig {
ColorProcessorHandle createFileTransform(ustring name,
bool inverse = false) const;

/// Construct a processor to perform color transforms determined by an
/// OpenColorIO NamedTransform. It is possible that this will return an
/// empty handle if the NamedTransform doesn't exist or is not allowed.
///
/// The handle is actually a shared_ptr, so when you're done with a
/// ColorProcess, just discard it. ColorProcessor(s) remain valid even
/// if the ColorConfig that created them no longer exists.
///
/// Created ColorProcessors are cached, so asking for the same color
/// space transformation multiple times shouldn't be very expensive.
ColorProcessorHandle
createNamedTransform(string_view name, bool inverse = false,
string_view context_key = "",
string_view context_value = "") const;
ColorProcessorHandle
createNamedTransform(ustring name, bool inverse = false,
ustring context_key = ustring(),
ustring context_value = ustring()) const;

/// Construct a processor to perform color transforms specified by a
/// 4x4 matrix.
///
Expand Down
44 changes: 44 additions & 0 deletions src/include/OpenImageIO/imagebufalgo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2063,6 +2063,50 @@ bool OIIO_API ociofiletransform (ImageBuf &dst, const ImageBuf &src,
ROI roi={}, int nthreads=0);


/// Return the pixels of `src` within the ROI, applying an OpenColorIO
/// "named" transform to the pixel values. In-place operations
/// (`dst` == `src`) are supported.
///
/// The first three channels are presumed to be the color to be
/// transformed, and the fourth channel (if it exists) is presumed to be
/// alpha. Any additional channels will be simply copied unaltered.
///
/// @param name
/// The name of the OCIO NamedTransform to apply.
/// @param unpremult
/// If true, unpremultiply the image (divide the RGB channels by
/// alpha if it exists and is nonzero) before color conversion,
/// then repremult after the after the color conversion. Passing
/// unpremult=false skips this step, which may be desirable if
/// you know that the image is "unassociated alpha" (a.k.a.,
/// "not pre-multiplied colors").
/// @param inverse
/// If `true`, it will apply the NamedTransform in the inverse
/// direction.
/// @param context_key/context_value
/// Optional key/value to establish a context (for example, a
/// shot-specific transform).
/// @param colorconfig
/// An optional `ColorConfig*` specifying an OpenColorIO
/// configuration. If not supplied, the default OpenColorIO
/// color configuration found by examining the `$OCIO`
/// environment variable will be used instead.
ImageBuf OIIO_API ocionamedtransform (const ImageBuf &src, string_view name,
bool unpremult=true, bool inverse=false,
string_view context_key="",
string_view context_value="",
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);
/// Write to an existing image `dst` (allocating if it is uninitialized).
bool OIIO_API ocionamedtransform (ImageBuf &dst, const ImageBuf &src,
string_view name, bool unpremult=true,
bool inverse=false,
string_view context_key="",
string_view context_value="",
const ColorConfig* colorconfig = nullptr,
ROI roi={}, int nthreads=0);


/// @defgroup premult (Premultiply or un-premultiply color by alpha)
/// @{
///
Expand Down
Loading

0 comments on commit 544150a

Please sign in to comment.