Framerator

on October 3, 2011, 12:29 am

As I have mentioned, building my Numberline iOS app has involved lots and lots of animation frames. I have been doing my artwork in Inkscape and then generating the frames based on the content in layers. It has been ok generating the low res frames I have been using for testing as I went along, but when I realised I needed to go back to all my SVG files and re-generate all the animation frames in three resolutions (iPad, iPhone and Retina) it became obvious that I could no longer do this by hand in Inkscape (show appropriate frames, file export, type the correct frame file name, set the resolution, export ... ugh).

I'm a programmer right? So it makes sense to automate that stuff. I wrote this simple Python script to run through a whole pile of SVGs, generate temporary SVG files containing a set of pre-configured layers and then drive Inkscape on the command line to generate the animation frame.

Here is the code:

from svgfig import * import os import config inkscape_location = '/Applications/Inkscape.app' def generateFile (detail): # load it and save it using SVG fig. This will write out elements on single lines. svg = load(detail[0]) svg.save ("temp.svg") # now we can mess with temp.svg using regex hackery fileOut = open ("temp_out.svg", "wt") fileIn = open ("temp.svg", "rt") lines = fileIn.readlines () for line in lines: # is this line a layer? exp = "(.*style=\\\")([^\\\"]+)(\\\".*inkscape:label=\\\")([^\\\"]+)(\\\".*inkscape:groupmode=\\\"layer\\\".*)" regexp = re.compile(exp, re.I) match = regexp.search(line) if (match): layer = match.group(4) if (layer in detail[4]): # this is a layer we want fileOut.write(match.group(1) + "display:inline" + match.group(3) + match.group(4) + match.group(5)) else: # hide this layer fileOut.write (match.group(1) + "display:none" + match.group(3) + match.group(4) + match.group(5)) else: # otherwise just write out the line fileOut.write (line) fileIn.close () fileOut.close () # run our command to generate the PNG based on our temporary SVG command = inkscape_location + '/Contents/Resources/script -without-gui -export-area-page --export-width=' \ +str(detail[2])+' -export-height='+str(detail[3])+' --export-png='+os.getcwd()+'/'+detail[1] + ' ' + os.getcwd() + '/temp_out.svg' print (command) os.system(command) for detail in config.config: generateFile (detail)

It depends on svgfig to sanitise the input and the following config file to describe the SVG files and the frames you need to generate:

# an array of tuples describing your SVG and the required output # [0] - The SVG file in question # [1] - The required PNG file to generate # [2] - The width # [3] - The height # [4] - An array of layer numbers to show in the generated PNG config = [ #left wobble ("monster_wobble_left.svg", "wobble_left4.PNG", 147, 201, ["Wobble3","Wobble3-bg"]), ("monster_wobble_left.svg", "[email protected]", 295, 402, ["Wobble3","Wobble3-bg"]), ("monster_wobble_left.svg", "ipad_wobble_left4.PNG", 323, 440, ["Wobble3","Wobble3-bg"]), ("monster_wobble_left.svg", "wobble_left3.PNG", 147, 201, ["Wobble2","Wobble2-bg"]), ("monster_wobble_left.svg", "[email protected]", 295, 402, ["Wobble2","Wobble2-bg"]), ("monster_wobble_left.svg", "ipad_wobble_left3.PNG", 323, 440, ["Wobble2","Wobble2-bg"]), ("monster_wobble_left.svg", "wobble_left2.PNG", 147, 201, ["Wobble1","Wobble1-bg"]), ("monster_wobble_left.svg", "[email protected]", 295, 402, ["Wobble1","Wobble1-bg"]), ("monster_wobble_left.svg", "ipad_wobble_left2.PNG", 323, 440, ["Wobble1","Wobble1-bg"]), ("monster_wobble_left.svg", "wobble_left1.PNG", 147, 201, ["standing","standing_bg"]), ("monster_wobble_left.svg", "[email protected]", 295, 402, ["standing","standing_bg"]), ("monster_wobble_left.svg", "ipad_wobble_left1.PNG", 323, 440, ["standing","standing_bg"]), #right wobble ("monster_wobble.svg", "wobble4.PNG", 147, 201, ["Wobble3","Wobble3-bg"]), ("monster_wobble.svg", "[email protected]", 295, 402, ["Wobble3","Wobble3-bg"]), ("monster_wobble.svg", "ipad_wobble4.PNG", 323, 440, ["Wobble3","Wobble3-bg"]), ("monster_wobble.svg", "wobble3.PNG", 147, 201, ["Wobble2","Wobble2-bg"]), ("monster_wobble.svg", "[email protected]", 295, 402, ["Wobble2","Wobble2-bg"]), ("monster_wobble.svg", "ipad_wobble3.PNG", 323, 440, ["Wobble2","Wobble2-bg"]), ("monster_wobble.svg", "wobble2.PNG", 147, 201, ["Wobble1","Wobble1-bg"]), ("monster_wobble.svg", "[email protected]", 295, 402, ["Wobble1","Wobble1-bg"]), ("monster_wobble.svg", "ipad_wobble2.PNG", 323, 440, ["Wobble1","Wobble1-bg"]), ("monster_wobble.svg", "wobble1.PNG", 147, 201, ["Standing","standing_bg"]), ("monster_wobble.svg", "[email protected]", 295, 402, ["Standing","standing_bg"]), ("monster_wobble.svg", "ipad_wobble1.PNG", 323, 440, ["Standing","standing_bg"]), ]

You can find the repo on Github

Permalink - Tags: Development