We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpSyntax Questions › 2 different ways of iterating over pixels
Page Index Toggle Pages: 1
2 different ways of iterating over pixels (Read 1248 times)
2 different ways of iterating over pixels
Feb 7th, 2010, 10:36am
 
hello, i was seeing that people uses 2 different ways to iterate over the pixels of an image, i would like to know which are the differences between both, in which cases one is better than another, or is there any differences in any term? thanks
here are both aprroaches:

 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);
}
}


and :

int imgSize = b.height * b.width * 3;
for(int i = 0; i < imgSize; i++) {
  // do something with myImage.pixels[i]);
}


Re: 2 different ways of iterating over pixels
Reply #1 - Feb 7th, 2010, 10:46am
 
Are you sure about the * 3 in the second example doesn't seem right to me. Undecided

If you want to do exactly the same thing to every pixel in the image the second version will be slightly quicker. The advantage of the first version is that you have 2 variables x, y which give the pixel coordinates so if what you want to do is dependent on the position of the pixel in the image e.g. apply a gradient transparency, then this would be the one to go for.
Smiley
Re: 2 different ways of iterating over pixels
Reply #2 - Feb 7th, 2010, 12:39pm
 
for the second one,

x = i % w
y = i / w
i = ?? i forgot
Re: 2 different ways of iterating over pixels
Reply #3 - Feb 7th, 2010, 1:00pm
 
Code:
for (int i = 0; i < image.pixels.length; i++) {
int x = i%image.width;
int y = i/image.width;
}

for (int y = 0; y < image.height; y++) {
for (int x = 0; x < image.width; x++) {
int i = y*image.width + x;
}
}


Two differents way to iterate. Simple loop or nested for-loops. Just pick up your favorite. If you don't need (x, y) coordinates, then use the first one : the less you write, the better it is. Smiley
Re: 2 different ways of iterating over pixels
Reply #4 - Feb 7th, 2010, 1:24pm
 
what do you mean with" if you dont need x, y corrdinates can you give me an example in the first example i see you can access the x, y isnt it


antiplastik wrote on Feb 7th, 2010, 1:00pm:
Code:
for (int i = 0; i < image.pixels.length; i++) {
 int x = i%image.width;
 int y = i/image.width;
}

for (int y = 0; y < image.height; y++) {
 for (int x = 0; x < image.width; x++) {
   int i = y*image.width + x;
 }
}


Two differents way to iterate. Simple loop or nested for-loops. Just pick up your favorite. If you don't need (x, y) coordinates, then use the first one : the less you write, the better it is. Smiley

Re: 2 different ways of iterating over pixels
Reply #5 - Feb 7th, 2010, 1:37pm
 
I just put it so you can see how to calculate x and y.

Sometimes you don't care about the x,y coordinates. Say you just want to sum up the red component of all pixels, you do something like :

Code:
int s;
for (int i = 0; i < image.pixels.length; i++) {
s += red(image.pixels[i]);
}

Re: 2 different ways of iterating over pixels
Reply #6 - Feb 8th, 2010, 12:05pm
 
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
Re: 2 different ways of iterating over pixels
Reply #7 - Feb 8th, 2010, 12:42pm
 
While I'm looking at some speed tests... similar idea, comparing bitwise operations for integer R,G,B values extracted from a pixel to using the red(), green(), blue methods (which return float values), again on a 1200x900 pixel grid (and using the fastest traversal method, just index = 0 to pixels.length)

       // 16.744ms
       float r = red(pixel);
       float g = green(pixel);
       float b = blue(pixel);
       
       // 17.626ms
       int r = (int)red(pixel);
       int g = (int)green(pixel);
       int b = (int)blue(pixel);

       // 11.458ms
       int r = (pixel >>> 16) & 0xff;
       int g = (pixel >>>  8) & 0xff;
       int b =  pixel         & 0xff;

So, around 5ms to be saved by using bit shifting methods.

-spxl
Re: 2 different ways of iterating over pixels
Reply #8 - Feb 9th, 2010, 12:20am
 
subpixel wrote on Feb 8th, 2010, 12:05pm:
...

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


Thanks for the extensive and informative post.
On the funny side: 1 sex/14.4ms is really fast....  Wink
Re: 2 different ways of iterating over pixels
Reply #9 - Feb 9th, 2010, 1:06am
 
Indeed! Those figures shouldn't have even had sec's there, and inverting for a 69... wasn't on purpose, I swear! It was all a very racy misunderstanding. Cheesy

Correction:

1 / (45ms / frame) -> 22.2 fps (max)
1 / (14.4ms / frame) -> 69.4 fps (max)

-spxl
Page Index Toggle Pages: 1