4.5
Image from the w4_02 sketch
The w4_02 sketch

Working with images

In addition to drawing with graphic shapes, Processing can read and draw with any digital image too.

Open and run the w4_02 sketch. This sketch is a kind of drawing program that uses rotating images as the ‘brush’.

You can click and drag the mouse around to draw a pattern with the image while it rotates. Press the left and right arrow keys to scale the image up and down. Press the ‘1’ and ‘2’ keys to change between different ‘brushes’. The ‘d’ key deletes the drawing and lets you start again.

Let’s look at some of the code in the sketch.

Processing has a special type for storing images called a PImage (for Processing Image). In the sketch, an array of PImages are created since we want to be able to draw with two different images while the sketch is running. We also create a background image, bgImage, that is used to store the picture as its being drawn.

PImage[] myImage;    // PImage is used to store an image in memory
PImage bgImage;
...
myImage = new PImage[2];
myImage[0] = loadImage("sample_01.png");
myImage[1] = loadImage("sample_02.png");
bgImage = createImage(width, height, RGB);

Notice the two different ways to create an image. loadImage() reads an image from your computer’s hard disk into the program’s memory, whereas createImage() creates a new empty image in memory. After these statements bgImage contains an empty RGB image the same size as the display window and the myImage array contains two images read from disk.

Images are always stored in a folder called ‘data’ inside the processing sketch’s folder. If you look inside the w4_02 folder you’ll see the ‘data’ folder that contains the two sample images.

Transformations

Next, let’s look at the code that draws with the images:

// draw image according to current scale and mouse position
pushMatrix();
translate(mouseX, mouseY);
float scaleValue = constrain(scaleOfImage, 0.05, 6);
scale(scaleValue); 
rotate(radians(frameCount));
imageMode(CENTER);
image(myImage[selectedImageNum], 0, 0);
popMatrix();

There’s quite a few new functions here! The functions translate(), rotate() and scale() do what you’d expect from their names: they translate (move), rotate and scale up or down the coordinate system. After you’ve made a call to one of these functions, any drawing you do will have these transformations applied.

The function image() draws an image at the location specified. In this case the location is (0,0), which would normally be at the top-left corner of the screen. But because we’ve called translate(), scale() and rotate() the coordinates have shifted. Note also the statement:

imageMode(CENTER);

Similar to functions we’ve already encountered like rectMode() this says to Processing to expect the coordinates passed to image() to be the centre of the image, rather than the default top left.

Finally, there’s the pushMatrix() and popMatrix() functions at the beginning and end of this code block. These functions ‘save’ and ‘restore’ any transformations applied between calls to pushMatrix() and popMatrix(). They do this by storing the accumulated transformations on something called a stack. A stack is just a more limited form of a list that we encountered in week 2. With a stack you can only add or remove elements from the end of the list, and you can only access the top element.

Stack operations with dinner plates

You can think of a stack like stacking a pile of dinner plates one on top of the next. ‘Pushing’ something on to the stack puts a new plate at the top of the pile. ‘Popping’ takes the plate at the top of the stack off and uses it.

What’s actually being stored on the stack is not dinner plates however, its a matrix, which unfortunately has nothing to do with the 1999 film staring Keanu Reeves, Laurence Fishburne, Carrie-Anne Moss and Hugo Weaving. A matrix is just a fancy name for an array of 16 floating point numbers that mathematically encode the transformations.

So calling pushMatrix() at the beginning stores the current transformations (which are just unity - no change) onto the stack. Since the stack starts off empty, it will just have one dinner plate…I mean matrix in it after the pushMatrix() call.

After we’ve transformed the coordinate system and drawn the image, popMatrix() removes whatever element is on top of the stack and restores the transformation it contains, which is the ‘unity’ transform, restoring everything to the default coordinate system.

One other thing that’s important: the order of calling of the transformations. Try changing the order of translate(), rotate() and scale() and see what happens.

There’s still more to look at in this sketch: pixels, which is our next topic of discussion.


Share this article:

This article is from the free online course:

Creative Coding

Monash University

Get a taste of this course

Find out what this course is like by previewing some of the course steps before you join: