Array of pixels (enclosed in shape)

Hi there!

If you draw a closed shape in processing, is there a way to get all points/pixels that the shape encloses in a separate array?

Best wishes,
Wouter

Hi @Wouter,

Welcome to the forum! :wink:

There’s probably multiple ways to do this but one that came to my mind:

Use a separate PGraphics instance to display your shape and then loop over all the pixels of the canvas and filter those who are exactly the color that you drew.

This might be expensive to compute depending on the size of the off-screen canvas but then you can draw complex flat shapes (by combining a circle and a square for example, mixing fill and stroke…) and it will work.

Don’t hesitate to ask if you have more questions! :yum:

2 Likes

Hello @Wouter ,

This tutorial may be of interest:

:)

Hi

1 Like

What is your goal with the array?

Thanks for all comments! For example if you want to rotate only a subselection of an image. I would draw a shape, get all these pixels and do a coordinate transformation. But there might be other options?

Are you working on a drawing program?

Your way is certainly possible.

It might be easier though when you store the shapes in an ArrayList (and not put all pixels to the canvas directly)

you could also work with different layers of PGraphics.

Example with ArrayList

  • Use 0,1,2 to choose type of shape (circle, rect, triangle)
  • click mouse to place a shape at mouse position
  • use Backspace to delete last
  • use ‘c’ to clear all
  • Use right mouse to drag previous items (shown in red).

Here you have access to each item and could change size and rotation also (when you program this). Hence you don’t need to know the pixels in the first place.

ArrayList<Shape> list = new ArrayList();

int currentShapeToGenerate = 0;

boolean hold = false;
int i_hold=0;

String[] texts = {
  "circle",
  "square",
  "triangle"
};

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

void setup() {
  size(1000, 700);
}

void draw() {
  background(0);

  // display all
  int i=0;
  for (Shape d : list) {
    // set col
    fill(255);
    if (hold&&i==i_hold) {
      fill(255, 0, 0);
    }
    // display
    d.display();
    //  d.move();
    i++;
  }//for

  // drag
  if (hold) {
    list.get(i_hold).setX( mouseX);
    list.get(i_hold).setY( mouseY);
  }

  // text
  fill(255);
  text ("Use 0,1,2, click mouse, use Backspace and 'c'.\nUse right mouse to drag previous items. \n"+ texts[ currentShapeToGenerate ], 17, 17);
}

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

void mousePressed() {

  if (mouseButton == LEFT ) { // ----------------------------------

    Shape newShape = null ;

    switch( currentShapeToGenerate ) {
    case 0:
      newShape = new shapeCircle (mouseX, mouseY);
      break;

    case 1:
      newShape = new shapeSquare (mouseX, mouseY);
      break;

    case 2:
      newShape = new shapeTriangle (mouseX, mouseY);
      break;
    }//switch

    // add
    if (newShape!=null)
      list.add(newShape);
  } else {
    // right mouse ------------------------------
    int i=0;
    for (Shape d : list) {
      if (dist(mouseX, mouseY, d.getX(), d.getY())<11) {
        //
        hold=true;
        (i_hold)=i;
      }
      i++;
    }
  }
}//func

void mouseReleased() {
  hold = false;
}

void keyPressed () {
  if (key=='0'||key=='1'||key=='2') {
    currentShapeToGenerate=int(key+"");
  } else if (key==ESC) {
    key=0;//kill Esc
  } else if (key==BACKSPACE) {
    //
    if (list.size()>0)
      list.remove(list.size()-1);
  } else if (key=='c') {
    list.clear();
  }
  //else if

  //
}// func

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

// not called directly
interface Shape {
  void move();
  void display();
  float getX();
  float getY();
  void setX(float x_);
  void setY(float y_);
} //interface

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

class shapeCircle implements Shape {
  float x = 50;
  float y = 50;

  shapeCircle(float x_, float y_) {
    x=x_;
    y=y_;
  }

  void move() {
    x = x + random(-1, 1);
  }

  void display() {
    ellipse(x, y, 16, 16);
  }

  Shape copy() {
    return new shapeCircle(x, y);
  }

  float getX() {
    return x;
  }
  float getY() {
    return y;
  }

  void setX(float x_) {
    x=x_;
  }
  void setY(float y_) {
    y=y_;
  }
} //class

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

class shapeSquare implements Shape {
  float x = 50;
  float y = 50;

