16BPP.net
 
 
 
 
 

How Random Art Works

Header Image

This article was written for issue 1.10 of the Glitchet webzine.  Thanks to Way (@wayspurrchen) for editing.

Edit (Feb 1st, 2017): I originally had some misleading wording regarding who first made Random Art.  It was created by Andrej Bauer, not Adrian Perrig & Dawn Song.  Those last two people introduced it as a security measure in paper.

 

There has always been a question if a computer can art.  Sure, computers have been vital to the creative industries even before the boom of the 1980's.  But what about a man made algorithm?  A set of organized logic creating imaginative works.  A process from the left brain making a product of the right.  We call it procedurally generated art.  I don't want to get into things like Deep Dream or WolframTones as those are more artificial intelligence projects, but none the less still fascinating creative computing projects.

Have you ever heart of "Random Art," before?  It originally came about as a visual way to verify SSH keys.  Take a look at these two strings of characters: 584fbda552f44fe68ae13fd56d0cfcf3 and 584fbda552f44fe68ae18fd56d0cfcf3.  They look awfully similar, but there is a difference of one character.  Maybe one is just a typo of the other?  Who knows.  But here is what's important: they can produce two radically different ASCII Random Art images.  Here is what the first could make:

+-----------------+
|             .ooo|
|       o   ..o   |
|      o + .oo .  |
|     . + o....   |
|    +...S  ..    |
|       .o   .    |
|    .  o o ..    |
|   E . .o +      |
|      ......     |
+-----------------+

 

And the second:

+-----------------+
|      o.         |
|       + .       |
|      =   +      |
|     . = = .     |
|      + S + ...  |
|       + . *..E. |
|        o +.. .  |
|           .. .. |
|             . ..|
+-----------------+

 

Now, don't those look completely distinct?  Say if someone had to manually input a crypto key (the poor soul), this can be used to easily tell if it was punched in correctly or not.

I was introduced to Random Art by the website random-art.org.  I was really taken in by the whimsical renders.  It will ask you for a string of characters (which are used to seed the random number generator), and then will take some time to make a colourful picture (with JavaScript).  The source on that site was written in OCaml and is unfortunately not freely available.  Though there is a Python implementation whose source is up here.  From that, I've ported that program over to C++, C#, and Nim.

Random Art was originally developed by Andrej Bauer, but it's application for security purposes was introduced by Adrian Perrig & Dawn Song in this paper.  But in a nutshell here is what is it: that string of characters that we gave are used to seed a (pseudo) random number generator.  Then from there it generates a series of equations (in the form of a grammar for us Comp. Sci. people).  Over a coordinate system, the equation tree is run through.  It can either barf out chunks of ASCII text or puke out a rainbow of pixels; all depending on how you want it rendered.

Still don't understand?  Let's build up the parts from the ground up.  If you want to play around with Random Art, I'd recommend grabbing a copy of my Nim implementation (GitHub mirror).

Colours are represented as a decimal that ranges from [-1, 1], which then upon rendering is mapped to the range of [0, 255]. 

Greyscale values

 

Right now that really isn't colour; it's a greyscale value.  To, well, add colour we take three of these. Shoving them into a triplet, assigning them each a primary colour of red, green, and blue.

Colour Triplets

 

If a value goes beyond that [-1, 1] range, it will be clamped to it (e.g. -1.5 will become -1, whereas 2.5 becomes 1).

 

Now let us simply render a solid colour.  Using this small equation, we get a block of pink:Solid Color

(const 1 0.75 -0.4 0.9)

In my Nim implementation, I added a fourth channel (that first "1") which represents an alpha value.  It doesn't do much right now though.  Just bear with it right now.

Lovely isn't it?  No.  It's pretty boring.  The fun happens when we start to involve some actual math.  Random Art goes over a coordinate system.  Typically this is your XY Cartesian plane, though the Y axis has been flipped along the horizontal.  Both axes are usually bound between [-1, 1].

Random Art Coordinate System

 

With this grid, the top-left point becomes the top-leftmost pixel on the render, and likewise the bottom-right point is the bottom-rightmost pixel.  So if our render size is 256x256, here is the pixel location of the four corners:

X Y Xp Yp
-1 -1 0 0
 1 -1 255 0
-1  1 0 255
 1  1 255 255

 

Let's backup to greyscale for a little bit to keep things easy.  What's the first math operation we all learned to do?  Add.Add Render

(sum
    (var x)
    (var y)
)

So taking the X and Y location of where we are looking at, those values are added, and then put on the render.  If' you're a little confused, maybe this chart will help:

X Y Result RGB Whiteness
-1 -1 -2 0%
 1 -1 0 50%
-1  1 0 50%
 1  1 2 100%

 

 

 

 

 

Here is multiplication:Multiplication Render

(mul
    (var x)
    (var y)
)
X Y Result RGB Whiteness
-1 -1 1 100%
 1 -1 -1 0%
-1  1 -1 0%
 1  1 1 100%

 

So those are a little boring.  Here is something that's more interesting:Interesting Render

(mul
  (var y)
  (mod
    (sum
      (var x)
      (var y)
    )
    (const 1 0.7 -0.1 0.95)
  )
)

If you're wondering what that mod keyword is, that stands for a Modulo operation.  This is specifically using the one that is found in Python.  It can generate some pretty cool looking effects.

For you Comp. Sci. inclined people, you might have noticed that these equations resemble a tree structure.  For those of you who aren't one of us, this is how that last one would look as a tree:

Tree of the above equation

 


Writing these equations/trees out by hand is pretty tedious; that's why we let machines do it for us by using an algorithm.  It's actually a pretty simple one.  First I need to get some terminology out of the way:

Expression – This is something like (sum ...), (var x), etc.
Terminal – This is an expression that can't have any child expressions.  These are things like (var y),(const ...), etc.
Non-Terminal – This is an expression that needs to have children.  (mul ...), (sin ...), etc.

There can be many different ways we could generate a tree of expressions.  The one in the Python version (and my Nim one) uses a recursive one that is similar to this:

def generate(K):
  if K is less than one:
    randomly choose a terminal expression and return it
  else:
    let E = randomly chose a non-terminal expression
    let N = number of children E requires
    let cK = randomly generate (N - 1) numbers that are less than K

    for each J, which is a number in cK:
      E.children += generate(J)

    E.chilren += generate(K - N - 1)
    
    return E


Generating random numbers is its own topic which I don't want to get into.  I'll leave this link here as a place to start.

And... that's all there really is.  You could always use some other method that generates the tree.  Make it right dominant, left dominant, add new types of expressions (random-art.org has a lot more expressions in it), etc.  It's all up to what you want to do.


 

Random Art in Motion

I took this concept of Random Art and made it into a film.  I'm a guy who likes Animation.  While I though these images were cool, I wondered what they would look like when they were moving.  I was in a film workshop class last semester that focused on experimental cinema.  Here is the short I produced:

style="text-align:center">

I used the song "一人で [Power]" by " チェスマスター[chess master]", thanks to Dream Catalouge for letting me.

 

This was made using a distributed C# rendering framework (for Random Art) that I wrote;  as rendering each frame on a single computer would take a long, very long, time.  I added an extra t variable to the list of possible expressions and then had it render over a range (e.g. [-1, 1]).  My little "artists," running on a cloud service would then upload their renders to a central source.  I would then download those images and compile them into clips using FFmpeg.  From there I would cut up and edit the strips together in Blender.  Added music and then voilà, I had a film.