Skip to content

Commit

Permalink
Implement initial support for *ACES* 2.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
KelSolaar committed May 4, 2024
1 parent 18c281c commit ee1ba33
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 127 deletions.
13 changes: 11 additions & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
[submodule "opencolorio_config_aces/config/reference/aces-dev"]
path = opencolorio_config_aces/config/reference/aces-dev
[submodule "opencolorio_config_aces/config/reference/ampas/aces-core"]
path = opencolorio_config_aces/config/reference/ampas/aces-core
url = https://github.com/ampas/aces-dev.git
[submodule "opencolorio_config_aces/config/reference/ampas/aces-input-and-colorspaces"]
path = opencolorio_config_aces/config/reference/ampas/aces-input-and-colorspaces
url = https://github.com/ampas/aces-input-and-colorspaces.git
[submodule "opencolorio_config_aces/config/reference/ampas/aces-look"]
path = opencolorio_config_aces/config/reference/ampas/aces-look
url = https://github.com/ampas/aces-look.git
[submodule "opencolorio_config_aces/config/reference/ampas/aces-output"]
path = opencolorio_config_aces/config/reference/ampas/aces-output
url = https://github.com/ampas/aces-output.git
1 change: 0 additions & 1 deletion opencolorio_config_aces/config/reference/aces-dev
Submodule aces-dev deleted from ea2afe
1 change: 1 addition & 0 deletions opencolorio_config_aces/config/reference/ampas/aces-core
Submodule aces-core added at 2429ac
1 change: 1 addition & 0 deletions opencolorio_config_aces/config/reference/ampas/aces-look
Submodule aces-look added at 48ccda
1 change: 1 addition & 0 deletions opencolorio_config_aces/config/reference/ampas/aces-output
Submodule aces-output added at 27983e
189 changes: 66 additions & 123 deletions opencolorio_config_aces/config/reference/discover/classify.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@

logger = logging.getLogger(__name__)


URN_CTL = "urn:ampas:aces:transformId:v1.5"
URN_CTL = "urn:ampas:aces:transformId:v2.0"
"""
*ACES* Uniform Resource Name (*URN*).
Expand All @@ -91,8 +90,8 @@
*ACEStransformID* separator used to tokenize the *ID* part of the
*ACEStransformID*.
urn:ampas:aces:transformId:v1.5:ODT.Academy.DCDM.a1.0.3
|-------------URN-------------|:|----------ID---------|
urn:ampas:aces:transformId:v2.0:CSC.Academy.ACES_to_ACEScc.a2.v1
|-------------URN-------------|:|--------------ID--------------|
SEPARATOR_ID_CTL : unicode
"""
Expand All @@ -112,18 +111,12 @@
"""

TRANSFORM_TYPES_CTL = [
"ACEScsc",
"ACESlib",
"ACESutil",
"IDT",
"InvLMT",
"InvODT",
"InvRRT",
"InvRRTODT",
"LMT",
"ODT",
"RRT",
"RRTODT",
"CSC",
"Lib",
"Look",
"InvLook",
"Output",
"InvOutput",
]
"""
*ACES* *CTL* transform types.
Expand All @@ -132,14 +125,10 @@
"""

TRANSFORM_FAMILIES_CTL = {
"csc": "csc",
"idt": "input_transform",
"lib": "lib",
"lmt": "lmt",
"odt": "output_transform",
"outputTransform": "output_transform",
"rrt": "rrt",
"utilities": "utility",
"aces-core": "lib",
"aces-input-and-colorspaces": "csc",
"aces-look": "lmt",
"aces-output": "output_transform",
}
"""
*ACES* *CTL* transform families mapping the *CTL* transform directories to
Expand Down Expand Up @@ -229,60 +218,37 @@ def patch_invalid_aces_transform_id(aces_transform_id):
-------
unicode
Patched *ACEStransformID*.
Notes
-----
- Fixed by https://github.com/scottdyer/aces-dev/\
commit/4b88ef35afc41e58ea52d9acde68af24e75b58c5
- https://github.com/ampas/aces-dev/issues/118
- https://github.com/ampas/aces-dev/pull/119
"""

# Addressed with https://github.com/scottdyer/aces-dev/
# commit/4b88ef35afc41e58ea52d9acde68af24e75b58c5
if False:
if True:
invalid_id = aces_transform_id

if not aces_transform_id.startswith(URN_CTL):
logger.warning('"%s" is missing "ACES" URN!', invalid_id)
logger.critical('"%s" is missing "ACES" URN!', invalid_id)

aces_transform_id = f"{URN_CTL}:{aces_transform_id}"

if "Academy.P3D65_108nits_7.2nits_ST2084" in aces_transform_id:
logger.warning('"%s" has an invalid separator in "7.2nits"!', invalid_id)

aces_transform_id = aces_transform_id.replace("7.2", "7")
elif "P3D65_709limit_48nits" in aces_transform_id:
logger.warning('"%s" is inconsistently named!', invalid_id)

aces_transform_id = aces_transform_id.replace(
"P3D65_709limit_48nits", "P3D65_Rec709limited_48nits"
)
elif "Rec2020_100nits.a1.1.0" in aces_transform_id:
logger.warning('"%s" is incorrectly named!', invalid_id)

aces_transform_id = aces_transform_id.replace(
"Rec2020_100nits", "Rec2020_P3D65limited_100nits_dim"
if ":ACEScsc." in aces_transform_id:
logger.critical(
'"%s" is using invalid "ACEScsc" type instead of "CSC"!', invalid_id
)
elif "ACEScsc" in aces_transform_id:
if "ACEScsc.Academy" not in aces_transform_id:
logger.warning('"%s" is missing "Academy" namespace!', invalid_id)

aces_transform_id = aces_transform_id.replace(
"ACEScsc", "ACEScsc.Academy"
)
aces_transform_id = aces_transform_id.replace(":ACEScsc.", ":CSC.")

if aces_transform_id.endswith("a1.v1"):
logger.warning('"%s" version scheme is invalid!', invalid_id)
if ":ODT." in aces_transform_id:
logger.critical(
'"%s" is using invalid "ODT" type instead of "Output"!', invalid_id
)

aces_transform_id = aces_transform_id.replace("a1.v1", "a1.1.0")
aces_transform_id = aces_transform_id.replace(":ODT.", ":Output.")

return aces_transform_id


ROOT_TRANSFORMS_CTL = os.path.normpath(
os.environ.get(
"OPENCOLORIO_CONFIG_CTL__CTL_TRANSFORMS_ROOT",
os.path.join(os.path.dirname(__file__), "../", "aces-dev", "transforms", "ctl"),
os.path.join(os.path.dirname(__file__), "../", "ampas"),
)
)
"""
Expand Down Expand Up @@ -604,6 +570,7 @@ def _parse(self):
aces_transform_id = patch_invalid_aces_transform_id(self._aces_transform_id)

