Hi guys. Straight to the question.
I have a bmp(eg:200x200). What I want to do is to take the values of the three channels(RGB) of every 10x10 region from this bitmap...
I hope you understand what I mean
I have tried with the source bellow...have a look and tell me what to do!
What am I doing wrong
private void button3_Click(object sender, EventArgs e)
{
int red = 0,green=0,blue=0;
Color clr;
int widthBound = 0;
int heightBound = 0;
Bitmap bmp = new Bitmap(pictureBox4.Image);
while (widthBound<bmp.Width)
{
for (int x = widthBound; x < widthBound + 10; x++)
{
for (int y = heightBound; y < heightBound + 10; y++)
{
clr = bmp.GetPixel(x, y);
red = red + Convert.ToInt32(clr.R);
green = green + Convert.ToInt32(clr.G);
blue = blue + Convert.ToInt32(clr.B);
}
}
listBox2.Items.Add(red/(bmp.Width*bmp.Height));
listBox2.Items.Add(green / (bmp.Width * bmp.Height));
listBox2.Items.Add(blue / (bmp.Width * bmp.Height));
listBox2.Items.Add("--------");
widthBound = widthBound + 10;
heightBound = heightBound + 10;
}
}
Any help would be greatly appreciated!
Thanks in advance.
KC

Image processing: question!
Lokesh
Yes, if the image has either the width or the height that is not a multiple of 10 you will end up trying to access pixels out of the bitmap.
Inserting constraints is rather easy, but keep in mind that all the "missing pixels" will be considered to be black, and this might mean you get a strange smudge on the edge. I would recommend you ignore the extra pixels.
Anyway, to insert the constraints alone and get rid of the exception:
private void button3_Click(object sender, EventArgs e)
{
Color clr;
Bitmap bmp = new Bitmap(pictureBox4.Image);
for (heightBound = 0; heightBound < bmp.Height; heightBound += 10) {
for (widthBound = 0; widthBound < bmp.Width; widthBound += 10) {
int red = 0,green=0,blue=0;
for (int y = heightBound; y < heightBound + 10 && y < bmp.Height; y++) {
for (int x = widthBound; x < widthBound + 10 && x < bmp.Width; x++) {
clr = bmp.GetPixel(x, y);
red = red + Convert.ToInt32(clr.R);
green = green + Convert.ToInt32(clr.G);
blue = blue + Convert.ToInt32(clr.B);
}
}
listBox2.Items.Add((red + 50) /(10 * 10));
listBox2.Items.Add((green + 50) / (10 * 10));
listBox2.Items.Add((blue + 50) / (10 * 10));
listBox2.Items.Add("--------");
}
}
Or, if you want to ignore the missing pixels:
private void button3_Click(object sender, EventArgs e)
{
Color clr;
Bitmap bmp = new Bitmap(pictureBox4.Image);
int width = (bmp.Width / 10);
int height = (bmp.Height / 10);
for (heightBound = 0; heightBound < height * 10; heightBound += 10) {
for (widthBound = 0; widthBound < width * 10; widthBound += 10) {
int red = 0,green=0,blue=0;
for (int y = heightBound; y < heightBound + 10; y++) {
for (int x = widthBound; x < widthBound + 10; x++) {
clr = bmp.GetPixel(x, y);
red = red + Convert.ToInt32(clr.R);
green = green + Convert.ToInt32(clr.G);
blue = blue + Convert.ToInt32(clr.B);
}
}
listBox2.Items.Add((red + 50) /(10 * 10));
listBox2.Items.Add((green + 50) / (10 * 10));
listBox2.Items.Add((blue + 50) / (10 * 10));
listBox2.Items.Add("--------");
}
}
HTH
--mc
aeshaw
clr = bmp.GetPixel(x, y);
it says that x has to be positive and <Height
How to put any constraints or something
loonysan
Chire,
I presume you are trying to get the average red, green and blue for every square of ten by ten pixels in your bitmap.
A few points you may want to consider:
1) First, a minor point: whenever you scan a bitmap (or a bidimensional array, for that matter), always try to scan X in the inner loop, not Y. This reduces the number of page changes and improves your performance greatly. Think of how bidimensional array of bytes is laid out in memory and you will see why.
2) You should reset your red, green and blue for each 10x10 area (i.e. within the while). Failing to do so, you are carrying the previous values over to the next square.
3) To get the average of the color for a 10x10 square you should divide by 100 (the number of pixels you are sampling), not by the width by the height of the whole bitmap... in your example you are dividing by 40000!
4) You are increasing widthBound and heightBound at the same time... this way you will end up sampling only the diagonal of your bitmap, not the whole.
5) Whenever you divide an integer by another integer, you end up truncating the number. It is sometimes a good idea to compensate this by adding half of the divisor. This means that, if you used floating point numbers, you would correctly round up values with decimal part 0.5 and over, and down values with decimal part < 0.5.
See a modified version of your code below (disclaimer: I did't test or compile it, so expect all sorts of syntax errors)
private void button3_Click(object sender, EventArgs e)
{
Color clr;
Bitmap bmp = new Bitmap(pictureBox4.Image);
for (heightBound = 0; heightBound < bmp.Height; heightBound += 10) {
for (widthBound = 0; widthBound < bmp.Width; widthBound += 10) {
int red = 0,green=0,blue=0;
for (int y = heightBound; y < heightBound + 10; y++) {
for (int x = widthBound; x < widthBound + 10; x++) {
clr = bmp.GetPixel(x, y);
red = red + Convert.ToInt32(clr.R);
green = green + Convert.ToInt32(clr.G);
blue = blue + Convert.ToInt32(clr.B);
}
}
listBox2.Items.Add((red + 50) /(10 * 10));
listBox2.Items.Add((green + 50) / (10 * 10));
listBox2.Items.Add((blue + 50) / (10 * 10));
listBox2.Items.Add("--------");
}
}
Something else you might want to consider is that the analysis you are making will have a very poor performance, since getting a single pixel is expensive (it's an API call for each pixel, 40000 in all). You could improve it using unsafe code, but I would not recommend it. An alternative approach would be to leverage the capabilities of the GDI+... make a copy of your bitmap, then stretch it to 10% of its size, making sure you use the best interpolation modes (I would recommend InterpolationMode.HighQualityBicubic, but you should probably experiment a little by yourself);
At this point, you have a bitmap each pixel of which represents an average of 10x10 pixels on the original, which is what you were trying to do.
HTH
--mc
_Aristotle_