Setting pixels of a movie file

Dear everyone,

I’m adapting some code I wrote setting the pixels of a live video capture from an external camera. (see topic )

I want to get the same effect using a movie file. The effect is a pixel mask that turns the alpha on certain pixels to 0 (eventually so some movie underneath can be seen). It’s working, but (just as in the version with the video capture) it flickers and is not a constant effect.

With some help in the last version, I used a volatile boolean to force thread execution, and a combination of noLoop() in setup and redraw() in the captureEvent function to smooth out the flickering. I’ve tried doing the same here by simply placing redraw() in the movieEvent function, but it seems to not even play the video file. I can only get it working with the flickering if I remove the noLoop() and redraw() functions. Furthermore, when I turn the ‘pixelMask’ effect off, the movie’s playback rate seems to speed up.

The code below is a simplified version of what I posted in the other topic, adapted for a movie file instead of a capture device.


import processing.video.*;


Capture video;
Movie performanceClip;


color trackColor;

boolean perfClipPlay = false;

boolean maskOn = false;
boolean delay = false;

//distance threshold for calculating which pixels are affected
float threshold = 50;

//forces order of execution
volatile boolean drawing;


void setup() {

  size(1200, 800);

  performanceClip = new Movie(this, "performanceClip.mp4");
  performanceClip.pause();
  performanceClip.volume(0);
  performanceClip.format = ARGB;
  trackColor = color(255, 0, 0);

  background(255);

  noLoop();
}


void draw() {


  drawing = true; //volatile boolean controls thread execution

  background(0);

  if (perfClipPlay) {
    performanceClip.play();
    image(performanceClip, 0, 0, width, height);
  } else if (!perfClipPlay) {
    performanceClip.stop();
  }
  
  drawRetina();

  drawing = false;//volatile boolean controls thread execution
}




void drawRetina() {
 stroke(255, 0, 0);
 strokeWeight(1.5);
 line(width/2, height/2 - 20, width/2, height/2 + 20);
 line(width/2 - 20, height/2, width/2 + 20, height/2);
 ellipse(width/2, height/2, 5, 5);
 }
 

void movieEvent(Movie m) {
  if (m==performanceClip && perfClipPlay && !maskOn) {
    m.read();
  } else if (!drawing && m==performanceClip && perfClipPlay && maskOn) {
    m.format=0;
    m.read();
    m.loadPixels();
    trackColor = m.pixels[(width/2 + height/2 * m.width)];
    pixelMask();
  }
  redraw();
}

void pixelMask() {
  //iterate through pixel array
  for (int x = 0; x < performanceClip.width; x++) {
    for (int y = 0; y < performanceClip.height; y++)
    {
      //location of individual pixels
      int loc = x + y * performanceClip.width;
      //what  is current color
      color currentColor = performanceClip.pixels[loc];
      //get color values
      int r1 = (currentColor >> 16) & 0xFF;  // Faster way of getting red(argb)
      int g1 = (currentColor >> 8) & 0xFF;   // Faster way of getting green(argb)
      int b1 = currentColor & 0xFF;//fast blue
      int r2 = (trackColor >> 16) & 0xFF;  // Faster way of getting red(argb)
      int g2 = (trackColor >> 8) & 0xFF;   // Faster way of getting green(argb)
      int b2 = trackColor & 0xFF; // Faster way of getting blue(argb)
      float d = distSq(r1, g1, b1, r2, g2, b2);
      //play with threshold values. greater than vs less than
      //if distance is below threshold squared
      if ( d < threshold * threshold) {
        performanceClip.pixels[loc] = color(0, 0, 0, 0);
      }
    }
  }
}


//3d distance for color comparison
float distSq(float x1, float y1, float z1, float x2, float y2, float z2) {
  float d = (x2-x1) * (x2-x1) + (y2 - y1 ) * (y2- y1) + (z2-z1) * (z2-z1);
  return d;
}


void keyPressed() {
  if (key == 'p') {
    println("playing");
    perfClipPlay = true;
  }
  if (key=='m') {
    maskOn=true;
  }
  if (key=='n') {
    maskOn=false;
  }
}

I’d be very grateful for some advice on this topic!