Source code for pierogis.course
import os
import subprocess
from typing import List
import imageio
import imageio_ffmpeg
import numpy as np
from .ingredients.dish import Dish
[docs]class Course:
"""treat a series of Dishes as a unit (animation)"""
_frames: int = None
_fps: int = None
@property
def frames(self):
return len(self.dishes)
def __init__(
self,
dishes: List[Dish] = None,
fps: float = None,
):
self.dishes = dishes
self.fps = fps
[docs] def serve(self):
cooked_dishes = []
for frame in range(self.frames):
dish = self.dishes[frame]
# cook with these pixels as first input
cooked_dish = dish.serve()
cooked_dishes.append(cooked_dish)
return Course(cooked_dishes)
[docs] def save(
self,
path: str,
optimize: bool = True,
duration: float = None,
fps: float = None
) -> None:
"""
:param path: path to save output
:param optimize: whether or not to try to optimize a gif output with gifsicle
:param duration: ms duration between frames (gets converted into fps)
:param fps: frames per second for image
"""
if len(self.dishes) > 1:
if duration is not None:
fps = 1000 / duration
if fps is None:
if self._fps is None:
fps = 30
else:
fps = self._fps
ext = os.path.splitext(path)[1]
if ext == ".gif":
# 30/60 fps is impossible for gif because maximum decimal precision is 2
# (duration .03 rounds to 25fps)
writer = imageio.get_writer(
path,
fps=fps
)
for dish in self.dishes:
writer.append_data(np.asarray(dish.pierogi.image))
else:
if ext == ".webm":
writer = imageio_ffmpeg.write_frames(
path,
size=self.dishes[0].pierogi.pixels.shape[:2],
fps=fps,
codec='libvpx-vp9',
bitrate='0',
output_params=['-crf', '30'],
input_params=['-thread_queue_size', '128'],
)
else:
writer = imageio_ffmpeg.write_frames(
path,
size=self.dishes[0].pierogi.pixels.shape[:2],
fps=fps
)
writer.send(None)
for dish in self.dishes:
writer.send(np.asarray(dish.pierogi.image))
writer.close()
if optimize and ext == '.gif':
try:
return_code = subprocess.call(
['gifsicle', '--optimize', path, '--output', path],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL
)
except:
return_code = 1
if return_code != 0:
print("install gifsicle and ensure it's on PATH to optimize gif")
elif len(self.dishes) == 1:
self.dishes[0].pierogi.save(path, optimize=optimize)
else:
raise Exception("Dish has no pierogis")