Vectorize Bitmaps to XAML using Potrace and Inkscape

To create vector images from bitmap images can be useful, for example, if you already have a raster-based picture in a common graphics format (such as a PNG, JPG, BMP, GIF, TIF or ICO file) and want to convert it to a vector-based format (such as a XAML, SVG, EPS or EMF file) to perhaps use it in a Silverlight or WPF application or simply to enlarge the image without seeing individual pixels as large blocks. The process of such an image conversion is referred to as vectorization, and the free Inkscape application (which is “an Open Source vector graphics editor, with capabilities similar to Illustrator, CorelDraw, or Xara X” – currently at version 0.46) has built-in tracing functionality, and it supports all the file formats mentioned above and more (yes, including the Microsoft XAML format). To vectorize images, Inkscape uses Potrace by Peter Selinger. Potrace (currently at version 1.8) can also be used as a standalone command-line application or API to transform bitmaps into vector graphics.

As an example of using Potrace and Inkscape to create a vector image, which will be saved as a XAML file (although the other vector formats might just as well have been used), the logo and mascot of Potrace will be used, which is available as a PNG bitmap image. (The logo is licensed under GPL.) After opening the source bitmap in Inkscape, you can use the Path | Trace Bitmap menu to vectorize your image, as illustrated in the screenshot below. (Make sure you have the image selected, or else it won’t work.)

Potrace logo in Inkscape with Path | Trace Bitmap menu for vectorization.

When tracing a color bitmap, one of the available options is to remove the background, but, for this image, both the background and the mascot’s eyes are white, which would result in the eyes also being removed. Therefore, you might sometimes first want to edit the original bitmap in an application like Paint.NET (which is another free image and photo editing program, similar to Adobe Photoshop, Corel Paint Shop Pro, Microsoft Photo Editor, and GIMP) and change the color of such regions before the vector trace. However, to keep the current example simple, we leave it as is for now. Since this is a color image, we select Colors, disable the Smooth option (which would just blur the image), then enable Remove Background and choose 7 Scans; usually you just play around with the last number while hitting the Update button until you’re happy with the Preview. The dialog box with selected values for this example is shown below. To get a better understanding of the Options values, such the Size of speckles (turdsize), the Threshold for smooth corners (alphamax) and the Tolerance of path optimization (opttolerance), you can refer to the technical documentation of the Potrace library API (see the “tracing parameters” section in particular).

Mode values on Trace Bitmap dialog for Potrace logo in Inkscape.

Options values on Trace Bitmap dialog for Potrace logo in Inkscape.

By clicking the OK button on Inkscape’s Trace Bitmap dialog box, Potrace is invoked and a vector image is created on top of the bitmap background. You can now remove the original bitmap image, for example, using the Edit | Invert Selection menu (since the vector image would be selected after creation) followed by Edit | Cut. Then save the vector image, for example as a XAML file, from the File | Save As menu, enter a new filename and select XAML for the file type. If you were to zoom in on the original bitmap image and compare it with a corresponding region of the new vector image, you would notice that the vector image is much smoother at higher resolutions; this is illustrated by the two screenshots below.

Zoomed region of the original bitmap Potrace logo in Inkscape showing individual pixels as blocks.

Zoomed region of the converted XAML vector Potrace logo in Inkscape showing smoothly interpolated vector lines and no individual blocks of pixels.

The XAML code produced by Inkscape looks something like the following:

<?xml version="1.0" encoding="UTF-8"?>
<Canvas Name="svg2440" Width="468" Height="508"
<Canvas Name="g2493">
<Path xmlns:x=""
Name="path2505" Fill="#A8A8A8"
Data="M 131 480.5 L 131 477 L 124 477 L 117 477 L 117 463.5
L 117 450 L 120.5 450 C 123.83333 450 124 449.83333 124
446.5 L 124 443 L 134 443 L 144 443 L 144 439.5 ...
C 363.96712 116 362.37172 115.38726 359.55909 112.91773 z"
<!-- more Path elements -->

The bulk of the XAML file is generally the Data attribute values of the Path elements, which describe the path segments and coordinates that have been serialized using Path Markup Syntax. This data are probably exactly what is returned by Potrace, which are line segments consisting of cubic Bezier curves and pairs of straight lines (what Potrace calls “corner segments”). The XAML can now easily be used in your Silverlight or WPF applications. It is also relatively easy to parse the path data into the fundamental segments (for example, using Geometry.Parse to convert from Path Markup Syntax strings, or XamlReader.Load or XamlReader.Parse to convert all the XAML at once) and use the path coordinates in other vector-based applications (for example, as vertex data in DirectX or XNA graphics).

Also distributed with Potrace is a program called mkbitmap, which “can be used to pre-process the input for better tracing behavior on grayscale and color images” – this is handy for adding dark outlines to images that are not just black-and-white. Since not all converted color images show the black outlines as clearly as the present mascot example, you might have to create two XAML images and combine them; for example, you may need to create one image for the color areas displayed as backgrounds, and another single-scan image for the black lines (which you may first need to pre-process manually in Paint.NET or using the mkbitmap utility to produce a source image containing only the black outlines to be vectorized). The combinations of the various techniques to create vector images are quite powerful once you start to realize what your different options are.


Conversion to XAML

This is strange: I have repeatedly tried to have InkScape produce valid XAML (i.e. XAML that can be loaded by a .NET 3.0 application as Canvas) but every time it failed. I get various error messages when my application tries to load it.
Fortunately, this is no longer much of a problem for me because I have now written a PDF to XAML converter (based on PDFRenderer) that works great for me (for a short description of it, see my blog) [in particular, see the posts “From PDF to XAML .. and back again”, “How to vectorize raster images” and “More about color separation”].
Since InkScape can also generate PDFs (through export via Cairo), I can convert the same formats to XAML (however: this time it is XAML that my application can load).
One downside of using bitmap tracing to get a vector drawing is that the resulting XAML can get very large. This is especially a problem for my particular application, which is a shared whiteboard that I use for online math-tutoring: I have PDFs, generated by TeX and friends, that may contain large amounts of text and formulas. Already bitmap tracing would be a problem, because it would not produce very sharp text and formulas, but the worst problem that the XAML resulting from one A4 page can easily be several megabytes that my shared whiteboard would have to transmit over the internet....
Now, with my own PDF to XAML converter, I can convert PDFs that I produce with LaTeX (containing text, formulas, and drawings) to valid and rather compact XAML on the command-line.

Hope to see the code

@Christian: It is good to know about alternative techniques to generate XAML. Let me know when you make the code available for others to follow your approach.

Runtime downloadable from my website

I have made the runtime version, PdfToXamlPaths.jar, of the converter that produces paths only available at the download section of my website. It is wrapped in the zip file together with two libraries that it requires (batik-awt-util.jar and PDFRenderer.jar).

Licensing and usage information: see the README.TXT file that is included. [non-commercial use only]

Note that my website is primarily in German, but you can switch to an English version (see upper right corner).

As I wrote, I have not been able to get InkScape to produce XAML that I could load with the .NET Framework 3.0 version of XamlReader.Load(). It should be possible to have InkScape export a drawing as PDF and then use my converter to convert it to a form of XAML that one can load with XamlReader.Load().

As I wrote in my first comment to your article I have another converter that generates much more compact XAML, but that depends on strong assumptions about the loading application and that requires a somewhat extensive modification of the PDFRenderer library: that's why I am not distributing this other converter.