You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat: support OCIO Viewing Rules, other OCIO-related improvements (#4780)
This PR fixes and improves a tiny constellation of OCIO-related bits,
directly or indirectly pertaining to OCIO Viewing Rules and File Rules,
and the propagation of `oiio:ColorSpace`.
## Description
The focus of this PR:
- feat: Permit the `ociodisplay` ImageBufAlgo to dynamically select a
default View for the `fromspace` (or current `oiio:ColorSpace` value),
as directed by the OCIO config's Viewing Rules (if present)
- feat: Have the `ociodisplay` IBA appropriately set the destination
ImageSpec's color space.
As part of this effort, a handful of additional changes and improvements
are addressed:
- fix: Re-enable the "looks" override functionality, matching the
previous OCIO-1-style behavior.
- fix: Improve `ColorConfig::getDisplayViewColorSpaceName(...)`'s
handling of Shared Views
- feat: Overload `ColorConfig::getDefaultViewName(...)` with function
that takes an additional `inputColorSpace` argument
- change: Alter the `ociofiletransform` IBA's behavior pertaining to
setting the destination spec's color space: instead of storing the
filepath as the `oiio:ColorSpace` value, attempt to get the color space
from the filepath; else, leave the `oiio:ColorSpace` attribute alone.
This isn't 100% foolproof, obviously, but I'd prefer to reserve the
`oiio:ColorSpace` attribute for color space names, unless there's a
reason not to. In a future PR, we can additionally attempt to divine a
valid color space string from specific CLF and CTF metadata, if present.
- feat: Implement a `ColorConfig::filepathOnlyMatchesDefaultRule(...)`
function, which wraps the OCIO::Config function of the same name.
- change: Alter `ColorConfig::getColorSpaceFromFilepath(...)` to behave
more like the OCIO::Config function of the same name. In particular,
return the Config's default color space name (instead of failing over to
OCIO-1 string-parsing heuristics, which, in turn, fail over to an empty
string); and provide an overloaded variant for implementing the legacy
(i.e., current) behavior. Update all usages in the codebase (i.e., in
oiiotool, w.r.t. autocc) to use the overloaded variant, so there's no
apparent change in behavior to how autocc functions.
## Background
This PR was inspired by #4753, which adds to the Python ImageBuf
bindings a `_repr_png_` magic method which returns a PNG bytestring
(which Jupyter notebooks can display inline), similar in behavior to
other libraries, like Pillow. This is great for previewing gamma-encoded
output-referred buffer data, but less great for previewing "linear"
encodings. Ideally, the `_repr_png_` method would apply an `ociodisplay`
ImageBufAlgo just before writing the PNG; but there would need to be
some means of controlling for the buffer "image state" when determining
how / whether to apply an `ociodisplay` IBA. For example, it would be
appropriate to apply the default ColorConfig's "ACES 1.0 - SDR Video"
View to an image buffer that contains scene-referred data; but very
evidently inappropriate to apply that same View to an image buffer that
holds display-referred data, yielding a "double-LUTted" appearance.
Fortunately, OCIO-2 `Viewing Rules` provides a solution. Viewing Rules
allow OCIO Config authors to selectively filter the set of Views
available for a given Display, on a per-input-colorspace basis.
Ostensibly, applications use the OCIO API's DisplayViewHelper class for
building View menu UX widgets that dynamically update as a function of
both the selected Display and Input Color Space; but there are
implications for headless applications, as well -- crucially, the Config
author may order Active Views such that different Input Color Spaces
elicit different default Views.
## Tests
I've included a test OCIO config with some Viewing Rules and File Rules
in testsuite/python-colorconfig; I'm testing that the new and updated
python bindings behave as expected; and I'm testing that the
`ociodisplay` IBA is OCIO-Viewing-Rules-aware and is properly
propagating `oiio:ColorSpace` to the dst buffer's spec.
Notably:
```python
import os
import OpenImageIO as oiio
import numpy as np
os.environ["OCIO"] = "/path/to/testsuite/python-colorconfig/src/oiio_test_v0.9.2.ocio"
a = oiio.ImageBuf(np.array([[[0.1, 0.2, 0.3]]]))
# The first time the ociodisplay IBA is applied, the lack of an `oiio:ColorSpace`
# attribute will be interpreted as the OCIO config's default color space -- in this case,
# "lin_rec709", which corresponds to a scene-referred default view (ACES 1.0 - SDR Video).
b = oiio.ImageBufAlgo.ociodisplay(a, "", "")
# The second time around, the `oiio:ColorSpace` attribute is now "sRGB (~2.22) - Display",
# a display-referred color space, thanks to the previous operation; as such, the IBA uses
# a different colorimetric "pass-thru" View as its default ("Colorimetry"), instead of the
# ACES View. Upshot is, values remain unchanged this time.
assert b.spec()['oiio:ColorSpace'], 'sRGB (~2.22) - Display'
c = oiio.ImageBufAlgo.ociodisplay(b, "", "")
assert c.spec()['oiio:ColorSpace'], 'sRGB (~2.22) - Display'
# Subsequent applications will be noops as well.
d = oiio.ImageBufAlgo.ociodisplay(c, "", "")
assert np.allclose(b.get_pixels(), c.get_pixels())
assert np.allclose(b.get_pixels(), d.get_pixels())
assert not np.allclose(b.get_pixels(), a.get_pixels())
```
## TL;DR
This PR enables OCIO config authors to dynamically control `ociodisplay`
IBA behavior w.r.t. the `oiio:ColorSpace` attribute, such that
`ImageBufAlgo.ociodisplay(buf, "", "")` always "does the right thing",
regardless of whether `buf` holds scene-referred or display-referred
data.
---------
Signed-off-by: Zach Lewis <zachcanbereached@gmail.com>
0 commit comments