Skip to content
This repository has been archived by the owner on Sep 20, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2569 from Ellipsanime/add-option-to-create-image-…
Browse files Browse the repository at this point in the history
…sequemce-with-photoshop-review

Photoshop: add sequence image option in review plugin
  • Loading branch information
kalisp authored Feb 25, 2022
2 parents eb5eecd + dc911a8 commit 5a4cd11
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 45 deletions.
22 changes: 22 additions & 0 deletions openpype/hosts/photoshop/api/ws_stub.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,28 @@ def set_visible(self, layer_id, visibility):
)
)

def hide_all_others_layers(self, layers):
"""hides all layers that are not part of the list or that are not
children of this list
Args:
layers (list): list of PSItem - highest hierarchy
"""
extract_ids = set([ll.id for ll in self.get_layers_in_layers(layers)])

self.hide_all_others_layers_ids(extract_ids)

def hide_all_others_layers_ids(self, extract_ids):
"""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
"""
for layer in self.get_layers():
if layer.visible and layer.id not in extract_ids:
self.set_visible(layer.id, False)

def get_layers_metadata(self):
"""Reads layers metadata from Headline from active document in PS.
(Headline accessible by File > File Info)
Expand Down
7 changes: 1 addition & 6 deletions openpype/hosts/photoshop/plugins/publish/extract_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,14 @@ def process(self, instance):
with photoshop.maintained_selection():
self.log.info("Extracting %s" % str(list(instance)))
with photoshop.maintained_visibility():
# Hide all other layers.
layer = instance.data.get("layer")
ids = set([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)])

for layer in stub.get_layers():
# limit unnecessary calls to client
if layer.visible and layer.id not in extract_ids:
stub.set_visible(layer.id, False)
stub.hide_all_others_layers_ids(extract_ids)

file_basename = os.path.splitext(
stub.get_active_document_name()
Expand Down
155 changes: 117 additions & 38 deletions openpype/hosts/photoshop/plugins/publish/extract_review.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import shutil

import openpype.api
import openpype.lib
Expand All @@ -7,7 +8,7 @@

class ExtractReview(openpype.api.Extractor):
"""
Produce a flattened image file from all 'image' instances.
Produce a flattened or sequence image file from all 'image' instances.
If no 'image' instance is created, it produces flattened image from
all visible layers.
Expand All @@ -20,54 +21,58 @@ class ExtractReview(openpype.api.Extractor):
# Extract Options
jpg_options = None
mov_options = None
make_image_sequence = None

def process(self, instance):
staging_dir = self.staging_dir(instance)
self.log.info("Outputting image to {}".format(staging_dir))

fps = instance.data.get("fps", 25)
stub = photoshop.stub()

layers = []
for image_instance in instance.context:
if image_instance.data["family"] != "image":
continue
layers.append(image_instance.data.get("layer"))

# Perform extraction
output_image = "{}.jpg".format(
os.path.splitext(stub.get_active_document_name())[0]
)
output_image_path = os.path.join(staging_dir, output_image)
with photoshop.maintained_visibility():
if layers:
# Hide all other layers.
extract_ids = set([ll.id for ll in stub.
get_layers_in_layers(layers)])
self.log.debug("extract_ids {}".format(extract_ids))
for layer in stub.get_layers():
# limit unnecessary calls to client
if layer.visible and layer.id not in extract_ids:
stub.set_visible(layer.id, False)

stub.saveAs(output_image_path, 'jpg', True)
self.output_seq_filename = os.path.splitext(
stub.get_active_document_name())[0] + ".%04d.jpg"

layers = self._get_layers_from_image_instances(instance)
self.log.info("Layers image instance found: {}".format(layers))

if self.make_image_sequence and len(layers) > 1:
self.log.info("Extract layers to image sequence.")
img_list = self._saves_sequences_layers(staging_dir, layers)

instance.data["representations"].append({
"name": "jpg",
"ext": "jpg",
"files": img_list,
"frameStart": 0,
"frameEnd": len(img_list),
"fps": fps,
"stagingDir": staging_dir,
"tags": self.jpg_options['tags'],
})

else:
self.log.info("Extract layers to flatten image.")
img_list = self._saves_flattened_layers(staging_dir, layers)

instance.data["representations"].append({
"name": "jpg",
"ext": "jpg",
"files": img_list,
"stagingDir": staging_dir,
"tags": self.jpg_options['tags']
})

ffmpeg_path = openpype.lib.get_ffmpeg_tool_path("ffmpeg")

