Different Paint tools for color picker

Hello everyone I am a beginner and I am trying to make four different drawing tools (one of them is a simple draw tool, i.e. dragging the mouse pointer draws pixels in the selected color; the other three tools could be, for example, a pipette, straight line, rectangle, spray paint, or ellipse tool). One tool or color can be assigned to each of the (left and right) mouse buttons; the default behavior is to draw a pixel with the current foreground color on the left mouse button click and with the current background color on right-click. A tool or color is assigned to the left of right mouse button by clicking on it. I only managed to do the colors and paint but i am stuck at the paint tools.

int cols=2;
int rows=10;
int counter;
int[] button = new int[5];
int col=0;
String saveText ="Save";
color f1 = color(0);
color f2 = color(255);
Cell[][] palette = new Cell[cols][rows];
color[] rectCol = new color[20];
void setup() {
  size(500,500);
  smooth();
  background(255);
  mousePressed();
  for (int i=0; i<cols; i++) {
    for (int j=0; j<rows; j++) {
      palette[i][j] = new Cell(i*20,j*20,20,20,2*j + i);
    }
  }
  rectCol[0] = color(0); //black
  rectCol[1] = color(255); //white
  rectCol[2] = color(46, 11, 11); //brown
  rectCol[3] = color(120, 10, 10); // dark red
  rectCol[4] = color(255, 0, 0); //red
  rectCol[5] = color(250, 71, 74); // light red
  rectCol[6] = color(245, 59, 255); //pinkish
  rectCol[7] = color(232, 0, 245); // pink
  rectCol[8] = color(129, 3, 137); //purple
  rectCol[9] = color(55, 55, 250); //light blue
  rectCol[10] = color(0, 0, 255); //blue
  rectCol[11] = color(0, 0, 150); //dark blue
  rectCol[12] = color(95, 247, 101); //light green
  rectCol[13] = color(0, 247, 10); //lime green
  rectCol[14] = color(0, 103, 4); //dark green
  rectCol[15] = color(58, 103, 0); //yellow green
  rectCol[16] = color(255, 255, 0); //yellow
  rectCol[17] = color(255, 100, 0); //orange
  rectCol[18] = color(155); // gray
  rectCol[19] = color(55); //grayer
}
void mousePressed(){
  // Check mouseX/mouseY against button position/size
  // Then if OK, save
  rect(420,10,50,30);
  fill(255);
  textSize(20);
  textAlign(CENTER, CENTER); 
  text(saveText, 421, 7, 50, 30);
  if (button[4]==1){
    rect(100,100,30,30);
  }
  
  if((mouseY<(button[1]+button[3]))&&(mouseY>(button[1]))){
  if((mouseX<(button[0]+button[2]))&&(mouseX>(button[0]))){
    col=150;
  }
  }

  //counter++;
  //String fileName = "savedImage-" + nf(counter, 3) + ".png";
  //// Save image here instead
  //println(fileName);
}

void draw() {
  for (int i=0; i<cols; i++) {
    for (int j=0; j<rows; j++) {
      palette[i][j].display();
      checkMouseOver(palette[i][j]);
    }
  }
  
}


void mouseDragged() {
  if (mouseButton == LEFT) {
    noFill();
    stroke(f1);
    strokeWeight(20);
    strokeJoin(ROUND);
    line(mouseX,mouseY,pmouseX,pmouseY);
  }
  if (mouseButton == RIGHT) {
    noFill();
    stroke(f2);
    strokeWeight(20);
    strokeJoin(ROUND);
    line(mouseX,mouseY,pmouseX,pmouseY);
  }
}
 
void checkMouseOver(Cell c) {
  if (mousePressed) {
    if (mouseButton == LEFT && mouseX > c.x && mouseX < c.x+c.w && mouseY > c.y && mouseY < c.y+c.h) {
      f1 = (get(mouseX,mouseY));
    }else if (mouseButton == RIGHT && mouseX > c.x && mouseX < c.x+c.w && mouseY > c.y && mouseY < c.y+c.h) {
      f2 = (get(mouseX,mouseY));
    }
  }
}
class Cell {
  float x,y,w,h;
  int c;
 
