I’ve been getting so much enjoyment out of generating fractals using my HTML5 Canvas Fractal Flame Generator, and I’ve put a lot more work into updating it with new features. You now can introduce either rotational or mirror symmetries to your fractals. Also, one more non-linear variation has been added which can produce some very pretty swirls. The underlying affine maps are still randomized, but you have a little more control over how they are chosen.

Click on the image below or here to open up the new application, but be sure to read below for a description of the controls and also an important note about saving images in Google Chrome. (Also, be sure not to use the highest setting unless you are prepared to wait a couple of minutes for 500 million points to be computed!)

## Download

The complete code for all of the above examples can be downloaded here: ChaosGame2.zip

## About the application

This application generates fractals according to a simplified version of the Fractal Flame algorithm invented by Scott Draves, which is described carefully in this well written article by Draves and Erik Reckase. Most of the ideas behind my application are taken from this article but I’ve chosen to handle symmetry a little differently; see below for more details. The algorithm is based on iterating a set of affine transformations to move a point around the plane a very large number of times, then rendering an image which records all of the positions the point visited. Some non-linear transformations can also be introduced for more variety. See my earlier post for a little more discussion of affine transformations.

### Quick Start

If you want to avoid reading all the details below, you can click the **preset** buttons in the application which will choose some of my favorite parameter combinations, then click the **regenerate** button. But be sure to read the important section below on saving images in Google Chrome, which at the time of this writing is occasionally experiencing some crashes when dragging large images (which will cause you to lose your fractal forever). This can be avoided with the easy workaround desribed below.

Repeatedly generate fractals with one of the lower settings (**lots** or **lots and lots**). When you find a shape and/or color selection you like, check the appropriate locking buttons to fix the maps or colors. When you find a fractal that you want to see in a high quality render, select **browser-crashing points** (which shouldn’t actually crash your browser!) to see the result of 100 million plotted points, which takes about 15 seconds on my laptop in Chrome.

You will almost never need to use the **seriously don’t use this** setting, which generates 500 million points and which can take a couple minutes to complete. This high setting often will not produce a picture of higher quality than the next lowest setting; it should be used only when you’re really willing to wait.

I recommend using Chrome. In my testing all other browsers were slower. The renders produced by Opera are undesireable, probably due to a different way of handling the pixel arithmetic. Again, be sure to read below about saving images in Chrome.

### The Affine Transformations

In short, an affine transformation of the plane can be defined by four properties: rotation, skewing, scaling, and translation. I’ve updated the application to give you a little more control over the range of values for each of these properties. Also, there is checkbox labeled **preserve aspect ratio**; when selected, scaling in the x and y directions will be the same (before skewing).

Sometimes the nicest, cleanest looking fractals are generated with only two or three affine maps. There is a ** fewer maps** checkbox to limit the number of maps (otherwise, there may be as many as six maps used).

### Symmetries

Both rotational and dihedral (mirror) symmetries can be introduced. For rotational symmetry, check the **rotational symmetry** checkbox, and type in a value for the symmetry. For example, a value of three will create a fractal which is symmetric with respect to rotation by 120 degrees.

Rotational and dihedral symmetries are actually affine maps, but they have to be included in a particular way to ensure that the coloring of the fractal will also be symmetric. I have chosen to handle this a little differently than as described in the article by Draves and Reckase; see below for more details.

### Non-linearity

The Fractal Flame algorithm is based on the classic Chaos Game algorithm. The Chaos Game is based on iterating a collection of affine maps; the Fractal Flame algorithm introduces some non-linear maps for greater variety. Draves and Reckase list a large number of interesting non-linear maps in their article, but I have chosen to implement only two of them: the **bubble** and **swirl** maps. (Note that I have changed the bubble map a little since the last version, to make it a little more bubbly).

The way the non-linear maps are applied in the Fractal Flame algorithm is a rather technical issue. Although Draves and Reckase describe a way to use multiple variation functions, I have chosen to apply these non-linear maps equally to all of the affine transformations. If you select both the bubble and swirl transformations, their composite will be applied.

### Colors

Each affine map used to generate the fractal has a color associated to it, and because of averaging, more recently applied transformations will have a more significant effect on the current color. These colors are selected at random. The **brighten** checkbox will push the RGB color components up so that the highest one will go to 100%. The **pastels** setting will select colors where all components are high. A brighter display overall can be made by using the **high gamma** setting, but often this setting can reduce the apparent complexity of the image.

### Fixing the maps

Checking **fix these base maps** will only fix the underlying affine transformations. You can then add or remove symmetries or non-linear transformations to these basic maps. It is interesting to see the effect of including symmetries, which does not work in the way you may expect: adding a rotational symmetry does more than simply painting rotated copies of the current image. Instead, the inclusion of the rotational symmetries can have a spreading effect.

### Saving Images in Chrome

To save an image from any browser, click on the **export image** button, which will open up a large saveable image in a new window. You should then be able to right-click on the image and save it to your machine.

The image is generated with JavaScript using the toDataURL() method, and when the image is large Chrome can misbehave (as of version 20). First, when you right-click and select “save as…” it can take a very long time for the saving dialog to appear, and it may seem that it will never appear. If you *drag* the image to a folder, this will happen instantly; however, this can result in a crash if the image is too large in file size.

Here is the workaround: first right-click on the image to see if “save as” is available; it may be grayed out. If “save as” is available, Chrome will not crash when you drag the image. If “save as” is grayed out, Chrome should still offer you the option to “copy image”. If you drag this image, Chrome will crash. Instead, copy the image and paste it into an image editor such as Photoshop or Gimp, then save the image from your image editor.

This annoyance is worth the effort, because Chrome seems to be the fastest at rendering the fractals!

### Implementing symmetries

This brief note is only for those interested in some of the mathematical details. In the article by Draves and Reckase, they suggest introducing rotational symmetry by adding the rotational transformations to the set of affine maps, being sure to include rotations by all appropriate amounts and statistically wieghing them properly. But although I tried their method I was unsuccessful in producing images with perfectly symmetric color densities.

I decided to take an alternate approach. I introduce symmetries by taking the basic affine maps and extending them by *conjugating* each of them with each of the symmetric transformations. The conjugate of a map A by another map B is the composite BAB^(-1), where B^(-1) represents the inverse of the map B. When B is a rotation, the conjugate BAB^(-1) can be decribed as having the same effect as the map A, but rotated according to B.

Here is an example: Suppose A is the map which shrinks the square down by a factor of 1/2 and shifts it to the upper right corner. Also, suppose B is the map which rotates the square by 180 degrees. Then the conjugate BAB^(-1) has the effect of shrinking the square down by a factor of 1/2 and shifting it to the lower left corner.

The net effect of including all the symmetric conjugates of the basic affine maps is to build a collection of maps which act on the space in a symmetric way.

### Have fun!

I put together a flickr set with some of the images generated with the older version of this application. I’m sure I’ll be uploading more images to flickr, because I continue to be fascinated by the pictures this algorithm can produce. If you generate your own images, I’d love to see your favorites posted on-line somewhere!