There are many ways to create pretty pictures on a computer, some more labour intensive than others. This article takes a look at the easy ways to generate eye candy.

We're not actually going to start with drawing DIKU, and we're not going to start with context free art, which will be explained later.

We'll start with a GUI!

Fractal flames

The Qosmic GUI

Qosmic is a program for easy creation of
flam3s which are
fractal images. Just modify a few triangles and their attributes to generate nice looking stuff.

A pretty flame

If you're very lazy, you can just click on Qosmic's magic wand

The Qosmic magic wand

which will generate a flame for you.

Another pretty flame

(Those flames were generated by repeatedly pressing the magic wand until something pretty was generated.)

Context free art

These flames may be cool, and the math is not that difficult -- but one still has to read the paper to understand how fractal flame generation really works and how the triangles in the GUI represent transformations. (Of course you can also generates flam3s without a GUI.)

So let's use something simpler.

"Context free art" is a term used by the image generator found at
www.contextfreeart.org to describe a language of context-free grammar rules which decide how images are drawn. The generator transforms a set of non-deterministic rules to pretty images. Its terminals include CIRCLE, SQUARE, TRIANGLE and paths. Let's look at a simple example:

# This is a comment.

# The first thing to draw is the shape 'simple'.
startshape simple

# This is the shape 'simple'.
shape simple {
  # Draw a triangle.
  TRIANGLE []

  # Draw the shape again, but with its x value offset by 1, with its size at
  # 99%, and rotated by 10 angles.  Do not draw it if it has reached a
  # sufficiently small size.
  simple [size .99 x 1 rotate 10]
}

which generates this image:

Simple 0

This is nice, but it can become nicer if we modify more attributes:

startshape simple

shape simple {
  # Draw a circle with saturation ('sat') set to 1 and brightness ('b') 
  # set to 1.
  CIRCLE [sat 1 b 1]

  # Draw it again like before, but with the hue ('h') value increased
  # by 20, and using shorthands for attributes.
  simple [s .99 x 1 r 10 h 20]
}

which generates this image:

Simple 1

Trees

Spirals are fine, but we can also draw more advanced figures, like a tree:

# Start with drawing 'tree' with start hue value 60 (yellow).
startshape tree [h 60 sat 1 b 1]

# Set the background color to black.
CF::Background = [b -1]

# A tree is a vertical line followed by two smaller trees at the end of the
# line.
shape tree {
  # Draw the line.
  line []

  # Branch 0: Rotate positively and increase hue value.
  tree [y 1 s .7 r 20 h 6]

  # Branch 1: Rotate negatively and decrease hue value.
  tree [y 1 s .7 r -20 h -6]
}

# A line is a path from (0, 0) to (0, 1).
path line {
  LINETO(0, 1)
  STROKE()[]
}

which generates this:

A tree

It looks a bit like a tree, but it's too rigid; it needs randomness. By writing x..y we make the generator choose a pseudo-random number between x and y.

# We'll make this tree green (hue 120) instead of yellow.
startshape tree [h 120 sat 1 b 1]

CF::Background = [b -1]

shape tree {
  line []

  tree [y 1 s .7 r 10..30 h 3..9]
  tree [y 1 s .7 r -30..-10 h -9..-3]
}

path line {
  LINETO(0, 1)
  STROKE()[]
}

A pseudo-random tree

That looks a bit more real.

Drawing DIKU

We have seen that the context free art generator can be used to create images whose shapes do not rely much on each other. Not all motives can be expressed in the language concisely; for example, to draw a pixel-perfect replica of a photograph, one would have to add a shape which draws 1 pixel for every pixel in the original image, unless there is a simple pixel pattern (which is very unlikely for a photograph) or lossy compression is allowed (and even then it's still hard).

One can always try to generalize a motive if focusing on the motive itself requires too many rules. Let's try that with DIKUs old logo:

DIKUs logo

To make rules for a superset of this logo, we need to make some observations about it:

  • Its line width varies but not drastically, though it does decrease a little as the lines approach the center.
  • Its line segments are almost straight.
  • There are 8 lines.
  • Each line is smoothly connected to the next line by an angle at about 90 degrees.
  • The lengths of the lines decrease as they approach the center.

I came up with this:

CF::Background = [b -.8]
startshape logo [sat 0 b 1]

# The shape 'logo' consists of three rules of different priorities.  When a
# 'logo' is to be drawn, the first rule is most likely to be chosen because of
# its much greater (implicit) priority compared to the other rules, and the
# second rule is more likely to be picked than the third.
shape logo
rule { # Priority: 1.0 - 0.04 - 0.0075 = 0.9525
  # Draw a square segment of an almost straight line.
  SQUARE []
  logo [x .5 s .89..1.1 r -2..2]
}
rule .04 { # Priority: 0.04
  SQUARE []
  # Draw a corner and continue with a new line.  The corner is composed of
  # 100 squares, each rotated 0.9 degrees and offset by 0.01 on their 
  # respective x axises.
  loop 100 [x .01 r .9] SQUARE [s .89..1.1]
  logo [r 90 x .66 y .66]
}
rule .0075 { # Priority: 0.0075
  # Empty rule.  Stop drawing.
}

When run, I get this:

DIKU logo 0

Hmm... Let's run it again:

DIKU logo 1

Again!

DIKU logo 2

That's a bit better. It's not the best lookalike, but it's probably close to the best one can do without adding many more rules and shapes.

More eye candy

A few lines of context free art code can create pretty pictures.

Feathers

The code

CF::Background = [sat 0 b -1]
startshape guardian [sat 1 b 1]

shape circle {
  # Draw 16 feathers with different hues and rotated around a center.
  loop 16 [h 22.5 r 22.5] feather []
}

shape feather {
  # Draw a feather of skewed (sheared) circles.
  CIRCLE []
  feather [s .9 x  2 skew -10..10 -10..10]
  feather [s .4 y  2 r 22.5]
  feather [s .4 y -2 r -22.5]
}

creates this:

Feathers

Shaded flowers

The code

CF::Background = [b -1]
startshape flower0 [sat 1 b 1]

shape flower0 {
  flower1 []
  flower0 [s .5 r 45]
}

shape flower1 {
  loop 30 [r 12 h -12] flower2 [x 1]
}

shape flower2 {
  TRIANGLE []
  flower2 [skew 0 .1 s .999 sat -.001]
}

creates this:

Shaded flower

Gallery

Many more pictures are available at their gallery.

Other tools

Electric Sheep helps make collaborative flam3s.

Mandelbulber generates 3D fractals.

Apophysis does the same as Qosmic, but on Windows.