python-lottie  0.6.11+deved4e6c7
A framework to work with lottie files and telegram animated stickers (tgs)
gif.py
Go to the documentation of this file.
1 import io
2 from PIL import Image
3 from PIL import features
4 
5 from .cairo import PngRenderer
6 from .base import exporter, io_progress
7 from ..parsers.baseporter import ExtraOption
8 
9 
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)
17  return image
18 
19 
20 def _log_frame(fmt, frame_no=None, end=None):
21  if frame_no is None:
22  io_progress().report_message("%s frame rendering completed" % (fmt))
23  else:
24  io_progress().report_progress("%s rendering frame" % fmt, frame_no, end)
25 
26 
27 @exporter("GIF", ["gif"], [ ExtraOption("skip_frames", type=int, default=1, help="Only renderer 1 out of these many frames"),
28 ])
29 def export_gif(animation, fp, dpi=96, skip_frames=1):
30  """
31  Gif export
32 
33  Note that it's a bit slow.
34  """
35  start = int(animation.in_point)
36  end = int(animation.out_point)
37  frames = []
38  with PngRenderer(animation, dpi) as renderer:
39  for i in range(start, end+1, skip_frames):
40  _log_frame("GIF", i, end)
41  file = io.BytesIO()
42  renderer.serialize(i, file)
43  file.seek(0)
44  frames.append(_png_gif_prepare(Image.open(file)))
45  _log_frame("GIF")
46 
47  io_progress().report_message("GIF Writing to file...")
48  duration = int(round(1000 / animation.frame_rate * skip_frames / 10)) * 10
49  frames[0].save(
50  fp,
51  format='GIF',
52  append_images=frames[1:],
53  save_all=True,
54  duration=duration,
55  loop=0,
56  transparency=255,
57  disposal=2,
58  )
59 
60 
61 @exporter("WebP", ["webp"], [ ExtraOption("lossless", action="store_true", help="If present, use lossless compression"),
62  ExtraOption("quality", type=int, default=80,
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"),
68 ])
69 def export_webp(animation, fp, dpi=96, lossless=False, quality=80, method=0, skip_frames=1):
70  """
71  Export WebP
72 
73  See https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#webp
74  """
75  if not features.check("webp_anim"):
76  raise Exception("WebP animations not supported in this system")
77 
78  start = int(animation.in_point)
79  end = int(animation.out_point)
80  frames = []
81  with PngRenderer(animation, dpi) as renderer:
82  for i in range(start, end+1, skip_frames):
83  _log_frame("WebP", i, end)
84  file = io.BytesIO()
85  renderer.serialize(i, file)
86  file.seek(0)
87  frames.append(Image.open(file))
88 
89  _log_frame("WebP")
90 
91  io_progress().report_message("WebP Writing to file...")
92  duration = int(round(1000 / animation.frame_rate * skip_frames))
93  frames[0].save(
94  fp,
95  format='WebP',
96  append_images=frames[1:],
97  save_all=True,
98  duration=duration,
99  loop=0,
100  background=(0, 0, 0, 0),
101  lossless=lossless,
102  quality=quality,
103  method=method
104  )
105 
106 
107 @exporter("TIFF", ["tiff"])
108 def export_tiff(animation, fp, dpi=96):
109  """
110  Export TIFF
111  """
112  start = int(animation.in_point)
113  end = int(animation.out_point)
114  frames = []
115  with PngRenderer(animation, dpi) as renderer:
116  for i in range(start, end+1):
117  _log_frame("TIFF", i, end)
118  file = io.BytesIO()
119  renderer.serialize(i, file)
120  file.seek(0)
121  frames.append(Image.open(file))
122  _log_frame("TIFF")
123 
124  io_progress().report_message("TIFF Writing to file...")
125  duration = int(round(1000 / animation.frame_rate))
126  frames[0].save(
127  fp,
128  format='TIFF',
129  append_images=frames[1:],
130  save_all=True,
131  duration=duration,
132  loop=0,
133  dpi=(dpi, dpi),
134  )
135 
def export_gif(animation, fp, dpi=96, skip_frames=1)
Definition: gif.py:30
def export_tiff(animation, fp, dpi=96)
Definition: gif.py:110
def export_webp(animation, fp, dpi=96, lossless=False, quality=80, method=0, skip_frames=1)
Definition: gif.py:71
def convert(animation, exporter_slug)