# Animated distortion gifs from a vector field and a scalar field

This short tutorial explains how to obtain this kind of effect on images with Processing : I advice to read the stripes tutorial first because this is kind of an extension to it.

This is the photograph we’ll work with : First of all let’s distort an image without animation. To do that we’ll use a vector field that indicates for each pixel of the resulting image which pixel from the original image to take. We’ll use a vector field based on Perlin noise :

```PVector vector_field(float x,float y){
float amount = 100;
float scale = 0.01;
return new PVector(amount*(noise(scale*x,scale*y)-0.5),4*amount*(noise(100+scale*x,scale*y)-0.5));
}
```

The “+100” is there to have independant noise values from the first calculated ones. The “-0.5” are there because noise values are centered on 0.5.

Here is the complete code achieve the static distortion :

```int numFrames = 25;

color[] result;
PImage img;

PVector vector_field(float x,float y){
float amount = 100;
float scale = 0.01;
return new PVector(amount*(noise(scale*x,scale*y)-0.5),4*amount*(noise(100+scale*x,scale*y)-0.5));
}

PVector distortion(float x,float y,float time){
PVector res = vector_field(x,y);
return res;
}

void setup() {
size(370,254);

result = new color[width*height];
}

void draw(){
// Time variable
float t = 1.0*(frameCount-1)%numFrames/numFrames;

image(img,0,0);

// Renders the pixels using the distortion field
for (int i=0; i<width; i++) {
for(int j=0;j<height;j++){
PVector res = distortion(i,j,t);

int ii = constrain(floor(i + res.x),0,width-1);
int jj = constrain(floor(j + res.y),0,height-1);

result[i + width*j] = pixels[ii + width*jj];
}
}
for (int i=0; i<width; i++) {
for(int j=0;j<height;j++){
pixels[i + width*j] = result[i + width*j];
}
}
updatePixels();

// Saves the frame
println(frameCount,"/",numFrames);
saveFrame("frame###.png");

// Stops when all the frames are rendered
if(frameCount==numFrames){
println("finished");
stop();
}
}
```

Result : The position of the pixel from which we take the color is constrained to avoid having an out of bounds error :

```      int ii = constrain(floor(i + res.x),0,width-1);
int jj = constrain(floor(j + res.y),0,height-1);
```

An array “result” is used to avoid ovewriting on original pixels that must be used to compute other resulting pixels.

Now to animate it, we’ll have moving stripes over the image activating and desactivating the distortion, that’s why I advice to understand the stripes tutorial first.

Here is the added code :

```float scalar_field(float x,float y){
return 0.03*y;
}

PVector distortion(float x,float y,float time){
PVector res = vector_field(x,y);

float intensity = map(sin(TWO_PI*(time+scalar_field(x,y))),-1,1,0,1);

res.mult(intensity);

return res;
}
```

It should be easy to understand if you understood the stripes tutorial, because here the white stripes correspond to the use of the distortion and black stripes to no distortion.

Here is the result : Now we can try other vector and scalar fields :

```PVector vector_field(float x,float y){
float amount = 50;
float scale = 0.01;
return new PVector(amount*(noise(scale*x,scale*y)-0.5),amount*(noise(100+scale*x,scale*y)-0.5));
}

float scalar_field(float x,float y){
return 0.05*dist(x,y,width/2,height/2);
}
```

Result : By reducing the intensity of the distortion away from the center :

```PVector vector_field(float x,float y){
float amount = 150;
float scale = 0.01;
float intensity = constrain(map(dist(x,y,width/2,height/2),0,0.75*height,1,0),0,1);
return new PVector(amount*(noise(scale*x,scale*y)-0.5)*intensity,amount*(noise(100+scale*x,scale*y)-0.5)*intensity);
}

float scalar_field(float x,float y){
return -0.05*dist(x,y,width/2,height/2);
}
```

Result : That is all, I hope things were quite clear and that this tutorial will inspire you to make something (maybe much better and interesting) yourself.

Here is the complete code to generate the last GIF in case you missed anything…

```int numFrames = 25;

color[] result;
PImage img;

PVector vector_field(float x,float y){
float amount = 150;
float scale = 0.01;
float intensity = constrain(map(dist(x,y,width/2,height/2),0,0.75*height,1,0),0,1);
return new PVector(amount*(noise(scale*x,scale*y)-0.5)*intensity,amount*(noise(100+scale*x,scale*y)-0.5)*intensity);
}

float scalar_field(float x,float y){
return -0.05*dist(x,y,width/2,height/2);
}

PVector distortion(float x,float y,float time){
PVector res = vector_field(x,y);

float intensity = map(sin(TWO_PI*(time+scalar_field(x,y))),-1,1,0,1);

res.mult(intensity);

return res;
}

void setup() {
size(370,254);

result = new color[width*height];
}

void draw(){
// Time variable
float t = 1.0*(frameCount-1)%numFrames/numFrames;

image(img,0,0);

// Renders the pixels using the distortion field
for (int i=0; i<width; i++) {
for(int j=0;j<height;j++){
PVector res = distortion(i,j,t);

int ii = constrain(floor(i + res.x),0,width-1);
int jj = constrain(floor(j + res.y),0,height-1);

result[i + width*j] = pixels[ii + width*jj];
}
}
for (int i=0; i<width; i++) {
for(int j=0;j<height;j++){
pixels[i + width*j] = result[i + width*j];
}
}
updatePixels();

// Saves the frame
println(frameCount,"/",numFrames);
saveFrame("frame###.png");

// Stops when all the frames are rendered
if(frameCount==numFrames){
println("finished");
stop();
}
}
```

