mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-25 05:14:40 +01:00
OP-3863 - attempt to speed up ExtractImage
If workfile has a large number of layers (hundreds or thousands), ExtractImage wasn't too efficient. It was hiding/showing layers too many times. Current logic is to hide all, show only publishable layers of instance, save to image, hide them again. get_layers replaced by argument if possible.
This commit is contained in:
parent
ebd8c16d27
commit
1ed5ef7dcd
3 changed files with 97 additions and 53 deletions
|
|
@ -64,10 +64,15 @@ def maintained_selection():
|
|||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def maintained_visibility():
|
||||
"""Maintain visibility during context."""
|
||||
def maintained_visibility(layers=None):
|
||||
"""Maintain visibility during context.
|
||||
|
||||
Args:
|
||||
layers (list) of PSItem (used for caching)
|
||||
"""
|
||||
visibility = {}
|
||||
layers = stub().get_layers()
|
||||
if not layers:
|
||||
layers = stub().get_layers()
|
||||
for layer in layers:
|
||||
visibility[layer.id] = layer.visible
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -229,10 +229,11 @@ class PhotoshopServerStub:
|
|||
|
||||
return self._get_layers_in_layers(parent_ids)
|
||||
|
||||
def get_layers_in_layers_ids(self, layers_ids):
|
||||
def get_layers_in_layers_ids(self, layers_ids, layers=None):
|
||||
"""Return all layers that belong to layers (might be groups).
|
||||
|
||||
Args:
|
||||
layers_ids <list of Int>
|
||||
layers <list of PSItem>:
|
||||
|
||||
Returns:
|
||||
|
|
@ -240,10 +241,13 @@ class PhotoshopServerStub:
|
|||
"""
|
||||
parent_ids = set(layers_ids)
|
||||
|
||||
return self._get_layers_in_layers(parent_ids)
|
||||
return self._get_layers_in_layers(parent_ids, layers)
|
||||
|
||||
def _get_layers_in_layers(self, parent_ids):
|
||||
all_layers = self.get_layers()
|
||||
def _get_layers_in_layers(self, parent_ids, layers=None):
|
||||
if not layers:
|
||||
layers = self.get_layers()
|
||||
|
||||
all_layers = layers
|
||||
ret = []
|
||||
|
||||
for layer in all_layers:
|
||||
|
|
@ -394,14 +398,17 @@ class PhotoshopServerStub:
|
|||
|
||||
self.hide_all_others_layers_ids(extract_ids)
|
||||
|
||||
def hide_all_others_layers_ids(self, extract_ids):
|
||||
def hide_all_others_layers_ids(self, extract_ids, layers=None):
|
||||
"""hides all layers that are not part of the list or that are not
|
||||
children of this list
|
||||
|
||||
Args:
|
||||
extract_ids (list): list of integer that should be visible
|
||||
layers (list) of PSItem (used for caching)
|
||||
"""
|
||||
for layer in self.get_layers():
|
||||
if not layers:
|
||||
layers = self.get_layers()
|
||||
for layer in layers:
|
||||
if layer.visible and layer.id not in extract_ids:
|
||||
self.set_visible(layer.id, False)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,61 +1,93 @@
|
|||
import os
|
||||
|
||||
import openpype.api
|
||||
import pyblish.api
|
||||
|
||||
from openpype.pipeline import publish
|
||||
from openpype.hosts.photoshop import api as photoshop
|
||||
|
||||
|
||||
class ExtractImage(openpype.api.Extractor):
|
||||
"""Produce a flattened image file from instance
|
||||
|
||||
This plug-in takes into account only the layers in the group.
|
||||
"""
|
||||
class ExtractImage(pyblish.api.ContextPlugin):
|
||||
"""Save scene before extraction."""
|
||||
|
||||
order = publish.Extractor.order - 0.48
|
||||
label = "Extract Image"
|
||||
hosts = ["photoshop"]
|
||||
|
||||
families = ["image", "background"]
|
||||
formats = ["png", "jpg"]
|
||||
|
||||
def process(self, instance):
|
||||
staging_dir = self.staging_dir(instance)
|
||||
self.log.info("Outputting image to {}".format(staging_dir))
|
||||
|
||||
# Perform extraction
|
||||
def process(self, context):
|
||||
stub = photoshop.stub()
|
||||
files = {}
|
||||
hidden_layer_ids = set()
|
||||
|
||||
all_layers = stub.get_layers()
|
||||
for layer in all_layers:
|
||||
if not layer.visible:
|
||||
hidden_layer_ids.add(layer.id)
|
||||
stub.hide_all_others_layers_ids([], layers=all_layers)
|
||||
|
||||
with photoshop.maintained_selection():
|
||||
self.log.info("Extracting %s" % str(list(instance)))
|
||||
with photoshop.maintained_visibility():
|
||||
ids = set()
|
||||
layer = instance.data.get("layer")
|
||||
if layer:
|
||||
ids.add(layer.id)
|
||||
add_ids = instance.data.pop("ids", None)
|
||||
if add_ids:
|
||||
ids.update(set(add_ids))
|
||||
extract_ids = set([ll.id for ll in stub.
|
||||
get_layers_in_layers_ids(ids)])
|
||||
stub.hide_all_others_layers_ids(extract_ids)
|
||||
# self.log.info("Extracting %s" % str(list(instance)))
|
||||
with photoshop.maintained_visibility(layers=all_layers):
|
||||
for instance in context:
|
||||
if instance.data["family"] not in self.families:
|
||||
continue
|
||||
|
||||
file_basename = os.path.splitext(
|
||||
stub.get_active_document_name()
|
||||
)[0]
|
||||
for extension in self.formats:
|
||||
_filename = "{}.{}".format(file_basename, extension)
|
||||
files[extension] = _filename
|
||||
staging_dir = self.staging_dir(instance)
|
||||
self.log.info("Outputting image to {}".format(staging_dir))
|
||||
|
||||
full_filename = os.path.join(staging_dir, _filename)
|
||||
stub.saveAs(full_filename, extension, True)
|
||||
self.log.info(f"Extracted: {extension}")
|
||||
# Perform extraction
|
||||
files = {}
|
||||
ids = set()
|
||||
layer = instance.data.get("layer")
|
||||
if layer:
|
||||
ids.add(layer.id)
|
||||
add_ids = instance.data.pop("ids", None)
|
||||
if add_ids:
|
||||
ids.update(set(add_ids))
|
||||
extract_ids = set([ll.id for ll in stub.
|
||||
get_layers_in_layers_ids(ids, all_layers)
|
||||
if ll.id not in hidden_layer_ids])
|
||||
|
||||
representations = []
|
||||
for extension, filename in files.items():
|
||||
representations.append({
|
||||
"name": extension,
|
||||
"ext": extension,
|
||||
"files": filename,
|
||||
"stagingDir": staging_dir
|
||||
})
|
||||
instance.data["representations"] = representations
|
||||
instance.data["stagingDir"] = staging_dir
|
||||
for extracted_id in extract_ids:
|
||||
stub.set_visible(extracted_id, True)
|
||||
|
||||
self.log.info(f"Extracted {instance} to {staging_dir}")
|
||||
file_basename = os.path.splitext(
|
||||
stub.get_active_document_name()
|
||||
)[0]
|
||||
for extension in self.formats:
|
||||
_filename = "{}.{}".format(file_basename,
|
||||
extension)
|
||||
files[extension] = _filename
|
||||
|
||||
full_filename = os.path.join(staging_dir,
|
||||
_filename)
|
||||
stub.saveAs(full_filename, extension, True)
|
||||
self.log.info(f"Extracted: {extension}")
|
||||
|
||||
representations = []
|
||||
for extension, filename in files.items():
|
||||
representations.append({
|
||||
"name": extension,
|
||||
"ext": extension,
|
||||
"files": filename,
|
||||
"stagingDir": staging_dir
|
||||
})
|
||||
instance.data["representations"] = representations
|
||||
instance.data["stagingDir"] = staging_dir
|
||||
|
||||
self.log.info(f"Extracted {instance} to {staging_dir}")
|
||||
|
||||
for extracted_id in extract_ids:
|
||||
stub.set_visible(extracted_id, False)
|
||||
|
||||
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 openpype.pipeline.publish import get_instance_staging_dir
|
||||
|
||||
return get_instance_staging_dir(instance)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue