Tiny, binary-encoded vector graphics.

zig (14) graphics (8) formats (3)

Table of Contents
  1. Frequently asked questions
  2. Did you have problems implementing TinyVG?
  3. Not
  4. At
  5. All
  6. See!
  7. Links

Project Website: tinyvg.tech

SVG is a bad choice for most applications, at least in my opinion.

No, seriously, hear me out!

I needed vector graphics for a Zig project and I figured that everyone inluding myself is using SVG. So I wanted to use SVG. What it learned in the process that implementing a new SVG library is hard.

First of all, SVG is built on top of several other technologies:

For the purpose of static graphics, we can ignore the scripting portion of that. But even without that, implementing both a good XML and CSS parser is a lot of work.

Then SVG on top. SVG is so complex that different implementations of SVG disagree how an image should look. Especially if that image contains <text>, as it depends on the system. What some of you probably learned by now is that if you want to have a redistributable SVG file, you have to have your authoring file in Inkscape, Illustrator, Batik, … and you have your final file which has all texts converted to paths. Otherwise, the file will look very different on each machine. An example:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="150" viewBox="0 0 400 150">
  <rect x="50" y="50" width="300" height="50" fill="red" />
  <text x="50" y="100" style="font-family: monospace; font-size: 50;">Hello</text>

How will this look in different browsers? Let’s test!

Windows 10, Edge Void Linux, Chrome Void Linux, Firefox

🤔 That didn’t go as expected. I thought that at least both files on my Linux machine look the same, but it seems like Firefox doesn’t like the font-size specification, while Chrome and Edge do.

And there are more and more edge cases which make implementation SVG too complex. Files can be pulled in from external sources via xlink, file contents could be built by complex scripts, and so on. But even simpler files might break.

#FF000080 isn’t a valid SVG color, but it’s a valid HTML color. Chrome, Firefox and Edge show us a half-transparent red, while Inkscape and QtSvg show a black square.

All of this stuff made me realize: XML is meant to be an authoring file for vector graphics like xcf or psd which contains not only the final graphic information, but also how that graphic is constructed piece by piece.

What we really need is a format like PNG for vector graphics. Compact, versatile and simple to implement. What most of us don’t need are vector graphic animations or vector graphic applications. What we definitly don’t need is a vector graphic format that can do raw sockets.

After the reasearch I did to implement SVG in Zig, I was disappointed and angry that stuff like vector graphics is so complex and in my stubbornness I decided:

I’ll make my own vector format, without blackjack and hookers.

I created a new format called Tiny Vector Graphics or short TinyVG that tries to have 95% of the features we actually need from SVG (so shapes, colors, gradients, scalability) but not have all the things we typically don’t need (animations, scripting, external resources, hierarchical document structure, …).

As recent developments shows that complexity makes things susceptible to vulnerabilities, so it seems that going the simple route (like QOI did) is the right way.

So before implementing a new graphics format, I looked at the things we have today:

Looking at these formats made me set my design goals:

Triggered by a discussion in the Zig discord, I started to work on TinyVG in September 2020 and in May 2021 I got it to a state where I could live with it and use it for things in other projects:

Dunstwolke Android Application

But then Dominic Szablewski published the The Quite OK Image Format and showed me that there was interest in simpler formats. It inspired and motivated me to push for TinyVG completion and I got back to the project.

The project was already in an OK state, but I wanted to go better. I refactored pretty much everything, streamlined the design of the format and got some things right.

This work made TinyVG smaller and more flexible than before and running benchmarks with a SVG converter showed me that I was on the right path.

I got the file size down to 40% compared to optimized SVG while retaining visual fidelity:

Comparison between SVG and TVG

The three images you see here are:

There are tiny differences in the files, but overall I’m very happy with the conversion process.

tiger.svg rendered with TinyVG

With this day, I release the first draft of the specification into the wild and open for review.

With the reference implementation is done and the first draft of the specification written, you can already go and try TinyVG!

On the website, you can find the following things:

So let’s recap if we succeeded in the goals set at the project start:

The benchmark shows that TinyVG is between 20% and 60% of an equivalent, optimized SVG file. This means the mission was a success in that regard. ✅

Both the Material Design icon set as well as the Papirus one can be converted to a large degree without any losses. This means that we can render application and toolbar icons very well.

The example files on the website also show examples for a comic, a chart, graph and art.

So the planned use cases can be covered with TinyVG. ✅

This one is easily shown: We successfully converted a huge load of SVG files in the benchmark (roughly 3500 files) without much problems.

Perfect! ✅

There’s both a CPU renderer implementation as well as a polyfill. This means we already have covered classic desktop applications as well as web content. There also is a Vulkan renderer implemented (not open source) for a older version of TinyVG, so GPU rendering also is covered.

But what about memory and cpu restricted environments like embedded platforms?

Let a photo speak for itself:

TinyVG graphics on a microcontroller

This goal: Achieved! ✅

Make it simpler than SVG. Well, that’s an easy one. But let’s compare some real numbers!

The TinyVG SDK in total has roughly 4000 lines of Zig and 2000 lines of C#. The C# portion only implements only the SVG to TinyVG conversion, utilizing the System.Xml.XmlSerializer class for parsing XML. This means that there is low semantic checking and zero rendering involved. The Zig implementation though implements parsing the text and binary representation of TinyVG, and provides a software renderer as well. The code also includes the command line tools and native bindings.

To compare this to a SVG implementation, I’ve chosen libresvg, a Rust library to render SVG files. RazrFalcon claims that the whole SVG implementatio is roughly 50kLOC with all dependencies.

This shows that TinyVG can be fully implemented in a lower level language (Zig) with a low amount of code, while SVG requires substantially more code in languages with even a higher language of abstraction (C#, Rust).

Also the TinyVG spec is 14 pages long and won’t grow by a lot if done more precise while the SVG 1.1 spec alone is 260 pages long, excluding the specifications for CSS, XML and ECMA-Script.

So I’d say: This is definitly a success! ✅

If you are interested in TinyVG, you have the following option:

Select anchorFrequently asked questions

Select anchorDid you have problems implementing TinyVG?

Select anchorNot

Alt Text

Select anchorAt

Alt Text Alt Text

Select anchorAll

Alt Text Alt Text

Select anchorSee!

Alt Text

Spoiler: This section isn’t really a FAQ, but I wanted to share these images anyways

Select anchorLinks