# Animated stripes gifs from scalar fields

This tutorial explains how to obtain this kind of GIF with Processing : We’ll start from this code that generates the following simple animation ;

```int margin = 50;
int numFrames = 20;

void setup(){
size(600,600);

}

float pixel_color(float x,float y,float t){
float result = map(sin(TWO_PI*t),-1,1,0,1);
return 255*result;
}

void draw(){
background(0);

float t = 1.0*(frameCount-1)%numFrames/numFrames;

// Draws every pixel
for(int i=margin;i<width-margin;i++){
for(int j=margin;j<height-margin;j++){
stroke(pixel_color(i,j,t));
point(i,j);
}
}

// Draws a white rectangle
stroke(255);
noFill();
rect(margin,margin,width-2*margin,height-2*margin);

// Saves the frame
println(frameCount,"/",numFrames);
saveFrame("frame###.png");

// Stops when all the frames are rendered
if(frameCount == numFrames){
println("finished");
stop();
}
}
``` That code makes each pixel in a white rectangle oscillate between black and white over time. The rest will be only little variations from there so make sure you understand the basis.

Now let’s have moving stripes !
So let’s change the pixel_color function so that the color of pixels doesn’t oscillate at the same time vertically.

```float pixel_color(float x,float y,float t){
float result = map(sin(TWO_PI*(t+0.05*y)),-1,1,0,1);
return 255*result;
}
``` Now let’s make those stripes more contrasted. To achieve that we’ll use an easing function that makes values between 0 and 0.5 closer to 0 and values between 0.5 and 1 closer to 1, with a parameter g to increase the effect.

```float ease(float p, float g) {
if (p < 0.5)
return 0.5 * pow(2*p, g);
else
return 1 - 0.5 * pow(2*(1 - p), g);
}
```

Let’s use it on our oscillating color :

```float pixel_color(float x,float y,float t){
float result = ease(map(sin(TWO_PI*(t+0.05*y)),-1,1,0,1),3.0);
return 255*result;
}
```

This is the result : Now let’s make a general function that controls the offset in the oscilation :
(a scalar field is just a function that gives a real value for each position of the plane in our case)

```float scalar_field_offset(float x,float y){
return 0.05*x+0.05*y;
}

float pixel_color(float x,float y,float t){
float result = ease(map(sin(TWO_PI*(t+scalar_field_offset(x,y))),-1,1,0,1),3.0);
return 255*result;
}
```

Result (there is now horzontal change due to 0.05*x) : Now to obtain different results we just have to change the scalar field. Let’s use the distance to the center.

```float scalar_field_offset(float x,float y){
float distance = dist(x,y,width/2,height/2);
return 0.05*distance;
}
``` Perlin noise (a very nice function given by Processing, I won’t make a tutorial about it here) :

```float scalar_field_offset(float x,float y){
float scale = 0.003;
float result = 40*noise(scale*x,scale*y);
return result;
}
``` Stripes and perlin noise gradually vertically :

```float scalar_field_offset(float x,float y){
float perlin_noise_intensity = pow(constrain(map(y,0.1*height,height,0,1),0,1),2);

float scale = 0.006;
float result = -0.05*y + 20*(noise(scale*x,scale*y)-0.5)*perlin_noise_intensity;
return result;
}
``` :

Perlin noise in the center :

```float scalar_field_offset(float x,float y){
float distance = dist(x,y,width/2,height/2);
float perlin_noise_intensity = ease(constrain(map(distance,0,0.3*height,1,0),0,1),2);

float scale = 0.002;
float result = -0.05*y -0.05*x + 60*(noise(scale*x,scale*y)-0.5)*perlin_noise_intensity;
return result;
}
``` Using distance differently :

```float scalar_field_offset(float x,float y){
float distance = dist(x,y,0.5*width,0.5*height);

float result = 300/(25+distance);
return result;
}
``` By adding the effect of many centers you can get something like this : And with many centers and using an effect only near them : Here is a complete code to generate one in case you missed anything :

```int margin = 50;
int numFrames = 20;

void setup(){
size(600,600);

}

float ease(float p, float g) {
if (p < 0.5)
return 0.5 * pow(2*p, g);
else
return 1 - 0.5 * pow(2*(1 - p), g);
}

float scalar_field_offset(float x,float y){
float distance = dist(x,y,0.5*width,0.5*height);

float result = 300/(25+distance);
return result;
}

float pixel_color(float x,float y,float t){
float result = ease(map(sin(TWO_PI*(t+scalar_field_offset(x,y))),-1,1,0,1),3.0);
return 255*result;
}

void draw(){
background(0);

float t = 1.0*(frameCount-1)%numFrames/numFrames;

// Draws every pixel
for(int i=margin;i<width-margin;i++){
for(int j=margin;j<height-margin;j++){
stroke(pixel_color(i,j,t));
point(i,j);
}
}

// Draws a white rectangle
stroke(255);
noFill();
rect(margin,margin,width-2*margin,height-2*margin);

// Saves the frame
println(frameCount,"/",numFrames);
saveFrame("frame###.png");

// Stops when all the frames are rendered
if(frameCount == numFrames){
println("finished");
stop();
}
}
```

I hope this was helpful and that you will be creative and come up with better stuff than me !

Bonus : if you know glsl, it would be a better idea to code this in glsl to have much faster rendering.

# Making GIFs with Processing and GIMP

Use the `saveFrame` function in Processing to save frames, for example like this :

`saveFrame("frame###.png"); `

Then import the frames as layers in GIMP, and export as .gif and as animation. You can choose the delay between frames there. There must be a more automated way to make gifs but this works and I’m fine with it.