contour
clone your own copy | download snapshot

Snapshots | iceberg

Inside this repository

make-frames-weekend3-long.py
text/x-python

Download raw (3.9 KB)

from svg.path import parse_path
from svg.path.path import Move, Line, CubicBezier
from bs4 import BeautifulSoup
import re
import os.path
import os

# height = 800
# width = height/(1920/1080)

sources = [
  # ('digital-city-poster-1080x1920.svg', '1080x1920-weekend-3'),
  ('digital-city-poster-weekend3-1920x1080-long.svg', '1920x1080-weekend-3-long'),
  # ('digital-city-poster-1920x2160.svg', '1920x2160-weekend-3')
]

fps = 25
still = [0, 0, 5, 2]
transition = [.75]

def parse_viewbox (viewboxstring):
  pattern = re.compile(r'(-?[\d\.]+) (-?[\d\.]+) (-?[\d\.]+) (-?[\d\.]+)')
  m = pattern.match(viewboxstring)
  return (float(m.group(1)), float(m.group(2)), float(m.group(3)), float(m.group(4)))

def framecount (length):
  return int(length * fps)

def get_translation (group):
  pattern = re.compile(r'translate\((-?[\d\.]+),\s*(-?[\d\.]+)\)')

  transform = group.get('transform')
  
  if transform:
    m = pattern.match(transform)
    if m:
      translation = (float(m.group(1)), float(m.group(2)))
    else:
      translation = (0, 0)
  else:
    translation = (0, 0)

  return translation


def get_group_by_label (svg, label):
  for group in svg.find_all('g'):
    if group.get('inkscape:label') == label:
      return group

def get_keypoints(svg):
  keypoints_layer = get_group_by_label(svg, 'keypoints')
  keypoints = keypoints_layer.find_all('circle')
  translation = get_translation(keypoints_layer)
  return [
    complex(translation[0] + float(point.get('cx')), translation[1] + float(point.get('cy'))) for point in keypoints]

def write_frame(f, svg, folder = ''):
  with open(os.path.join(folder, '{:05d}.svg'.format(f)), 'w') as o:
    o.write(svg.prettify(formatter=None)
      .replace('lineargradient', 'linearGradient')
      .replace('gradienttransform', 'gradientTransform')
      .replace('gradientunits', 'gradientUnits')
      .replace('spreadmethod', 'spreadMethod')
      .replace('viewbox', 'viewBox')
      .replace('flowroot', 'flowRoot')
      .replace('textpath', 'textPath')
      .replace('startoffset', 'startOffset')
      .replace('spreadmethod', 'spreadMethod')
      .replace('clippath', 'clipPath'))
    o.close()

for drawing, target in sources:
  print(drawing)
  with open(drawing, 'r') as handle:
    # use bs 4 to find paths
    soup = BeautifulSoup(handle.read(), 'lxml')
    svg = soup.find('svg')
    outputdir = os.path.join(target, 'svg')

    if not os.path.exists(outputdir):
      os.makedirs(outputdir)

    viewbox = parse_viewbox(svg['viewbox'])
    print(viewbox)
    width = viewbox[2] - viewbox[0]

    keypoints_layer = get_group_by_label(soup, 'keypoints')
    keypoints = sorted(get_keypoints(soup), key=lambda point: point.real)


    animation = get_group_by_label(soup, 'animation')
    translation = get_translation(animation)
    
    keypoints_layer.extract()
    
    f = 0

    for k, center in enumerate(keypoints):
      if k > 0:
        for i in range(framecount(transition[min(k, len(transition) - 1)])):
          t = i / float(framecount(transition[min(k, len(transition) - 1)]))
          d = keypoints[k].real - keypoints[k-1].real
          x = translation[0] - keypoints[k-1].real - (t * d) + (float(width) / 2)
          y = translation[1]
          animation['transform'] = 'translate({}, {})'.format(x, y)
          get_group_by_label(svg, 'text')['style'] = 'display:inline;visibility:visible;'
          write_frame(f, svg, folder=outputdir)
          f += 1

      for i in range(framecount(still[min(k, len(still) - 1)])):
        x = translation[0] + (-1 * (center.real - (float(width) / 2)))
        y = translation[1]
        animation['transform'] = 'translate({}, {})'.format(x, y)
        get_group_by_label(svg, 'text')['style'] = 'display:inline;visibility:visible;'
        write_frame(f, svg, folder=outputdir)
        f += 1
        # print(path, 'translate({}, {})'.format(center.real - (width / 2), 0))
      

      # output = svgwrite.Drawing(filename="frames/output.svg", size=(width, height))