  shapeSquare(float x_, float y_) {
    x=x_;
    y=y_;
  }

  void move() {
    y = y + random(-1, 1);
  }

  void display() {
    rect(x, y, 16, 16);
  }
  float getX() {
    return x;
  }
  float getY() {
    return y;
  }
  void setX(float x_) {
    x=x_;
  }
  void setY(float y_) {
    y=y_;
  }
} //class

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

class shapeTriangle implements Shape {
  float x = 50;
  float y = 50;

  shapeTriangle(float x_, float y_) {
    x=x_;
    y=y_;
  }

  void move() {
    y = y + random(-1, 1);
  }

  void display() {
    triangle(x, y,
      x+36, y,
      x+3, y+39);
  }
  float getX() {
    return x;
  }
  float getY() {
    return y;
  }
  void setX(float x_) {
    x=x_;
  }
  void setY(float y_) {
    y=y_;
  }
} //class
//


Another example

  • here you can drag, resize and rotate each item individually

// Demo for Drawing Program with ArrayList

// for mouse is on item / drag
final float hotSpotSize = 22; // radius

// Help text
final String helpText =
  "Use 0,1,2, click mouse, use Backspace and 'c'.\n"
  + "Use right mouse to drag previous items. \nWhen you hold an item (right mouse button) use cursor to change size and rotation, use DEL to remove.";

// shapes / items
ArrayList<Shape> listShapes = new ArrayList();

// the type we add
int currentShapeToGenerate = 0;

// current shape we are adding (from currentShapeToGenerate)
String[] texts = {
  "circle",
  "square",
  "triangle"
};

// mouse drag
boolean hold = false;
int i_hold=0;

// -----------------------------------------------------------------------------------------------
// Core funcs

void setup() {
  size(1000, 700);
}

void draw() {
  background(0);

  // display all
  displayShapes();

  // drag
  dragItem();

  // show when mouse is on Hot Spot
  showSmallRedCircleOnHotSpot();

  // text
  showText();
}

// -----------------------------------------------------------------------------------------------
// Input funcs

void mousePressed() {

  if (mouseButton == LEFT) { // ----------------------------------

    Shape newShape = null ;

    switch( currentShapeToGenerate ) {
    case 0:
      newShape = new shapeCircle (mouseX, mouseY);
      break;

    case 1:
      newShape = new shapeSquare (mouseX, mouseY);
      break;

    case 2:
      newShape = new shapeTriangle (mouseX, mouseY);
      break;
    }//switch

    // add
    if (newShape!=null) {
      listShapes.add(newShape);
    } //if
    //
  } else {
    // right mouse button --------------------------------
    // search the item to drag
    int i=0;
    for (Shape currentShape : listShapes) {
      if ( currentShape.underMouse() ) {
        // store the item to drag
        hold=true;
        i_hold=i;
        return;
      }
      i++;
    }
  }
}//func

void mouseReleased() {
  hold = false;
}

void keyPressed() {
  // get keys:
  // these first keys apply always ---
  if (key=='0'||key=='1'||key=='2') {
    currentShapeToGenerate=int(key+"");
  } else if (key==ESC) {
    key=0;//kill Esc
  } else if (key==BACKSPACE) {
    // delete last item
    if (listShapes.size()>0)
      listShapes.remove(listShapes.size()-1);
  } else if (key=='c') {
    listShapes.clear();
  } else if ( hold && keyCode == DELETE ) {  // these following keys only apply when we hold a shape ---
    listShapes.remove(i_hold);
    hold=false;
  } else if ( hold && keyCode == LEFT ) {
    listShapes.get(i_hold).incAngle();
  } else if ( hold && keyCode == RIGHT ) {
    listShapes.get(i_hold).decAngle();
  } else if ( hold && keyCode == UP ) {
    listShapes.get(i_hold).incSize();
  } else if ( hold && keyCode == DOWN ) {
    listShapes.get(i_hold).decSize();
  }
  //
}// func

// --------------------------------------------------------------------------------------------
// Other funcs

void displayShapes() {
  stroke(0);
  int i=0;
  for (Shape currentShape : listShapes) {
    // set color (hold / not hold)
    fill(255); // White = not hold
    if (hold && i==i_hold) {
      fill(255, 0, 0); // Red = hold
    }
    // display
    currentShape.display();
    // currentShape.move();
    i++;
  }//for
}

