Night #8: Rendering an image sequence

How can one render a movie from a Processing sketch? In Processing 1.5.1, there is a class called MovieMaker which generates a Quicktime file directly. However, this class uses ye old Quicktime for Java and will be removed from Processing 2.0. Instead, 2.0 is going to introduce a MovieMaker “tool” which will generate a movie file from a directory containing an image sequence. So how do you get this image sequence? Easy:

void draw() {
  saveFrame("output/frames####.png");
}

This will create a folder called “output” in your sketch folder and for each frame of draw(), it will write a file — frames0001.png, frames0002.png, etc. The ‘#’ sign tells processing to auto-number the images.

There are a couple additional tricks included in this new example. First, it uses a boolean variable to turn rendering on and off and cycles the boolean in keyPressed() allowing recording to be stopped and started by pressing ‘r’.

void draw() {
  // If we are recording call saveFrame!
  if (recording) {
    saveFrame("output/frames####.png");
  }
}
 
void keyPressed() {  
  // If we press r, start or stop recording!
  if (key == 'r' || key == 'R') {
    recording = !recording;
  }
}

In addition, if you draw anything after saveFrame() it won’t actually appear in the output, but will be seen on screen. This is useful for debugging information that you don’t want included in the render.

void draw() {
 
  // Draw lots of stuff to be recorded!
 
  if (recording) {
    saveFrame("output/frames####.png");
  }
 
  // Draw our debugging stuff that won't be recorded!
}

Until 2.0 is released, I recommend you use 3rd party software to take the image sequence and turn it into a movie. The old Quicktime 7 will do the trick, as well as any number of video production applications like final cut, after effects, iMovie, etc. The nice thing about using a PNG sequence is that the images are uncompressed, but aren’t as large as say TIFFs. I don’t recommend saving JPGs because then you will likely be compressing twice (once when saving the image, once when exporting the movie file).

Source: SavingFrames.zip

Night #6: Image Sequence Object (with variable speed)

I have an example from Learning Processing which demonstrates how to package a “pre-made” animation (i.e. sequence of images) into an object in Processing so that it can be duplicated many times on screen. For tonight’s example, I’m going to make a new version that improves a few key points.

First, in the original example the the image files are loaded in the class itself. This is problematic. Sure, if you make one object then you are loading files from the hard drive once. However, if you make many objects, then you are loading the same images over and over again which is totally unnecessary (and can cause problems like using too much memory, stuttering if objects are made during draw(), taking too long to start up, etc.).

We can fix this by loading an array of images in setup() and passing it to the object.

Animation a;
 
void setup() {
  // Load the image sequence first!
  PImage[] seq = new PImage[40];
  for (int i = 0; i < seq.length; i++) {
    seq[i] = loadImage("stick/stick"+nf(i+1,2)+".png"); 
  }
 
  // Now when you make the animation object, you pass it the image array!
  a = new Animation(seq);  
}

The class then receives the array in the constructor and passes it to its own array.

class Animation {
  // The array of images
  PImage[] images;
 
  Animation(PImage[] images_) {
    images = images_;
  }

This way (as you'll see in the example) if we make an array of objects, each one uses the same array of images (which we loaded only once). Another feature of this improvement is that the Animation object is more generic, and can be created with any arbitrary array of images.

The original example demonstrated how to have the sequences start at different images so that they didn't all appear to be perfectly in sync. However, the question I usually get is instead: "How can the sequences play back at variable speeds?"

The original example used an integer to keep track of the current "frame" of the animation.

int index = 0;
 
void next() {
  index = (index + 1) % images.length;
}

Here, you see that we move one spot in the array each frame, and the animation is then shown at the frame rate of our sketch. So in theory, you could change the above to "index = index + 2" to, say, double the speed. A more flexible way to vary the rate of the animation, however, is to use a float for the index in the array, i.e.

float index = 0;
float speed = random(1,5);
 
void next() {
  // Move the index forward in the animation sequence
  index += speed;
  // If we are at the end, go back to the beginning
  if (index >= images.length) {
    // We could just say index = 0
    // but this is slightly more accurate
    index -= images.length;
  } 
}

Of course, you can't actually use this float when you go to look up an image in the array -- indices must be integers! So we simply convert it to an int when the time comes to draw the image.

void display() {
  int imageIndex = int(index);
  image(images[imageIndex], x, y);
}

Here is the example.

Download source: AnimationExample.zip