Working with Images
Load, display, tint, and manipulate pixel data from image files and the webcam.
Loading an image
Use preload() to load assets before setup() runs. p5.js guarantees preload() completes before calling setup():
let img;
function preload() {
img = loadImage('photo.jpg');
}
function setup() {
createCanvas(img.width, img.height);
}
function draw() {
image(img, 0, 0); // draw at (0,0) at original size
}
image() parameters
image(img, x, y); // position only
image(img, x, y, w, h); // position + size
image(img, sx, sy, sw, sh, dx, dy, dw, dh); // source crop + destination
imageMode()
Like rectMode, images default to CORNER (x,y is top-left):
imageMode(CENTER); // x,y is the centre of the image
imageMode(CORNER); // default
Resizing images
img.resize(300, 0); // resize to 300px wide, maintain aspect ratio
img.resize(0, 200); // resize to 200px tall, maintain aspect ratio
img.resize(300, 200); // force exact dimensions
Tinting
tint() overlays a colour filter on images drawn after it:
tint(255, 100, 50); // warm tint (RGB)
tint(255, 180); // full colour, 180/255 opacity
tint(255, 255, 255, 128); // half transparent, no colour shift
noTint(); // remove tint
Animated hue shift using HSB:
function draw() {
colorMode(HSB, 360, 100, 100);
let hue = (frameCount * 0.5) % 360;
tint(hue, 60, 100);
image(img, 0, 0, width, height);
}
Pixel manipulation
Access individual pixels through the pixels array. You must call loadPixels() first and updatePixels() after any changes:
function draw() {
image(img, 0, 0);
loadPixels();
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
let index = (x + y * width) * 4; // each pixel = 4 values: R,G,B,A
let r = pixels[index];
let g = pixels[index + 1];
let b = pixels[index + 2];
// Grayscale conversion
let gray = (r + g + b) / 3;
pixels[index] = gray;
pixels[index + 1] = gray;
pixels[index + 2] = gray;
// pixels[index + 3] = alpha (leave unchanged)
}
}
updatePixels();
}
Pixel manipulation on large images is slow. Process every Nth pixel, use a smaller canvas, or move this to a shader for performance.
Image as data — pixel art mosaic
Sample the image colour at a grid of points and draw shapes instead of pixels:
let img;
function preload() {
img = loadImage('portrait.jpg');
}
function setup() {
createCanvas(600, 600);
img.resize(60, 60); // shrink to grid resolution
noLoop();
}
function draw() {
background(20);
img.loadPixels();
let cellW = width / img.width;
let cellH = height / img.height;
for (let x = 0; x < img.width; x++) {
for (let y = 0; y < img.height; y++) {
let c = img.get(x, y); // get(x,y) returns a [r,g,b,a] array
fill(c);
noStroke();
let size = map(brightness(color(c[0], c[1], c[2])), 0, 255, 2, cellW * 0.9);
circle(
x * cellW + cellW / 2,
y * cellH + cellH / 2,
size
);
}
}
}
Webcam input
p5.js can capture the webcam with createCapture():
let cam;
function setup() {
createCanvas(640, 480);
cam = createCapture(VIDEO);
cam.size(640, 480);
cam.hide(); // hide the default HTML video element
}
function draw() {
image(cam, 0, 0, width, height);
}
Webcam requires HTTPS in production (localhost works without it). Always cam.hide() so you only see the p5 canvas, not the raw video element.
Saving a processed image
function keyPressed() {
if (key === 's') saveCanvas('processed', 'png');
}
Key takeaways
- Use
preload()to load images before the sketch starts image(img, x, y, w, h)draws an image;imageMode(CENTER)centres ittint()applies a colour overlay;noTint()removes itloadPixels()/updatePixels()expose the raw RGBA byte array for pixel-level manipulationimg.get(x, y)returns the colour of a single pixel as a[r, g, b, a]arraycreateCapture(VIDEO)gives you live webcam input