As reference, I used the Wikipedia page about the BMP file format. The code is released under a BSD license and is available for download here. It can make 24-bit colour bitmaps. It also contains some functions to manipulate colours. Bitmaps are created by calling a write-bmp function.

It was an interesting experience to work with binary streams, and I learned a lot. The code's not that nice, and probably not that efficient either, but it does what I want, which is output pictures.

One of the arguments to write-bmp is used to determine the colour of each pixel, and can be either a list of lists, or a function of two arguments. Here's a call that produces a twelve colour diagonal rainbow:

(write-bmp (path "bitmaps/diagonal-rainbow3.bmp") 80 80

#'(lambda (row col) (rainbow12 (/ (+ row col) 2))))

The function rainbow12 selects a colour based on the floor of it's input mod 12. The above call produces*:

Here's a fun example using MathP:

(write-bmp (path "bitmaps/picture-perfect.bmp") 80 80

#M(fn(r c)

{applR = 2.5

inRad(x y rad) = (c-x)^2 + (r-y)^2 < rad^2

if inRad(15 65 6) yellow; inner sun

if inRad(15 65 8) orange; outer sun

if inRad(48 55 applR) || inRad(65 45 applR) || inRad(52 40 applR) red

if (r-50)^2+(c-55)^2<15^2 darkgreen

if r<20+3*cos(c/10) green; grass

if 50<c<60 && r<50 brown blue}))

It produces*:

But since computers are good at calculations, let's try something a little more intense (and random, and ... psychedelic):

(write-bmp (path "bitmaps/trigonometric2.bmp")

360 300

#'(lambda (row col)

(rainbow12

#M{(row^1.1 + 0.6*col + 35*cos(col/15)*sin(row/16)

+ 2 * sqrt((row-250)^2 + (col-200)^2)

+ 20 * cos((col-0.3*row)/70) * (2-sin(row/80))

+ 20 * (1-cos(0.7+col/25)) * cos(0.6-row/50))/15})))

Viola*:

I hope your eyes aren't bleeding too much after that one. ;-)

I've also implemented some anti-aliasing, here's are some anti-aliased pictures:

The last one above is an attempt at creating a 'world' map with things like seas (blue), beaches (yellow), vegetation (green) and mountains (brown and white). The jump from vegetation to beach is sharp, but the anti-aliasing smooths it nicely.