A mouse controlled Quadtree that samples an underlying image’s RGB values per rectangle centroid. Written in Processing 3 by Andrew Reitz and Armon Jahanshahi.
Download  Quadtree-Image-Sampler

/*
 qTree Image Sampler: Written by Andrew Reitz and Armon Jahanshahi @ Mode Lab on 4/22/2016.
 Objective: Create a Quad Tree. At the Centroid of each Rectangle in the Tree, sample the underlying Image's RGB Color Value. 
 */



// GLOBAL VARIABLES>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
PImage img;                                             // Declare Var. for the loaded Image. 
ArrayList<Float> x1 = new ArrayList<Float>();           // Array List for the Starting X Coordinate.
ArrayList<Float> x2 = new ArrayList<Float>();           // Array List for the Ending X Coordinate.
ArrayList<Float> y1 = new ArrayList<Float>();           // Array List for the Starting Y Coordinate. 
ArrayList<Float> y2 = new ArrayList<Float>();           // Array List for the Ending Y Coordinate. 
ArrayList<Float> cX = new ArrayList<Float>();           // Array List for the Centroid's X Coordinate. 
ArrayList<Float> cY = new ArrayList<Float>();           // Array List for the Centroid's Y Coordinate. 


// SETUP>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
void setup() {

  background(255);                            // Set the Background to Black. 
  size(1024, 768);                           // Set the Media Window to 600 x 600 Pixels
  rectMode(CORNERS);                        // Set the Rectangle Mode to "CORNERS". 
  img = loadImage("Aphex-Twin.jpg");         // Load the Image. 
  //img.resize(1600,900);
  loadPixels();                             // Load the Image's pixel data. 



  // Create Base Rectangle Coordinates. 
  x1.add(0.0);                              // Starting X Coordinate. 
  x2.add(float(width));                     // Ending X Coordinate.
  y1.add(0.0);                              // Starting Y Coordinate.
  y2.add(float(height));                    // Ending Y Coordinate. 

  cX.add(float(width/2));                   // Centroid's X Coordinate.
  cY.add(float(height/2));                  // Centroid's Y Coordinate. 

  fill(0);                                // Set the Base Rectangle's Fill to Black. 
  rect(0.0, 0.0, width, height);            // Create the Base Rectangle.
}



// DRAW>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
void draw() {
  if (mousePressed == true) {              // If my Mouse is Pressed.
    inclusionTest();                       // Run the inclusionTest(); Method. 
    drawRect();                            // Run the drawRect(); Method. 
  }
}



// METHODS  >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>


// 01 | IS MY MOUSE WITHIN THIS RECTANGLE?
void inclusionTest() {
  for (int i = x1.size()-1; i >= 0; i = i-1) {                                                        // Loop Backwards through the x1 ArrayList Size. 
    if (mouseX > x1.get(i) && mouseX < x2.get(i) && mouseY > y1.get(i) && mouseY < y2.get(i)) {       // If my Mouse is within the bounds of a Rectangle's Coordinates.  

      float stX = x1.get(i);                                                                          // stX is the starting x value of the sub Rects.                          
      float midX = (((x2.get(i)-x1.get(i))/2) + x1.get(i));                                           // midX is the middle x value of the sub Rects. 
      float endX = x2.get(i);                                                                         // endX is the ending x value of the sub Rects.

      float stY = y1.get(i);                                                                          // stY is the starting y value of the sub Rects. 
      float midY = ((y2.get(i)-y1.get(i))/2 + y1.get(i));                                             // midY is the middle y value of the sub Rects. 
      float endY = y2.get(i);                                                                         // endY is the ending y value of the sub Rects. 

      float stCentX = ((x2.get(i)-x1.get(i))/4)+x1.get(i);                                            // stCentX is the starting x centroid value. 
      float stCentY = ((y2.get(i)-y1.get(i))/4)+y1.get(i);                                            // stCentY is the starting y centroid value.
      float endCentX = ((x2.get(i)-x1.get(i))/4)+(((x2.get(i)-x1.get(i))/2)+x1.get(i));               // endCentX is the ending x centroid value. 
      float endCentY = ((y2.get(i)-y1.get(i))/4)+(((y2.get(i)-y1.get(i))/2)+y1.get(i));               // endCentY is the ending y centroid value.

 
      x1.add(stX);      // Top Left Starting X Coordinate. 
      x1.add(midX);     // Top Right Starting X Coordinate. 
      x1.add(stX);      // Bottom Left Starting X Coordinate. 
      x1.add(midX);     // Bottom Right Starting X Coordinate. 

      x2.add(midX);     // Top Left Ending X Coordinate. 
      x2.add(endX);     // Top Right Ending X Coordinate. 
      x2.add(midX);     // Bottom Left Ending X Coordinate. 
      x2.add(endX);     // Bottom Right Ending X Coordinate. 

      y1.add(stY);      // Top Left Starting Y Coordinate. 
      y1.add(stY);      // Top Right Starting Y Coordinate. 
      y1.add(midY);     // Bottom Left Starting Y Coordinate. 
      y1.add(midY);     // Bottom Right Starting Y Coordinate. 

      y2.add(midY);     // Top Left Ending Y Coordinate. 
      y2.add(midY);     // Top Right Ending Y Coordinate. 
      y2.add(endY);     // Bottom Left Ending Y Coordinate. 
      y2.add(endY);     // Bottom Right Ending Y Coordinate. 

      cX.add(stCentX);      // Top Left Centroid X Coordinate. 
      cX.add(endCentX);     // Top Right Centroid X Coordinate. 
      cX.add(stCentX);      // Bottom Left Centroid X Coordinate. 
      cX.add(endCentX);     // Bottom Right Centroid X Coordinate.

      cY.add(stCentY);      // Top Left Centroid Y Coordinate. 
      cY.add(stCentY);      // Top Right Centroid Y Coordinate. 
      cY.add(endCentY);     // Bottom Left Centroid Y Coordinate. 
      cY.add(endCentY);     // Bottom Right Centroid Y Coordinate. 

      x1.remove(i);  // Remove Parent Rectangle Starting X Coordinate.
      x2.remove(i);  // Remove Parent Rectangle Ending X Coordinate. 
      y1.remove(i);  // Remove Parent Rectangle Starting Y Coordinate. 
      y2.remove(i);  // Remove Parent Rectangle Ending Y Coordinate. 

      cX.remove(i);  // Remove Parent Rectangle Centroid X Coordinate. 
      cY.remove(i);  // Remove Parent Rectangle Centroid Y Coordinate. 
    }
  }
}


// 02 | DRAW RECTANGLES >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
void drawRect() {
  for (int i = 0; i < x1.size(); i++) {                // Loop Forward through the x1 ArrayList Size. - this will construct 4 new rectangles. 
    noStroke();                                        // Set the Stroke to no Stroke. 
    fill(img.get(int(cX.get(i)), int(cY.get(i))));     // Fill the Rectangle with the RGB Values sampled from New Rectangle Centroid. 
    rect(x1.get(i), y1.get(i), x2.get(i), y2.get(i));  // Construct the New Rectangle. 4 New Rectangles will be constructed for every mousePressed calculated. 
  }
}