Change rgb pixel color when overllaping

Hello everyone, I wrote a well commented code. I want to change the color of an object but only the part that is overlapping with a shape (rectangle). Please help me, thank you for your time.

import processing.video.*;
Movie myMovie;
Video v1;

void setup() {
  size (640, 640);
  myMovie = new Movie(this, "fogata.mp4");
  myMovie.loop();

  v1 = new Video(4096/10, 2160/10);
}
void draw() {
  background(0);
  v1.dip();
  v1.display();
}
void movieEvent(Movie m) {
  m.read();
}
class Video {
  float rectW, rectH;
  float rectX, rectY;
  float w= width+1, h= height/2;
  float x = -1, y = 320;
  Video(float w, float h) {
    rectW = w;
    rectH = h;
  }
  void dip() {
    loadPixels();
    myMovie.loadPixels(); 

    //collision detection
    if (rectX+rectW > x && rectX < x + w
      && rectY +rectH > y && rectY < y+h) {

      //campture distance of dipping
      float tinting = rectY - y;
      float distanceToTint = tinting;
      println(tinting);

      //access video pixels
        for (int a= 0; a< 0; a++) {
        for (int d= 0; d< 0; d++) {
          int loc = a*d*myMovie.width;
          //three colors from pixels
          float r = red(myMovie.pixels[loc]);
          float g = green(myMovie.pixels[loc]);
          float b = blue(myMovie.pixels[loc]);
          
          //change rgb value by distance
          b *= distanceToTint;
          
          //set the display pixel to video pixel
          pixels[loc] = color(r, g, b);
        }
      }
      updatePixels();
    }
  }
  void display() {
    fill(0, 255, 255);
    rect(x, y, w, h);
    rectX = mouseX;
    rectY = mouseY;
    image(myMovie, rectX, rectY, rectW, rectH);
  }
}

So it is not clear what you wrote. I mean, if you read your code, one can only guess what you mean. You are referring to an object and a shape. Is your object the video? The shape is the rectangle in the bottom half?

Also, do you mean to do this pixels[loc] = color(r, g, b); (currently) or this myMovie.pixels[loc] = color(r, g, b);?

Last, you need to fix this:

for (int a= 0; a< 0; a++) {
for (int d= 0; d< 0; d++) {

Kf

color c = color(0, 255, 102);

void dip() {
    loadPixels();
    myMovie.loadPixels(); 

    //collision detection
    if (rectX+rectW > x && rectX < x + w
      && rectY +rectH > y && rectY < y+h) {

      //campture distance of dipping
      float tintOnly = h - rectH;
      println(tintOnly);


      //access video pixels
      for (int i = 0; i < myMovie.height/2 *width+tintOnly; i++) {

        myMovie.pixels[i]=c;

      }

      updatePixels();
    }
  }

Please do not create code-only posts with no question or discussion.

Is it your solution? It is the same problem, or another problem? What part isn’t working?

You list a funtion dip() – but don’t show it being used. What is this code fragment?

It is part of the original question, in response Kfrajer suggestions. I managed to change the pixels colors when the object overlaps the rectangle but the pixels changing are at the top of the object instead of at the bottom. The idea is to change the color of the object from the bottom up progressively, depending on how much the object is overlapping the rectangle the amount of pixels color change . So if the two (the video object and the rectangle) are completely overlapped all the object’s pixels change color.

Here the complete code


import processing.video.*;
Movie myMovie;
Video v1;


void setup() {
  size (640, 640);
  myMovie = new Movie(this, "fogata.mp4");
  myMovie.loop();

  v1 = new Video(4096/10, 2160/10);
}
void draw() {
  background(0);
  v1.dip();
  v1.display();
}
void movieEvent(Movie m) {
  m.read();
}
class Video {
  float rectW, rectH;
  float rectX, rectY;

  float w= width+1, h= height/2;
  float x = -1, y = 320;

  color c = color(0, 255, 102);

  Video(float w, float h) {
    rectW = w;
    rectH = h;
  }

void dip() {
    loadPixels();
    myMovie.loadPixels(); 

    //collision detection
    if (rectX+rectW > x && rectX < x + w
      && rectY +rectH > y && rectY < y+h) {


      //access video pixels
      for (int i = 0; i < (myMovie.height)*(rectY+rectH+mouseY); i++) {

        myMovie.pixels[i]=c;

      }

      updatePixels();
    }
  }
  void display() {
    fill(0, 255, 255);
    rect(x, y, w, h);

    rectX = mouseX;
    rectY = mouseY;
    image(myMovie, rectX, rectY, rectW, rectH);
  }
}

Could this be tested without requiring fogata.mp4?

If so, what should be commented out or replaced?

If not, where can we get fogata.mp4 or a suitable replacement movie of the same dimensions?

here’s a download link for a 7 second video clip. https://videos.pexels.com/videos/blurred-bokeh-video-855204

1 Like

Thanks – that works well for testing your code.

The first thing that I notice is that you have several surprising numbers stored in your class. For example:

  float w = width+1;
  float h = height/2;
  float x = -1;
  float y = 320;

Later on you do math on the pixels array based in part on these numbers – specifically, in dip(). But I don’t think those values are what you think they are.

Can you explain plainly what x/y/w/h represents, vs rectX/rectY/rectW/rectH?

Alternate approach:

For your purposes, there is a much simpler way of computing the starting pixel in Video to begin blocking out. That is the row width of the Video * the height of the intersection – just those two values gives you an index. The key question is, what is the height of the intersection?

Rather than looping through every pixel and testing it, just skip straight to that index as the first value of your for loop: for x = myStartingIndex; x < myMovie.pixels.length; x++)` … and alter every pixel value from then on.

I also want to point out that, for performance optimization, your current approach is extremely expensive. Your video is 1920 × 1080 (2,073,600 pixels), but you are only drawing 419 x 216 onto the screen (~90,504). So you are looping through and checking 2 million+ pixels each frame, rewriting them, then resizing the end result down to the five-argument image(), which is an expensive transformation that also throws away 96% of your changes.

If speed matters, a more efficient approach is:

  1. load the movie frame
  2. resize the frame
  3. rewrite pixels in the resized frame
  4. draw the resized frame

Or even skip rewriting pixels altogether:

  1. load the movie frame
  2. resize the frame
  3. copy-draw only the top part of the movie frame onto the screen
    https://processing.org/reference/copy_.html
  4. draw a colored rectangle onto the bottom part of the screen
    https://processing.org/reference/rect_.html

Thank you so much. I have a rectangle with stored positions at x and y and width as w and height as h. Object position is stored as rectX, rectY and the width and height as rectH, rectW. Since rect is the function that makes the rectangle it only makes sense for me to name the variables the other way… oops.

I’m making all the changes, thank you for you time.

I made the for-loop change and it works but it doesn’t do what I want, which is : the image-object ( image(myMovie, rectX, rectY, rectW, rectH)) to gradually increase or decrease the pixel color change by overlapping with the rect(x, y, w, h). So, I need to capture the height of the rectangle and subtracted the object’s height and apply that some how with the ‘y’ coordinates and then make a conditional statement, if y++ then increase pixel index color change, else if y-- decrease/leave as is.