Learning Python and being creative. Making art with code.

Kevin howbrook
Nov 14, 2017 · 5 min read

What do words look like as colours? What would Shakespear’s sonnets look like as colours? This mini project renders text as colours using Python and saves them in a grid as an image.

All titles of Shakespear’s sonnets

What is this?

It started as a bit of fun late one night on codepen, toying with ways to make images with code. In a really simple way, how can a colour represent a word? Easy… just convert a word to a colour code right?

As it turns out, it wasn’t so easy. Like most developers, I started looking for a JS library that already did this, wishful thinking as it’s not really that useful. I thought this from Charlie Coleman was pretty cool, but I was more interested in showing a more granular representation. A color for each word, no matter how many letters or words.

Why? And Why Python?

Like many developers I have met along the way, my degree wasn’t in a technical subject. In fact, it was Art. More specifically, sculpture and illustration, but, even though my career is in web development, I still have a creative practice. Code really is just another material to work with.

Why Python? Well, JavaScripts was good, but it was slow and getting slower. I heard python was really fast and I planned to be throwing hundreds of words at it.

Planning

After the Codepen version, I came to decide the following:

  • The colours created from the words should get the colour values using every letter, not just the first few.
  • The ‘canvas’ on which the colours sit should be adjustable, I should be able to print a huge image of a whole book, or a small image of my name.
  • The final rendering should be an image, not a web view.

An example: the letters ‘Abcd’ as a word

Given ‘Abcd’ each letter of the word is assigned a value to where it sits in the alphabet like this:

# position   0   1   2   3   4   5  ...
alphabet = ["a","b","c","d","e","f",...]

As RGB values only need 3 numbers, we use the remaining letters to increase the values of the numbers representing the first three letters. So…

  • Word is ‘Abcd’
  • Values are [0,1,2]
  • Remaining values are [3]
  • Add [3] to the first value (0).
Some small word examples

What happens with large words?

This is where it started to get tricky. I want all the letters in a word to affect the 3 RGB color values, leaving them out just seemed dodgy and not fair. So using a zip cycle, we can iterate and add the all values after the third letter accordingly, e.g.:

  • Word is ‘Abcdefghij’
  • Values are [0,1,2]
  • Remaining values are [3,4,5,6,7,8,9]
  • For each of the remaining values, go through the initial values and add them to the 3 RGB values one at a time so,
  • Remaining value 3 is added to val[0]
  • Remaining value 4 is added to val[1]
  • Remaining value 5 is added to val[2]
  • Remaining value 6 is added to val[0]
  • Remaining value 7 is added to val[1]
  • Etc

That zip cycle function saved me a lot of trouble:

for i, j in zip(cycle(range(len(colors))), additions):
colors[i] += j
colors[i] = int(colors[i])

There are also some other nice bits in the code to ensure the values don’t exceed [255,255,255], really it was just something that came up that needed some thought. You’ll notice that in the list above, the initial values could be small, like [0,1,2]. So they are multiplied by (255 /26) or (value limit/letters in alphabet). This gives a better base to add values to. [0,9.8,19.6].

As we start adding the leftover values, they are multiplied, to ensure we are don’t tip over 255, we divide by 26, for values above 3 but lower than 6. Then for words with more than 6 letters, they get really small values by dividing more. (x * n /26)(1/26). Here is that function:

Adding to the initial RGB values, getting smaller and smaller as the word grows

What about large text inputs?

I made the canvas size a variable, so if large texts are used, you can increase the canvas size… it really will process anything. Here is the King James Bible:

The King James Bible — In squares

Drawing, Plotting, and Some Note-taking.

Having the colours list ready was one part, plotting the squares and drawing was another. This is pretty easy on the web, there are libraries like Masonry that have been able to position things really well. But, I had not even googled a Python image drawing library before. I found one called Pillow that did the trick.

So why so many notes and working out? Well in the code at this point we have a list (potentially huge) of colour values, e.g.:

[[45,65,221],[36,187,35],[66,84,224]...]

This list needs to be looped over and a square drawn for each item using the values as colours. The hard part here was drawing the squares in a horizontal line and dropping down a row when we hit the end. But how do we know we are at the end? What size should the drop-down value be?

Here is how that’s done with 5 words as an example:

  • Given I know how many squares I have (5) I work out what ‘grid’ I will need. For example, 5 words would require a 3 x 3 grid.
  • Now I know each row and column will consist of three squares, and I have a canvas size of 1000. 1000 / 3 will be the width and height of each inner square. And also the amount of distance I need to shift my drawing points horizontally and vertically.
  • To find what ‘grid’ I need, I created a function (grid(n,m)) that takes the list of words and a list of squared numbers and works that out:
Calculating the grid

Finally, all that left is the most confusing iteration I have ever written:

Drawing the squares.

All in all, this started as a bit of fun, but I ended up learning a lot about Python and drawing with code (something I would love to do more of). One really nice feature is that the canvas can be huge and your squares a few millimetres. And thank you to my partner Ashley Burdett for helping me with the plotting math :)

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store