OmniSVG's picture
Upload 80 files
c1ce505 verified
import os
import uuid
import json
import numpy as np
from moviepy.editor import ImageClip, concatenate_videoclips
import shutil
from deepsvg.svglib.svg import SVG
from deepsvg.svglib.geom import Bbox
from ..config import ROOT_DIR
class Frame:
def __init__(self, index, keyframe=False, svg=None):
self.index = index
self.keyframe = keyframe
if svg is None:
svg = SVG([], viewbox=Bbox(256))
self.svg = svg
self.kivy_bezierpaths = None
def to_dict(self):
return {
"index": self.index,
"keyframe": self.keyframe
}
@staticmethod
def load_dict(frame):
f = Frame(frame["index"], frame["keyframe"])
return f
class DeepSVGProject:
def __init__(self, name="Title"):
self.name = name
self.uid = str(uuid.uuid4())
self.frames = [Frame(index=0)]
@property
def filename(self):
return os.path.join(ROOT_DIR, f"{self.uid}.json")
@property
def base_dir(self):
base_dir = os.path.join(ROOT_DIR, self.uid)
if not os.path.exists(base_dir):
os.makedirs(base_dir)
return base_dir
@property
def cache_dir(self):
cache_dir = os.path.join(self.base_dir, "cache")
if not os.path.exists(cache_dir):
os.makedirs(cache_dir)
return cache_dir
def load_project(self, file_path):
with open(file_path, "r") as f:
data = json.load(f)
self.name = data["name"]
self.uid = data["uid"]
self.load_frames(data["frames"])
shutil.rmtree(self.cache_dir)
def load_frames(self, frames):
self.frames = [Frame.load_dict(frame) for frame in frames]
for frame in self.frames:
frame.svg = SVG.load_svg(os.path.join(self.base_dir, f"{frame.index}.svg"))
def save_project(self):
with open(self.filename, "w") as f:
data = {
"name": self.name,
"uid": self.uid,
"frames": [frame.to_dict() for frame in self.frames]
}
json.dump(data, f)
self.save_frames()
def save_frames(self):
for frame in self.frames:
frame.svg.save_svg(os.path.join(self.base_dir, f"{frame.index}.svg"))
def export_to_gif(self, frame_duration=0.1, loop_mode=0):
from .state import LoopMode
imgs = [frame.svg.copy().normalize().draw(do_display=False, return_png=True) for frame in self.frames]
if loop_mode == LoopMode.REVERSE:
imgs = imgs[::-1]
elif loop_mode == LoopMode.PINGPONG:
imgs = imgs + imgs[::-1]
clips = [ImageClip(np.array(img)).set_duration(frame_duration) for img in imgs]
clip = concatenate_videoclips(clips, method="compose", bg_color=(255, 255, 255))
file_path = os.path.join(ROOT_DIR, f"{self.uid}.gif")
clip.write_gif(file_path, fps=24, verbose=False, logger=None)