Would you like to learn about the distortion process involved in creating a tiny planet? Are you interested in how I coded the distortion in Matlab? Click through to learn how the pixels in a tiny planet stretch and watch an animation.
Quick note before you begin: this is a very technical post, I have highlighted the more technical aspects in blue so feel free to skip those if the topic interests you and want to learn about it without all the hasstle of the maths! If you’re only interested in a couple of equations but not many check out the ones highlighted in orange, they are the most relevant :)
As you might already know, a tiny planet turns an photograph into it’s own little world. They are super easy to make using Photoshop, and can even be coded in languajes such as Matlab (my choice), Python, or C#. In this post I am going to explain how to calculate the tiny planet distortion in a gradual way. The final product is essentially a change from rectangular to polar coordinates, but the intermediate steps in the gradual distortion are a mixture of both.
In the following animation you can see an image of the Sydney Opera House (100 x 100 pixels) being gradually distorted into a tiny planet. Notice how at the end of the distortion process the pixels are not evenly distributed along the image. There are many more pixels in the centre of the tiny planet than in the edges. In an image file (such as JPG, PNG, TIF…) all pixels must be evenly spaced along the image, in a grid. This means that the result of the tiny planet distortion will have to be averaged and interpolated after the distortion takes place. This is why creating tiny planets in Photoshop is a technique that is very destructive for the image pixels (not to mention that Photoshop has to “invent” all the pixels that fall outside of the final circle to complete the square).
There are several ways to tackle the problem of coding the gradual tiny planet distortion. In this post I am going to calculate the new location of each original pixel in the image for a given ammount of distortion. I will then individually plot all the pixels with their original colour at their new location. (I will be using grayscale to deal with just 1 number instead of the 3 that would be associated to an RGB colour JPG). I found that this way of calculating the distortion is the most intuitive for me, but plotting each pixel one at a time was very demanding on my computer!! There are ways to speed up the calculation and plotting time, but I will leave those for a future post :)
In the following diagram I have illustrated several steps in the gradual distortion of the tiny planet. If we measure the level of distortion as going from 0% (original undistorted image) to 100% (round tiny planet) you can see that for increasing level of distortion the bottom corners of the image move towards the centre and the upper corners move outwards and will eventually join at the bottom to complete the circle.
I am going to characterise the amount of distortion of the image with the parameter t. This parameter will go from 0 (for 0% distortion – original image) to 1 (for 100% distortion – tiny planet). I chose the letter t because it represents in some sense the “time” it takes for the image to turn into a tiny planet in my animation. For each level of distortion t we will have an angle alpha (that squiggly “a” you see in the diagram above is the greek letter alpha). Alpha is the angle of the right edge of the image with respect to the horizontal axis.
Alpha will start at 90 degrees (pi/2 radians) (for 0% distortion – original image) and finish at -90 degrees (pi/2 radians) (for 100% distortion – tiny planet). Summarising:
I want to make the change in alpha linear with t, so for a certain amount of distortion, the angle alpha associated with it will be:
Using this relationship we can see that for the start and end of the distortion we obtain the desired angles:
The next step is to calculate, for a certain distortion t, what is the new location of the corners of the original image. The new position of the bottom right corner xBR goes from x0+X for t = 0 (original) to xo+X/2 (the middle) for t = 1 (tiny planet). Again we want the relationship to be linear, thus:
Where x0 is the bottom right corner of the original image and X is the width of the original image. Similarly, the new position of the bottom left corner xBL goes from x0 for t = 0 (original) to xo+X/2 (the middle) for t = 1 (tiny planet). Again we want the relationship to be linear, thus:
It is important to note that in the way I have decided to calculate the distortion, the central area (shaded orange in the diagram above) remains undistorted and the pixels are in the same location as in the original image. The only areas that are distorted are the sides of the image, the larger the distortion the larger these side areas will be and the more pixels that will have moved to a new location.
Lets look now at the top-right corner. In order to calculate its new location we are going to use triangle number (1) in the diagram below. Using some basic trigonometry we can see that:
Hence, rearranging we obtain:
Where xTR is the x coordinate of the new location of the top right corner of the distorted image, and Xs is the projected “length” of the right edge of the distorted image (see diagram above).
Each pixel on the top edge that is not part of the shaded area will spread out all the way from the top to xTR.
Say there are 12 pixels there, their locations will have an angle alpha_R that ranges from 90 degrees to alpha (which depends on the ammount of distortion we are calculating at the moment). Hence in Matlab we will write:
alpha_R = linspace(pi()/2, alpha, size(col_R,2));
Where “size(col_R,2)” is the number of pixels that have to be displaced on the right side (that are not in the central area shaded orange). This creates an array of alpha_R which go linearly from pi/2 rad = 90 deg to alpha (which, as we saw above, depends on the level of distortion).
For example: say we have an image of 100 x 100 pixles and 25% distortion:
Based on the first hightlighted formula above:
If we consider the origin of coordinates to be the bottom left corner we get that: (x0, y0) = (0,0). Since we have 100 pixels on each side we can consider that X = Y = 100. Hence the bottom right corner of the distorted image will be (according to the second highlighted formula above):
This means that we will have 100 – 87.5 = 12.5 horizontal pixels that get distorted on the right side (we will make it 12 since we can’t have “half pixels”).
So: size(col_R,2) = 12 (see Matlab code at the end for a more detailed calculation). We then tell Matlab to calculate alpha_R in linear steps starting at 90 degrees, finishing at 45 degrees, and having a total of 12 numbers:
alpha_R = linspace(90, 45, 12);
alpha_R = [90.0000, 85.9091, 81.8182, 77.7273, 73.6364, 69.5455, 65.4545, 61.3636, 57.2727, 53.1818, 49.0909, 45.0000]
Each of these distorted pixels (12 in the example above) will have the new coordinates (xT, yT).
We will calculate these now using triangle number (2) in the diagram below. Using some basic trigonometry we can see that:
Because yTR = y0, as we can see in the diagram above. Hence, rearranging we obtain:
Now that we know the new position of the distorted pixels of the top edge we repeat this calculation for pixels at other heights (they will just have a different Y value). And then we apply the same process (but mirrored) to the left side of the image. I will not elaborate on all this here so as not to make the post too long, but if you are interested feel free have a look at the Matlab code attached at the end of this post, you will be able to see the whole process from start to finish.
I hope this post has proved a little bit enlightening. It has taken me a lot of work to put together and I’ve loved every second of it!! There have been many hours of figuring out the coding and many hours of making it somewhat understandable (hopefully!) with equations and diagrams. If you know of any books or websites that perform a similar calculation to what I have explained here please let me know, I am very interested in finding out alternative calculations and explanations.
If your brain is now too full of information and equations feel free to spend some time relaxing those neurons by checking out the pretty Tiny Planet creations on my photography portfolio. I even have a Tiny Planets photobook available for purchase, maybe some one you know would enjoy it as a Christmas gift! :)
Thank you for reading!
xx Ana :)
Ps. Here is the MATLAB code and a sample image to try it out with.
If you have Matlab installed on your computer you should be able to paste this into a new file and it should be ready to run and automatically work (fingers crossed). Remember to downsize your image to 100 x 100 pixels max beforehand or your computer will take forever to execute the code (seriously). I am working on making it faster, but that will have to wait for a future post :)
The code will generate one image for each distortion value specified. So if you make distortion from 0% to 100% in steps of 10% (default values) you will get 11 files for distortions of: 0%, 10%, 20%, 30%, 40%, 50%, 60%, 70%. 80%, 90%, and 100%. This will take some time, be patient.
The images will be saved (if you click yes) both as .fig and .bmp files. The automatially saved .bmp files look a bit off in the colours but if you manually save the .fig files as .png they should look better (a bit weird, I know, I’m working on it). You can then turn the images into a GIF animation online, in Photoshop or even in Matlab too.