self._urn, components = aces_transform_id.rsplit(SEPARATOR_URN_CTL, 1)

components = components.split(SEPARATOR_ID_CTL)
self._type, components = components[0], components[1:]

Expand All @@ -613,47 +580,24 @@ def _parse(self):
)

attest(
len(components) in (3, 4, 5),
len(components) == 4,
f'{self._aces_transform_id} is an invalid "ACEStransformID"!',
)

if len(components) == 3:
(
self._major_version,
self._minor_version,
self._patch_version,
) = components
elif len(components) == 4:
if self._type in ("ACESlib", "ACESutil"):
(
self._name,
self._major_version,
self._minor_version,
self._patch_version,
) = components
elif self._type == "IDT":
(
self._namespace,
self._name,
self._major_version,
self._minor_version,
) = components
else:
(
self._namespace,
self._name,
self._major_version,
self._minor_version,
self._patch_version,
) = components
(
self._namespace,
self._name,
self._major_version,
self._minor_version,
) = components

attest(
self._type in TRANSFORM_TYPES_CTL,
f"{self._aces_transform_id} type {self._type} is invalid!",
)

if self._name is not None:
if self._type == "ACEScsc":
if self._type == "CSC":
source, target = self._name.split("_to_")

if source == "ACES":
Expand All @@ -663,23 +607,12 @@ def _parse(self):
target = "ACES2065-1"

self._source, self._target = source, target
elif self._type in ("IDT", "LMT"):
self._source, self._target = self._name, "ACES2065-1"
elif self._type == "InvLMT":
elif self._type in ("Look", "InvLook"):
self._source, self._target = "ACES2065-1", "ACES2065-1"
elif self._type == "Output":
self._source, self._target = "ACES2065-1", self._name
elif self._type == "ODT":
self._source, self._target = "OCES", self._name
elif self._type == "InvODT":
self._source, self._target = self._name, "OCES"
elif self._type == "RRTODT":
self._source, self._target = "ACES2065-1", self._name
elif self._type == "InvRRTODT":
elif self._type == "InvOutput":
self._source, self._target = self._name, "ACES2065-1"
else: # noqa: PLR5501
if self._type == "RRT":
self._source, self._target = "ACES2065-1", "OCES"
elif self._type == "InvRRT":
self._source, self._target = "OCES", "ACES2065-1"


class CTLTransform:
Expand Down Expand Up @@ -1182,6 +1115,10 @@ def find_ctl_transform_pairs(ctl_transforms):

basename = basename.replace("ACES_to_", "")

logger.debug(
'Is "%s" CTL transform is forward? "%s"', ctl_transform, is_forward
)

