Tutorial: Kaleidoscopic Reflections With GIMP

This is a short tutorial on creating kaleidoscopic reflections using The GIMP. The main text of the tutorial shows how to do a 16-fold reflection. Following that, there is a brief explanation of how to do a 12-fold refleciton. Finally, there is a C++ program that can be used to make arbitrary (2n)-fold reflections (for integer n greater than one) of binary PPM images.

16-fold reflections

Original image

Start by opening the image you want to mirror. You should pick an image with interesting colors or identifiable small features. In this case, the eye is a small feature and the green-brown-orange color scheme is pleasing.

Next, crop out a square portion of the image. You probably want an area which contains the interesting features and colors but not too much of any one of them. Technically, you don't have to work with a square area, but it's much, much easier if you do.


Use the width/height settings on the Crop Dialog box to make sure that you have a square.

Create a new layer in the foreground color. Make the new layer twice the size of the old layer. In this case, since we cropped the image to 800x800, we make the new layer 1600x1600.

Then, duplicate the 'New Layer'.

New Layer
Rotate -45

Rotate the 'New Layer' (not the copy) -45.00 degrees. Use the rotation dialog box to get exactly -45.00 degrees and to center the rotation at (0,0).

Rotate the 'New Layer copy' -22.50 degrees centered at (0,0).

Select 'Alpha To Selection' from the 'New Layer copy' in the Layers dialog box.

Invert the selection.

Delete the 'New Layer copy'.

Cut (Ctrl+X) the inverted selection from the 'New Layer'. Then, do 'Layer to Image Size' on the 'New Layer'. And, set the opacity of the 'New Layer' to 50%.

At this point, you may wish to play around a bit to get something prettier under the black section. For my purposes, I'm just going to rotate the 'Background' that I have 90-degrees clockwise.

You should now have something like this.

You may prefer to copy in the original full-sized image to get exactly what you want under the triangle. If you do, make sure you do a 'Layer to Image Size' and merge it with the 'Background' layer or the rest of this tutorial is going to be confusing.... 8^)

Mirroring area
Add Layer mask

Do 'Alpha To Selection' on 'New Layer'.

Now, do 'Add Layer Mask' on the 'Background' initializing it to 'Selection'.

Clear the selection (Ctrl+Shift+A). Delete the 'New Layer'. Apply the layer mask. This is our wedge.

For good measure, do 'Layer to Image Size'. We're going to start rotating and reflecting things and we want to be sure of exactly what we're moving.

Rotate 'Background copy' 45-degrees centered at (0,0).

Merge the layers together. Again, do 'Layer to Image Size' just to be safe. You should now have one layer which contains two copies of the wedge that had been under our triangle. There should be two empty wedges in the picture, too.

Two copies of our wedge
Two copies of our dual wedge

Duplicate the layer. Rotate the copy 90-degrees clockwise. This looks kinda funky, but we'll fix it in a moment.

Mirror the copy horizontally. Merge the layers. Do 'Layer to Image Size' just to be safe.

At this point, there are probably some gaps along the seams. The most obvious gap here is the diagonal line in the upper-left. We're going to fix that by duplicating the layer, merging the duplicate onto a neutral background, blurring the merged duplicate, putting that blurred version below this layer, and then flattening the image.

Rough tile
Filler layer

Duplicate the layer.

Between the two layers, make a grey layer. You can do this by setting the foreground color to grey and creating a layer initialized to the 'Foreground color'. Or, you can make a layer however you like, select it all, and fill it with a grey. It doesn't matter.

Merge the copy and the grey layer. Blur it... say maybe a Gaussian of radius 5.

Move the 'New Layer copy' down below the 'Background' layer. Then, flatten the image using 'Flatten Image' from the 'Image' menu.

Now, we just have to mirror this four times to get our 16-fold symmetry.

Final tile
Scale down

Scale the image down by a factor of two in each direction. Our image is 800x800, so we're going to make it down to 400x400. I've selected 'Cubic' scaling because that's almost always the best thing to do. It certainly is the best for this image.

