Collection of mostly command line tools / PHP scripts. Somewhat out of date.

⌈⌋ branch:  scripts + snippets

changed spline pacing mode: one less iteration to avert last section stuck at 1.0, reset .frame.args.delay just in case (repeat animations, e.g. fg/bg frames)
mario authored 26 days ago last checkin 483352ece
📂 test implement repeatCount, some tests‹› 33 days ago
📄 LICENSE add LICENSE, fix location=inx reference‹› 61 days ago
📄 Makefile hex_color int(alpha), -background None fallback (semi-transparency li‹› 48 days ago
📄 NEWS hex_color int(alpha), -background None fallback (semi-transparency li‹› 48 days ago
📄 animate_yo.inx translatable=no for combo boxes‹› 47 days ago
📄 hex_color redundant with inkex.Color‹› 46 days ago
📄 animate_yo.svg restructure and fix attributes to get some functional results‹› 56 days ago
📄 export_gif.inx recombine zip_args into imagick_gif(), distribute some flags onto fra‹› 44 days ago
📄 changed spline pacing mode: one less iteration to avert last section ‹› 26 days ago
📄 export_gif.svg Add global options for subframes, [pace] and custom _rotate handler.‹› 51 days ago
📄 layers.svg sample files for export_gif‹› 61 days ago
📄 pmd2inks separate handler for notebook/page sectioning‹› 46 days ago
📄 pytest.ini more pacing tests‹› 26 days ago
📄 saveas_gif.inx merge animgif branch back into main‹› 57 days ago
📄 screenshot.jpeg updated dialog‹› 51 days ago


Inkscape export_gif extension

Generates a GIF slideshow from image layers ☰ (Shift+Ctrl+L). The menu option Extensions➜Export➔GIF-slideshow… iterates over layers to generate animation slides. They get merged from bottom to top. Depending on shape overlap or layer transparency, there's different usage modes:

  • With a solid background in each layer, there's no accumulation to take care of.
  • Alternatively elect layers` can be labeled as [background] to stick, or [fixed] as permanent foreground, or [merge] for down-grouping.
  • If the -layers option is composite/coalesce/merge then all lower layers remain visible until the current frame.
  • Any [animate] layers get interpolated as is; layer transparency preserved.

Requires ImageMagick installed; fit for standard Linux setups. But might work with convert.exe on Windows. And alternatively there's the builtin Pillow conversion method. The options mostly map to IM flags.

  • Without the PNG conversion step, SVG interpretation is up to Imagick, and will not render fancy font/path effects. Just for plain old SVGs.
  • The [PNG→Pillow] option works without ImageMagick, but often generates rougher GIFs, yet might produce smaller result files.
  • In [JavaScript] mode, no output file will be generated. It just adds a script for animating slides into the current document (web views).
  • A [fixed] layer label describes a permanent foreground (until overdrawn), but never constitues a frame. Whereas [background] layers only become active and permanent when its frame is reached. Additionally [merge] labels will enjoin partial layers to the preceding full slide. Or use [exclude] to omit layers entirely.
  • There's also a experimental [animate] option to craft subframes from embedded <animate*> instructions. Motions require pip install svgelements or a bundled version for accurate paths. Bonus label tag [animate][pace] will honor begin= and dur= times.
  • Each layer label may also specify ImageMagick arguments [--delay=2.5].
  • The "default background color" is useful for otherwise transparent layers. Half-transparancy can be useful to gradually fade out lower frames (only seems to work in SVG/ImageMagick -displace mode).
  • Extra arguments are just a list of sample options, might not be particularly useful by themselves. Use the second input or [--flag=X] labels for more refined combinations.
  • Can't run two instances in parallel, due to fixed /tmp/inkscape… dir
  • It's also available as File > Save As... option (fewer options).

Might require some experimentation, and heavily utilizing the preview option. Potential error popups become informative at the very end. Most current documentation is in the script itself.

Code was derived from Xavi's Export Layers Redux For Inkscape 1.1+ - Which might still be the better fit for more customization, post-processing via Gimp, or generating a video via ffmpeg for example.

[fixed] and [background] layers

Per default each resulting GIF slide will be comprised of exactly one layer. Except when coalesce mode is on, or if layers are labelled accordingly. In the layers ☰ (Shift+Ctrl+L) pane, you can double click any name to edit the label. Then press ENTER.

  • Any fixed or [fixed] layer label will make it always painted regardless of the iterated frame. The position of the layer is still relevant. So the lowest layer being labeled fixed could still be drawn over by upper layers.
    This label is really most suited to foreground graphics, masks, titles, and any static fixtures (like a puppet theatre box bounding the whole animation).
  • background or [bg] work similar to fixed labels. Except that they will end up becoming a slide frame of their own. (Whereas fixed layers won't without any regular frame). So they're really best suited to, like the name suggest, background fixtures. They can still be drawn over, as always.
    So for exmaple, a full background scenery, with a simpler rectangle on consecutive layers to refresh or overdraw it.
  • [merge] can be used to join consecutive layers (partial shapes), and may merge with background or standard layers.

In any case, there can be multiple of them. A fixed or background layer can still be overlapped by higher ups. And you can thus clear scenes, and use multiple [background] or [fixed] foregrounds for different frame sections.

layer label behaviour
🗋 Layer 8 [exclude] Won't become a slide or merged in any way
🗋 Layer 7 [animate] Interpolates into subframes, <animate> instructions
🗋 Layer 6 Might do an all-solid reset over lower-layer shapes
🗋 Framebox [fixed] Always painted above lower layers, but doesn't become a slide itself
🗋 Layer 4 [--delay=5] Longer delay than other slides
🗋 Layer 3 [merge] Will be grouped/joined with Layer 2 into one frame
🗋 Layer 2 Individual slide
🗋 Layer 1 [bg] Painted as normal frame, but remains visible throughout

coalesce mode

Additionally if the -layers option is set to any of "coalesce", "merge", "composite", or "*plus"; then lower-layer-visibility is active. Which means then when iterating over slides, the preceding layers get painted below. Which provides for more aggregation than the usual only-current-layer-visible. It still combines with any fixed layers.

For example, whilst assembling slide 4, layers 1 + 2 + 3 will also remain visible (even if covered).

Embedded convert options

Additionally there's the --option=xyz syntax for layer labels. It's mostly meant for changing the -delay for a frame. From v1.1+ it will automatically reset for the following slide. And can be used for other options (-colors 32).

layer label behaviour
🗋 Layer 5 --dispose=background Might make the fallback color work
🗋 Layer 3 --delay=5 reset to standard delay time
🗋 Layer 2 --delay=2.5 pause for 2.5 seconds
🗋 Layer 1 default flags

Notably this isn't convert´s own argument syntax. Here --delay=2.5 will be mirrored as -delay 250 frameX.png for example. The allowed syntax is very restricted, doesn't permit expressions or a different -write target. Nonetheless you could use it to inject prepared image files --verbose=/tmp/frameX.png into the slide list (-verbose just happens to act as void argument there), or even paint --format=Singleword text.

Animation support

There's now some support for rudimentary SVG <animate*> instructions. Which will expand a single layer into multiple subframes, each taking a slice of the original per-frame delay. Per default [animate] would interpolate 5 subframes, but [animate=25][--delay=1] or [steps=10] could expand that. (There's now a global dialog option for that default). Note that this also incurs longer generation time.

It's still largely an experiment, but works for scaling and style changes. Some caveats of course:

  • Rotation is somewhat wonky with the inkex tweening default, so there's a more trivial fallback now.
  • Color changes don't work with semi-transparent colors, so it's fixed to altering RGB for now.
  • Proper <animateMotion> along a path requires svgelements (in ZIP and DEB package). Maybe that'll become redundant in a future Inkscape/inkex versions though..
  • Per default it just distributes animations onto the frame time slice (so for delay=1s and 5 subframes, it would be 0.2s each).
  • Timing cues (keyTimes= or calcMode=paced) now sortof works (really basic approach), but requires setting the global option or a per-layer [animate] [pace] flag. Nobody is ever going to use this, but it's there now.
  • Irrespective of the global option, having animations in a [background] or [fixed] layer will not engage the interpolation, unless the current slide also contains an animated object. But the timing/animation resets per slide anyhow; thus likely not useful for constant motions.
  • Combinatory animateTransforms won't work very well. And even animate styles could overwrite each other. (tweening sets all CSS flags)

Don't expect this to be as exact as SVG browser display. It's just meant as basic alternative to real animation tools. (And I really can't recommend enve2d enough, even if incomplete. Enabling path transforms requires some getting used to, but the timeline interactions are quite practical.)


PNG→ImageMagick: Preconverts slides to PNG first, before having convert assemble the target GIF. The conversion is done via background Inkscape incantations, and is thus a bit slower. Usually creates the best output however.

  • Most dialog options work best in this processing mode.
  • Except for the fallback background color, still.
  • The -layers options do not make a whole lot of difference.
  • Custom arguments can be found in the convert(1) man page.

SVG→ImageMagick: Doesn't invoke Inkscape for each slide, but lets ImageMagick convert the raw SVGs directly. Which will fail for gradient layers, and any path or font effects. It's really just suitable for solid drawings, or standard text slides. But in such cases can be faster to produce output. Additionally this is the mode where the fallback background color (for fading effects) gets applied behind partially transparent slides.

PNG→Pillow: Utilizes the PIL/Pillow module to generate GIFs instead of an external tool. It will still preconvert slides to PNG first. It doesn't recognize many of the options yet (and probably never will).
It's potentially the fastest option, though that won't matter for >20 slides. There's no dithering enabled, so might end up with more blocky graphics instead of gradients.

JavaScript-embed: Is a shallow alternative to JessyInk. Merely injects a <script> tag to loop over slides. It's kind of the same algorithm of the standard slide mode, honoring potentially fixed layers, but not the coalesce mode (only ever one layer plus fixed overlays). Any animations would run with an actual browser interpreter.

Extending via pmd2inks

The script itself contains the config: options in a #comment, which simplifies adapting available flags. Most intestingly the present convert options can be customized. The select: line is just a string of alternatives, and could be added onto:

 { name: extra, type: select, select: "-quiet|-scale 1024x768|-resize 640x360|-alpha…" }
                                                 add here

Afterwards, you would use pmd2inks > export_gif.inx to update the according Inkscape plugin XML. While in this case you could well edit that XML directly, the script extraction could be more practical for repeat changes.

However, if you do want defaults changed (for the save-as mode, which doesn't bring up the dialog), then you'll have to copy the pars.add_argument(…) section back into the *.py script.


Not sure those are gonna happen (but we have a compact dialog now):

  • gifsicle optimize option?

Animate Yo

There's now a companion tool Animate Yo, which can craft actual SVG animation (SMIL) tags. Some of which might be recognized by the tweening and export_gif subframe generation.


  • Select a shape.
  • Open Extensions→Animation→Animate Yo
  • Pick one of the notebook tabs to animate colors, rotation, or shape transforms.
  • Alternatively select a path alongside the animated object, and the [move] option will apply.

The according instructions will be visible and editable in Inkscape’s 🗔 XML editor (Ctrl+Shift+X). Where you could replace edit to="20" or the list of values="10;20;30" for example, or change other attributes like calcMode="paced" (now available in new dialog notebook).

Some caveats:

  • Moved shapes often carray a transform=matrix(…), and thus might need recreating the <animateTransform> tag. (It's best to create new objects with [Ctrl] held, to avoid any such transforms.) For some shapes this can impair animating rotation, scale, and moving along paths.
  • The scale option also works with a single 3.0 value (applied to width and height).
  • With strip previous animation the existing <animate> OR <animateMotion> OR <animateTransform> would be removed. But only the tag/type that will be recreated by the current tab selection.
  • The #id option might not be particular useful. (If you embed the SVG for JavaScript interaction, you'd edit it in anyway.)
  • You can actually have multiple <animate> or Transform tags per shape. They might interfere with each other, though.
  • Also note that SVG/SMIL animations are talked about being deprecated somewhen in the future (but JavaScript/CSS shims certain to emerge, if so).

It's sometimes practical to have both extension dialogs open atop the drawing board (where you can still select objects, change params). The DEB package bundles both extensions, btw.