if is_forward:
ctl_transform_pairs[basename]["forward_transform"] = ctl_transform
else:
Expand Down Expand Up @@ -1216,10 +1153,11 @@ def discover_aces_ctl_transforms(root_directory=ROOT_TRANSFORMS_CTL):
>>> ctl_transforms = discover_aces_ctl_transforms()
>>> key = sorted(ctl_transforms.keys())[0]
>>> os.path.basename(key)
'ACEScc'
'lib'
>>> sorted([os.path.basename(path) for path in ctl_transforms[key]])
['ACEScsc.Academy.ACES_to_ACEScc.ctl', \
'ACEScsc.Academy.ACEScc_to_ACES.ctl']
['Lib.Academy.ColorSpaces.ctl', 'Lib.Academy.DisplayEncoding.ctl', \
'Lib.Academy.OutputTransform.ctl', 'Lib.Academy.Tonescale.ctl', \
'Lib.Academy.Utilities.ctl']
"""

root_directory = os.path.normpath(os.path.expandvars(root_directory))
Expand Down Expand Up @@ -1282,13 +1220,13 @@ def classify_aces_ctl_transforms(unclassified_ctl_transforms):
'csc'
>>> genera = sorted(ctl_transforms[family])
>>> print(genera)
['ACEScc', 'ACEScct', 'ACEScg', 'ACESproxy', 'ADX', 'arri', \
['ACEScc', 'ACEScct', 'ACEScg', 'ACESproxy', 'ADX', 'apple', 'arri', \
'blackmagic_design', 'canon', 'panasonic', 'red', 'sony']
>>> genus = genera[0]
>>> sorted(ctl_transforms[family][genus].items()) # doctest: +ELLIPSIS
[('ACEScsc.Academy.ACEScc', CTLTransformPair(\
CTLTransform('csc...ACEScc...ACEScsc.Academy.ACES_to_ACEScc.ctl')', \
CTLTransform('csc...ACEScc...ACEScsc.Academy.ACEScc_to_ACES.ctl')'))]
[('CSC.Academy.ACEScc', CTLTransformPair(CTLTransform(\
'aces-input-and-colorspaces...ACEScc...CSC.Academy.ACES_to_ACEScc.ctl')', \
CTLTransform('aces-input-and-colorspaces...ACEScc...CSC.Academy.ACEScc_to_ACES.ctl')'))]
"""

classified_ctl_transforms = defaultdict(lambda: defaultdict(dict))
Expand Down Expand Up @@ -1359,7 +1297,7 @@ def unclassify_ctl_transforms(classified_ctl_transforms):
... discover_aces_ctl_transforms())
>>> sorted( # doctest: +ELLIPSIS
... unclassify_ctl_transforms(ctl_transforms), key=lambda x: x.path)[0]
CTLTransform('csc...ACEScc...ACEScsc.Academy.ACES_to_ACEScc.ctl')
CTLTransform('aces-core...lib...Lib.Academy.ColorSpaces.ctl')
"""

unclassified_ctl_transforms = []
Expand Down Expand Up @@ -1410,7 +1348,7 @@ def filter_ctl_transforms(ctl_transforms, filterers=None):
>>> sorted( # doctest: +ELLIPSIS
... filter_ctl_transforms(ctl_transforms, [lambda x: x.genus == 'p3']),
... key=lambda x: x.path)[0]
CTLTransform('odt...p3...InvODT.Academy.P3D60_48nits.ctl')
CTLTransform('aces-output...p3...InvOutput.Academy.P3D60.ctl')
"""

if filterers is None:
Expand Down Expand Up @@ -1459,27 +1397,32 @@ def print_aces_taxonomy():
logger.info("\t( %s )", name)
if isinstance(ctl_transform, CTLTransform):
logger.info(
'\t\t"%s" --> "%s"',
'\t\tACEStransformID : "%s"',
ctl_transform.aces_transform_id.aces_transform_id,
)
logger.info(
'\t\t\t"%s" --> "%s"',
ctl_transform.source,
ctl_transform.target,
)
elif isinstance(ctl_transform, CTLTransformPair):
logger.info(
'\t\tACEStransformID : "%s"',
ctl_transform.aces_transform_id.aces_transform_id,
ctl_transform.forward_transform.aces_transform_id.aces_transform_id,
)
elif isinstance(ctl_transform, CTLTransformPair):
logger.info(
'\t\t"%s" <--> "%s"',
'\t\t\t"%s" --> "%s"',
ctl_transform.forward_transform.source,
ctl_transform.inverse_transform.target,
ctl_transform.forward_transform.target,
)
logger.info(
'\t\tACEStransformID : "%s"',
ctl_transform.forward_transform.aces_transform_id.aces_transform_id,
ctl_transform.inverse_transform.aces_transform_id.aces_transform_id,
)
logger.info(
'\t\tACEStransformID : "%s"',
ctl_transform.inverse_transform.aces_transform_id.aces_transform_id,
'\t\t\t"%s" --> "%s"',
ctl_transform.inverse_transform.source,
ctl_transform.inverse_transform.target,
)


Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ keywords = [
]

[tool.poetry.dependencies]
python = ">= 3.9, < 3.12"
python = ">= 3.9, < 3.13"
opencolorio = ">= 2, < 3"
requests = ">= 2, < 3"
semver = ">= 3, < 4"
Expand Down

0 comments on commit ee1ba33

Please sign in to comment.