  Cell (float tempX, float tempY, float tempW, float tempH, int tempC) {
    x = tempX;
    y = tempY;
    w = tempW;
    h = tempH;
    c = tempC;
  }
  void display() {
    stroke(0);
    strokeWeight(3);
    fill(rectCol[c]);
    rect(x,y,w,h);
  }
}

A fill bucket and pipette tool should be fairly easy to make. In fact, I recently programmed these tools in my own paint program not too long ago. However, you need to change the way you store the color data of the picture. You could use a PGraphics objects for this. Some golobal variable like PGraphics picture; All the stroke(); fill(); rect(); line(); background(); can be apllied to a PGraphics object. In order to call these you need to write something like

PGraphics picture;
picture.beginDraw();
picture.background(255);
picture.endDraw();

In order to display this, use

image(picture, 0, 0);

You can access the individual pixels of this PGraphics object like so:

picture.beginDraw();
picture.loadPixels();
//you can now access the pixels[] with picture.pixels[index]
picture.updatePixels();  //only neccessary when the contents of pixels[] are modified
picture.endDraw();

This should make the pipette tool trivial.
Coding the fill bucket in such a way that it doesn’t completely lag the entire program can be quite challenging however (see this wikipedia article: https://en.wikipedia.org/wiki/Flood_fill, number 1 of alternative implementations). In my own program this looked like this:

color targetc = editImage.data[mx][my];  //thanks widipedia 200iq
color replacementc = color1*int(mouseButton==LEFT)+color2*int(mouseButton==RIGHT);
ArrayList<Position> queue = new ArrayList<Position> ();
queue.add(new Position(mx, my));
editImage.data[mx][my] = replacementc;
if (targetc != replacementc) {
  tabs.get(tabIndex).addBackup();
  while (queue.size() > 0) {
    int nx = queue.get(0).x;
    int ny = queue.get(0).y;
    queue.remove(0);
    if (nx > 0) {
      if (editImage.data[nx-1][ny] == targetc) {
        editImage.data[nx-1][ny] = replacementc;
        queue.add(new Position(nx-1, ny));
      }
    }
    if (nx < editImage.w-1) {
      if (editImage.data[nx+1][ny] == targetc) {
        editImage.data[nx+1][ny] = replacementc;
        queue.add(new Position(nx+1, ny));
      }
    }
    if (ny > 0) {
      if (editImage.data[nx][ny-1] == targetc) {
        editImage.data[nx][ny-1] = replacementc;
        queue.add(new Position(nx, ny-1));
      }
    }
    if (ny < editImage.h-1) {
      if (editImage.data[nx][ny+1] == targetc) {
        editImage.data[nx][ny+1] = replacementc;
        queue.add(new Position(nx, ny+1));
      }
    }
  }
}

I hope you can make any sense out of this. In my example, I have and object named editImage, which has a color [] [] data that stores the color of the pixels; in your example you would use the pixels[] of the PGraphics object.
I hoped this could help you.

O man, I really appreciate your help but I am still confused about how to implement this in my code. Sorry, I am still at the begging

Hello,

here is an example where you can draw a line by clicking twice (start and end of the line)

The trick is that

  • the potential line can be aborted.
  • You can also move it until you are happy with its position and then click again to draw it.
  • You can move it over an existing line without destroying the existing line.

Chrisir


// to draw a line click mouse once, release mouse, click mouse again and release mouse 

// The coordinates of the lines: each line goes "from" a point "to" a point (PVector).

// The lists are parallel in that sense that the elements of both lists together make a line: 
// the 0th element of both lists make one line, the 1st element of both lists make one line, the 2nd etc. 
ArrayList<PVector> from = new ArrayList(); 
ArrayList<PVector> to = new ArrayList();

// necessary to know if the mouse currently enters a "from" or a "to" point of a line: 
int situation=0;

// -------------------------------------------------------------------------
// processing core functions  

void setup() {
  size(600, 1000);
  stroke(255);
}//func

void draw() {
  background (0); 
  stroke(255);

  // show all stored lines 
  for (int i = 0; i < to.size(); i++) {
    PVector currentFrom = from.get(i);
    PVector currentTo   = to.get(i);
    // the line 
    linePV ( currentFrom, 
      currentTo );
  }//for

  // Eval siutuation here: 
  if (situation==0) {
    fill(255); 
    text("click and release mouse to start a line", 16, 16);
  } else if (situation==1) {
    // we show current (potential) line in GREEN
    stroke(0, 255, 0); 
    linePV(from.get(from.size()-1), 
      new PVector(mouseX, mouseY));
    //text  
    fill(0, 255, 0); // in GREEN 
    text("Move the mouse now to position the line. \nClick and release mouse to END the line. Key to abort the line.", 
      16, 16);
  }
}//func 

// -------------------------------------------------------------------------
// Inputs 

void mousePressed() {
  // depending on situation we store mouse-position as "from" or as "to" point 
  if (situation==0) 
    from.add (new PVector (mouseX, mouseY));
  else if (situation==1)
    to.add (new PVector (mouseX, mouseY));

  // manage situation variable  
  situation++;
  if (situation>1)
    situation=0;
}//func

void keyPressed() {
  if (situation==1) {
    from.remove(from.size()-1);
  }
  situation=0; 
  key=0; // kill ESC
}

// -------------------------------------------------------------------------
// Tools 

void linePV ( PVector pv1, PVector pv2) {
  line(pv1.x, pv1.y, 
    pv2.x, pv2.y);
}//func 
//

Hello !

Okay, you got a pretty cool color palette with a class Cell.

The cell knows each cell position and size.

(I just moved checkMouseOver() INSIDE the class, because it’s better)

Similar to Cell class you want a button class for your new command BUTTONs that knows its
position and size and text (Save, ellipse…).

When clicked, you need to evaluate it. I did this for SAVE.

For the other buttons I recommend to set a global variable int typeOfTool (so declare it before setup()) depending on the button, so

  • pipette would be 2, straight line 3, ellipse 4, rectangle 5 etc.

When you draw with the mouse, depending on typeOfTool act differently (draw ellipse or rectangle…).

Here is an example.

Warm regards,

Chrisir

// https://discourse.processing.org/t/different-paint-tools-for-color-picker/24931

// for image saving
int counter=0;  

// colors 
color f1 = color(0);
color f2 = color(255);
int cols=2;
int rows=10;
CellForColor[][] palette = new CellForColor[cols][rows];
color[] rectCol = new color[20];

// command buttons !!!!!!!!!!!!!!
String[] namesOfCommands = {
  "Save", 
  "Pipette", 
  "straight line", 
  "rectangle", 
  "spray paint", 
  "ellipse"
};
CellForCommandButton[] buttons = new CellForCommandButton[namesOfCommands.length];

// --------------------------------------------------------------------------------

void setup() {
  size(500, 500);
  smooth();
  background(255);

  // command buttons !!!!!!!!!!!!!!
  for (int j=0; j<buttons.length; j++) {
    // j is y here 
    buttons[j] = new CellForCommandButton(width-120, j*45+5, 
      100, 40, 
      namesOfCommands[j] );
  }//for 

  //------

  // colors 
  for (int i=0; i<cols; i++) {
    for (int j=0; j<rows; j++) {
      palette[i][j] = new CellForColor(i*20, j*20, 20, 20, 2*j + i);
    }
  }

  rectCol[0] = color(0); //black
  rectCol[1] = color(255); //white
  rectCol[2] = color(46, 11, 11); //brown
  rectCol[3] = color(120, 10, 10); // dark red
  rectCol[4] = color(255, 0, 0); //red
  rectCol[5] = color(250, 71, 74); // light red
  rectCol[6] = color(245, 59, 255); //pinkish
  rectCol[7] = color(232, 0, 245); // pink
  rectCol[8] = color(129, 3, 137); //purple
  rectCol[9] = color(55, 55, 250); //light blue
  rectCol[10] = color(0, 0, 255); //blue
  rectCol[11] = color(0, 0, 150); //dark blue
  rectCol[12] = color(95, 247, 101); //light green
  rectCol[13] = color(0, 247, 10); //lime green
  rectCol[14] = color(0, 103, 4); //dark green
  rectCol[15] = color(58, 103, 0); //yellow green
  rectCol[16] = color(255, 255, 0); //yellow
  rectCol[17] = color(255, 100, 0); //orange
  rectCol[18] = color(155); // gray
  rectCol[19] = color(55); //grayer
}

void draw() {
  // command buttons !!!!!!!!!!!!!!
  for (CellForCommandButton currentButton : buttons) {
    currentButton.display();
  }

  // colors 
  for (int i=0; i<cols; i++) {
    for (int j=0; j<rows; j++) {
      palette[i][j].display();
      palette[i][j].checkMouseOver();
    }
  }
}

// -----------------------------------------------------------------------------

void mousePressed() {
  // colors 
  for (int i=0; i<cols; i++) {
    for (int j=0; j<rows; j++) {
      if (  palette[i][j].checkMouseOver() ) 
        return;
    }
  }

  // 
  // command buttons !!!!!!!!!!!!!!
  // Check mouseX/mouseY against button position/size
  String foundCMD="NONE"; 
  for (CellForCommandButton currentButton : buttons) {
    foundCMD = currentButton.checkMouseOver();  
    if (!foundCMD.equals("NONE") ) {
      break;
    }//if
  }//for

  // if found a command 
  if  (!foundCMD.equals("NONE") ) {
    println(foundCMD); 
    // eval cmd 
    switch(foundCMD) {
    case "Save":
      //// Save image here 
      String fileName = "savedImage-" + nf(counter, 3) + ".png";
      println("saving "+fileName); 
      save(fileName);
      counter++;
      break;

    case "Pipette":
      break;

    case "straight line":
      break;

    case "line":
      break;

    case "rectangle":
      break;

    case "NONE":
      //ignore
      break; 

    default: 
      break;
    }//switch
    //
  }//if
}//func 

void mouseDragged() {
  if (mouseButton == LEFT) {
    noFill();
    stroke(f1);
    strokeWeight(20);
    strokeJoin(ROUND);
    line(mouseX, mouseY, pmouseX, pmouseY);
  }
  if (mouseButton == RIGHT) {
    noFill();
    stroke(f2);
    strokeWeight(20);
    strokeJoin(ROUND);
    line(mouseX, mouseY, pmouseX, pmouseY);
  }
}

// ==============================================================================

class CellForCommandButton {

  // for the Command Buttons !!!!!!!!!

  float x, y, 
    w, h;
  String textCommandButton=""; 

  CellForCommandButton (float tempX, float tempY, 
    float tempW, float tempH, 
    String tempText1) {
    x = tempX;
    y = tempY;
    w = tempW;
    h = tempH;
    textCommandButton = tempText1;
  }

  void display() {
    // rect 
    stroke(0);
    strokeWeight(1);
    fill(111); 
    rect(x, y, w, h);

    //text 
    fill(255);
    textAlign(CENTER, CENTER); 
    text(textCommandButton, 
      x+w/2, y+h/2);
  }

  String checkMouseOver() {
    if (mouseX > x &&
      mouseX < x+w && 
      mouseY > y && 
      mouseY < y+h) {
      return textCommandButton;
    }//if
    return "NONE";
  }//method
  //
}//class
//
// ==============================================================================

class CellForColor {

  // for the colors !!!!!!!!!

  float x, y, 
    w, h;
  int c;

  CellForColor (float tempX, float tempY, 
    float tempW, float tempH, 
    int tempC) {
    x = tempX;
    y = tempY;
    w = tempW;
    h = tempH;
    c = tempC;
  }

  void display() {
    stroke(0);
    strokeWeight(3);
    fill(rectCol[c]);
    rect(x, y, w, h);
  }

  boolean checkMouseOver() {
    if (mouseX > x &&
      mouseX < x+w && 
      mouseY > y && 
      mouseY < y+h) {
      if (mouseButton == LEFT) 
        f1 = (get(mouseX, mouseY));
      else  
      if (mouseButton == RIGHT)  f2 = (get(mouseX, mouseY));
      return true;
    }//if
    return false;
  }//method
  //
}//class
//

O man, that looks really good but I need to create the functionality for each button for them to work, right?

I did some like that but I just need to implement the buttons you created.

This is a link to my zip file i created.

1 Like

That’s right!

Looking forward to see it!