I've been trying to copy a p5 script into processing for a school project but I cant completely figure it out. Here you can find the original script : https://www.youtube.com/watch?v=KfLqRuFjK5g
I keep getting this error : ArrayIndexOutOfBoundsException: Index 5832960 out of bounds for length 5801040.
Thanks in advance!
PImage img; // creates image variable
int size = 7; // element size
int startx = 0; // starting x coordinate
int starty = 0; // starting y coordinate
void preload() {
}
void setup() {
size(500, 400); // creates canvas
img = loadImage("Dubbel_augurk-01.jpg"); // preloads Virginia picture
img.loadPixels(); // loads image
img.resize(displayWidth, 0); // resizes image to window size
img.updatePixels(); // updates image
}
void draw() {
clear();
background(0);
int size = floor(map(mouseX, 0, width, 7, 40)); // maps mouseX value to element size
for (var starty = 0; starty < img.height; starty ) { // creates pixel index
for (var startx = 0; startx < img.width; startx ) {
var index = (startx starty * img.width) * 4;
var r = img.pixels[index 0];
var g = img.pixels[index 1];
var b = img.pixels[index 2];
//var bright = ((1 * r) (0.59 * g) (0.11 * b)); // sets pixel value to adjusted grayscale
fill(r,g,b); // fills element with adjusted grayscale
rect(startx, starty, size, size);
startx = startx size -1; // set new startx value
}
starty = starty size -1; // set new starty value
}
}
CodePudding user response:
There's a difference between how p5.js (html canvas) stores pixels[]
and how Processing's Pimage stores pixels[]
.
While they're both 1D arrays, p5.js pixels[]
uses 4 values per pixels (e.g. [r1,g1,b1,a1, r2,g2,b2,a2, ...]
, etc.) and Processing uses 1 value per pixel (e.g. [pixel1ARGB, pixel2ARGB, etc.
] for ARGB
image / [pixel1RGB, pixel2RGB, etc.]
for RGB
images).
This is why there's a * 4
on this line in p5.js:
var index = (startx starty * img.width) * 4;
Hence the array index out of bounds error: the p5.js pixels[]
has 4 times more elements than pixels[]
in Processing.
Remember to also change the data types (you can't use var
in Processing(java)).
Removing the unused(shadowed) startx,starty
variables at the top and slightly
renaming them as per Java naming conventions, your snippet would look like this:
PImage img; // creates image variable
int size = 7; // element size
void setup() {
size(500, 400); // creates canvas
img = loadImage("Dubbel_augurk-01.jpg"); // preloads Virginia picture
img.loadPixels(); // loads image
img.resize(displayWidth, 0); // resizes image to window size
img.updatePixels(); // updates image
}
void draw() {
clear();
background(0);
int size = floor(map(mouseX, 0, width, 7, 40)); // maps mouseX value to element size
for (int startY = 0; startY < img.height; startY ) { // creates pixel index
for (int startX = 0; startX < img.width; startX ) {
int index = (startX startY * img.width);
int pixelRGB = img.pixels[index];
fill(pixelRGB); // fills element with adjusted grayscale
rect(startX, startY, size, size);
startX = startX size -1; // set new startX value
}
startY = startY size -1; // set new startY value
}
}
(Note: this code isn't tested, but hopefully it illustrates the points on pixel indexing)
Bare in mind, the main point of the video tutorial was on accessing/reading individual pixel values and using them in some way (e.g. mapping brightness to shape properties (circle size, line thickness, triangle colour, etc.)).
If you simply want to display a low-res version of the image and don't care about pixel values, it might be simpler to downsample the image (resize smaller), but render at the original size (or larger) with no aliasing (to get that crisp pixel art look instead of the blurry aliasing).
Here's a basic example you could run (remember to drag and drop the same "Dubbel_augurk-01.jpg" image on top of this sketchh too):
PImage img; // creates image variable
int downScale = 7; // how many times to scale the image down
void setup() {
size(500, 400); // creates canvas
// disable aliasing
noSmooth();
img = loadImage("Dubbel_augurk-01.jpg"); // preloads Virginia picture
img.resize(img.width / downScale, img.height / downScale); // resizes image
}
void draw() {
background(0);
int size = floor(map(mouseX, 0, width, 7, 40)); // maps mouseX value to element size
image(img, 0, 0, img.width * size, img.height * size);
}
(There are more options out there, but a bit more advanced (for example using texture()
, beginShape()
, vertex(x, y, u, v)
and aliasing again to scale the texture coordinate or using a fragment shader (via PShader))