Handle resizing of animated images with blended frames correctly
This commit is contained in:
parent
2dad179285
commit
56193f6902
@ -135,12 +135,13 @@ class RenderedImage(ImageData):
|
|||||||
|
|
||||||
|
|
||||||
def render_image(
|
def render_image(
|
||||||
path: str, output_template: str,
|
path: str, output_prefix: str,
|
||||||
m: ImageData,
|
m: ImageData,
|
||||||
available_width: int, available_height: int,
|
available_width: int, available_height: int,
|
||||||
scale_up: bool,
|
scale_up: bool,
|
||||||
only_first_frame: bool = False
|
only_first_frame: bool = False
|
||||||
) -> RenderedImage:
|
) -> RenderedImage:
|
||||||
|
import tempfile
|
||||||
exe = find_exe('convert')
|
exe = find_exe('convert')
|
||||||
if exe is None:
|
if exe is None:
|
||||||
raise OSError('Failed to find the ImageMagick convert executable, make sure it is present in PATH')
|
raise OSError('Failed to find the ImageMagick convert executable, make sure it is present in PATH')
|
||||||
@ -162,13 +163,15 @@ def render_image(
|
|||||||
# we have to coalesce, resize and de-coalesce all frames
|
# we have to coalesce, resize and de-coalesce all frames
|
||||||
resize_cmd = ['-coalesce'] + resize_cmd + ['-deconstruct']
|
resize_cmd = ['-coalesce'] + resize_cmd + ['-deconstruct']
|
||||||
cmd += resize_cmd
|
cmd += resize_cmd
|
||||||
cmd += ['-depth', '8']
|
cmd += ['-depth', '8', '-set', 'filename:f', '%w-%h-%g']
|
||||||
run_imagemagick(path, cmd + [output_template])
|
|
||||||
bytes_per_pixel = 3 if m.mode == 'rgb' else 4
|
|
||||||
ans = RenderedImage(m.fmt, width, height, m.mode)
|
ans = RenderedImage(m.fmt, width, height, m.mode)
|
||||||
for i, src in enumerate(m):
|
if only_first_frame:
|
||||||
frame = Frame(src)
|
ans.frames = [Frame(m.frames[0])]
|
||||||
frame.path = output_template if only_first_frame else (output_template % frame.index)
|
else:
|
||||||
|
ans.frames = list(map(Frame, m.frames))
|
||||||
|
bytes_per_pixel = 3 if m.mode == 'rgb' else 4
|
||||||
|
|
||||||
|
def check_resize(frame: Frame) -> None:
|
||||||
# ImageMagick sometimes generates RGBA images smaller than the specified
|
# ImageMagick sometimes generates RGBA images smaller than the specified
|
||||||
# size. See https://github.com/kovidgoyal/kitty/issues/276 for examples
|
# size. See https://github.com/kovidgoyal/kitty/issues/276 for examples
|
||||||
sz = os.path.getsize(frame.path)
|
sz = os.path.getsize(frame.path)
|
||||||
@ -181,11 +184,25 @@ def render_image(
|
|||||||
' it generated {} < {} of data (w={}, h={}, bpp={})'.format(
|
' it generated {} < {} of data (w={}, h={}, bpp={})'.format(
|
||||||
path, sz, expected_size, frame.width, frame.height, bytes_per_pixel))
|
path, sz, expected_size, frame.width, frame.height, bytes_per_pixel))
|
||||||
frame.height -= missing // (bytes_per_pixel * frame.width)
|
frame.height -= missing // (bytes_per_pixel * frame.width)
|
||||||
if i == 0:
|
if frame.index == 0:
|
||||||
ans.height = frame.height
|
ans.height = frame.height
|
||||||
ans.frames.append(frame)
|
ans.width = frame.width
|
||||||
if only_first_frame:
|
|
||||||
break
|
with tempfile.TemporaryDirectory(dir=os.path.dirname(output_prefix)) as tdir:
|
||||||
|
output_template = os.path.join(tdir, f'im-%[filename:f]-%d.{m.mode}')
|
||||||
|
run_imagemagick(path, cmd + [output_template])
|
||||||
|
for x in os.listdir(tdir):
|
||||||
|
parts = x.split('.', 1)[0].split('-')
|
||||||
|
index = int(parts[-1])
|
||||||
|
f = ans.frames[index]
|
||||||
|
f.width, f.height = map(positive_int, parts[1:3])
|
||||||
|
sz, pos = parts[3].split('+', 1)
|
||||||
|
f.canvas_width, f.canvas_height = map(positive_int, sz.split('x', 1))
|
||||||
|
f.canvas_x, f.canvas_y = map(int, pos.split('+', 1))
|
||||||
|
f.path = output_prefix + f'-{index}.{m.mode}'
|
||||||
|
os.rename(os.path.join(tdir, x), f.path)
|
||||||
|
check_resize(f)
|
||||||
|
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
|
|
||||||
@ -199,6 +216,7 @@ def render_as_single_image(
|
|||||||
fd, output = tempfile.mkstemp(prefix='icat-', suffix=f'.{m.mode}', dir=tdir)
|
fd, output = tempfile.mkstemp(prefix='icat-', suffix=f'.{m.mode}', dir=tdir)
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
result = render_image(path, output, m, available_width, available_height, scale_up, only_first_frame=True)
|
result = render_image(path, output, m, available_width, available_height, scale_up, only_first_frame=True)
|
||||||
|
os.rename(result.frames[0].path, output)
|
||||||
return output, result.width, result.height
|
return output, result.width, result.height
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user