Trying to make a nested list for pixel storage

I’m trying to make a program that finds the average pixel color of pixel clusters of an image. I’m having trouble making a list to store those averages ((int red, int green, int blue), (int red, int green, int blue), etc.)
I’ve tried regular int[] arrays and ArrayLists<> and neither has been useful.
I can post my code if necessary but it isn’t very interesting right now.
Thank you.

Please post your code. Without seeing it, it’s hard to know what you are having trouble with. Is it picking a cluster of pixels? Counting them? Looping over them? Getting the R/G/B values from a color? Keeping a running total for the R/G/B values? Working out the average? Working with the color type?

Without seeing what you’re doing, we don’t even know where to start. So please, post your code.

Always post your code…

the thing is, I have three different docs im working with. I know how to get the clusters and how to get the averages, i just need a global list to store the pixels in.
Below is a demonstration of getting the total image average color and for covering the background in tiles, but the tiles are all the same color and not the color of the image they’re covering

ArrayList cr = new ArrayList(); // this is where i want my nested list to hold the pixels
PImage thing = loadImage(“smash-01.jpg”);
size(720, 405);
thing.resize(720, 405);
background(thing);
//populate list
int red = 0;
int green = 0;
int blue = 0;
int count = 0;
for(int i = 0 ; i < width; i++){
for(int j = 0; j < height; j++){
color c = get(i+8, j+4);
cr.add(color(get(i,j)));
print(get(i,j));
red += red©; //gets total red in the image
green += green©; // gets total green
blue += blue©; // gets total blue
count++; // counts the pixels
}
}

//retrieve values from list
for(int i = 0 ; i < width; i++){
for(int j = 0; j < height; j++){
//noStroke();
fill(cr.get(j));
rect(i16,j9,16,9);
}
fill(red/count, green/count, blue/count);
rect(width/2 - 50, height/2 - 50, 100, 100);
}

Hi CottonSquab,

Lists can be generic, so supplying the type of data they will contain will let you get the most out of them. Colors in Processing are integers, for example 0xffff7f00 equals -33024. The red, green, blue and alpha functions can be used to extract each channel from the color (bitwise operators are faster).

A list of integers ArrayList<Integer> cr = new ArrayList<Integer>(); could store colors from a source image with cr.add(thing.get(0, 0); or cr.add(thing.pixels[0]); (following thing.loadPixels();). I’m not sure I understand why a nested list is necessary, but even so, is this what you are looking for?

ArrayList<ArrayList<Integer>> nestedList
  = new ArrayList<ArrayList<Integer>>();

void setup() {
  size(128, 128);
  for (int i = 0; i < width; ++i) {
    ArrayList<Integer> innerList = new ArrayList<Integer>();
    for (int j = 0; j < height; ++j) {
      innerList.add(
        color(random(255.0), 
        random(255.0), 
        random(255.0), 
        255.0));
    }
    nestedList.add(innerList);
  }

  int i = 0;
  loadPixels();
  for (ArrayList<Integer> outerList : nestedList) {
    for (Integer clr : outerList) {
      pixels[i++] = clr;
    }
  }
  updatePixels();
}

Since you’d like to analyze color channels separately, it might be helpful to find or create a Color class and load the list with objects of that type. As an example

static class Color {
  static final float ONE_255TH = 1.0 / 255.0;
  static final String STRING_FORMAT = "( %.2f, %.2f, %.2f, %.2f )";
  float r = 0.0, g = 0.0, b = 0.0, a = 0.0;

  Color() { }
  Color(color clr) { set(clr); }
  Color(float r, float g, float b, float a) { set(r, g, b, a); }

  String toString() {
    return String.format(STRING_FORMAT, r, g, b, a);
  }

  Color set(color clr) {
    // Format: 0xAARRGGBB
    // Transparency is in 24th place; red, 16th; green, 8th; blue 0th.
    return set((clr >> 16 & 0xff) * ONE_255TH, 
      (clr >> 8 & 0xff) * ONE_255TH, 
      (clr & 0xff) * ONE_255TH, 
      (clr >> 24 & 0xff) * ONE_255TH);
  }

  Color set(float r, float g, float b, float a) {
    this.r = constrain(r, 0.0, 1.0);
    this.g = constrain(g, 0.0, 1.0);
    this.b = constrain(b, 0.0, 1.0);
    this.a = constrain(a, 0.0, 1.0);
    return this;
  }

  color toInteger() {
    return int(a * 255.0) << 24
      | int(r * 255.0) << 16
      | int(g * 255.0) << 8
      | int(b * 255.0);
  }
}

If you want to store the x and y location at which that color was found, that could be included, too, if this were a Pixel class. If need be, you can also sort the list with Comparator<Color> objects.

The main sketch:

PImage diagnosticImage;
int kernelSize = 32;
ArrayList<Color> colors = new ArrayList<Color>(kernelSize * kernelSize);
Color average = new Color();

void setup() {
  size(512, 512);
  rectMode(CENTER);
  diagnosticImage = loadImage("exmpl.jpg");
  diagnosticImage.resize(width, height);
  diagnosticImage.loadPixels();
}

void draw() {
  background(diagnosticImage);

  // Show average.
  kernel(diagnosticImage, kernelSize, mouseX, mouseY, colors);
  color avg = averageColor(colors, average).toInteger();
  stroke(0xffffffff);
  fill(avg);
  rect(mouseX, mouseY, kernelSize + 1, kernelSize + 1);
}

static Color averageColor(ArrayList<Color> clrList) {
  return averageColor(clrList, new Color());
}

static Color averageColor(ArrayList<Color> clrList, Color out) {
  int sz = clrList.size();
  if (sz == 0) {
    return out.set(0.0, 0.0, 0.0, 0.0);
  }

  float denom = 1.0 / float(sz);
  float r = 0.0;
  float g = 0.0;
  float b = 0.0;
  float a = 0.0;
  for (int i = 0; i < sz; ++i) {
    Color current = clrList.get(i);
    r += current.r;
    g += current.g;
    b += current.b;
    a += current.a;
  }

  return out.set(r * denom, g * denom, b * denom, a * denom);
}

static ArrayList<Color> kernel(PImage source, int kernelSize, 
  int centerX, int centerY) {
  return kernel(source, kernelSize, centerX, centerY, 
    new ArrayList<Color>(kernelSize * kernelSize));
}

static ArrayList<Color> kernel(PImage source, int kernelSize, 
  int centerX, int centerY, ArrayList<Color> clrList) {
  clrList.clear();
  int w = source.width;
  int halfSize = kernelSize / 2;

  // Clamp ranges to size of image to prevent
  // array out of bounds exception.
  int minX = centerX - halfSize;
  minX = minX < 0 ? 0 : minX;

  int maxX = centerX + halfSize;
  maxX = maxX > w ? w : maxX; 

  int minY = centerY - halfSize;
  minY = minY < 0 ? 0 : minY;

  int maxY = centerY + halfSize;
  maxY = maxY > source.height ? source.height : maxY;

  for (int x = minX, y; x < maxX; ++x) {
    for (y = minY; y < maxY; ++y) {
      int index = x + w * y;
      Color current = new Color(source.pixels[index]);
      clrList.add(current);
    }
  }
  return clrList;
}

Hope that is helpful.