void dragItem() {
  if (hold) {
    listShapes.get(i_hold).setX(mouseX);
    listShapes.get(i_hold).setY(mouseY);
  }//if
}

void showSmallRedCircleOnHotSpot() {
  for (Shape currentShape : listShapes) {
    if (currentShape.underMouse()) {
      // display the empty red circle
      currentShape.showSmallRectCircle();
      return;
    }//if
  }//for
}

void showText() {
  fill(255);
  text (helpText
    + "\n"
    + "curent > "
    + texts[ currentShapeToGenerate ], 17, 17);
}

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

// not called directly
interface Shape {
  void display();
  void move();

  float getX();
  float getY();

  void setX(float x_);
  void setY(float y_);

  void incAngle();
  void decAngle();

  void incSize();
  void decSize();

  boolean underMouse();

  void showSmallRectCircle();
} //interface

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

class shapeCircle implements Shape {
  float x = 50;
  float y = 50;
  float angle;
  float size1=25;

  shapeCircle(float x_, float y_) {
    x=x_;
    y=y_;
  }

  void move() {
    x = x + random(-1, 1);
  }

  void display() {
    fill(255);
    ellipse(x, y, size1, size1);
  }

  Shape copy() {
    return new shapeCircle(x, y);
  }

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

  float getX() {
    return x;
  }
  float getY() {
    return y;
  }

  void setX(float x_) {
    x=x_;
  }
  void setY(float y_) {
    y=y_;
  }
  void incAngle() {
    angle+=0.01;
  }
  void decAngle() {
    angle-=0.01;
  }

  void incSize() {
    size1+=1;
  }
  void decSize() {
    size1-=1;
  }
  boolean underMouse() {
    return
      dist(mouseX, mouseY, x, y)<hotSpotSize;
  }
  void showSmallRectCircle() {
    // display the empty red circle
    noFill();
    stroke(255, 0, 0);
    circle(x, y, hotSpotSize);
  }
} //class

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

class shapeSquare implements Shape {
  float x = 50;
  float y = 50;
  float angle=0;
  float size1 = 25;

  shapeSquare(float x_, float y_) {
    x=x_;
    y=y_;
  }

  void move() {
    y = y + random(-1, 1);
  }

  void display() {
    rectMode(CENTER);
    push();
    translate(x, y);
    rotate(angle);
    rect(0, 0, size1, size1);
    pop();
    //reset
    rectMode(CORNER); // default mode
  }

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

  float getX() {
    return x;
  }
  float getY() {
    return y;
  }
  void setX(float x_) {
    x=x_;
  }
  void setY(float y_) {
    y=y_;
  }
  void incAngle() {
    angle+=0.01;
  }
  void decAngle() {
    angle-=0.01;
  }
  void incSize() {
    size1+=1;
  }
  void decSize() {
    size1-=1;
  }
  boolean underMouse() {
    return
      dist(mouseX, mouseY, x, y)<hotSpotSize;
  }
  void showSmallRectCircle() {
    // display the empty red circle
    noFill();
    stroke(255, 0, 0);
    circle(x, y, hotSpotSize);
  }
} //class

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

class shapeTriangle implements Shape {
  float x = 50;
  float y = 50;
  float angle;
  float size1=25;

  shapeTriangle(float x_, float y_) {
    x=x_;
    y=y_;
  }

  void move() {
    y = y + random(-1, 1);
  }

  void display() {
    push();
    translate(x, y);
    rotate(angle);
    triangle(0, 0,
      0-size1, 0,
      0, 0+size1);
    pop();
  }

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

  float getX() {
    return x;
  }
  float getY() {
    return y;
  }
  void setX(float x_) {
    x=x_;
  }
  void setY(float y_) {
    y=y_;
  }
  void incAngle() {
    angle+=0.01;
  }
  void decAngle() {
    angle-=0.01;
  }
  void incSize() {
    size1+=1;
  }
  void decSize() {
    size1-=1;
  }
  boolean underMouse() {
    return
      dist(mouseX, mouseY, x, y)<hotSpotSize;
  }
  void showSmallRectCircle() {
    // display the empty red circle
    noFill();
    stroke(255, 0, 0);
    circle(x, y, hotSpotSize);
  }
} //class
//

1 Like

If it’s a simple shape like a rectangle selection, you can use the get() function to grab the section of an image. You can then display it and rotate it freely.

Thanks a lot, I ll explore these options!!

2 Likes