Using photographs in Processing adds a few steps, but it is well worth the extra legwork. After you've added a photograph to your sketch, you will learn how to modify it with filters and change the tint.
If you're like me, you have hundreds of images on your computers/phone. To add images you click the sketch drop-down menu and select Add File. Find an image you want to use as long as it is a .jpg, .bmp, .png, .gif or .tga. If your image has a crazy name, rename it. Select the image and click OPEN.
Next, go back to the code window, click the sketch drop-down menu, and select show sketch folder. This folder is where your sketch resides when you save it, but it also includes all of the other assets that your sketch needs to run properly. There shouldn't be much there right now, but your projects will have more files as they become more complicated.
Open the folder named data, and you should see a copy of the image file you just added. I will be using the photograph of my friend Matthew. I named the file matthew.jpg take note of the file format.
In this project you use PImage which is an advanced data type used for storing an image file. PImage is considered advanced because when you create a PImage variable, you have to go through an extra step to initialize or assign an image to it. Here, I created a global variable at the top of the sketch called img with a data type of PImage. Notice that I only create the variable and don't initialize it with a value.
PImage img;
void setup() {
size(800,800);
img = loadImage("matthew.jpg");
}
To assign a value to img, you have to laod your image. Using loadImage() function tells Processing to literally load, or pack, the img variable with every single pixel of the image. To specify which image to pack, just pass loadImage() the file-name as a string in quotes; I passed it "matthew.jpg". Since img is global, after you initialize it, you can use the image it contains anywhere in your draw() loop or in any other function that follows.
Not that you have a variable holding your image, you need to put it to good use in the draw() loop by using the image() function. Think of an image as a rectangle that you can manipulate. The image() function accepts three parameters.
void draw() {
image(img, 0 ,0); //image variable, location x and y
}
You can also pass 5 parameters ( img variable, x, y, width, height) to make the image larger or smaller. When you use images in Processing, resolution really matters, because resolution is essentially the size of your image in pixels. Once you pull an image into Processing, you may notice that it is larger or smaller than you thought, and that can throw off your program. Be sure to check the original resolution of the images you are using under your image file properties before you use them in a project.
You should also think about about aspect ratio - the ratio of height to width - when you choose images for your projects. If you are looking to scale or change the width or height of an image, that scaling will also stretch or contort the image. You may need to crop or edit some images to make them work for your project.
By default, the origin of an image is the same as that of a rectangle- the top-left corner. You can change this by using a function called imageMode() . For example, if you want the origin to be the center of the image, you can pass the mode CENTER to imageMode() and it will move the origin for you.
void draw() {
imageMode(CENTER);
image(img, width/2, height/2);
}
Thanks to imageMode() it takes only a couple of lines of code to place matthew.jpg in the center of my sketch window. To place the image using the image() function, I passed it img, which is the image I want to show, and the x and y coordinates of the sketch to width/2 and height/2.
You can also choose from two other modes. Passing CORNER sets the origin back to the default (the top left corner). Calling imageMode(CORNERS) will let you draw based on where you want the top left and bottom-right corners of the image to fall in your sketch.
Since an image can be treated like a rectangle you can even pass the mouseX and mouseY variables to set its origin.
void draw() {
imageMode(CENTER);
image(img, mouseX,mouseY);
}
You can translate, scale, and rotate your image just as you did for the basic shapes. All you need to do is set up a matrix in your draw loop and then you can transform the image as much as you want! For examples let's play with scale!
void draw() {
background(150);
imageMode(CENTER);
pushMatrix();
translate(width/2,height/2);
scale(map(mouseX, 0, width, .5, 2));
image(img,0,0);
popMatrix();
}
Notice that I passed a mapped value of mouseX to scale(). Processing's map() function maps a value onto a different range of values. Here, I've told Processing to map the range of mouseX- which would normally be from 0 to the width of your sketch- to values ranging from .5 to 2, resulting in scales from 50 to 200 percent. This should turn your mouse MOVEMENTs into a zoom control.
The main reason for using matrices is so you can group individual or sets of objects together and manipulate them independently from the rest of your sketch. In a photo collage, you may want to modify a specific image or group of images while keeping others intact. I recommend placing each image on its own matrix so that you can work with it freely. If you want to apply the same effects to multiple images you can place them within the same matrix, but at some point you may want to separate them.
I'm going to use images of my other family members to create a photo collage in Processing. You can create a scrapbook page from your last family trip or a collage of your friends at school or really just a montage of your dog.
To use multiple images in a project, first you need to add those images to your data folder. Click sketch - -- - add file. Change the names of the images to something simple. Next, create a variable for each image, with the data type PImage. Since you have more than one image, use descriptive variable names to keep them all straight. I named each image variable after the person in the photo I plan to load into that variable.
PImage matthew;
PImage andrea;
PImage maria;
PImage chris;
PImage dj;
PImage alex;
void setup() {
size(1000,1000);
matthew= loadImage("matthew.png");
andrea= loadImage("andrea.png");
maria= loadImage("maria.png");
chris= loadImage("chris.png");
dj= loadImage("dj.png");
alex= loadImage("alex.png");
}
void draw() {
image(matthew,20,20);
image(andrea,600,400);
image(maria, 300,20);
image(chris,20,400);
image(dj,600,20);
image(alex,300,400);
}
The final step of preparing your images is loading the files to variables. Call the loadImage() function inside the setup() code and assign the image files to the variables you created at the top of your sketch. Now you can draw them onto your sketch window by calling the image() function and supplying your desired coordinates.
Whenever you're working with multiple images, I recommend getting into the habit of using matrices. You can give each image its own matrix and then manipulate those matrices independently of one another. For example, I'm going to tweak the draw() loop from the previous section to get each image ready for using a matrix.
void draw() {
pushMatrix();
translate(20,20);
image(matthew,0,0);
popMatrix();
pushMatrix();
translate(600,400);
image(andrea,0,0);
popMatrix();
pushMatrix();
translate(300,20);
image(maria, 0,0);
popMatrix();
pushMatrix();
translate(20,400);
image(chris,0,0);
popMatrix();
pushMatrix();
translate(600,20);
image(dj,0,0);
popMatrix();
pushMatrix();
translate(300,400);
image(alex,0,0);
popMatrix();
}
All you have to do is place each image in its own matrix and translate that matrix to the position at which you were drawing the image before. Remember how each matrix has its own origin? I placed all of the images at 0,0 and moved the matrices- not the images. To move the matrices, give each a translate() function at the top. When you click run all of the images should be at the same location as before. Now you can manipulate each image within its matrix. So to move one of your images, you'll use the translate() function to move the matrix rather than the image itself. This may seem like a lot of work, but trust me: it's worth the effort. Now, let's make your collage a bit more interesting.
Straight and true images are a little boring. Since each image is in its own matrix you can add some transformation functions to give your sketch a little more depth and interest. You can also rotate, scale and otherwise manipulate each image as you see fit once they're all inside matricES. Give it a try! Mix up that perfectly aligned collage to make the pictures look like they've been strewn on the sketch.
PImage matthew;
PImage andrea;
PImage maria;
PImage chris;
PImage dj;
PImage alex;
void setup() {
size(1000,800);
matthew= loadImage("matthew.png");
andrea= loadImage("andrea.png");
maria= loadImage("maria.png");
chris= loadImage("chris.png");
dj= loadImage("dj.png");
alex= loadImage("alex.png");
background(200,0,200);
imageMode(CENTER); //YOU DONT HAVE TO USE THIS MODE
}
void draw() {
pushMatrix();
translate(500,20);
rotate(1.6);
scale(1.5);
image(matthew,0,0);
popMatrix();
pushMatrix();
translate(200,200);
rotate(.5);
image(andrea,0,0);
popMatrix();
pushMatrix();
translate(600,600);
rotate(1.3);
scale(1.5);
image(maria, 0,0);
popMatrix();
pushMatrix();
translate(150,500);
rotate(.15);
image(chris,0,0);
popMatrix();
pushMatrix();
translate(800,200);
rotate(-1);
image(dj,0,0);
popMatrix();
pushMatrix();
translate(500,400);
scale(.75);
rotate(.2);
image(alex,0,0);
popMatrix();
}
In this version of my collage code, I added the imageMode() and background() function to the setup. In draw, I scaled and rotated images. Those changes offer more appeal than just static images. Now you are ready for more image-specific modifiers so you can give your collage more creative depth.
First explore the tint() function, which allows you to add a colored tint to an image. tint() is a modifier, so just like fill() or stroke() it must be placed before the image that you're tinting. Changing the tint of your image is as simple as passing tint() red, green, and blue values, but I think the coolest part of the tint() function is that it allows you to set the transparency value of the image as well. To set the transparency, pass a fourth argument ranging from 0 to 255, where 0 is completely invisible and 255 is completely opaque or solid.
Try it out now!
PImage matthew;
PImage andrea;
PImage maria;
PImage chris;
PImage dj;
PImage alex;
void setup() {
size(1000,800);
matthew= loadImage("matthew.png");
andrea= loadImage("andrea.png");
maria= loadImage("maria.png");
chris= loadImage("chris.png");
dj= loadImage("dj.png");
alex= loadImage("alex.png");
background(200,0,200);
imageMode(CENTER); //YOU DONT HAVE TO USE THIS MODE
}
void draw() {
Background(150);
pushMatrix();
translate(500,20);
rotate(1.6);
scale(1.5);
tint(second() * 4, second() *4, second() *4);
image(matthew,0,0);
popMatrix();
pushMatrix();
translate(200,200);
rotate(.5);
tint(255, mouseX/4);
image(andrea,0,0);
popMatrix();
pushMatrix();
translate(600,600);
rotate(1.3);
scale(1.5);
tint(100,150,0);
image(maria, 0,0);
popMatrix();
pushMatrix();
translate(150,500);
rotate(.15);
tint(mouseX/4, mouseY/4, 0);
image(chris,0,0);
popMatrix();
pushMatrix();
translate(800,200);
rotate(-1);
tint(255,255,255,mouseX/4);
image(dj,0,0);
popMatrix();
pushMatrix();
translate(500,400);
scale(.75);
rotate(.2);
noTint();
image(alex,0,0);
popMatrix();
}
Try adding variables to the tint() function so you can make your work interactive. The tint for some of the above code changes color over time, and some change via the mouse location.
You can accomplish a lot with the tint() function, but you can extend image manipulation and modification even further by using the filter() function, which has filters similar to those available in photo editing software. The filter() function doesn't work exactly like other image modifiers. The filter is placed over the image, like a mask that you're looking through. The filter() function requires a filter name, rather than numeric values.
filter(THRESHOLD); //ranges from 0-1
filter(GRAY);
filter(INVERT);
filter(POSTERIZE, 4); //ranges from 2-255
filter(BLUR,1); //range: >= 1
filter(ERODE);
filter(DILATE);
A few of these filters are stand-alone, meaning there is only one setting. A few of them - THRESHOLD, POSTERIZE, BLUR- allow you to pass an additional value to change a setting or intensity. For those, I have provided the range of numbers that you can pass to the filter. There are two different techniques for applying a filter. The simplest way it to place the filter over the entire sketch. This is helpful when you want to use a general filter, such as a blur, or when you want to make everything grayscale. For example, at the very end of your photo collage, add the line filter(GRAY); to produce a grayscale sketch.
You can also stack image filters by adding a second filter function after the first one. For example, add a BLUR filter with a level of 7 after your intial gray filter.
filter(GRAY);
filter(BLUR,7);
This combination should produce a blurry black and white image.
Advanced data types have two faces. The first, and the most apparent is that they're data types, just like an int or a float. But unlike a variable with an int or float value, variables that have advanced data types like PImage are considered objects. In OOP you create an object with is an instance of a class. A class has certain properties that it passes on to every object of that class type. Remember this?
Methods, such as filter() or save() is a procedure to do something. resize() copy() blend() get() set() save() are all methods. Mehtods have parentheses.
Fields return information about the object like width, height, and pixels[]. Fields are usually just keywords.
When you think about your images as objects, you can start to consider different aspects of the image that you can either use as variables or change. For example, the filter of an image is something that you can change by calling a method on an image object:
For this example, I used an image of Matthew stored in a PImage object named matthew. I then applied the filter() method to matthew by adding dot syntax or a period after the object name followed by the call method. Follow the same rule any time you want to apply one of the class's methods to any object of that class. But a word of warning! You can't just use any old function in this way! The function must actually be a method, which means it must exist as part of the object's class. I can apply filter() because matthew is an instance of the PImage class, which includes that function.
This OOP approach is what allows you to apply a specific filter to a specific image. If you want to apply specific filters to certain images add the functions in the setup() of your sketch rather than in the draw() loop.
matthew.filter(GRAY);
andrea.filter(ERODE);
maria.filter(INVERT);
here is code to get you started