p5.js Beginner Article 5

Working with Images

Load, display, tint, and manipulate pixel data from image files and the webcam.

⏱ 20 min read images pixels preload tint 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 it
  • tint() applies a colour overlay; noTint() removes it
  • loadPixels() / updatePixels() expose the raw RGBA byte array for pixel-level manipulation
  • img.get(x, y) returns the colour of a single pixel as a [r, g, b, a] array
  • createCapture(VIDEO) gives you live webcam input