Working with Images
Load, display, tint, and manipulate image pixels using the PImage class in Processing.
The PImage class
Processing represents raster images with the PImage class. It stores the pixel data, dimensions, and format of an image. You load an image from disk, store it in a PImage variable, and then draw it onto the canvas wherever and at whatever size you like.
Loading and displaying an image
Before you can load an image, the file must live inside the data/ folder of your sketch. Create that folder next to your .pde file and drop photo.jpg (or .png, .gif) into it.
PImage img;
void setup() {
size(800, 600);
img = loadImage("photo.jpg"); // loaded once in setup
}
void draw() {
background(0);
// Draw at original size, top-left corner at (0, 0)
image(img, 0, 0);
// Or scale to fill the canvas
// image(img, 0, 0, width, height);
}
loadImage() is slow — always call it in setup(), never in draw().
Resizing and positioning
The four-argument form of image() lets you place and scale simultaneously:
// Centre the image at half its original size
float w = img.width * 0.5;
float h = img.height * 0.5;
image(img, (width - w) / 2, (height - h) / 2, w, h);
You can also resize the PImage object itself (this changes the stored pixel data permanently for that session):
img.resize(400, 0); // 400 px wide; height scales proportionally (0 = auto)
Tint: colour overlays and transparency
tint() multiplies each pixel’s colour channels by the tint colour before drawing. Call noTint() to remove it.
// Red tint
tint(255, 80, 80);
image(img, 0, 0);
// Greyscale (all channels equal)
tint(150);
image(img, 200, 0);
// Semi-transparent (fourth argument is alpha 0–255)
tint(255, 255, 255, 128);
image(img, 400, 0);
noTint(); // restore to no tint
Tint is GPU-accelerated in Processing’s default renderer, so it is cheap to use every frame.
Accessing individual pixels
The pixels[] array exposes every pixel as a color value. The array is one-dimensional: pixel at column x, row y maps to index y * img.width + x.
img.loadPixels(); // sync pixels[] from image data
for (int y = 0; y < img.height; y++) {
for (int x = 0; x < img.width; x++) {
int index = y * img.width + x;
color c = img.pixels[index];
float r = red(c);
float g = green(c);
float b = blue(c);
// Convert to greyscale using luminance weights
float grey = 0.299 * r + 0.587 * g + 0.114 * b;
img.pixels[index] = color(grey);
}
}
img.updatePixels(); // push modified pixels[] back into the image
image(img, 0, 0);
Always bracket pixel edits with loadPixels() before and updatePixels() after.
Pixel manipulation: threshold
A threshold filter converts any pixel brighter than a value to white, and anything darker to black:
PImage src;
PImage result;
void setup() {
size(800, 400);
src = loadImage("photo.jpg");
result = src.copy(); // work on a copy to preserve the original
result.loadPixels();
float threshold = 128;
for (int i = 0; i < result.pixels.length; i++) {
color c = result.pixels[i];
float lum = 0.299 * red(c) + 0.587 * green(c) + 0.114 * blue(c);
result.pixels[i] = (lum > threshold) ? color(255) : color(0);
}
result.updatePixels();
}
void draw() {
image(src, 0, 0, width / 2, height);
image(result, width / 2, 0, width / 2, height);
}
Mouse movement can drive the threshold interactively: replace float threshold = 128 with float threshold = map(mouseX, 0, width, 0, 255) inside draw().
get() and set()
get(x, y) and set(x, y, c) are convenience methods for reading and writing individual pixels without touching the pixels[] array directly.
// Sample a pixel colour from the canvas
color sample = get(mouseX, mouseY);
fill(sample);
rect(10, 10, 60, 60); // show sampled colour as a swatch
// Or sample from a PImage
color fromImg = img.get(50, 80);
get() on the canvas samples what is currently visible; img.get() samples from the image’s stored data.
Webcam capture preview
Live video requires the Video library. Install it via Sketch → Import Library → Manage Libraries, search for “Video”.
import processing.video.*;
Capture cam;
void setup() {
size(640, 480);
// List available cameras to the console
String[] cameras = Capture.list();
if (cameras.length == 0) {
println("No cameras found.");
exit();
}
println("Available cameras:");
for (String c : cameras) println(" " + c);
// Open the first available camera
cam = new Capture(this, cameras[0]);
cam.start();
}
void draw() {
if (cam.available()) {
cam.read();
}
image(cam, 0, 0);
}
cam.available() is true when a new frame has arrived from the hardware. Always check it before calling cam.read() to avoid blocking. After read(), the cam object behaves like a PImage and can be passed to image(), tint(), or the pixel manipulation routines above.
Key takeaways
- Place image files in the
data/subfolder; load once insetup()withloadImage(). image(img, x, y, w, h)draws an image at any position and scale.tint()applies a colour and/or transparency overlay;noTint()removes it.- Pixel-level access requires
loadPixels()→ editpixels[]→updatePixels(). get(x, y)/set(x, y, c)are handy for reading or writing single pixels.- Live video works through the Video library’s
Captureclass.