Tutorials
comment 1

How to create interactive loops using lenticular animation and GifPop

lenticular_prints

Golan Levin, director of The Frank-Ratchye STUDIO for Creative Inquiry (Carnegie Mellon University), has 27 students in his Interactive Art & Computational Design class. They range from sophomores (2nd-year undergraduates) to doctoral students. They come from 10 different department (Art, Architecture, Design, Robotics, Computer Science) and they use a huge variety of programming techniques. The purpose of this assignment was to sharpen the students’ craft as a creative technologist and provide a good/basic introduction to programming. For their 3rd week of class Golan developed an assignment titled “A Looping, Computationally-Generated Animated GIF, and a Lenticular GIFPop! Print”. The following learning objectives were set out:

  • Create computational animations using an arts-engineering toolkit;
  • Prepare animated imagery for publication in GIF and lenticular formats;
  • Conceive and appraise graphical concepts within the constraints of the GIF format.
  • Compare the qualities of physical and virtual media

The purpose of this tutorial is to enable you to write code to create a brief looping animation, using computationally-generated graphics, suitable for both online and lenticular publishing. Then, using the unique GifPop services, you can get your GIFPOPs printed.

5abed64c96702e422405a0d1ae21621b_originalba8667159dc40d3d30977807b5966660_original

You can use provided Processing sample code below but also have the liberty to work in any programming environment you are comfortable with. Students mostly worked in Processing and openFrameworks, but some responses were made in Node.js, JavaScript, and other tools.

Founded by the computational designer-entrepreneurs Rachel Binx and Sha HwangGIFPOP! is a recently Kickstarted enterprise which “creates custom cards from animated GIFs, using the magic of lenticular printing”.

Before starting, here are some suggestions:

  • SKETCH FIRST! Before doing anything, make some (real) sketches in your notebook. Try to come up with graphical concepts.
  • Your design may be abstract, figurative, etc. according to your tastes.
  • GIFS are palette-based images, which means that they must represent all of your frames with a single common palette of just 256 colours. For this reason, you may obtain better results with imagery that just uses a small number of colours, or is monochromatic.
  • Avoid using recorded (i.e. photographic and/or video) media.
  • You may find this repository of nonlinear mapping functions helpful.
  • Export a series of frames, and compile these into an animated GIF. Here is a helpful tutorial for creating animated GIFs from folders of images, using Photoshop. Remember to set its duration to “forever”, and to adjust the frame durations to something appropriate.
  • Your GIF can be any length, but keeping it under 2MB would be sensible.
  • Test out your GIF to make sure it animates as you expect! You can open most animated GIFs with web browsers to test them out.

GIFPOP also offer the following suggestions for creating lenticular prints with their system:

  • Looping in 10 frames is great. It makes the effect that much more magical as you don’t get that “seam” of the animation restarting.
  • There will always be some ghosting in high frame-count lenticular printing. A good way to imagine (or simulate!) this is that every frame you see will have 10-20% opacity visible of the frames on either side.
  • Smooth movements will work well. 10 completely different images won’t be super legible. The “cinematography” here is important: less slam cuts, more long takes. Small movements, not big movements.
  • Geometric patterns are great, bright colours work well. Thin lines are harder to see without enough contrast.
  • By default, their 5″x5″ cards are printed so that you rotate them up/down to see them. Left/right rotation gives blurrier animation when your head is close to the card because of the spacing of your eyes, but if you rotate your animation 90 degrees it will print left/right. For example, Jono did this and rotated his.

Here is an animated GIF, and the Processing code template below that produced it.

iacd-anim-demo

Some things to observe about this animated GIF:

  • It uses a simple colour palette — just a couple of colours.
  • Visual elements move smoothly and in small increments.
  • It has 30 frames, at 30fps, which looks nice in a webpage. But for Gifpop lenticular prints, you’ll need to export a version which has no more than 10 frames, and the amount of movement (pixel deltas) between frames should be even smaller.
// This is a template for creating a looping animation in Processing. 
// When you press a key, this program will export a series of images
// into an "output" directory located in its sketch folder. 
// These can then be combined into an animated GIF. 
// Prof. Golan Levin, January 2014 - CMU IACD
 
//===================================================
// Global variables. 
 
int nFramesInLoop = 30; // For lenticular export, REMEMBER TO CHANGE THIS to 10!
int nElapsedFrames;
boolean bRecording; 
 
//===================================================
void setup() {
  size (400, 200); 
  bRecording = false;
  nElapsedFrames = 0;
  frameRate (nFramesInLoop); 
}
//===================================================
void keyPressed() { 
  // Press a key to export frames to the output folder
  bRecording = true;
  nElapsedFrames = 0;
}
 
