A long time ago, I created a logo that sits at the top of my web page with Photoshop, and I'd been dragging it around with me ever since. I liked it, but it was a static PNG; it features a celtic knot that was probably originally scanned, which I chopped out of something else and then blew up. As a result, it looked a little grainy, and I'd been meaning to redo it correctly for some time. Technology has advanced enough that I was finally able to do it, and here are the results and how I achieved them.


I needed five tools to do this job:

Going through the motions

First I found the celtic knot I wanted, online as a GIF. I converted this to a PNG, with convert from ImageMagick. autotrace doesn't understand GIFs, so the conversion was neccessary. After the conversion, I ran autotrace on the PNG. I didn't need to tweak the parameters to autotrace at all in this case, but sometimes you have to play with the it to get the results you want.

I then found the font I wanted to write my name in: CelticHand. It was pure luck that I was able to find this font again, after six years. The font needs to be in True Type Font (TTF) format. Batik comes with a utility called ttf2svg -- this is a truely beautiful application. I ran ttf2svg on the TTF file to generate an SVG font description of CelticHand.

With this done, I copied the <def> block from the SVG font file to the head of the knot file -- just after the <svg ...> declaration will do. To reduce the size of the image, I cut out all of the character definitions from the font def; in this case, I removed all letters but aelnrsu.

Then I added a group block containing a text block and tweaked the translate and scale values until the text was centered and the right size. The characters were bleeding into the knot, so I did a shadow trick by telling SVG to stroke the characters in a light color. In Java, you specify the order of stroking and painting, but in SVG it is statically set to fill, then stroke. This means that 50% of the stroke overlaps your fill, which can make aenemic looking fonts. What you want is to stroke, then fill, which creates a nice border. I couldn't change the order, so I drew the text stroked, then again not stroked, which produces the desired effect. I wrapped the text in a group so that I could easily move it around and share the styles between the text, saving some space.

Post Processing

The next step was to get the SVG back into PNG format. Batik also comes with a rasterizer that works pretty well, and turns SVGs into PNGs. Once I had the PNG, I took it into Gimp and made the white background transparent. Running the result through pngcrush saved about 33% of the file size.

The file was still over 4 times as large as the original -- 44k vs the original 9k. I didn't know why that was, or why it should be, so I took it back into Gimp and turned from an RGB into an indexed image. That cut the file size in half. The result is still over twice as large as the original. I don't know why, but I have a theory:

The conversion to SVG actually added detail to the image. Since the original knot was fairly low-resolution, converting to SVG and then back to PNG smoothed out the lines and added complexity to the image. The additional detail looks much better, and the file correspondingly larger because the compression algorithm can't be as efficient.

The compressed SVG file is 1.5 times as large as the original PNG, and is 1.4 times smaller than the most optimized converted PNG.


Old browsers require the "embed" tag for embedding SVG; however, the "embed" tag is an illegal tag, and the proper way to include SVG images is via the "object" tag. The Adobe SVG plugin should allow for transparent embedding. If you have an SVG capable browser, try zooming in on the SVG image and experience the vector goodness. :-).

Original PNG version

PNG converted from SVG version

SVG version

For the font to show up correctly, you have to use a browser with a non-broken SVG implementation. Firefox's is broken. FF used to be the standard bearer for standards, but they gave up at some point. Chrome has a working SVG implementation, and renders it correctly, as does Safari.