OP-3723 - resize saved images in PS for ffmpeg

Ffmpeg cannot handle pictures higher than 16384x16384. Uses PIL to resize to max size(with aspect ratio).
In the future this plugin should be refactored (to use general ExtractThumbnail and ExtractReview).
This commit is contained in:
Petr Kalis 2022-08-16 12:18:53 +02:00
parent e93558f961
commit c9f3340f3c

View file

@ -1,5 +1,6 @@
import os
import shutil
from PIL import Image
import openpype.api
import openpype.lib
@ -8,10 +9,17 @@ from openpype.hosts.photoshop import api as photoshop
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"
@ -49,7 +57,7 @@ class ExtractReview(openpype.api.Extractor):
"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)
@ -57,26 +65,33 @@ class ExtractReview(openpype.api.Extractor):
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({
@ -94,11 +109,12 @@ class ExtractReview(openpype.api.Extractor):
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({
@ -120,6 +136,33 @@ class ExtractReview(openpype.api.Extractor):
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.
"""
max_ffmpeg_size = 16384
first_url = os.path.join(staging_dir, processed_img_names[0])
with Image.open(first_url) as im:
width, height = im.size
if width > max_ffmpeg_size or height > max_ffmpeg_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((max_ffmpeg_size, max_ffmpeg_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 = []