https://github.com/tomkwok/svgasm Skip to content Sign up * Why GitHub? Features - + Mobile - + Actions - + Codespaces - + Packages - + Security - + Code review - + Project management - + Integrations - + GitHub Sponsors - + Customer stories- + Security - * Team * Enterprise * Explore + Explore GitHub - Learn and contribute + Topics - + Collections - + Trending - + Learning Lab - + Open source guides - Connect with others + The ReadME Project - + Events - + Community forum - + GitHub Education - + GitHub Stars program - * Marketplace * Pricing Plans - + Compare plans - + Contact Sales - + Nonprofit - + Education - [ ] [search-key] * # In this repository All GitHub | Jump to | * No suggested jump to results * # In this repository All GitHub | Jump to | * # In this user All GitHub | Jump to | * # In this repository All GitHub | Jump to | Sign in Sign up {{ message }} tomkwok / svgasm * Sponsor Sponsor tomkwok/svgasm * Notifications * Star 18 * Fork 0 SVG animation from multiple SVGs or single GIF using tracer Apache-2.0 License 18 stars 0 forks Star Notifications * Code * Issues 0 * Pull requests 0 * Actions * Security * Insights More * Code * Issues * Pull requests * Actions * Security * Insights master Switch branches/tags [ ] Branches Tags Nothing to show {{ refName }} default View all branches Nothing to show {{ refName }} default View all tags 1 branch 0 tags Go to file Code Clone HTTPS GitHub CLI [https://github.com/t] Use Git or checkout with SVN using the web URL. [gh repo clone tomkwo] Work fast with our official CLI. Learn more. * Open with GitHub Desktop * Download ZIP Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Go back Launching GitHub Desktop If nothing happens, download GitHub Desktop and try again. Go back Launching Xcode If nothing happens, download Xcode and try again. Go back Launching Visual Studio If nothing happens, download the GitHub extension for Visual Studio and try again. Go back Latest commit @tomkwok tomkwok convert command output ppm format; add quiet argument handling; more ... ... f451a2f Feb 28, 2021 convert command output ppm format; add quiet argument handling; more ... ...autotrace examples in ipynb f451a2f Git stats * 16 commits Files Permalink Failed to load latest commit information. Type Name Latest commit message Commit time .github add build status badge Feb 18, 2021 examples convert command output ppm format; add quiet argument handling; more ... Feb 28, 2021 readme convert command output ppm format; add quiet argument handling; more ... Feb 28, 2021 src convert command output ppm format; add quiet argument handling; more ... Feb 28, 2021 .gitattributes add stylesextra handling; add negate example in README; include full ... Feb 26, 2021 .gitignore convert command output ppm format; add quiet argument handling; more ... Feb 28, 2021 LICENSE.md add stylesextra handling; add negate example in README; include full ... Feb 26, 2021 Makefile add stylesextra handling; add negate example in README; include full ... Feb 26, 2021 README.md convert command output ppm format; add quiet argument handling; more ... Feb 28, 2021 View code README.md svgasm Sponsor Build status Language grade: C/C++ License svgasm is a proof-of-concept SVG assembler to generate a self-contained animated SVG file from multiple still SVG files with CSS keyframes animation to play frames in sequence. Steps listed in reverse order of execution: * Produces single animated SVG file that is viewable in Chrome, Safari, Firefox, Edge and IE 10+. * Executes SVG cleaner svgcleaner (by default) or svgo to minify each SVG file. * Executes bitmap tracer potrace (by default) or autotrace, or primitive to convert raster image input to SVG. * Executes image processor graphicsmagick (by default) or imagemagick to convert GIF animation to frames. Flow diagram of svgasm from animated GIF to animated SVG Examples SVG animation from single GIF using tracer If the two versions of animation below are out of sync, try reloading this page without refreshing by clicking here. Show evolution of life GIF example Note that colors are inverted with gm convert -negate to obtain black-on-white images before tracing with potrace. The SVG output is hence black-on-transparent but restyled to white-on-black to match the input GIF. svgasm -t 'gm convert -negate "%s" pgm:- | mkbitmap -x -f 1 -s 1 - -o - | potrace -t 0.4 --svg -o -' -s 'svg {background-color: black} path {fill: white}' examples/_evolution_of_life.gif > examples/ evolution_of_life.svg Input GIF (6,843 KiB) Output SVG (3,490 KiB - 1,394 KiB gzipped) [_evolution_of_life] [evolution_of_life] Show rotating cross GIF example svgasm examples/_rotating_cross.gif > examples/rotating_cross.svg (with potrace as tracer by default) Input GIF (665 KiB) Output SVG (462 KiB - 119 KiB gzipped) [_rotating_cross] [rotating_cross] Show infinity spiral GIF example svgasm -t 'mkbitmap -t 0.4 -s 1 "%s" -o - | potrace -t 4 --svg -o -' -s 'svg {background-color: white}' examples/_infinity_spiral.gif > examples/infinity_spiral.svg Input GIF (349 KiB) Output SVG (715 KiB - 285 KiB gzipped) [_infinity_spiral] [infinity_spiral] Show NSFW cartoon GIF example svgasm -t 'mkbitmap -x -t 0.44 -s 1 "%s" -o - | potrace --svg -o -' -s 'svg {background-color: #ddd}' examples/_mickey_mouse_nsfw.gif > examples/mickey_mouse_nsfw.svg Input GIF (912 KiB) Output SVG (1,164 KiB - 473 KiB gzipped) [_mickey_mouse_nsfw] [mickey_mouse_nsfw] Note that potrace only natively handles two-valued images. The color values in the SVG output can be specified with extra CSS styles definitions in the -s argument to the svgasm tool as in the command for the evolution of life GIF example. The colors do not have to be black or white or colors in grayscale used in the above examples. All of the above examples traced with potrace can also be traced with autotrace with less configuration but also less accurate (sometimes funky) shapes in results, which can be viewed in examples/ autotrace_results.ipynb. Use of multiple colors in SVG output is supported natively in autotrace but gradients are hard for any tracer. Show Spongebob GIF example svgasm -t 'autotrace --output-format svg --color-count 64 --despeckle-level 10 --despeckle-tightness 0.8 --remove-adjacent-corners "%s"' examples/_spongebob.gif > examples/ spongebob.svg Input GIF (426 KiB) Output SVG (888 KiB - 259 KiB gzipped) [_spongebob] [spongebob] Show anime GIF example svgasm -t 'autotrace --output-format svg --color-count 120 --despeckle-level 16 --despeckle-tightness 1.5 --tangent-surround 1 --remove-adjacent-corners "%s"' -s 'svg {background-color: gray}' examples/_anime.gif > examples/anime.svg Input GIF (1,616 KiB) Output SVG (1,268 KiB - 496 KiB gzipped) [_anime] [anime] While primitive is not a tracer, it can be used for raster-to-vector conversion with aesthetically pleasing results. Show lions GIF example svgasm -t 'gm convert "%s" png:- | primitive -i - -o - -n 250' examples/_lions.gif > examples/lions.svg Input GIF (2,180 KiB) Output SVG (673 KiB - 193 KiB gzipped) [_lions] [lions] SVG animation from multiple still SVGs Show build status badge example An example of a 2-fps 2-frame animated build status badge for this project is generated using svgasm from 2 GitHub Workflows status badge SVG files. Build status badge animation example Show calendar plot example A worked example of a 1-fps 2-frame animated calendar plot in examples/calplot_animation.ipynb (Jupyter Notebook) is generated using calplot and svgasm. Calplot animation example Show contour plot example While the above two examples can be created with CSS animation with some effort without the help of svgasm, the following example is not so easy. The following example is a 30-fps 41-frame animated contour plot of F[b] score from a sequence of 41 plots pre-generated using matplotlib animated with svgasm. Contour plot animation example Notably, svgasm does not use JavaScript in SVG output. (An alternative approach would be to re-program plot generation with a JavaScript library like D3.js to have the browser generate the values of text, paths, gradients, etc.) Usage svgasm [options] infilepath... Options: -d animation time delay in seconds (default: 0.1) -o path to SVG animation output file or - for stdout (default: -) -p prefix added to element IDs (default: _) -i animation iteration count (default: infinite) -e index of frame to stop at in last iteration if not infinite (default: -1) -l loading text in output or '' to turn off (default: 'Loading ...') -s extra CSS styles definition in output (default: '') -c command for SVG cleaner with "%s" (default: 'svgcleaner --multipass -c "%s"') -t command for tracer for non-SVG still image with "%s" (default: 'gm convert +matte "%s" ppm:- | potrace --svg -o -') -m command for magick program for GIF animation with %s (default: 'gm %s') -q silence verbose standard error output -h print help information Usage examples * svgasm -d 2 -i 5 -e 0 -o animation.svg input1.svg input2.svg input3.svg Generates output animation.svg from input1.svg, input2.svg and input3.svg that animates with a delay of 2 seconds per frame, iterates 5 times, and stops at the first frame in the last iteration. * svgasm -d 1/30 -l '' intro.jpg frame*.png > animation.svg Generates output animation.svg from intro.jpg and wild card frame*.png that animates with 30 frames per second, iterates infinitely, and with loading text turned off. * svgasm animation1.gif animation2.gif > animation.svg Generates output animation.svg from animation1.gif and animation2.gif that animates with the same time delay as the first GIF file. Installing on macOS To install and run a pre-compiled binary of svgasm on macOS with Homebrew installed, run the following commands, which would also install dependencies svgcleaner, potrace and graphicsmagick: brew install tomkwok/tap/svgasm svgasm Building on macOS or Linux To clone this repository and build svgasm with a C++98 complier installed, run the following commands: git clone https://github.com/tomkwok/svgasm cd svgasm/ make ./svgasm svgasm can be executed as a standalone program. However, the only working feature without dependencies is svgasm [options] input*.svg > output.svg (with automatic fallback to cat as dummy cleaner program). For more features, install runtime dependencies. An example instruction is provided for Arch Linux as follows: sudo pacman -S svgcleaner potrace graphicsmagick To download the example files in this repository with git-lfs installed, run the following commands: git lfs install git lfs pull Installing optional runtime dependencies * svgo: running the command npm install -g svgo or yarn global add svgo * autotrace: downloading a release binary from the release page of autotrace or install with a package manager * primitive: running the command go get -u github.com/fogleman/ primitive Benchmark with different SVG cleaners svgasm has been tested to work with the following cleaners: * cat can be specified as a dummy cleaner program for most SVG files. (In particular, ensure that there are no unnecessary white-spaces in tags.) cat is the fallback program if svgcleaner is not installed on the system. * svgcleaner is the default cleaner program. svgcleaner is chosen as the default cleaner because it is generally very fast and produces small output. * svgo can be specified as the cleaner program. svgo is typically over an order of magnitude slower than svgcleaner. Nonetheless, svgo can sometimes produce smaller files than svgcleaner does. The following are the results of using svgasm to produce the 41-frame contour plot animation example above on an Intel Core i5 processor with different cleaners. The size of output after compression with gzip at the best level -9 is provided in brackets for reference since SVG files are usually served via HTTP which supports compression. Command executed Output SVG size Real elapsed (gzip) time svgasm -c 'cat "%s"' [...] 3,143 KiB (1,145 0.265 s +- KiB) 0.006 s svgasm -c 'svgcleaner --multipass -c 2,232 KiB (992 0.844 s +- "%s"' [...] KiB) 0.041 s svgasm -c 'svgo --multipass -o - 2,054 KiB (884 34.839 s +- "%s"' [...] KiB) 0.292 s Benchmark with GraphicsMagick and ImageMagick GraphicsMagick is a fork of ImageMagick, and it is reportedly faster in benchmarks. The following are the results of using svgasm to produce the 60-frame rotating cross animation example above on an Intel Core i5 processor with GraphicsMagick and ImageMagick specified as the magick command. Note that the magick program is also present in the default tracer command for potrace. Identical output is obtained with the two utility programs. Command executed Real elapsed time GraphicsMagick svgasm -c 'cat "%s"' -m 'gm %s' -t 'gm 3.205 s +- convert "%s" [...]' 0.037 s ImageMagick svgasm -c 'cat "%s"' -m '%s' -t 'convert 5.493 s +- "%s" [...]' 0.041 s How svgasm is implemented * Refer to an example on Stack Overflow of animating a sequence of hand-drawn vector graphics. The principal method employed in the svgasm tool of playing SVGs in sequence with CSS animation is credited to its author. * Implementation is fine-tuned in the svgasm tool to better accommodate browser behavior. In particular, since Chrome renders elements on the fly and starts timing animations on elements as SVG file loads, attention was given to styles placement to prevent flickering in Chrome due to mismatching animation start times for different group elements for frames. See inline comments in src/svgasm.cpp for details. Note that such flickering is only apparent in an animation with a high fps value. (It is not clear in the CSS Animations specification whether a style rule is considered resolved or not when the styles are parsed but the elements referenced are not yet in the DOM. The answer is apparently no in Chrome, so CSS animations need to be moved to the end for animation of frames to start at the same time.) * An SVG file cleaner is executed to pre-process SVG files to ensure that svgasm can successfully parse input SVG files. For simplicity, svgasm uses string operations in standard library instead of an XML parser. The animated SVG file output generated does not seem to be further minifiable using svgcleaner or svgo. Currently, svgo gives an empty SVG when given the output of svgasm. * The tag including its attributes (such as width, height and viewbox) in the first SVG file in the sequence of command-line arguments to the svgasm tool is copied to the output. It is assumed that all frames have the same size and viewport bounds, or all frames are effectively cropped to the size of the first frame. This approach is taken for simplicity in this proof-of-concept implementation and can be improved. * The svgasm tool generates a self-contained output file with a configurable loading text, the content of all SVG frames and CSS animation styles in