OP-4643 - added ExtractColorTranscode

Added method to convert from one colorspace to another to transcoding lib
This commit is contained in:
Petr Kalis 2023-01-06 11:58:51 +01:00
parent 0410910330
commit 2f1888bbfb
2 changed files with 177 additions and 0 deletions

View file

@ -1045,3 +1045,56 @@ def convert_ffprobe_fps_to_float(value):
if divisor == 0.0:
return 0.0
return dividend / divisor
def convert_colorspace_for_input_paths(
input_paths,
output_dir,
source_color_space,
target_color_space,
logger=None
):
"""Convert source files from one color space to another.
Filenames of input files are kept so make sure that output directory
is not the same directory as input files have.
- This way it can handle gaps and can keep input filenames without handling
frame template
Args:
input_paths (str): Paths that should be converted. It is expected that
contains single file or image sequence of samy type.
output_dir (str): Path to directory where output will be rendered.
Must not be same as input's directory.
source_color_space (str): ocio valid color space of source files
target_color_space (str): ocio valid target color space
logger (logging.Logger): Logger used for logging.
"""
if logger is None:
logger = logging.getLogger(__name__)
input_arg = "-i"
oiio_cmd = [
get_oiio_tools_path(),
# Don't add any additional attributes
"--nosoftwareattrib",
"--colorconvert", source_color_space, target_color_space
]
for input_path in input_paths:
# Prepare subprocess arguments
oiio_cmd.extend([
input_arg, input_path,
])
# Add last argument - path to output
base_filename = os.path.basename(input_path)
output_path = os.path.join(output_dir, base_filename)
oiio_cmd.extend([
"-o", output_path
])
logger.debug("Conversion command: {}".format(" ".join(oiio_cmd)))
run_subprocess(oiio_cmd, logger=logger)

View file

@ -0,0 +1,124 @@
import pyblish.api
from openpype.pipeline import publish
from openpype.lib import (
is_oiio_supported,
)
from openpype.lib.transcoding import (
convert_colorspace_for_input_paths,
get_transcode_temp_directory,
)
from openpype.lib.profiles_filtering import filter_profiles
class ExtractColorTranscode(publish.Extractor):
"""
Extractor to convert colors from one colorspace to different.
"""
label = "Transcode color spaces"
order = pyblish.api.ExtractorOrder + 0.01
optional = True
# Configurable by Settings
profiles = None
options = None
def process(self, instance):
if not self.profiles:
self.log.warning("No profiles present for create burnin")
return
if "representations" not in instance.data:
self.log.warning("No representations, skipping.")
return
if not is_oiio_supported():
self.log.warning("OIIO not supported, no transcoding possible.")
return
colorspace_data = instance.data.get("colorspaceData")
if not colorspace_data:
# TODO get_colorspace ??
self.log.warning("Instance has not colorspace data, skipping")
return
source_color_space = colorspace_data["colorspace"]
host_name = instance.context.data["hostName"]
family = instance.data["family"]
task_data = instance.data["anatomyData"].get("task", {})
task_name = task_data.get("name")
task_type = task_data.get("type")
subset = instance.data["subset"]
filtering_criteria = {
"hosts": host_name,
"families": family,
"task_names": task_name,
"task_types": task_type,
"subset": subset
}
profile = filter_profiles(self.profiles, filtering_criteria,
logger=self.log)
if not profile:
self.log.info((
"Skipped instance. None of profiles in presets are for"
" Host: \"{}\" | Families: \"{}\" | Task \"{}\""
" | Task type \"{}\" | Subset \"{}\" "
).format(host_name, family, task_name, task_type, subset))
return
self.log.debug("profile: {}".format(profile))
target_colorspace = profile["output_colorspace"]
if not target_colorspace:
raise RuntimeError("Target colorspace must be set")
repres = instance.data.get("representations") or []
for idx, repre in enumerate(repres):
self.log.debug("repre ({}): `{}`".format(idx + 1, repre["name"]))
if not self.repre_is_valid(repre):
continue
new_staging_dir = get_transcode_temp_directory()
repre["stagingDir"] = new_staging_dir
files_to_remove = repre["files"]
if not isinstance(files_to_remove, list):
files_to_remove = [files_to_remove]
instance.context.data["cleanupFullPaths"].extend(files_to_remove)
convert_colorspace_for_input_paths(
repre["files"],
new_staging_dir,
source_color_space,
target_colorspace,
self.log
)
def repre_is_valid(self, repre):
"""Validation if representation should be processed.
Args:
repre (dict): Representation which should be checked.
Returns:
bool: False if can't be processed else True.
"""
if "review" not in (repre.get("tags") or []):
self.log.info((
"Representation \"{}\" don't have \"review\" tag. Skipped."
).format(repre["name"]))
return False
if not repre.get("files"):
self.log.warning((
"Representation \"{}\" have empty files. Skipped."
).format(repre["name"]))
return False
return True