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 #3676 from pypeclub/enhancement/OP-3723_PS-Extract…
Browse files Browse the repository at this point in the history
…Review-fails-for-large-resolution

Photoshop: resize saved images in ExtractReview for ffmpeg
  • Loading branch information
kalisp authored Aug 22, 2022
2 parents 370c7f8 + 3beca31 commit 77645c3
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 6 deletions.
57 changes: 51 additions & 6 deletions openpype/hosts/photoshop/plugins/publish/extract_review.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import shutil
from PIL import Image

import openpype.api
import openpype.lib
Expand All @@ -8,10 +9,17 @@

class ExtractReview(openpype.api.Extractor):
"""
Produce a flattened or sequence image file from all 'image' instances.
Produce a flattened or sequence image files from all 'image' instances.
If no 'image' instance is created, it produces flattened image from
all visible layers.
It creates review, thumbnail and mov representations.
'review' family could be used in other steps as a reference, as it
contains flattened image by default. (Eg. artist could load this
review as a single item and see full image. In most cases 'image'
family is separated by layers to better usage in animation or comp.)
"""

label = "Extract Review"
Expand All @@ -22,6 +30,7 @@ class ExtractReview(openpype.api.Extractor):
jpg_options = None
mov_options = None
make_image_sequence = None
max_downscale_size = 8192

def process(self, instance):
staging_dir = self.staging_dir(instance)
Expand Down Expand Up @@ -49,34 +58,41 @@ def process(self, instance):
"stagingDir": staging_dir,
"tags": self.jpg_options['tags'],
})

processed_img_names = img_list
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,
"files": img_list, # cannot be [] for single frame
"stagingDir": staging_dir,
"tags": self.jpg_options['tags']
})
processed_img_names = [img_list]

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

instance.data["stagingDir"] = staging_dir

# Generate thumbnail.
source_files_pattern = os.path.join(staging_dir,
self.output_seq_filename)
source_files_pattern = self._check_and_resize(processed_img_names,
source_files_pattern,
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", os.path.join(staging_dir, self.output_seq_filename),
"-i", source_files_pattern,
"-vf", "scale=300:-1",
"-vframes", "1",
thumbnail_path
]
self.log.debug("thumbnail args:: {}".format(args))
output = openpype.lib.run_subprocess(args)

instance.data["representations"].append({
Expand All @@ -94,11 +110,12 @@ def process(self, instance):
args = [
ffmpeg_path,
"-y",
"-i", os.path.join(staging_dir, self.output_seq_filename),
"-i", source_files_pattern,
"-vf", "pad=ceil(iw/2)*2:ceil(ih/2)*2",
"-vframes", str(img_number),
mov_path
]
self.log.debug("mov args:: {}".format(args))
output = openpype.lib.run_subprocess(args)
self.log.debug(output)
instance.data["representations"].append({
Expand All @@ -120,6 +137,34 @@ def process(self, instance):

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

def _check_and_resize(self, processed_img_names, source_files_pattern,
staging_dir):
"""Check if saved image could be used in ffmpeg.
Ffmpeg has max size 16384x16384. Saved image(s) must be resized to be
used as a source for thumbnail or review mov.
"""
Image.MAX_IMAGE_PIXELS = None
first_url = os.path.join(staging_dir, processed_img_names[0])
with Image.open(first_url) as im:
width, height = im.size

if width > self.max_downscale_size or height > self.max_downscale_size:
resized_dir = os.path.join(staging_dir, "resized")
os.mkdir(resized_dir)
source_files_pattern = os.path.join(resized_dir,
self.output_seq_filename)
for file_name in processed_img_names:
source_url = os.path.join(staging_dir, file_name)
with Image.open(source_url) as res_img:
# 'thumbnail' automatically keeps aspect ratio
res_img.thumbnail((self.max_downscale_size,
self.max_downscale_size),
Image.ANTIALIAS)
res_img.save(os.path.join(resized_dir, file_name))

return source_files_pattern

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

Expand Down
1 change: 1 addition & 0 deletions openpype/settings/defaults/project_settings/photoshop.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
},
"ExtractReview": {
"make_image_sequence": false,
"max_downscale_size": 8192,
"jpg_options": {
"tags": []
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,15 @@
"key": "make_image_sequence",
"label": "Makes an image sequence instead of a flatten image"
},
{
"type": "number",
"key": "max_downscale_size",
"label": "Maximum size of sources for review",
"tooltip": "FFMpeg can only handle limited resolution for creation of review and/or thumbnail",
"minimum": 300,
"maximum": 16384,
"decimal": 0
},
{
"type": "dict",
"collapsible": false,
Expand Down

0 comments on commit 77645c3

Please sign in to comment.