sebastiano wrote on Feb 7th, 2010, 10:36am: for (int y = 0; y<img.height;y++){
for (int x = 0; x<img.width;x++) {
imageColors[y*img.height + x]= img.get(x,y);
}
}
This sort-of/almost shows 2 different methods, though it actually appears to be defective...
The two ways of accessing an individual pixel are:
color pixelSimple = get(x,y);
color pixelAdvanced = pixels[index];
The pixelSimple way is obvious: get the pixel value from the (x,y) coordinates.
The pixelAdvanced way is used for SPEED of program execution, and is especially handy if your pixel calculations don't depend on the pixel location.
Memory is not "2-dimensional", it is a simple, long list of numbers, one after the other, and a "picture" is stored as a single list of pixels, ordered like text on a page (start top-left, continue to right, when reaching the right end of the page go down one row and start again at the left, with the bottom-right pixel being the last in the list).
Equivalent code (each will access all pixels in the same order: starting at the top left corner, scanning to the right across rows and moving down one row each time, always starting from the left):
Code:for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// "Slow" method call
color pixel = get(x, y);
}
}
Code:loadPixels(); // You must call this before using pixels[]
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
// Faster array access, but still involves math to find index
color pixel = pixels[x + (y * width)];
}
}
Code:loadPixels(); // You must call this before using pixels[]
// Note: pixels.length == width * height
for (int i = 0; i < pixels.length; i++)
{
// Fastest array access, no math to determine index
// x and y coordinates are not known, but if you don't
// need them, then we don't care about x and y
color pixel = pixels[i];
}
Code:loadPixels(); // You must call this before using pixels[]
// Hybrid method: keep track of x,y AND index...
for (int i = 0, y = 0; y < height; y++)
{
for (int x = 0; x < width; x++, i++)
{
// Fast array access (no math), and also have x,y
color pixel = pixels[i];
}
}
For simple tasks, these optimisations are not especially important. However, if you want/need things to be FAST, it can pay dividends to avoid unnecessary calculations, especially calculations performed on EVERY PIXEL, and even more especially when you have a LOT of pixels (eg 800x600 is nearly half a million, 1024x768 is about 3/4 of a million, 1920x1200 is 2.3 million). If you save a multiplication and an addition for every pixel, that is potentially millions of operations you save for every frame (and an "operation" is probably several machine instructions).
Division is also usually a baddie when it comes to speed. It is a "bad idea" to run along the index and calculate x and y by using division, especially by doing two divisions! (Note: the % operator does a division and gives the remainder). It is okay if you just need a couple of conversions, but if you're processing every pixel, it is inefficient.
The "hybrid method" above (keeping track of x,y and the index) is one I invented, but I'm sure has been invented before (many times!), and you're welcome to try it. I can see a potential for it being slower than using the pixels[x + (y * width)] method if the time spent writing the new i value to memory each time it is incremented is slower than doing the math without storing the index value.
I ran some crude speed tests for 1200x900 pixels on my system, repeating the the x/y/i loops (and loadPixels() for all the methods accessing the pixels[] array) 50 or 500 times to get an average and noted the lowest time I saw over a dozen or so runs. I also included a simple calculation (total += pixel) to the inner loop to make sure that the compiler and/or runtime environment didn't cheat by not doing anything!
color pixel = pixels[i]; // no x,y : 11.376ms
color pixel = pixels[i]; // hybrid : 12.578ms
color pixel = pixels[x + (y * width)]; // 14.40ms
color pixel = get(x,y); // 45.06ms
So, as you can see, using get(x,y) is a lot slower, and if you don't need to use x,y then running along the index is about 20% faster than doing the math [x + (y * width)], though it is probably more meaningful to think of it as 3ms faster since the complexity of whatever other calculations you do will drastically alter the percentage.
Discounting other factors and overhead:
1sec / (45ms / frame) -> 22.2 fps (max)
1sex / (14.4ms / frame) -> 69.4 fps (max)
Frame rate could make or break the niceness of your sketch.
-spxl