mirror of
https://github.com/ynput/ayon-core.git
synced 2026-01-01 16:34:53 +01:00
Merge pull request #4556 from ynput/feature/OP-5006_Nuke-publish-colorspaceData-from-rendered-images
This commit is contained in:
commit
f5ef4597b2
6 changed files with 61 additions and 44 deletions
|
|
@ -3,12 +3,14 @@ from pprint import pformat
|
||||||
import nuke
|
import nuke
|
||||||
import pyblish.api
|
import pyblish.api
|
||||||
from openpype.hosts.nuke import api as napi
|
from openpype.hosts.nuke import api as napi
|
||||||
|
from openpype.pipeline import publish
|
||||||
|
|
||||||
|
|
||||||
class CollectNukeWrites(pyblish.api.InstancePlugin):
|
class CollectNukeWrites(pyblish.api.InstancePlugin,
|
||||||
|
publish.ColormanagedPyblishPluginMixin):
|
||||||
"""Collect all write nodes."""
|
"""Collect all write nodes."""
|
||||||
|
|
||||||
order = pyblish.api.CollectorOrder - 0.48
|
order = pyblish.api.CollectorOrder + 0.0021
|
||||||
label = "Collect Writes"
|
label = "Collect Writes"
|
||||||
hosts = ["nuke", "nukeassist"]
|
hosts = ["nuke", "nukeassist"]
|
||||||
families = ["render", "prerender", "image"]
|
families = ["render", "prerender", "image"]
|
||||||
|
|
@ -66,6 +68,9 @@ class CollectNukeWrites(pyblish.api.InstancePlugin):
|
||||||
write_file_path = nuke.filename(write_node)
|
write_file_path = nuke.filename(write_node)
|
||||||
output_dir = os.path.dirname(write_file_path)
|
output_dir = os.path.dirname(write_file_path)
|
||||||
|
|
||||||
|
# get colorspace and add to version data
|
||||||
|
colorspace = napi.get_colorspace_from_node(write_node)
|
||||||
|
|
||||||
self.log.debug('output dir: {}'.format(output_dir))
|
self.log.debug('output dir: {}'.format(output_dir))
|
||||||
|
|
||||||
if render_target == "frames":
|
if render_target == "frames":
|
||||||
|
|
@ -128,6 +133,12 @@ class CollectNukeWrites(pyblish.api.InstancePlugin):
|
||||||
else:
|
else:
|
||||||
representation['files'] = collected_frames
|
representation['files'] = collected_frames
|
||||||
|
|
||||||
|
# inject colorspace data
|
||||||
|
self.set_representation_colorspace(
|
||||||
|
representation, instance.context,
|
||||||
|
colorspace=colorspace
|
||||||
|
)
|
||||||
|
|
||||||
instance.data["representations"].append(representation)
|
instance.data["representations"].append(representation)
|
||||||
self.log.info("Publishing rendered frames ...")
|
self.log.info("Publishing rendered frames ...")
|
||||||
|
|
||||||
|
|
@ -145,8 +156,7 @@ class CollectNukeWrites(pyblish.api.InstancePlugin):
|
||||||
instance.data["farm"] = True
|
instance.data["farm"] = True
|
||||||
self.log.info("Farm rendering ON ...")
|
self.log.info("Farm rendering ON ...")
|
||||||
|
|
||||||
# get colorspace and add to version data
|
# TODO: remove this when we have proper colorspace support
|
||||||
colorspace = napi.get_colorspace_from_node(write_node)
|
|
||||||
version_data = {
|
version_data = {
|
||||||
"colorspace": colorspace
|
"colorspace": colorspace
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,13 @@ import shutil
|
||||||
import pyblish.api
|
import pyblish.api
|
||||||
import clique
|
import clique
|
||||||
import nuke
|
import nuke
|
||||||
|
from openpype.hosts.nuke import api as napi
|
||||||
from openpype.pipeline import publish
|
from openpype.pipeline import publish
|
||||||
from openpype.lib import collect_frames
|
from openpype.lib import collect_frames
|
||||||
|
|
||||||
|
|
||||||
class NukeRenderLocal(publish.ExtractorColormanaged):
|
class NukeRenderLocal(publish.Extractor,
|
||||||
|
publish.ColormanagedPyblishPluginMixin):
|
||||||
"""Render the current Nuke composition locally.
|
"""Render the current Nuke composition locally.
|
||||||
|
|
||||||
Extract the result of savers by starting a comp render
|
Extract the result of savers by starting a comp render
|
||||||
|
|
@ -85,7 +86,7 @@ class NukeRenderLocal(publish.ExtractorColormanaged):
|
||||||
)
|
)
|
||||||
|
|
||||||
ext = node["file_type"].value()
|
ext = node["file_type"].value()
|
||||||
colorspace = node["colorspace"].value()
|
colorspace = napi.get_colorspace_from_node(node)
|
||||||
|
|
||||||
if "representations" not in instance.data:
|
if "representations" not in instance.data:
|
||||||
instance.data["representations"] = []
|
instance.data["representations"] = []
|
||||||
|
|
|
||||||
|
|
@ -335,9 +335,10 @@ def get_imageio_config(
|
||||||
get_template_data_from_session)
|
get_template_data_from_session)
|
||||||
anatomy_data = get_template_data_from_session()
|
anatomy_data = get_template_data_from_session()
|
||||||
|
|
||||||
|
formatting_data = deepcopy(anatomy_data)
|
||||||
# add project roots to anatomy data
|
# add project roots to anatomy data
|
||||||
anatomy_data["root"] = anatomy.roots
|
formatting_data["root"] = anatomy.roots
|
||||||
anatomy_data["platform"] = platform.system().lower()
|
formatting_data["platform"] = platform.system().lower()
|
||||||
|
|
||||||
# get colorspace settings
|
# get colorspace settings
|
||||||
imageio_global, imageio_host = _get_imageio_settings(
|
imageio_global, imageio_host = _get_imageio_settings(
|
||||||
|
|
@ -347,7 +348,7 @@ def get_imageio_config(
|
||||||
|
|
||||||
if config_host.get("enabled"):
|
if config_host.get("enabled"):
|
||||||
config_data = _get_config_data(
|
config_data = _get_config_data(
|
||||||
config_host["filepath"], anatomy_data
|
config_host["filepath"], formatting_data
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
config_data = None
|
config_data = None
|
||||||
|
|
@ -356,7 +357,7 @@ def get_imageio_config(
|
||||||
# get config path from either global or host_name
|
# get config path from either global or host_name
|
||||||
config_global = imageio_global["ocio_config"]
|
config_global = imageio_global["ocio_config"]
|
||||||
config_data = _get_config_data(
|
config_data = _get_config_data(
|
||||||
config_global["filepath"], anatomy_data
|
config_global["filepath"], formatting_data
|
||||||
)
|
)
|
||||||
|
|
||||||
if not config_data:
|
if not config_data:
|
||||||
|
|
@ -372,12 +373,12 @@ def _get_config_data(path_list, anatomy_data):
|
||||||
"""Return first existing path in path list.
|
"""Return first existing path in path list.
|
||||||
|
|
||||||
If template is used in path inputs,
|
If template is used in path inputs,
|
||||||
then it is formated by anatomy data
|
then it is formatted by anatomy data
|
||||||
and environment variables
|
and environment variables
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
path_list (list[str]): list of abs paths
|
path_list (list[str]): list of abs paths
|
||||||
anatomy_data (dict): formating data
|
anatomy_data (dict): formatting data
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
dict: config data
|
dict: config data
|
||||||
|
|
@ -389,30 +390,30 @@ def _get_config_data(path_list, anatomy_data):
|
||||||
|
|
||||||
# first try host config paths
|
# first try host config paths
|
||||||
for path_ in path_list:
|
for path_ in path_list:
|
||||||
formated_path = _format_path(path_, formatting_data)
|
formatted_path = _format_path(path_, formatting_data)
|
||||||
|
|
||||||
if not os.path.exists(formated_path):
|
if not os.path.exists(formatted_path):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"path": os.path.normpath(formated_path),
|
"path": os.path.normpath(formatted_path),
|
||||||
"template": path_
|
"template": path_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _format_path(tempate_path, formatting_data):
|
def _format_path(template_path, formatting_data):
|
||||||
"""Single template path formating.
|
"""Single template path formatting.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
tempate_path (str): template string
|
template_path (str): template string
|
||||||
formatting_data (dict): data to be used for
|
formatting_data (dict): data to be used for
|
||||||
template formating
|
template formatting
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
str: absolute formated path
|
str: absolute formatted path
|
||||||
"""
|
"""
|
||||||
# format path for anatomy keys
|
# format path for anatomy keys
|
||||||
formatted_path = StringTemplate(tempate_path).format(
|
formatted_path = StringTemplate(template_path).format(
|
||||||
formatting_data)
|
formatting_data)
|
||||||
|
|
||||||
return os.path.abspath(formatted_path)
|
return os.path.abspath(formatted_path)
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ from .publish_plugins import (
|
||||||
RepairContextAction,
|
RepairContextAction,
|
||||||
|
|
||||||
Extractor,
|
Extractor,
|
||||||
ExtractorColormanaged,
|
ColormanagedPyblishPluginMixin
|
||||||
)
|
)
|
||||||
|
|
||||||
from .lib import (
|
from .lib import (
|
||||||
|
|
@ -64,7 +64,7 @@ __all__ = (
|
||||||
"RepairContextAction",
|
"RepairContextAction",
|
||||||
|
|
||||||
"Extractor",
|
"Extractor",
|
||||||
"ExtractorColormanaged",
|
"ColormanagedPyblishPluginMixin",
|
||||||
|
|
||||||
"get_publish_template_name",
|
"get_publish_template_name",
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ from abc import ABCMeta
|
||||||
from pprint import pformat
|
from pprint import pformat
|
||||||
import pyblish.api
|
import pyblish.api
|
||||||
from pyblish.plugin import MetaPlugin, ExplicitMetaPlugin
|
from pyblish.plugin import MetaPlugin, ExplicitMetaPlugin
|
||||||
|
from openpype.lib.transcoding import VIDEO_EXTENSIONS, IMAGE_EXTENSIONS
|
||||||
from openpype.lib import BoolDef
|
from openpype.lib import BoolDef
|
||||||
|
|
||||||
from .lib import (
|
from .lib import (
|
||||||
|
|
@ -288,28 +288,29 @@ class Extractor(pyblish.api.InstancePlugin):
|
||||||
return get_instance_staging_dir(instance)
|
return get_instance_staging_dir(instance)
|
||||||
|
|
||||||
|
|
||||||
class ExtractorColormanaged(Extractor):
|
class ColormanagedPyblishPluginMixin(object):
|
||||||
"""Extractor base for color managed image data.
|
"""Mixin for colormanaged plugins.
|
||||||
|
|
||||||
Each Extractor intended to export pixel data representation
|
|
||||||
should inherit from this class to allow color managed data.
|
|
||||||
Class implements "get_colorspace_settings" and
|
|
||||||
"set_representation_colorspace" functions used
|
|
||||||
for injecting colorspace data to representation data for farther
|
|
||||||
integration into db document.
|
|
||||||
|
|
||||||
|
This class is used to set colorspace data to a publishing
|
||||||
|
representation. It contains a static method,
|
||||||
|
get_colorspace_settings, which returns config and
|
||||||
|
file rules data for the host context.
|
||||||
|
It also contains a method, set_representation_colorspace,
|
||||||
|
which sets colorspace data to the representation.
|
||||||
|
The allowed file extensions are listed in the allowed_ext variable.
|
||||||
|
The method first checks if the file extension is in
|
||||||
|
the list of allowed extensions. If it is, it then gets the
|
||||||
|
colorspace settings from the host context and gets a
|
||||||
|
matching colorspace from rules. Finally, it infuses this
|
||||||
|
data into the representation.
|
||||||
"""
|
"""
|
||||||
|
allowed_ext = set(
|
||||||
allowed_ext = [
|
ext.lstrip(".") for ext in IMAGE_EXTENSIONS.union(VIDEO_EXTENSIONS)
|
||||||
"cin", "dpx", "avi", "dv", "gif", "flv", "mkv", "mov", "mpg", "mpeg",
|
)
|
||||||
"mp4", "m4v", "mxf", "iff", "z", "ifl", "jpeg", "jpg", "jfif", "lut",
|
|
||||||
"1dl", "exr", "pic", "png", "ppm", "pnm", "pgm", "pbm", "rla", "rpf",
|
|
||||||
"sgi", "rgba", "rgb", "bw", "tga", "tiff", "tif", "img"
|
|
||||||
]
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_colorspace_settings(context):
|
def get_colorspace_settings(context):
|
||||||
"""Retuns solved settings for the host context.
|
"""Returns solved settings for the host context.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
context (publish.Context): publishing context
|
context (publish.Context): publishing context
|
||||||
|
|
@ -375,7 +376,10 @@ class ExtractorColormanaged(Extractor):
|
||||||
ext = representation["ext"]
|
ext = representation["ext"]
|
||||||
# check extension
|
# check extension
|
||||||
self.log.debug("__ ext: `{}`".format(ext))
|
self.log.debug("__ ext: `{}`".format(ext))
|
||||||
if ext.lower() not in self.allowed_ext:
|
|
||||||
|
# check if ext in lower case is in self.allowed_ext
|
||||||
|
if ext.lstrip(".").lower() not in self.allowed_ext:
|
||||||
|
self.log.debug("Extension is not in allowed extensions.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if colorspace_settings is None:
|
if colorspace_settings is None:
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ import pyblish.api
|
||||||
from openpype.pipeline import publish
|
from openpype.pipeline import publish
|
||||||
|
|
||||||
|
|
||||||
class ExtractColorspaceData(publish.ExtractorColormanaged):
|
class ExtractColorspaceData(publish.Extractor,
|
||||||
|
publish.ColormanagedPyblishPluginMixin):
|
||||||
""" Inject Colorspace data to available representations.
|
""" Inject Colorspace data to available representations.
|
||||||
|
|
||||||
Input data:
|
Input data:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue