mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Refactors color space conversion with oiiotool
Consolidates color space conversion logic into a dedicated `oiiotool_transcode` function for better flexibility and clarity. This change introduces support for display/view transformations, enhancing the tool's ability to handle complex color management workflows. It also fixes issues with conflicting color space parameters and improves handling of source and target display/view configurations.
This commit is contained in:
parent
539be6c527
commit
dba8d78a2a
3 changed files with 184 additions and 38 deletions
|
|
@ -977,7 +977,60 @@ def convert_colorspace(
|
|||
additional_command_args=None,
|
||||
logger=None,
|
||||
):
|
||||
"""Convert source file from one color space to another.
|
||||
"""Backward compatibility function for convert_colorspace.
|
||||
|
||||
Args:
|
||||
input_path (str): Path to input file that should be converted.
|
||||
output_path (str): Path to output file where result will be stored.
|
||||
config_path (str): Path to OCIO config file.
|
||||
source_colorspace (str): OCIO valid color space of source files.
|
||||
target_colorspace (str, optional): OCIO valid target color space.
|
||||
If filled, 'view' and 'display' must be empty.
|
||||
view (str, optional): Name for target viewer space (OCIO valid).
|
||||
Both 'view' and 'display' must be filled (if not 'target_colorspace').
|
||||
display (str, optional): Name for target display-referred reference space.
|
||||
Both 'view' and 'display' must be filled (if not 'target_colorspace').
|
||||
additional_command_args (list, optional): Additional arguments for oiiotool
|
||||
(like binary depth for .dpx).
|
||||
logger (logging.Logger, optional): Logger used for logging.
|
||||
|
||||
Returns:
|
||||
None: Function returns None.
|
||||
|
||||
Raises:
|
||||
ValueError: If parameters are misconfigured.
|
||||
"""
|
||||
return oiiotool_transcode(
|
||||
input_path,
|
||||
output_path,
|
||||
config_path,
|
||||
source_colorspace,
|
||||
target_colorspace=target_colorspace,
|
||||
target_display=display,
|
||||
target_view=view,
|
||||
additional_command_args=additional_command_args,
|
||||
logger=logger,
|
||||
)
|
||||
|
||||
|
||||
def oiiotool_transcode(
|
||||
input_path,
|
||||
output_path,
|
||||
config_path,
|
||||
source_colorspace,
|
||||
source_display=None,
|
||||
source_view=None,
|
||||
target_colorspace=None,
|
||||
target_display=None,
|
||||
target_view=None,
|
||||
additional_command_args=None,
|
||||
logger=None,
|
||||
):
|
||||
"""Transcode source file to other with colormanagement.
|
||||
|
||||
Oiiotool also support additional arguments for transcoding.
|
||||
For more information, see the official documentation:
|
||||
https://openimageio.readthedocs.io/en/latest/oiiotool.html
|
||||
|
||||
Args:
|
||||
input_path (str): Path that should be converted. It is expected that
|
||||
|
|
@ -989,17 +1042,26 @@ def convert_colorspace(
|
|||
sequence in 'file.FRAMESTART-FRAMEEND#.ext', `output.1-3#.tif`)
|
||||
config_path (str): path to OCIO config file
|
||||
source_colorspace (str): ocio valid color space of source files
|
||||
source_display (str, optional): name for source display-referred
|
||||
reference space (ocio valid). If provided, source_view must also be
|
||||
provided, and source_colorspace will be ignored
|
||||
source_view (str, optional): name for source viewer space (ocio valid)
|
||||
If provided, source_display must also be provided, and
|
||||
source_colorspace will be ignored
|
||||
target_colorspace (str): ocio valid target color space
|
||||
if filled, 'view' and 'display' must be empty
|
||||
view (str): name for viewer space (ocio valid)
|
||||
both 'view' and 'display' must be filled (if 'target_colorspace')
|
||||
display (str): name for display-referred reference space (ocio valid)
|
||||
target_display (str): name for target display-referred reference space
|
||||
(ocio valid) both 'view' and 'display' must be filled (if
|
||||
'target_colorspace')
|
||||
target_view (str): name for target viewer space (ocio valid)
|
||||
both 'view' and 'display' must be filled (if 'target_colorspace')
|
||||
additional_command_args (list): arguments for oiiotool (like binary
|
||||
depth for .dpx)
|
||||
logger (logging.Logger): Logger used for logging.
|
||||
|
||||
Raises:
|
||||
ValueError: if misconfigured
|
||||
|
||||
"""
|
||||
if logger is None:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -1024,23 +1086,99 @@ def convert_colorspace(
|
|||
"--ch", channels_arg
|
||||
])
|
||||
|
||||
if all([target_colorspace, view, display]):
|
||||
raise ValueError("Colorspace and both screen and display"
|
||||
" cannot be set together."
|
||||
"Choose colorspace or screen and display")
|
||||
if not target_colorspace and not all([view, display]):
|
||||
raise ValueError("Both screen and display must be set.")
|
||||
# Validate input parameters
|
||||
if all([target_colorspace, target_view, target_display]):
|
||||
raise ValueError(
|
||||
"Colorspace and both screen and display cannot be set together."
|
||||
"Choose colorspace or screen and display"
|
||||
)
|
||||
|
||||
if all([source_view, source_display]) and source_colorspace:
|
||||
logger.warning(
|
||||
"Both source display/view and source_colorspace provided. "
|
||||
"Using source display/view pair and ignoring source_colorspace."
|
||||
)
|
||||
|
||||
if not target_colorspace and not all([target_view, target_display]):
|
||||
raise ValueError(
|
||||
"Both screen and display must be set if target_colorspace is not "
|
||||
"provided."
|
||||
)
|
||||
|
||||
if ((source_view and not source_display) or
|
||||
(source_display and not source_view)):
|
||||
raise ValueError(
|
||||
"Both source_view and source_display must be provided if using "
|
||||
"display/view inputs."
|
||||
)
|
||||
|
||||
if additional_command_args:
|
||||
oiio_cmd.extend(additional_command_args)
|
||||
|
||||
# Handle the different conversion cases
|
||||
if target_colorspace:
|
||||
oiio_cmd.extend(["--colorconvert:subimages=0",
|
||||
source_colorspace,
|
||||
target_colorspace])
|
||||
if view and display:
|
||||
oiio_cmd.extend(["--iscolorspace", source_colorspace])
|
||||
oiio_cmd.extend(["--ociodisplay:subimages=0", display, view])
|
||||
# Case 1: Converting to a named colorspace
|
||||
if all([source_view, source_display]):
|
||||
# First convert from source display/view to a role/reference space
|
||||
# that can be used with colorconvert
|
||||
# For example, converting to "scene_linear" or an appropriate
|
||||
# intermediate space
|
||||
# This is a two-step conversion process since there's no direct
|
||||
# display/view to colorspace command
|
||||
# This could be a config parameter or determined from OCIO config
|
||||
tmp_role_space = "scene_linear"
|
||||
oiio_cmd.extend([
|
||||
"--ociodisplay:inverse=1:subimages=0", source_display,
|
||||
source_view, "--colorconvert:subimages=0", tmp_role_space,
|
||||
target_colorspace,
|
||||
])
|
||||
else:
|
||||
# Standard color space to color space conversion
|
||||
oiio_cmd.extend([
|
||||
"--colorconvert:subimages=0", source_colorspace,
|
||||
target_colorspace,
|
||||
])
|
||||
else: # Using display/view target
|
||||
if all([source_view, source_display]):
|
||||
if source_display == target_display and source_view == target_view:
|
||||
# No conversion needed if source and target display/view are
|
||||
# the same
|
||||
logger.debug(
|
||||
"Source and target display/view pairs are identical. "
|
||||
"No color conversion needed."
|
||||
)
|
||||
elif source_display == target_display:
|
||||
# When only the view changes but display stays the same
|
||||
# First convert from source view to a reference space, then to
|
||||
# target view
|
||||
# This could be configured
|
||||
tmp_role_space = "scene_linear"
|
||||
oiio_cmd.extend([
|
||||
"--ociodisplay:inverse=1:subimages=0",
|
||||
source_display,
|
||||
source_view,
|
||||
"--ociodisplay:subimages=0",
|
||||
target_display,
|
||||
target_view,
|
||||
])
|
||||
else:
|
||||
# Complete display/view pair conversion
|
||||
# Similar approach: go through a reference space
|
||||
# This could be configured
|
||||
tmp_role_space = "scene_linear"
|
||||
oiio_cmd.extend([
|
||||
"--ociodisplay:inverse=1:subimages=0",
|
||||
source_display,
|
||||
source_view, "--ociodisplay:subimages=0",
|
||||
target_display,
|
||||
target_view,
|
||||
])
|
||||
else:
|
||||
# Standard conversion from colorspace to display/view
|
||||
oiio_cmd.extend([
|
||||
"--iscolorspace", source_colorspace,
|
||||
"--ociodisplay:subimages=0", target_display, target_view,
|
||||
])
|
||||
|
||||
oiio_cmd.extend(["-o", output_path])
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from ayon_core.lib import (
|
|||
is_oiio_supported,
|
||||
)
|
||||
from ayon_core.lib.transcoding import (
|
||||
convert_colorspace,
|
||||
oiiotool_transcode,
|
||||
)
|
||||
|
||||
from ayon_core.lib.profiles_filtering import filter_profiles
|
||||
|
|
@ -94,6 +94,8 @@ class ExtractOIIOTranscode(publish.Extractor):
|
|||
|
||||
colorspace_data = repre["colorspaceData"]
|
||||
source_colorspace = colorspace_data["colorspace"]
|
||||
source_display = colorspace_data.get("display")
|
||||
source_view = colorspace_data.get("view")
|
||||
config_path = colorspace_data.get("config", {}).get("path")
|
||||
if not config_path or not os.path.exists(config_path):
|
||||
self.log.warning("Config file doesn't exist, skipping")
|
||||
|
|
@ -124,7 +126,7 @@ class ExtractOIIOTranscode(publish.Extractor):
|
|||
|
||||
transcoding_type = output_def["transcoding_type"]
|
||||
|
||||
target_colorspace = view = display = None
|
||||
target_colorspace = target_view = target_display = None
|
||||
# NOTE: we use colorspace_data as the fallback values for
|
||||
# the target colorspace.
|
||||
if transcoding_type == "colorspace":
|
||||
|
|
@ -136,18 +138,20 @@ class ExtractOIIOTranscode(publish.Extractor):
|
|||
colorspace_data.get("colorspace"))
|
||||
elif transcoding_type == "display_view":
|
||||
display_view = output_def["display_view"]
|
||||
view = display_view["view"] or colorspace_data.get("view")
|
||||
display = (
|
||||
target_view = (
|
||||
display_view["view"]
|
||||
or colorspace_data.get("view"))
|
||||
target_display = (
|
||||
display_view["display"]
|
||||
or colorspace_data.get("display")
|
||||
)
|
||||
|
||||
# both could be already collected by DCC,
|
||||
# but could be overwritten when transcoding
|
||||
if view:
|
||||
new_repre["colorspaceData"]["view"] = view
|
||||
if display:
|
||||
new_repre["colorspaceData"]["display"] = display
|
||||
if target_view:
|
||||
new_repre["colorspaceData"]["view"] = target_view
|
||||
if target_display:
|
||||
new_repre["colorspaceData"]["display"] = target_display
|
||||
if target_colorspace:
|
||||
new_repre["colorspaceData"]["colorspace"] = \
|
||||
target_colorspace
|
||||
|
|
@ -166,16 +170,18 @@ class ExtractOIIOTranscode(publish.Extractor):
|
|||
new_staging_dir,
|
||||
output_extension)
|
||||
|
||||
convert_colorspace(
|
||||
input_path,
|
||||
output_path,
|
||||
config_path,
|
||||
source_colorspace,
|
||||
target_colorspace,
|
||||
view,
|
||||
display,
|
||||
additional_command_args,
|
||||
self.log
|
||||
oiiotool_transcode(
|
||||
input_path=input_path,
|
||||
output_path=output_path,
|
||||
config_path=config_path,
|
||||
source_colorspace=source_colorspace,
|
||||
target_colorspace=target_colorspace,
|
||||
target_display=target_display,
|
||||
target_view=target_view,
|
||||
source_display=source_display,
|
||||
source_view=source_view,
|
||||
additional_command_args=additional_command_args,
|
||||
logger=self.log
|
||||
)
|
||||
|
||||
# cleanup temporary transcoded files
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ from ayon_core.lib import (
|
|||
path_to_subprocess_arg,
|
||||
run_subprocess,
|
||||
)
|
||||
from ayon_core.lib.transcoding import convert_colorspace
|
||||
from ayon_core.lib.transcoding import oiiotool_transcode
|
||||
|
||||
from ayon_core.lib.transcoding import VIDEO_EXTENSIONS, IMAGE_EXTENSIONS
|
||||
|
||||
|
|
@ -431,13 +431,15 @@ class ExtractThumbnail(pyblish.api.InstancePlugin):
|
|||
oiio_default_view = display_and_view["view"]
|
||||
|
||||
try:
|
||||
convert_colorspace(
|
||||
oiiotool_transcode(
|
||||
src_path,
|
||||
dst_path,
|
||||
colorspace_data["config"]["path"],
|
||||
colorspace_data["colorspace"],
|
||||
display=repre_display or oiio_default_display,
|
||||
view=repre_view or oiio_default_view,
|
||||
source_display=colorspace_data.get("display"),
|
||||
source_view=colorspace_data.get("view"),
|
||||
target_display=repre_display or oiio_default_display,
|
||||
target_view=repre_view or oiio_default_view,
|
||||
target_colorspace=oiio_default_colorspace,
|
||||
additional_command_args=resolution_arg,
|
||||
logger=self.log,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue