3 from PIL
import features
5 from .cairo
import PngRenderer
6 from .base
import exporter, io_progress
7 from ..parsers.baseporter
import ExtraOption
10 def _png_gif_prepare(image):
11 if image.mode
not in [
"RGBA",
"RGBa"]:
12 image = image.convert(
"RGBA")
13 alpha = image.getchannel(
"A")
14 image = image.convert(
"RGB").
convert(
'P', palette=Image.ADAPTIVE, colors=255)
15 mask = Image.eval(alpha,
lambda a: 255
if a <= 128
else 0)
16 image.paste(255, mask=mask)
20 def _log_frame(fmt, frame_no=None, end=None):
22 io_progress().report_message(
"%s frame rendering completed" % (fmt))
24 io_progress().report_progress(
"%s rendering frame" % fmt, frame_no, end)
27 @exporter("GIF", ["gif"], [
ExtraOption("skip_frames", type=int, default=1, help="Only renderer 1 out of these many frames"),
29 def export_gif(animation, fp, dpi=96, skip_frames=1):
33 Note that it's a bit slow.
35 start =
int(animation.in_point)
36 end =
int(animation.out_point)
39 for i
in range(start, end+1, skip_frames):
40 _log_frame(
"GIF", i, end)
42 renderer.serialize(i, file)
44 frames.append(_png_gif_prepare(Image.open(file)))
47 io_progress().report_message(
"GIF Writing to file...")
48 duration =
int(round(1000 / animation.frame_rate * skip_frames / 10)) * 10
52 append_images=frames[1:],
61 @exporter("WebP", ["webp"], [
ExtraOption("lossless", action="store_true", help="If present, use lossless compression"),
63 help=
"Compression effort between 0 and 100\n" +
64 "for lossy 0 gives the smallest size\n" +
65 "for lossless 0 gives the largest file"),
66 ExtraOption(
"method", type=int, default=0, help=
"Quality/speed trade-off (0=fast, 6=slower-better)"),
67 ExtraOption(
"skip_frames", type=int, default=1, help=
"Only renderer 1 out of these many frames"),
69 def export_webp(animation, fp, dpi=96, lossless=False, quality=80, method=0, skip_frames=1):
73 See https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#webp
75 if not features.check(
"webp_anim"):
76 raise Exception(
"WebP animations not supported in this system")
78 start =
int(animation.in_point)
79 end =
int(animation.out_point)
82 for i
in range(start, end+1, skip_frames):
83 _log_frame(
"WebP", i, end)
85 renderer.serialize(i, file)
87 frames.append(Image.open(file))
91 io_progress().report_message(
"WebP Writing to file...")
92 duration =
int(round(1000 / animation.frame_rate * skip_frames))
96 append_images=frames[1:],
100 background=(0, 0, 0, 0),
107 @exporter("TIFF", ["tiff"])
112 start =
int(animation.in_point)
113 end =
int(animation.out_point)
116 for i
in range(start, end+1):
117 _log_frame(
"TIFF", i, end)
119 renderer.serialize(i, file)
121 frames.append(Image.open(file))
124 io_progress().report_message(
"TIFF Writing to file...")
125 duration =
int(round(1000 / animation.frame_rate))
129 append_images=frames[1:],
135
def export_gif(animation, fp, dpi=96, skip_frames=1)
def export_tiff(animation, fp, dpi=96)
def export_webp(animation, fp, dpi=96, lossless=False, quality=80, method=0, skip_frames=1)
def convert(rifx, comp, expressions)