Sign in to follow this  
Great_White

[Solved]help my code

Recommended Posts

Hi guys, I'm trying to compute average color values of an grayscale image blocks. My grayscale image is divided into 64 blocks(think of it like placing a 8x8 grid on the image, hence each block size is image width/8 and image height/8. Here is my source code,

static void averageColorOf8x8_Blocks(unsigned char* img, int width, int height, long avgc[8][8]) {
	
	// validate arguments
	assert(img);
	assert(width);
	assert(height);

	// calculate block size(block width x block height)
	int blck_w= width/8, blck_h=height/8;

	// compute average of each block(to get 64 color values)
	for(int y=0;y<height;y+=blck_h) { // for each vertical block
		for(int x=0;x<width;x+=blck_w) { // for each horizontal block
			for(int z=0;z<blck_h;++z) {  // for each block entry
				for(int w=0;w<blck_w;++w) {
					avgc[y/blck_h][x/blck_w] += (long)img[(y+z)*width +x+w ];
				}
			}

			avgc[y/blck_h][x/blck_w] *= 1/(blck_w*blck_h); // average
		}
	}
}




But when I try it on some images that are not multiple of 8, it crashes. Can somebody explain me what I'm doing wrong ? [Edited by - Great_White on November 21, 2008 1:17:51 AM]

Share this post


Link to post
Share on other sites
This won't break on every size that's not a multiple of 8, but it will on many of them, and it'll go into infinite-loop world on sizes < 8. For instance all sizes 8-16 will work just fine. Anyway let's examine why.

Let's go through a test situation. Imagine a simple greyscale image that is 17x17. You get your blck_w and blck_h, and naturally they are both "2" (as 17/8 = 2.125 or something... in integer world that's 2).

Alright great... recap the vars:
width = 17 height = 17 blck_w = 2 blck_h = 2

Now let's look at the for loops. If you were to set a breakpoint in here, you would end up starting your "y" loop, "x" loop, "z" loop, and "w" loop, you would eventually make it through the "z" and "w" loops successfully. You would start the next "x" loop, with x = 2 now. This will go on until x == 14. We go through the "z" and "w" loops like usual, but let's zoom in and see what happens next.

The for loop says "Well, 'x' == 14. I need to add 'blck_w' to it. That's 2. Cool, so now 'x' == 16. Is that less than 'width'? 'width' is 17... sooo... yup 16 is certainly less than 17, let's move on."

And the "z" loop and "w" loop start. Since the "z" loop and "w" loop both iterate "blck_w" times, you are going past your image width and height of 17, as if it was 18x18. This is why it crashes.

Solution?

Decide what to do with the "extra" pixels when it's not evenly divisible by 8. Throw them away, or determine a way to only include what's there.

Cheers
-Scott

Share this post


Link to post
Share on other sites
Here's a hint: Try iterating through each pixel of the image and finding out which cell of avgc it should go in. Also, it may be helpful to know that the average is the sum of all elements then divided by how many elements possible.


Does this give you any ideas?

Share this post


Link to post
Share on other sites
Oh, wait. What's this in my back pocket? Some sample code?
</inside_joke>



static void averageColorOf8x8_Blocks(unsigned char* img, int width, int height, /* unsigned */ long avgc[8][8])
{
assert( width > 8 );
assert( height > 8 );

int block_w = width / 8;
int block_h = height / 8;

// I'll be assuming that argvc is initialized to 0


// Calculate the sum:
int x, y;
for ( y = 0; y < height; ++y ) // For each row
for ( x = 0; x < width; ++x ) // For each column:
avgc[y*8/height][x*8/width] += img[ width * y + x ];

// y * 8 / height is equivalent to y / (height / 8) is equivalent to y / block_h.
// The difference is, is that you're operating on integer operations.
// Therefore, if the height is 15 (making block_h = 15 / 8 = 1)
// and y was 14, you'd be accessing avgc[15], which is not cool.


// Then calculate the average:
int k = block_w * block_h;
for ( y = 0; y < 8; ++y )
for ( x = 0; x < 8; ++x )
avgc[y][x] /= k;
}




[Edited by - _fastcall on November 19, 2008 9:31:33 PM]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this