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; myImage = loadImage("sample_01.png"); myImage = 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.
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
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.
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
rotate() the coordinates have shifted. Note also the statement:
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
popMatrix() functions at the beginning and end of this code block. These functions ‘save’ and ‘restore’ any transformations applied between calls to
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.
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.
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
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
scale() and see what happens.
There’s still more to look at in this sketch: pixels, which is our next topic of discussion.
© Monash University 2017. CRICOS No. 00008C