A couple of days ago a friend posted this image on my wall on facebook. Apart from the possible stoned references this image looked incredibly interesting to create. So the question was: how do I create one? The answer was relatively simple and the code wasn't too complex to write. So lets start with the explanation shall we?
First of all lets look at the einstein pic without animations.
The animation is only 10 frames long but something looks odd from the pics. Lets convert a single frame into greyscale like this:
The border of the hair and the shirt look darker than expected. Upon closer examination I finally saw it. The image is photoshoped. The face, hair and shirt are inverted compared to the rest of the image. This doesnt needs to be done other than to give the final image more contrast. Now that we know about that detail lets keep going.
The image seems to be changing from one color to the other and then back. Going for example from black to white and then back to white. So to start the program we need a function that bounces from 0 to 1. Its important to notice that this function cant be simply a triangle.
This is a simple function defined in the interval [0,1] being x, (1,2] being 2-x and (2,3] being 2-x. The reason for the last interval will be evident in a bit more.
Now lets talk about how mathematica represents an image:
As you can see in a greyscale image the values are only a list of lists with values between 0 and 1.
The algorithm is simply this:
For each pixel in the image:
Add a value to each pixel. When it reaches above 1 subtract the value instead of adding and then when it reaches 0 start adding again.
So for example if we started with 0.75 and the value we add is 0.2 the 0.75 will change like this.
0.75, 0.95, 0.85, 0.65, 0.45, 0.25, 0.05, 0.15, 0.35, 0.55
To make the image a nice cycle the last value should be the previous value of the starting one. This means that we could for example use a value of 1 and the pixel would be white with a value of 1 and the changing values would go like this.
1, 0
The function outlined before does this exactly no matter the starting value and the constant that we add to it as long as its between 0 and 1(including).
The next function that we must write is one that given an initial value and the number of frames that we want returns a list like the one above.
Now there are only a couple of problems to tackle. when we apply that function to each value in the image we are going to end with lots of lists. But the problem with this is that each list shows the life of a pixel but we need the snapshot of each frame. That is we need the first element of each list for the first row on the image and this is only for the first frame.
We have this
{{0.1, 0.2, 0.3}, {0.4, 0.5, 0.6},{0.7, 0.8, 0.9}}
We want this
{{0.1, 0.4, 0.7},{0.2, 0.5, 0.8},{0.3, 0.6, 0.9}}
Therefore we need an interleave function.
Only two functions more and we are done.
With what we have so far we can create the images but only in greyscale. We want colors. Let me explain something about points in space. When you have two points and you want to create a line that joins them there is a simple way of doing this.
Lets suppose we have the point A and B.
A___________________B
To create a line that goes from A to B we can parametrize the line like this.
A + (B-A)t
When t is 0 we only have A, when t is 1 we get B but when t is 0.5 we get the middle point between A and B. Now this idea can be extended to points in any dimension. In our case points in 3D.
Now lets get back to the colors. A color in mathematica is a list with 3 values Red, Green and Blue. These are between 0 and 1.
{0.21, 0.412, 0.634}
To go from one color to another we use the parametrization above.
P1 = {A, B, C}
P2 = {D, E, F}
So the line that joins those two colors would be
{A, B, C} + {D-A, E-B, F-C}*t
We finally have the idea that gives a color between two arbitrary colors. YAY Now you may be wondering what will be t? t will be the original value in greyscale. We will get the image, and for each line and then for each value we will replace it by a list with the value given by the function above.
With all this we only need a function that creates the frames and colorizes them.
This could make an interesting picture but we want the gif. This last command solves the issue.









