Randomizing Color Fills for Imported SVG in Py Processing

The command line version Python mode for Processing is definitely a cool alternative to the Java syntax flavored version. My favorite aspect is the ability to write a python program in VI/VIM and run it from the command line immediately. I typically use an executable shell script named "r" with the following commands. Note: I'm on Mac OS, and I store the processing-py.jar in my HOME directory.

#!/bin/bash
java -jar $HOME/processing-py.jar sketch.py

External SVG Assets

Another awesome feature of Processing (non-language specific) is the ability to load various types of externally created assets into the program using the designated functions. For instance, you can load a compatible SVG file using the loadShape() function. Once loaded, the vector objects, now known as shape(s), can be manipulated in various ways such as transforming or modifying its colors. By default Processing will use the styles defined in the SVG file for the vector objects. If you want to manipulate the styles after loading into your sketch, you will have to use the .disableStyle() method on your loaded shape. The sketch file below will load SVG file and render the vector objects with their original style attributes.

def setup():
  size(640,480)
  global s
  s = loadShape("smiley.svg")
  noLoop()

def draw():
  shapeMode(CENTER)
  translate(width/2,height/2)
  shape(s,0,0)

Here is a screenshot of the resulting output showing the contents of the loaded SVG file and the smiley face consisting of several separate vector objects.

Screenshot of smiley.svg rendered in Processing without altering any attributes.

Changing the Shape's Fill Color

Let's say that you didn't want to use the original colors in the loaded shape from the SVG file. To do this you will need to tell Processing not to use the style attributes already associated with the vector objects, and this is done in several steps.

  1. Disable the original styles
  2. Assign fill attributes in Processing
The sketch code below shows the changes need to set the objects fill color to red.

def setup():
  size(640,480)
  global s
  s = loadShape("smiley.svg")
  # ------------------------------
  # Disable shape's original style
  s.disableStyle()
  # ------------------------------
  noLoop()

def draw():
  shapeMode(CENTER)
  translate(width/2,height/2)
  # ------------------------------
  # Set current fill to red
  fill(255,0,0)
  # ------------------------------
  shape(s,0,0)

In the next screenshot you'll notice that smiley is now all red and there is a black outline around all the elements now. Processing added a stroke attribute to the vector objects by default.

Smiley is now red with black outlines.

Monkeying with all the Vector Objects' Colors

There is a little more trickery that can be done to manipulate individual colors of the vector objects if desired, usually in combination with randomization. I have found that success using this technique is based on the "pristine-ness" of the SVG file itself. The SVG internal transforms can be problematic when attempting to display the elements in Processing. In other words, the resulting output (sizes, locations) may not appear the same in Processing as they do in the original vector editing/illustration program. For purposes of the journal entry I used Inkscape v0.92 on Mac.

def setup():
  size(640,480)
  global s
  s = loadShape('smiley.svg')
  noLoop()

def draw():
  colors = [
    color(255,255,0),
    color(0,255,255),
    color(255,0,255),
    color(0,0,255),
    color(111,222,68),
    color(88,88,117)
  ]

  shapeMode(CENTER)

  layer1 = s.getChild("layer1")
  for c in layer1.getChildren():
    rand_color = colors[int(floor(random(len(colors))))]
    c.setFill(rand_color)

  translate(width/2,height/2)

  shape(s,0,0)

The majority of the setup() in the code listing above is the same as in the previous two iterations. One thing to note is that there is no .disableStyle() method called here, since we're working on the "internals" so to speak. It is also helpful to know a bit about the construction of the SVG file itself. Inkscape provides a layer1 by default so I did not modify any of the layer attributes, and I created all Smiley's vector objects on this layer. It is import to know the "id" of the layer to get a reference to it in the code. Once you have a reference to the layer, you can iterate its elements and use .setFill() to change the color of the individual vector object. You call shape() once the previous step is completed and the shape is drawn to the Processing output window with the new randomized colors.

Smiley is now psychedelic! :)

COOL, HUH?

Cheers!