Programming Digital Media

Animation

Animation For our purposes, "animation" doesn't (necessarily) mean characters that make jokes while they squash and stretch. When we make an individual image, we control that image with a variety of numeric controls, or parameters. For animation, we can change any of these parameters on a frame by frame basis. This can either create the illusion of coherent movement — for example, by moving the center of a circle along a straight line — or, by using some random or chaotic means of generating numeric data, create other effects entirely.

Click on the script title to download it. Change the beginning and ending parameters to modify the animation. You also need to download a Python module called "utilities.py" that includes the "fit" function that's very useful in converting the frame number to a parameter value for the animation.

     utilities.py

To run the moving_bump.py script, you also need to download the current Image libraries and the "duchamp.tif" image:

     Image.py
     _image.so
     duchamp.tif

If you have the "Pro" version of QuickTime, you can select "Open Image Sequence" from the "File" menu to make your animation into a QuickTime movie.


The "File" menu in QuickTime

The "fit" function

The scripts below use a function called "fit". It takes a value in a range and scales it to fit into a new range with the same proportional relationship.

The "fit" function remaps values from one range to another

The arguments to "fit" are:
    fit(value, old_minimum, old_maximum, new_minimum, new_maximum, clamp=1) 
The final clamp argument is optional; if you don't specify it, then a value of 1 (meaning "keep the result within the range, or 'clamp' it") is used. The "fit" function is very handy in converting the frame number into a parameter value in the animation. For example, if I want the opacity to fade from 1.0 to 0.0 from frame 31 to 60, I could use "fit" like this:
    opacity = fit(frame, 31, 60, 1.0, 0.0) 
Because the "clamp" variable defaults to 1 (meaning "do clamping"), the frames before 31 are set to 1.0, and frames after 60 are set to 0.0.


moving_circle.py













from CoreGraphics import * 
from utilities import fit 
from math import pi 
 
frame_count = 30 
 
image_width = 320 
image_height = 240 
 
start_x = 0 
start_y = 0 
end_x = image_width 
end_y = image_height 
 
start_radius = 100 
end_radius = 1 
 
for f in range(1, frame_count+1): 
    print 'Frame', f 
    x = fit(f, 1, frame_count, start_x, end_x) 
    y = fit(f, 1, frame_count, start_y, end_y) 
    radius = fit(f, 1, frame_count, start_radius, end_radius) 
    c = CGBitmapContextCreateWithColor( 
        image_width, image_height,  # width, height 
        CGColorSpaceCreateDeviceRGB(), 
        (1, 1, 0, 1))  # yellow with opaque background 
    c.setRGBFillColor(1, 0, 0, 1)  # opaque red 
    c.addArc(x, y, radius, 0, 2*pi, 1) 
    c.fillPath() 
    c.writeToFile("circle.%04d.tif" % (f), kCGImageFormatTIFF) 

moving_boxes.py













from CoreGraphics import * 
from utilities import * 
 
# The "uniform" function returns a random number betwen the arguments. 
from whrandom import uniform 
 
frame_count = 30 
 
image_width = 640 
image_height = 480 
 
box_count = 5000 
 
box_min_size = 10 
box_max_size = 30 
 
box_min_red = .2 
box_max_red = .5 
 
box_min_green = .4 
box_max_green = .6 
 
box_min_blue = .5 
box_max_blue = .8 
 
box_min_alpha = .3 
box_max_alpha = .7 
 
# Make a list of box attributes to use every frame 
boxes = [] 
for i in range(box_count): 
    width   = uniform(box_min_size, box_max_size) 
    height  = uniform(box_min_size, box_max_size) 
    start_x = uniform(-box_max_size, image_width) 
    start_y = uniform(-box_max_size, image_height) 
    end_x   = uniform(-box_max_size, image_width) 
    end_y   = uniform(-box_max_size, image_height) 
    red     = uniform(box_min_red, box_max_red) 
    green   = uniform(box_min_green, box_max_green) 
    blue    = uniform(box_min_blue, box_max_blue) 
    alpha   = uniform(box_min_alpha, box_max_alpha) 
    boxes.append([width, height, start_x, start_y, end_x, end_y, 
                  red, green, blue, alpha]) 
 
 
c = CGBitmapContextCreateWithColor( 
    image_width, image_height, 
    CGColorSpaceCreateDeviceRGB(), (.3, .5, .4, 1)) 
 
for f in range(1, frame_count+1): 
    print 'Frame', f 
    for w, h, x1, y1, x2 ,y2, r, g, b, a in boxes: 
        x = fit(f, 1, frame_count, x1, x2) 
        y = fit(f, 1, frame_count, y1, y2) 
        box = CGRectMake(x, y, w, h) 
        c.setRGBFillColor(r, g, b, a) 
        c.addRect(box) 
        c.fillPath() 
    c.writeToFile("boxes.%04d.tif" % (f), kCGImageFormatTIFF) 

moving_bump.py

















from Image import * 
from utilities import fit 
 
frame_count = 8 
start_radius = 0 
end_radius = 170 
 
for f in range(1, frame_count+1): 
    radius = fit(f, 1, frame_count, start_radius, end_radius) 
    p = Image("duchamp.tif") 
    p.BumpDistortion(Vector(p.width/2,p.height/2), radius, 5) 
    p.save("bump.%04d.gif" % (f))