9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153 | class ExtractImage(
pyblish.api.ContextPlugin,
publish.ColormanagedPyblishPluginMixin
):
"""Extract all layers (groups) marked for publish.
Usually publishable instance is created as a wrapper of layer(s). For each
publishable instance so many images as there is 'formats' is created.
Logic tries to hide/unhide layers minimum times.
Called once for all publishable instances.
"""
order = publish.Extractor.order - 0.48
label = "Extract Image"
hosts = ["photoshop"]
families = ["image", "background"]
formats = ["png", "jpg", "tga"]
settings_category = "photoshop"
def process(self, context):
# Filter instances
filtered_instances = []
for instance in context:
product_base_type = instance.data.get("productBaseType")
if not product_base_type:
product_base_type = instance.data["productType"]
if product_base_type in self.families:
filtered_instances.append(instance)
if not filtered_instances:
return
stub = photoshop.stub()
all_layers = stub.get_layers() # Fetch once, reuse for all instances
native_colorspace = stub.get_color_profile_name()
self.log.info(f"Document colorspace profile: {native_colorspace}")
host_name = context.data["hostName"]
project_settings = context.data["project_settings"]
host_imageio_settings = project_settings["photoshop"]["imageio"]
with photoshop.maintained_selection():
for instance in filtered_instances:
suffix = instance.data["name"]
staging_dir = self.staging_dir(instance)
self.log.info(f"Outputting image to {staging_dir}")
# Get instance layer ID
members = instance.data("members")
if not members:
continue
instance_id = int(members[0])
# Context manager handles all visibility: show instance path,
# hide siblings, restore original state on exit
with photoshop.isolated_layers_visibility(stub, instance_id, all_layers):
# Perform extraction
files = {}
ids = set()
# real layers and groups
if members:
ids.update(int(member) for member in members)
# virtual groups collected by color coding or auto_image
add_ids = instance.data.pop("ids", None)
if add_ids:
ids.update(set(add_ids))
file_basename, workfile_extension = os.path.splitext(
stub.get_active_document_name()
)
workfile_extension = workfile_extension.strip(".")
for extension in self.formats:
repre_filename = f"{file_basename}_{suffix}.{extension}"
files[extension] = repre_filename
full_filename = os.path.join(
staging_dir, repre_filename)
if extension == "tga":
self._save_image_to_targa(
stub,
full_filename,
extension,
workfile_extension
)
else:
stub.saveAs(full_filename, extension, True)
self.log.info(f"Extracted: {extension}")
representations = []
for extension, filename in files.items():
repre = {
"name": extension,
"ext": extension,
"files": filename,
"stagingDir": staging_dir,
"tags": [],
}
ayon_colorspace = get_remapped_colorspace_from_native(
native_colorspace,
host_name,
host_imageio_settings,
)
self.log.debug(f"ayon_colorspace: {ayon_colorspace}")
# inject colorspace data
self.set_representation_colorspace(
repre, context,
colorspace=ayon_colorspace
)
self.log.debug(f"representation: {repre}")
representations.append(repre)
instance.data["representations"] = representations
instance.data["stagingDir"] = staging_dir
self.log.info(f"Extracted {instance} to {staging_dir}")
def staging_dir(self, instance):
"""Provide a temporary directory in which to store extracted files
Upon calling this method the staging directory is stored inside
the instance.data['stagingDir']
"""
from ayon_core.pipeline.publish import get_instance_staging_dir
return get_instance_staging_dir(instance)
def _save_image_to_targa(self, stub, full_filename, extension, workfile_extension):
"""Hacky way to save image in targa. Save the psd file
in quiet mode with targa options first and then convert it into targa
***Caution to use it.
Args:
stub (RPC stub): stub to call method
full_filename (str): full published filename
extension (str): published extension
workfile_extension (str): workfile extension
"""
src_file = full_filename.replace(extension, workfile_extension)
stub.saveAs(full_filename, extension, True)
if os.path.exists(src_file):
os.rename(src_file, full_filename)
|