//===================================================
void draw() {
 
  // Compute a percentage (0...1) representing where we are in the loop.
  float percentCompleteFraction = 0; 
  if (bRecording) {
    percentCompleteFraction = (float) nElapsedFrames / (float)nFramesInLoop;
  } 
  else {
    float modFrame = (float) (frameCount % nFramesInLoop);
    percentCompleteFraction = modFrame / (float)nFramesInLoop;
  }
 
  // Render the design, based on that percentage. 
  renderMyDesign (percentCompleteFraction);
 
  // If we're recording the output, save the frame to a file. 
  if (bRecording) {
    String  myName = "golanlevin"; 
    saveFrame("output/"+ myName + "-loop-" + nf(nElapsedFrames, 4) + ".png");
    nElapsedFrames++; 
    if (nElapsedFrames == nFramesInLoop) {
      bRecording = false;
    }
  }
}
 
//===================================================
void renderMyDesign (float percent) {
 
  // This is an example of a function that renders a temporally looping design. 
  // It takes a "percent", between 0 and 1, indicating where we are in the loop. 
  // This example uses two different graphical techniques. 
  // Use or delete whatever you prefer from this example. 
  // Remember to SKETCH FIRST!
 
  //----------------------
  // here, I set the background and some other graphical properties
  background (180);
  smooth(); 
  stroke (0, 0, 0); 
  strokeWeight (2); 
 
  //----------------------
  // Here, I assign some handy variables. 
  float cx = 100;
  float cy = 100;
 
  //----------------------
  // Here, I use trigonometry to render a rotating element.
  float radius = 80; 
  int nSpokes = 7; 
  for (int i=0; i < nSpokes; i++) {
    float armAngle = (percent + i) * (TWO_PI/nSpokes); 
    float px = cx + radius*cos(armAngle); 
    float py = cy + radius*sin(armAngle); 
    fill    (255); 
    line    (cx, cy, px, py); 
    ellipse (px, py, 20, 20);
  }
 
  //----------------------
  // Here, I use graphical transformations 
  // to render a rotated square. 
  pushMatrix(); 
  translate (cx, cy);
  float rotatingSquareAngle =  percent * TWO_PI * -0.25;
  rotate (rotatingSquareAngle); 
  fill (255, 128); 
  rect (-40, -40, 80, 80);
  popMatrix(); 
 
  //----------------------
  // Here's a set of linearly-moving circles
  float ballSize = 20;
  float topY = 0 - ballSize - 2;
  float botY = height;
  float spanY = botY - topY; 
 
  int nMovingBalls = 5; 
  for (int i=0; i <= nMovingBalls; i++) {
    float ballSpacing = spanY / (float)nMovingBalls;
    float yBase = topY + ballSize/2; // offset for radius of ball 
    float yPercent = map(percent, 0, 1, topY, topY+ballSpacing);
    float yPosition = yBase + (yPercent + (i*ballSpacing))%spanY; 
 
    fill (255, 255, 255); 
    ellipse (250, yPosition, ballSize, ballSize);
  }
 
  //----------------------
  // Here's a pulsating ellipse
  float ellipsePulse = cos ( percent * TWO_PI); 
  float ellipseW = map(ellipsePulse, -1, 1, 20.0, 80.0); 
  float ellipseH = map(ellipsePulse, -1, 1, 80.0, 20.0); 
  float ellipseColor = map(ellipsePulse, -1, 1, 0, 255); 
  fill (ellipseColor, ellipseColor, ellipseColor); 
  ellipse (340, cy, ellipseW, ellipseH); 
 
  //----------------------
  fill (0, 0, 0);
  textAlign (CENTER); 
  String percentDisplayString = nf(percent, 1, 3);
  text (percentDisplayString, 340, 40);
}

To achieve more nuanced animation effects, you may also be interested in Golan’s Pattern Master functions.

In the process of making the works, it’s also a good idea to compare the visual results of screen-based works to the lenticular one since they may be very different. For example, Thomas Langerak made a colour-changing GIF. His aim was to create something different than motion. Unfortunately he was not particularly happy with how it turned out on-screen, however the lenticular Gifpop print was a surprisingly interesting object. You can download Thomas’ piece here.

To print your animations, GifPop! currently offers two sizes for custom gifs. Business Card (2 1/8″ x 3 3/8″) at $12 each, Landscape Postcard (5″ x 3 ½”), Portrait Postcard (3 ½” x 5″) and Large Square (5″ x 5″) all at $15 and finally a Small Square (2 ¾” x 2 ¾”) at $12 each. All of these get less expensive as you order more including 50% off if you order 50+ (think of all your friends!).

Huge thanks to Golan for sharing his class instructions with CAN. You can access and browse all of the student responses here. Their blog posts generally include their project narratives, sketches, and code. For any other info, please see additional links below.

Project Page | Student Gifs | The Frank-Ratchye STUDIO for Creative Inquiry | GifPop

Selected students work:

  • Lindsey

    I’ve been super interested in gifs for a while now and came across this post. The tutorials are great and the application into print is exciting. Thank you! lindseykyokoadams.com