Rainbow Labyrinths


This started when a friend of mine, who is into the spiritual aspects of labyrinths, asked me about how to consistently resize a Cretan Labyrinth to fit a garden for a party. Thinking about that I realised that the path of a basic Cretan design could be minimally drawn on a 16x16 grid and I was needing a 16x16 pixel icon for my website (websites don't need favicons but many web browsers try to download a 'favicon' when they display a page giving spurious server log errors). As the 16x16 grid did not include the walls between neighbouring paths, I needed some other way to distinguish them. As there would be 256 cells and such icons can have 256 grey levels, I thought that a path progressing from black to white through the greys would do. Not wanting to have to draw that manually with all the shades correct, I wrote a program to do it for me. Unfortunately the result looked like a boring square splodge; it was too complicated to be recognisable without an explanation and too detailed to be clear at its small size.

However it looked as if would be good as a pure artwork if it were enlarged and the walls were included so I added wall rendering to the program and the result indeed looked good. Since then I have added several more features as I thought up more artistic effects including spectrum path fills, documentation, different path & wall widths, image series output for animations, HTML/Javascript animation output, reading a maze template from a file instead of hardcoded so non-Cretan labyrinths can be done, multiple cycles through the spectrum, monochrome path fills, starting hue changing, background colour changing, branching of fill (making it equivalent to a flood fill) so non-labyrinth mazes can be done, fill stop cells, multiple start cells & logging.

The Program

Download my Spectrum Fill program.

The program is written in Perl so it needs a Perl interpreter installed. Run it by opening a command terminal window, changing to the directory containing the program, typing "perl SpectrumFill.pl" & pressing 'Enter'. If you need more explanation, see my instructions for running Perl programs.

As I mainly made the program for my own infrequent use, I made it easy for the programmer to maintain (i.e. easy for me to add more features to) rather than to run quickly or be easy for a non-programmer user to use. Its known deficiencies include:

Input Format

The input is a maze template which is an image in ASCII PGM format. The templates on this site are in PNG format because PNG is much more highly compressed. To convert PNG to PGM, open the image in an image editing program (Gimp, Paintshop Pro, Photoshop, etc.) and save as type PGM with the option of 'ASCII' or 'uncompressed' selected not 'binary' or 'compressed'. Alternatively use an image file conversion utility such as Imagemagick (where the command is "convert -compress none <filename>.png <filename>.pgm").

The pixels of the template image define what each cell is:

The image must contain at least one start cell. It need not contain any stop cells. They are just lest one wants to determine the direction of propagation around a loop by blocking the undesired direction.

Preferably the path should be 1 pixel wide to get the cleanest colour fill. If it is desired to resize the path to a different width from the wall then all pixels with both x & y even must be walls or be surrounded on all four sides by path cells. (This is because whole rows & whole columns are resized together).

Output Format

If 'OutputType' is 'Static', the output is an image in ASCII PPM format. Convert it to PNG or whatever other format you want using an image editing or conversion program. I don't recommend keeping the images in PPM format or putting them on WWW because they are huge (e.g. the basic Cretan labyrinth was 2.5 KiB as PNG, 30 KiB as GIF, 460 KiB as BMP & 1.2 MiB as PPM!).

If 'OutputType' is 'Series', the output will be a series of such images with the path colouring progressing around the path.

If 'OutputType' is 'Javascript', the output will a HTML with embedded Javascript that draws the image as an HTML table and animates the path colouring progressing around the path by repeatedly changing the CSS values for the table cells.

Changing the Settings

Sorry but I have not implemented a way of changing the settings outside of the program. As I am usually rewriting extensions to the program as I am using it, the most convenient place for me to store the options was within the program itself. Hence open up the program file in a plain text editor (a plain text editor like Ultraedit, Kate, TextEdit, Jedit, Nedit, Gedit, Notepad, Nano, Emacs or Vim not a wordprocessor) and find the section looking like the following.

# Settings

my %Settings=(
# Output type: Static, Series or Javascript
# Colouring scheme: Spectrum, Monochrome or Greyscale
# Wall colour: 'R G B' in ASCII
'ColourWall'=>'0 0 0',
# Path colour: 'R G B' in ASCII
'ColourPath'=>'255 255 255',

The strings in quotation marks on the left each '=>' are the settings names and the value on the right of the '=>' is the corresponding value of the setting. The lines beginning with '#' are ignored by the computer when the program is run and are just there as reminders to human readers. Edit the values to as you want and save the modified program file.

Example Settings

To take take a template from 'Input.pgm', make the path 4 pixels wide and coloured with a single cycle through the spectrum starting from red, make the walls 12 pixels wide and coloured black and output into 'Output.ppm' whilst logging progress (comment lines omitted for brevity):

'ColourWall'=>'0 0 0',
'ColourPath'=>'255 255 255',

Settings: OutputType

String. Allowed values are 'Static', 'Series' and 'Javascript'.

It specifies what type of output to generate. The options are:

The 'Series' & 'Javascript' options are, of course, useless 'ColouringScheme' setting is 'Monochrome' as all the frames will be the same.

Settings: ColouringScheme

String. Allowed values are 'Spectrum, 'Greyscale' & 'Monochrome'.

It specifies how to colour the path. The options are:

It is irrelevant, of course, if the path width (specified by the 'PathWall' setting) is zero.

Settings: ColourWall

String of 3 decimal numbers separated by whitespace. The numbers are respectively the red, green & blue components of the colour. Each number is in the range 0 to 255 inclusive.

It is the colour to use for the wall/background of the maze.

It is irrelevant, of course, if the wall width (specified by the 'WidthWall' setting) is zero.

Settings: ColourPath

String of 3 decimal numbers separated by whitespace. The numbers are respectively the red, green & blue components of the colour. Each number is in the range 0 to 255 inclusive.

It is the colour to use for the path of the maze when coloured in Monochrome mode.

It is irrelevant if the 'ColouringScheme' setting is not 'Monochrome' or if the path width (specified by the 'WidthPath' setting) is zero.

Settings: StartOffset

Floating point number. 0 to 1 inclusive.

How far into the cycle (0 = beginning, 1 = end) to start the colouring cycle. In the 'Spectrum' colouring scheme, it is the hue offset. In the 'Greyscale' colouring scheme, it is the brightness offset.

It is irrelevant if the 'ColouringScheme' setting is 'Monochrome'.

Settings: NumberOfCycles

Integer number. 0 or above.

In the 'Spectrum' & 'Greyscale' colouring schemes, it is the number of times to cycle through the complete colour set between the start and the end of the path.

It is irrelevant if the 'ColouringScheme' setting is 'Monochrome'.

Settings: WidthPath

Integer number. 0 or above (but a value of 0 would be silly as it would merely produce a blank image of pure background colour).

It is the width to render the path in pixels for each pixel of width in the template. Allowed values are 0 and above.

Settings: WidthWall

Integer number. 0 or above.

It is the width to render the wall in pixels for each pixel of width in the template.

Settings: SeriesLength

Integer number. 1 or above.

It is the number of images will be produced with the cycles offset progressively through the range in an image series.

It is irrelevant if the 'OutputType' setting is not 'Series'.

Settings: AnimationStepPeriod

Integer number. 0 or above.

It is the time between animation frames for Javascript HTML animation in milliseconds.

It is irrelevant if the 'OutputType' setting is not 'Javascript'.

Settings: TemplateFileName


The path to the template file to use (don't include the '.pgm' file extension).

Settings: OutputFileName


The path to the file to output to (don't include the '.ppm' file extension). If the 'OutputType' setting is 'Series' then this will be suffixed with serial numbers.

Settings: Verbose

Number. 1 or 0.

If it is 0 then the program will not output progress messages.

Resizing Output Images

You can enlarge an image by an integer multiple by multiplying both the path & wall widths by the same factor in the program settings. Alternatively you could use an image editing program or image a conversion program (e.g. 'convert -scale <percentage>% <file-from> <file-to>' in Imagemagick) but remember to use a method that duplicates pixels rather than interpolating (hence the '-scale' instead of the more common '-geometry' in Imagemagick) to preserve the sharp edges. Similarly only use integer multiples to preserve the sharp edges and regular widths.

A method that does not work well is resizing in an HTML WWW page by increasing the 'WIDTH' & 'HEIGHT' attributes of the 'IMG' element. That would have had the advantage that the enlargement is done after transmission across the Internet so saving bandwidth & server space. Unfortunately there is no way in HTML of specifying how such an image is to be enlarged and some browsers may interpolate between the pixels instead of duplicating them (ironically it is the better web browsers that tend to do interpolation as interpolation is better for most images).

Making Animations: Movie Files

First create an image series by running the program with the 'OutputType' setting as 'Series' and the 'SeriesLength' as the number of frames desired then combine the resulting series of images an animation as frames. Animated GIF & MNG formats for the resulting movie will probably give clearer output than MPEG, MJPEG, QT, AVI or WMV as the former are optimised for lossless compression of frames with areas of block colour whereas the latter are optimised for lossy compression of natural texture patterns. MNG is a successor to animated GIF with substantially better lossless compression & without the 256 colour limit but still unfortunately without built-in support in most web browsers.

There are many programs available for combining individual images into MNG or animated GIF. I used Imagemagick ('convert -delay <interframe-spacing-in-10-ms-units> -loop 0 <OutputFileName>*.ppm <animation-filename>.<gif-or-mng>').

Making Animations: HTML & Javascript

Run the program with the 'OutputType' setting as 'Javascript', the 'SeriesLength' as the number of frames desired and the 'AnimationStepPeriod' as the desired period between frames. The output HTML should work in a web browser supporting HTML version 4, CSS version 2, Javascript and Dynamic HTML. All the popular browsers support those present (M$ Internet Explorer 6 was, as normal with IE, much slower than Opera, Mozilla or Safari but I've added specific aids to the Javascript to help speed up damn IE by element Id pointer caching as IE's associative array look-up for that was absurdly slow).

The settings in the HTML for the period between frames, path width & wall width can be directly edited using a text editor without regenerating the file.

The image can be embedded into another HTML page by copying the Javascript section from the header of the output file into your page (you can separate out the Javascript function definitions into another file if you like, as I have done on this site), copying the ONLOAD='Animate(0);' into the BODY tag and copying the CreateGrid(); Javascript into the document body where you want the image to be.

I have been mainly using 50 ms for the animations on this site as all the common web browsers on all the typical PCs I have tried it on (the slowest being IE 6 on Win2k on a midrange 2003 PC) can cope with that speed for a basic Cretan labyrinth and it is just about fast enough to appear as motion not discrete frames.

Example Rainbow Labyrinths

For the pictures, go up to the Rainbow Labyrinth Gallery home page.