Using pixels array to fill shape

Hi, I’m pretty new to p5 and have never used the pixels array before. I’ve read the documentation and watched some videos on the pixels array but I can’t work out how to achieve the specific effect I’m looking for.

I want to use pixels from vid1, which is hidden, to fill an ellipse that’s rendered when I move my mouse over the canvas so that it paints the same area of vid1 on to the canvas replacing vid2. The effect is sort of like a scratch card that reveals vid1 as you move the mouse over the canvas.

Is this possible? The code I have so far is below and I’ve created a sketch in editor:
https://editor.p5js.org/andy-pewter/sketches/SJwiNV7oy

Thanks!

Andy

let vid1;
let vid2;
let cnv;
let positions = [];
let button;

function setup() {
  cnv = createCanvas(600, 400);

  vid1 = createVideo("cut1.mp4");
  vid2 = createVideo("cut2.mp4");

  button = createButton("play");
  button.mousePressed(togglePlaying);
  vid1.hide();
  vid2.hide();

}

function togglePlaying() {
  vid1.loop();
  vid1.volume(0);
  vid2.loop();
  vid2.volume(0);
}

function draw() {
  vid1.loadPixels();
  image(vid2, 0, 0);

  positions.push({ x: mouseX, y: mouseY });
  noStroke();
  fill(0); // need to fill using pixels from vid1

  for (let i = 0; i < positions.length; i++) {
    let x = positions[i].x;
    let y = positions[i].y;
    ellipse(x, y, 80, 80);
  }
}


1 Like

I believe a much more intuitive and easy way would be to use a mask.
Create a pgraphics where you will draw your ellipses (with or without arrays).
Use this as a mask for vid1.
Here’s another thread on how to use a mask with video.

2 Likes

And more threads below.
https://forum.processing.org/one/topic/how-to-creat-a-mask-on-video.html
https://processing.org/discourse/beta/num_1159143409.html

2 Likes

Thanks @AuXie2k9, my original approach with the pixels array was creating performance issues so this is really useful, I’ll read up on using a mask :+1:t2:

Hi @AuXie2k9, thanks again for your advice, I’ve read up on using a mask and I’ve managed to get it working with an image as a mask on top of video, however, I can’t get it to work with video as a mask on top of video. In p5.js it throws a type error:

Uncaught TypeError: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The provided value is not of type '(CSSImageValue or HTMLImageElement or SVGImageElement or HTMLVideoElement or HTMLCanvasElement or ImageBitmap or OffscreenCanvas)'

I think this might be because it’s expecting an image as opposed to a video.

Do you know if there’s support for video as a mask in p5? I can’t seem to find any official documentation on this. My updated code is as follows:

let video;
let video2;
let maskedVideo;
let maskImage;
let mask;

function preload() {
  video = createVideo(["cut1.mp4"]);
  video.hide();
  video.size(600, 600);

  video2 = createVideo(["cut2.mp4"]);
  video2.hide();
  video2.size(600, 600);

  maskImage = loadImage("mask.png");
}

function setup() {
  createCanvas(600, 600);

  mask = createGraphics(width, height);
  mask.imageMode(CENTER);

  maskedVideo = video2.get();
  maskedVideo.mask(mask.get());

  button = createButton("play");
  button.mousePressed(togglePlaying);
}

function togglePlaying() {
  video.loop();
  video.volume(0);

  video2.loop();
  video2.volume(0);
}

function draw() {
  image(video, 0, 0, 600, 600);
  image(maskedVideo, 0, 0, 600, 600);

  if (mouseIsPressed) {
    mask.image(maskImage, mouseX, mouseY, 100, 100);
    maskedVideo = video2.get();
    maskedVideo.mask(mask.get());
  }
}

Thanks!

Hi @AuXie2k9, I solved it, I needed to use loadPixels() !

2 Likes