Generative Art in Python

January 18, 2019 ยท 3 minute read

Generative art is a fascinating topic. Anything can happen with a few construction principles, and unlike production system, randomness is desirable. It is also an option for people who cannot draw to express a more creative side with a familiar toolbelt.

Python is probably not your best option

If you know javascript, p5 looks pretty amazing for example. Processing is an overall solid choice, and while it’s meant to be used with java there is also a python mode that appeared a couple versions ago.

Python is what I know best, so processing.py was my obvious first option. It is great, and a lot of things work out of the box. The community is good, and resources are available to get you oriented. The issue is: the IDE feels a bit clunky, and since I suspect some jython takes place in the background the number of importable libraries is limited.

Generative Art the rough way: pycairo

Since my primary objective was to throw random stuff at the math I use for work, I wanted to use libraries ranging from the obvious (numpy) to the arcane (shapely or dlib for example). I also wanted a “real” IDE; I sometimes use vim (with jedi) but pycharms is a robust editor. Surprisingly, pycairo is really the only viable option I found. Since I don’t really look at animations, I skipped the whole gtk install. The trade off is that pycairo is really, really low level, and that I need todo a lot of higher-level wrapping. Since the documentation I rely on is the sparce pycairo doc and an old zet tutorial. I figured I’d share some ideas here.

The rough guide

Cairo/pycairo seems fussy to install. I mostly got away with:

brew install cairo
brew install py2cairo
pip install pycairo

I also have an ubuntu install, and I believe I went for a simple sudo apt-get cairo or something like that. It seems however than the cffi step-in replacement is an easier option, and so somehting like sudo apt-get install python-cairocffi python3-cairocffi should work and expose the same(ish) api. One thing I would advise it to initialize a git repo so you can access your code from multiple machines, and a virtual environment (pycharms can actually manage that, but pipenv is my go-to virtual environment manager). If you don’t have a few years and/or python version under your belt, you will probably skip this step. Dont. Doing so inevitably leads to that:

relevant xkcd: python environment

One thing I didn’t get to work is the xcb surface, but I didn’t try very hard. My workflow is usually to create a svg or eps surface, and ‘finish’ it. Something like:

s = SVGSurface('{}.svg'.format(fil_nam), WIDTH, HEIGHT)
...
s.finish()

This way, I can use pycharm’s shortcuts ctr+r to rerun my code, and cmd+shift+] or cmd+shift+[ to navigate to the result. Good enough for me, and works across environment.

A rough template

After working my way around things, my current template roughly looks like that:

from cairo import Context, SVGSurface
import math
from math import pi

####
#General parameters
show = True
fil_nam = ""
####
# Image parameters
WIDTH = w = 3508
HEIGHT = h = 3508
bgd_color = (1,1,1)
#Functions

#Class


s = SVGSurface('{}.svg'.format(fil_nam), WIDTH, HEIGHT)
c = Context(s)


if __name__ == "__main__":



    s.write_to_png("{}_.png".format(fil_nam))
    s.finish()

This way, I can reuse functions and classes across projects with a simple from .file import cool_function, CoolClass

Suggested background music

Martha Van Straten plays great tunes. This is a powerful mix on the slower sides on things, perfect to get the creative juices flowing.