I would consider storing your sampled pixel colors in a 2D array instead of an arraylist:
float[][] array = new float[cols][rows];
I find it easier to grasp in regards to what you want to do after.
I checked your code with the arraylist though and here are few comments:
you need to separate your x resolution and your y resolution since the numbers of rows and columns can be differents as well as the size of your image
when you compute your resolutions, don’t forget to convert you cols and rows variables to a float so you get the correct result (otherwise you get an int as a result)
The order in wich you store your colors is really important and you need to first start to loop for the columns then loop for the row to get the same logic as the pixel array
To get the index of your pixel, it is better to round both i * resX and j * resY so it gives you the index of the closest pixel. Otherwise, you are rounding the index directly and can have a pixel on the other side of the image.
That beeing said, this is the result code. I also reduced the size of the image by a factor of 2:
PImage img;
ArrayList<Float> array = new ArrayList<Float>();
int cols = 200;
int rows = 200;
float rx, ry;
void setup() {
size(1600, 533);
img = loadImage("test.jpg");
rx = img.width / (float)cols; // Parse the cols variable to a float to keep decimals for rx
ry = img.height / (float)rows; // Parse the rows variable to a float to keep decimals for ry
for (int j = 0; j < rows; j++) { // Start looping through the rows
for (int i = 0; i < cols; i++) { // And then the columns to keep the same "pixel order" in your array
int p = int(i * rx) + int(j * ry) * img.width; //Get closest x AND closet y to get your index BUT DON'T get closest index directly => int(i * rx + j * ry * img.width)
float h = (red(img.pixels[p]) + green(img.pixels[p]) + blue(img.pixels[p]) + brightness(img.pixels[p]))/4.0;
array.add(h);
}
}
};
void draw() {
background(0);
// Resize picture by half
rx /= 2.0;
ry /= 2.0;
// Display resized image
for (int i = 0; i < cols; i++) {
for (int j = 0; j < rows; j++) {
noStroke();
fill(array.get(i + j * cols)); // Get index with same method as you would use for the index of a pixel of an image
rect(i * rx, j * ry, rx, ry);
}
}
// Display original image
image(img, 800, 0);
noLoop();
};