To make things easier below, we're going to rotate the image 180-degrees. We're going to resize our canvas and we're going to want this tile to be at the upper-left of the larger canvas.

Now, resize the canvas back up to twice its current size. We had scaled down to 400x400, so we're going to make the canvas 800x800. And, we want to leave the offset at (0,0).

If we were feeling cunning, we could have skipped the 180-degree rotation and offset by (400,400) and still be fine. But, I usually prefer to keep to a minimum the number of times that I have to actually know the image size.

Half done

Duplicate the layer. Do 'Layer to Image Size' on the duplicate. Then, mirror the layer horizontally.

Now, merge the layers together.

If you don't do the 'Layer to Image Size' here, you will end up with both layers in the same spot in the upper-left corner.

Again, duplicate the layer. Do 'Layer to Image Size' on the copy. Now, mirror the copy vertically.

Now, flatten the image.

16-fold Goose

This is the final image. In this case, things worked out okay for us. But, for more complicated angles or small pictures, you may find that there are problems at the edges during the final mirrorings here. You may find it useful to hold off on the whole "duplicate, merge with neutral layer, blur, move blur to bottom, flatten image" process until the very end. That way, all of the seams get filled with very close to the right thing.

For more fun, repeat the process another time or two. You may also like to use 'Offset' in the 'Layer' menu to offset the layer, with wrap around, by (x/2,y/2) before starting the next mirroring pass. (Or, just skip the 180-degree rotation after the scaling.)

16-fold twice Goose
16-fold thrice Goose

Here is the image after three 16-fold mirroring passes without offsetting the image at all. You can get pretty quick with the process after only a few passes. So, enjoy.

Because this looks like ugly linoleum, I scaled them down to 200x200, bevelled them, and then tiled them. Here is the best of those. Your mileage may vary. Have fun. I hope this tutorial was helpful.

Goose floor tiles

12-fold reflections

6-fold Hannah

To make a 12-fold refleciton, I did the same basic thing as above.

Instead of -45.00 and -22.50, I used the angles -30.00 and +30.00 to create my wedge shape using the 'New Layer' and 'New Layer copy'.

I duplicated the wedge, rotated it clockwise 90-degrees, then mirrored it horizontally. Then, I duplicated the duplicate. I rotated one copy +30.00 centered at (0,0) and rotated the other copy -30.00 centered at (0,0).

Then, I merged-visible, did the 'Layer to Image Size' thing, and picked up with the whole scaling-down-by-two, rotating by 180, resizing the canvas, dup, image-size, mirror, merge, dup, image-size, mirror, merge.

For this, it looked much better if I waited until the end to do the gap filling (dup, merge with neutral, blur, move to bottom, flatten).

A Quicker Way...

Being a computer programmer and wanting to experiment with a variety of reflections, I wasn't going to just sit down and do the whole above process over and over again. I wrote a program to do it. Here's the C++ source code. (My usual license applies.)

It takes a (comment-free) binary PPM image on standard input and emits one on standard output. The output image will be roughly the same size as the input image (exactly the same size if both width and height are even). The first thing the program does is scale down the input by a factor of two. If you don't want this effect, then (nearest-neighbor) scale it up by a factor of two before sending it to the program.

You should probably use a square input image. You're on your own if you don't.

It recognizes these command-line arguments:

-n ###
Here, '###' is the half the number of reflections and it must be at least two. In other words, for 12-fold kaleidoscoping, use -n 6.
This tells it to move the image so as to offset it by 1/2 the width and half the height. When you repeat the same kaleidoscoping action a few times in succession, you can end up with some more interesting patterns if you use the -m option on a few of the reflections.
When you're mirroring a wedge that's kite shape, like we are, the result isn't going to be rectangular (unless your kite is rectangular). This option tells the program to fit the result entirely within the output square. It does it naively. So, you may end up with more space than you wanted around the edges if your foldedness isn't divisible by four. *shrug*

I used the options -n 6 -m on an input image multiple times in succession to make the following sequence:

6-fold once Hannah
6-fold twice Hannah
6-fold thrice Hannah
6-fold fource(??) Hannah