instance.data["representations"].append({
"name": "jpg",
"ext": "jpg",
"files": output_image,
"stagingDir": staging_dir,
"tags": self.jpg_options['tags']
})
instance.data["stagingDir"] = staging_dir

# Generate thumbnail.
thumbnail_path = os.path.join(staging_dir, "thumbnail.jpg")
self.log.info(f"Generate thumbnail {thumbnail_path}")
args = [
ffmpeg_path,
"-y",
"-i", output_image_path,
"-i", os.path.join(staging_dir, self.output_seq_filename),
"-vf", "scale=300:-1",
"-vframes", "1",
thumbnail_path
Expand All @@ -81,14 +86,17 @@ def process(self, instance):
"stagingDir": staging_dir,
"tags": ["thumbnail"]
})

# Generate mov.
mov_path = os.path.join(staging_dir, "review.mov")
self.log.info(f"Generate mov review: {mov_path}")
img_number = len(img_list)
args = [
ffmpeg_path,
"-y",
"-i", output_image_path,
"-i", os.path.join(staging_dir, self.output_seq_filename),
"-vf", "pad=ceil(iw/2)*2:ceil(ih/2)*2",
"-vframes", "1",
"-vframes", str(img_number),
mov_path
]
output = openpype.lib.run_subprocess(args)
Expand All @@ -99,15 +107,86 @@ def process(self, instance):
"files": os.path.basename(mov_path),
"stagingDir": staging_dir,
"frameStart": 1,
"frameEnd": 1,
"fps": 25,
"frameEnd": img_number,
"fps": fps,
"preview": True,
"tags": self.mov_options['tags']
})

# Required for extract_review plugin (L222 onwards).
instance.data["frameStart"] = 1
instance.data["frameEnd"] = 1
instance.data["frameEnd"] = img_number
instance.data["fps"] = 25

self.log.info(f"Extracted {instance} to {staging_dir}")

def _get_image_path_from_instances(self, instance):
img_list = []

for instance in sorted(instance.context):
if instance.data["family"] != "image":
continue

for rep in instance.data["representations"]:
img_path = os.path.join(
rep["stagingDir"],
rep["files"]
)
img_list.append(img_path)

return img_list

def _copy_image_to_staging_dir(self, staging_dir, img_list):
copy_files = []
for i, img_src in enumerate(img_list):
img_filename = self.output_seq_filename % i
img_dst = os.path.join(staging_dir, img_filename)

self.log.debug(
"Copying file .. {} -> {}".format(img_src, img_dst)
)
shutil.copy(img_src, img_dst)
copy_files.append(img_filename)

return copy_files

def _get_layers_from_image_instances(self, instance):
layers = []
for image_instance in instance.context:
if image_instance.data["family"] != "image":
continue
layers.append(image_instance.data.get("layer"))

return sorted(layers)

def _saves_flattened_layers(self, staging_dir, layers):
img_filename = self.output_seq_filename % 0
output_image_path = os.path.join(staging_dir, img_filename)
stub = photoshop.stub()

with photoshop.maintained_visibility():
self.log.info("Extracting {}".format(layers))
if layers:
stub.hide_all_others_layers(layers)

stub.saveAs(output_image_path, 'jpg', True)

return img_filename

def _saves_sequences_layers(self, staging_dir, layers):
stub = photoshop.stub()

list_img_filename = []
with photoshop.maintained_visibility():
for i, layer in enumerate(layers):
self.log.info("Extracting {}".format(layer))

img_filename = self.output_seq_filename % i
output_image_path = os.path.join(staging_dir, img_filename)
list_img_filename.append(img_filename)

with photoshop.maintained_visibility():
stub.hide_all_others_layers([layer])
stub.saveAs(output_image_path, 'jpg', True)

return list_img_filename
3 changes: 2 additions & 1 deletion openpype/settings/defaults/project_settings/photoshop.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
]
},
"ExtractReview": {
"make_image_sequence": false,
"jpg_options": {
"tags": []
},
Expand All @@ -43,4 +44,4 @@
"create_first_version": false,
"custom_templates": []
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,11 @@
"key": "ExtractReview",
"label": "Extract Review",
"children": [
{
"type": "boolean",
"key": "make_image_sequence",
"label": "Makes an image sequence instead of a flatten image"
},
{
"type": "dict",
"collapsible": false,
Expand Down

0 comments on commit 5a4cd11

Please sign in to comment.