Suppose I have a two-dimensional grid of pixels (4 by 4 pixels) - and I have an image the size of my sketch that has been cut into 16 parts. Now I load all 16 parts into an array. I want to map this array onto the 2D grid in turn, so that my overall image is put together again correctly. That is, top left image 0.png and bottom right image 16.png.
I just can't find the formula that allows me to do this. For example, I know that with x y*width
you can run trough all pixels – from top left to bottom right - so I tried that. Without *width
it doesn't sit together properly - with x y*width
- ArrayIndexOutOfBoundsException (for sure).
So I thought I needed a 2D array - but with images[x][y]
i get a NullPointerException. I attached you an image of what I am trying to create:
This is my code so far – without the 2D Array…
float pixelamount = 4;
float pixelsize;
PImage[] images = new PImage [16];
void setup() {
size(1080, 1080);
pixelsize = width/pixelamount;
for (int i = 0; i < images.length; i ) {
images[i] = loadImage(i ".png");
}
imageMode(CENTER);
}
void draw() {
background(0);
pushMatrix();
translate(pixelsize/2, pixelsize/2);
for (int x = 0; x < pixelamount; x ) {
for (int y = 0; y < pixelamount; y ) {
pushMatrix();
translate(pixelsize*x, pixelsize*y);
image(images[x y], 0, 0, pixelsize, pixelsize);
popMatrix();
}
}
popMatrix();
}
As I said – in the line image(images[x y], 0, 0, pixelsize, pixelsize);
I just do not get the math right. Do I need a 2D Array to solve this? Or something totally different?
CodePudding user response:
This should be resolved without 2D array.
If the dimensions of the field are known 4x4, then possibly the loop should run from 0 to 4 something like this:
void draw() {
background(0);
pushMatrix();
translate(pixelsize/2, pixelsize/2);
for (int x = 0; x < 4; x ) {
for (int y = 0; y < 4; y ) {
pushMatrix();
translate(pixelsize * x, pixelsize * y);
image(images[4 * x y], 0, 0, pixelsize, pixelsize);
popMatrix();
}
}
popMatrix();
}
CodePudding user response:
Alex is correct. Cyrill, you're on the right track but seem to get confused between 3 ways at looking at your data:
- The images array is a 1D array (indices 0 to 15)
- The for loop is nested therefore you need to convert 2D indices to 1D. You are right:
x y*width
would give you the correct array index, but in this casewidth
is not the full width of your sketch in pixels but the width of the grid (i.e. the number of columns in the 4x4 grid: 4) - You are getting a null pointer pointer because you're trying to access elements in a 1D array as if it's 2D.
Something like this should work:
float pixelamount = 4;
float pixelsize;
PImage[] images = new PImage [16];
void setup() {
size(1080, 1080);
pixelsize = width/pixelamount;
for (int i = 0; i < images.length; i ) {
images[i] = loadImage(i ".png");
}
//imageMode(CENTER);
}
void draw() {
background(0);
pushMatrix();
translate(pixelsize/2, pixelsize/2);
for (int x = 0; x < pixelamount; x ) {
for (int y = 0; y < pixelamount; y ) {
pushMatrix();
translate(pixelsize*x, pixelsize*y);
image(images[x y * pixelamount], 0, 0, pixelsize, pixelsize);
popMatrix();
}
}
popMatrix();
}
If you want to loop with a single for loop (instead of a nested for loop) which would match how you store your data you can use this formula to go from 1D index to 2D indices:
x = index % gridColumns
y = index / gridColumns
(Bare in mind these are integers (so in other languages (like Python/JS/etc.) you'd pay attention to the division operation))
Here's a basic example to illustrate this:
size(1080, 1080);
textAlign(CENTER, CENTER);
textFont(createFont("Courier New Bold", 12));
int pixelAmount = 4;
int pixelSize = width/pixelAmount;
int gridColumns = 4;
// iterate once
for(int i = 0; i < 16; i ){
// calculate 2D grid indices
int xIndex = i % gridColumns;
int yIndex = i / gridColumns;
// convert from index to pixel size
int x = xIndex * pixelSize;
int y = yIndex * pixelSize;
// render debug data
String debugText = "1D index:" i
"\n2D indices:[" xIndex "][" yIndex "]"
"\nx, y pixels::" x "," y;
fill(255);
rect(x, y, pixelSize, pixelSize);
fill(0);
text(debugText, x pixelSize / 2, y pixelSize / 2);
}
Here's the same example as the above using a 2D array and nested loops:
size(1080, 1080);
textAlign(CENTER, CENTER);
textFont(createFont("Courier New Bold", 12));
int pixelAmount = 4;
int pixelSize = width/pixelAmount;
int[][] grid = new int[pixelAmount][pixelAmount];
// mimick image loading (storing 1D index)
int index = 0;
for(int y = 0; y < pixelAmount; y )
for(int x = 0; x < pixelAmount; x )
grid[x][y] = index ;
// mimick reading 2D array data
for(int y = 0; y < pixelAmount; y ){
for(int x = 0; x < pixelAmount; x ){
int xPixels = x * pixelSize;
int yPixels = y * pixelSize;
// manually copute index
// index = x y * pixelAmount;
// or retrieve stored index
index = grid[x][y];
String debugText = "1D index:" index ".png"
"\n2D indices:[" x "][" y "]"
"\nx, y pixels::" xPixels "," yPixels;
fill(255);
rect(xPixels, yPixels, pixelSize, pixelSize);
fill(0);
text(debugText, xPixels pixelSize / 2, yPixels pixelSize / 2);
}
}
My answer is more for the sake of completeness: displaying both 1D/2D ways at looking at the data.
CodePudding user response:
Based on the latest answer – this is my code – working perfectly!
float pixelamount = 4;
float pixelsize;
PImage[] images = new PImage [16];
void setup() {
size(1080, 1080);
pixelsize = width/pixelamount;
for (int i = 0; i < images.length; i ) {
images[i] = loadImage(i ".png");
}
imageMode(CENTER);
}
void draw() {
background(0);
pushMatrix();
translate(pixelsize/2, pixelsize/2);
for (int x = 0; x < pixelamount; x ) {
for (int y = 0; y < pixelamount; y ) {
pushMatrix();
translate(pixelsize * x, pixelsize * y);
image(images[x y * int(pixelamount)], 0, 0, pixelsize, pixelsize);
popMatrix();
}
}
popMatrix();
}