import os, time
from . import file_writer, renderer
from ... colors import COLORS
from .. import exception, log
DEFAULT_RENDER = {
'color': COLORS.Black,
'pixel_width': 12,
'pixel_height': None,
'ellipse': True,
'vertical': False,
'frame': 2,
'padding': 2,
}
[docs]class MovieWriter:
"""Write an animated GIF given frames from an animation."""
def __init__(self, filename='output.gif', render=None,
divide=1, frames=128, time=10, speed=1.0, options=None,
gif_dir=None, duration=None, fps=None):
self.render = dict(DEFAULT_RENDER, **(render or {}))
self.divide = divide
self.frames = frames
self.time = time
self.speed = speed
self.duration = duration
self.fps = fps
self.options = options or {}
self.gif_dir = gif_dir
filename = os.path.expanduser(os.path.abspath(filename))
file_root, suffix = os.path.splitext(filename)
self.suffix = suffix
self.filename = file_root + suffix
self.basename = os.path.basename(file_root)
os.makedirs(os.path.dirname(self.filename), exist_ok=True)
self.finished = self.written = False
self.times = []
[docs] def set_project(self, project):
self.time = project.clock.time
self.render = renderer.renderer(project.layout, **self.render)
assert self.render
self.file_writer = file_writer.file_writer(self)
self.fps = project.animation.runner.fps
[docs] def step(self, cur_step):
if self.finished or (self.divide >= 1 and cur_step % self.divide):
return True
self.frame = cur_step / max(self.divide, 1)
self.times.append(self.time())
if self.time:
elapsed = self.times[-1] - self.times[0]
self.finished = (elapsed >= self.time)
else:
self.finished = (self.frame >= self.frames)
if self.finished:
self.write()
else:
self.file_writer.step()
return self.finished
[docs] def cleanup(self):
exception.report(self.write)
[docs] def write(self):
if not self.written:
self.file_writer.write()
self.written = True
@property
def length(self):
return self.times and self.times[-1] - self.times[0] or 0
@property
def fps(self):
if self._fps:
return self._fps
if self.duration:
return 1 / self.duration
if len(self.times) < 2:
return 1
return (len(self.times) - 1) / self.length
@fps.setter
def fps(self, fps):
self._fps = fps
@property
def scaled_fps(self):
return self.fps * self.speed