Saving the Processing screen as an SVG file

I have been falling behind on daily sketches, so yesterday’s sketch was super simple: circles bounce around the screen, and their velocity changes randomly every loop. If a circle has more than some threshold speed, it will spit out a new circle. To avoid the exponential growth and sudden explosion of my CPU I also made circles slowly die off (they’d get smaller and smaller until they disappear). Not terribly complicated, but it made some pretty nice looking figures:

This is pretty, and looking at it immediately gave me the urge to zoom in and see all the beautiful details implied by these little pixels. But of course, doing so gives you nothing but facepalms:

But the beauty wasn’t in the pixels; it was in the abstract form of the lines and ellipses – if I could save THAT information, instead of blocky 24-bit arbitrators of aliasing, then I could re-render the scene at any resolution I wanted, possibly in realtime! This realization almost immediately led to the next realization, that such ideas have already been implemented by the SVG vector format and Inkscape. I was also hopeful that perhaps Processing had already done some of the work, since PShape can load SVG files. Unfortunately, there wasn’t a way to just create a PShape, and even besides that there wasn’t any code to parse it back into XML.

If you look at PApplet’s source code, you’ll notice that a lot of methods call themselves on a “recorder” instance, e.g.

  public void rect(float a, float b, float c, float d) {
    if (recorder != null) recorder.rect(a, b, c, d);
    g.rect(a, b, c, d);

It turns out there’s an extremely undocumented feature in Processing (perhaps not public quality code yet) that lets you attach another PGraphics object to receive drawing commands whenever you make normal drawing commands in PApplet. You call “beginRecord(myPGraphicsInstance)” to hook myPGraphicsInstance into the sketch. There’s also a no-args method “beginRecord()” that returns a PShape object – there’s a commented out version with javadoc "Starts shape recording and returns the PShape object that will contain the geometry." so I’m sure the developers of Processing have plans to implement what I was looking for (right now calling beginRecord() will give an error message saying that the method isn’t supported yet).

Anyways, barring Processing’s own implementation, I wrote a very simple Scala object to receive drawing commands and append them to a DOM object. The code is here.
[EDIT 7-13-2011: The link should actually work now.]

Basically, your draw method will look like this:

override def draw() {
    if(recordFrame) {
      beginRecord(SVGOut) //hooks SVGOut to this PApplet
      SVGOut.begin() //call SVGOut.begin to initiate it.
    ... do all of your drawing
    if(recordFrame) {
      val out = SVGOut.end
      //out now contains the XML as a String object
      ... do something with the output (write it to a file, pipe it to another method, etc.)

After I had everything wired together, I saved the output as an svg file, opened it in Inkscape, and rendered it to my heart’s content :) I made a larger render (1024×1072) for the background of my website, and am considering doing a really huge render for printing (or maybe just for the lulz). While the program and graphics are too simple to warrant anything really cool, I can imagine that saving any scene in an SVG format could prove extremely useful for more complicated graphics.


2 Comments on “Saving the Processing screen as an SVG file”

  1. Matt says:

    It looks interesting !
    However, it seems that the link to the SVGOut.scala file is not available…
    Would it be possible to enable it ? Or maybe put the file somewhere else.
    Thank you !!

    • hellochar says:

      Hey Matt! Apologies, my website has moved since I wrote this article, and I must not have transfered this file over since I can’t find it. I’ll grab it from my local machine later today.

      Xiaohan Zhang

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s