Draw rectangles with the mouse, background refresh

hello everybody,
I’m new to processing. I am looking to write a program in which I select an area of an image ( like “rect selection” in Photoshop for example…), this area has a red stroke and is slightly opaque, once the area is selected, the rectangle fills with the average color of the pixels of the same area and the red stroke turns off. The idea is to be able to repeat this action several times on the same image. When I released the mouse, the fill is erased because of “background(buff);” in “void draw();”. I would like the rectangle filled with the new color to be saved. I think I need to use an array, class, but I don’t understand how these work. If someone is able to help me, it would be a great help. Thank you.

PImage buff1;
int x1,y1,x2,y2,h1,h2;

void setup()
{
size(1000, 721);
buff1 = loadImage(“buff1.jpg”);
background(buff1);
}

color extractColorFromImage(final PImage buff1) {
buff1.loadPixels();
color r = 1, g = 1, b = 1;

for (final color c : buff1.pixels) {
r += c >> 020 & 255;
g += c >> 010 & 255;
b += c & 255;
}
r /= buff1.pixels.length;
g /= buff1.pixels.length;
b /= buff1.pixels.length;
return color(r, g, b);
}

void draw()
{
background(buff1);
rectMode(CORNERS);
stroke(255,0,0);
strokeWeight(2);
strokeJoin(ROUND);
rect(x1,y1,x2,y2,2);
fill(255,0,0,50);
noStroke();
cursor(ARROW);
}

void mousePressed()
{
x1 = mouseX;
y1 = mouseY;
}

void mouseDragged()
{
x2 = mouseX;
y2 = mouseY;
}

void mouseReleased()
{
{
int H1 = abs(1+x2-x1);
int H2 = abs(1+y2-y1);

for (int i=0; i<width; i+=H1)
{
for (int j=0; j<height; j+=H2)
{
PImage newImg = buff1.get(x1, y1, H1, H2);
fill(extractColorFromImage(newImg), 40);
noStroke();
cursor(ARROW);
}
}
}
}

You should use PGraphics instead of PImage. You then can simply draw your rect by referencing the PGraphics object and do rect on that one.

PGraphics pg;

void setup() {
size(800, 800);
img = loadImage(...);
pg = new PGraphics(img.width, img.height);
pg.background(img);
}

void drawOnPGraphics(color col, float x, float y, float w, float h) {
   fill(col);
   pg.rect(x, y, w, h);
}

Btw, why are you using final for the PImage parameter in colorExtract…?

ok … I’m not sure I understand … An error message appears “img can not be resolved to be a variable” … I admit to being lost and not knowing how to do it clearly

PImage buff;
int startX;
int startY;
int endX;
int endY;
boolean drawing;
int strokeW = 2;
int f = 0;
Shape shape;
 
PGraphics shapeLayer; 
ArrayList<PGraphics> layersList = new ArrayList();
 
void setup() {
  size(525, 700);
  //buff = loadImage("buff.jpg");
  //background(buff);
}
 
void draw() {

  buff = loadImage("buff.jpg");
  background(buff);
  if (f==0)
  {
    if (mousePressed == true)
    {
  strokeWeight(strokeW);
  stroke(255,0,0);
  fill(255,0,0,30);
 
  for(int i = 0; i < layersList.size(); i++) {
    image(layersList.get(i), 0, 0);
  }
  if (drawing) {
    shape.createRectangle();
    
  }}}
  if (f==0)
  {
    if (mousePressed == false)
    
  { 
       int H1 = abs(10+endX-startX); 
       int H2 = abs(10+endY-startY); 

  for (int i=0; i<width; i+=H1) 
    {
      for (int j=0; j<height; j+=H2) 
    {
  PImage newImg = buff.get(startX, startY, H1, H2);
      fill(extractColorFromImage(newImg), 40);
      rect(startX, startY, endX, endY,4);
      noStroke();
    }
    }
  }}
}
void mouseClicked() 
{
  if (f == 0) 
  {
    f = 1;
  } 
  else 
  {
    f = 0;
  }
}  
void mousePressed() {
  startX = mouseX;
  startY = mouseY;
 
  shapeLayer = createGraphics(width, height);
  shapeLayer.beginDraw();
}  
 
void mouseDragged() {
  drawing = true;
  endX = constrain(mouseX, 0, 525);
  endY = constrain(mouseY, 0, 700); 
 
  shape = new Shape(startX, startY, endX, endY);
  shapeLayer.clear();
}
 
void mouseReleased() {
  drawing = false;
  shapeLayer.endDraw();
}  

class Shape {
  int startX;
  int startY;
  int endX;
  int endY;
 
  Shape(int x1, int y1, int x2, int y2) {
    startX = x1;
    startY = y1;
    endX = x2;
    endY = y2;
  }    
 
  void createRectangle() {
    shapeLayer.strokeWeight(strokeW);
    shapeLayer.rectMode(CORNERS);  
    rectMode(CORNERS);
    rect(startX, startY, endX, endY);

 
 
  }
 
}  
color extractColorFromImage(PImage buff) {
  buff.loadPixels();
  color r = 1, g = 1, b = 1;
 
  for (color c : buff.pixels) {
    r += c >> 020 & 255;
    g += c >> 010 & 255;
    b += c        & 255;
  }
 
  r /= buff.pixels.length;
  g /= buff.pixels.length;
  b /= buff.pixels.length;
 
  return color(r, g, b);
}

otherwise I tried with this code, I’m close to the goal, but in both of them I really do not understand where I have to change for the rectangle fill by the color average is all the time displayed…

There was an error Message because that Code was not meant to be executed. It just shows how to use a PGraphics to do what you are trying to achieve…

I can‘t Test it right now, but you can probably do exactly what you want to achieve by replacing in your first Code, the PImage buff with a PGraphics and changing the way you intitialize it, then adding another PImage variable and set the background of your PGraphics to be that image. It‘s 2 changed lines and 3 lines of Code added. That should do it… actually, remember to change the reference to PImage into PGraphics, so some more lines changed… and i‘m not sure wether you can use background(PGraphics), so you might have to use image(PGraphics, x, y, w, h);