Wednesday, March 20, 2013

Determining percentage of colors in a bitmap using C# without getPixel

To keep things simple, let's suppose we have a black and white bitmap image.
I will not use getPixel method here, Bitmap.getPixel() is a very expensive method, and it alone can turn your program into a lazy snail.

Please note that I am using a Format24bpprgb image format here, 24BPPRGB can be defined as:
Each pixel in the image is represented by 24 bits. First 8 bits represent red color, next 8 bits represent green color, and last 8 bits represent blue color in a bitmap.

Another popular format is 32BPPARGB, in this format the first 8 bits represent "Alpha" or the opacity of pixel, next 3 bytes or 24 bits describe the RGB components same like 24BPPRGB.

Given below is the C# language source code for checking pixel colors without Bitmap.getPixel() method.



public void 








calculateBlackAndWhitePixels

(string strFileName, ref int nBlackCount, ref int nWhiteCount,  ref int nTotalPixels)
{
Image image = null;
Bitmap bmpCrop = null;

BitmapData bmpData = null;
byte[] imgData = null;
int n = 0;
      
try
{
image = new Bitmap(strFileName);
bmpCrop = new Bitmap(image);
             
nBlackPercent = 0;
nWhitePercent = 0;
             
for (int h = 0; h < bmpCrop.Height; h++)// scan through all rows of image
{
       // This part is a very fast replacement of getPixel() method
bmpData = bmpCrop.LockBits(new Rectangle(0, h, bmpCrop.Width, 1),
System.Drawing.Imaging.ImageLockMode.ReadOnly, image.PixelFormat);
imgData = new byte[bmpData.Stride];
System.Runtime.InteropServices.Marshal.Copy(bmpData.Scan0, imgData, 0
, imgData.Length);
bmpCrop.UnlockBits(bmpData);

for (n = 0; n < imgData.Length - 3; n += 3)// scanning width of image
{
if ((int)imgData[n] == 0 && (int)imgData[n + 1] == 0 && (int)imgData[n + 2] == 0)// Color black is #000000
{
 nBlackCount++;
}
else
{
 nWhiteCount++;
}
}

nTotalPixels += n;
}
             
string.Format("{0} pixels are black, {1} are white(or non black at least)."nBlackCountnWhiteCount);
}
catch(Exception e)
{
MessageBox.Show(ex.Message);
}     
}

Now that you have the number of total pixels inside the image, the white pixels, and the black pixels calculating the percentages is trivial, do it as a home work :)

Note:
The code is copied from a working software, their might be a small typo but over all it is supposed to work.
Please feel free to ask questions and post comments.

I'm working as a freelance programmer through ODesk.com, I have a strong profile over there. Feel free to ping me if you need an Android app.

https://www.odesk.com/users/~012d73aa92fad47188




5 comments:

  1. Error 1 The type or namespace name 'BitmapData' could not be found (are you missing a using directive or an assembly reference?) C:\Users\LENOVO\documents\visual studio 2010\Projects\amiraakj\amiraakj\Form2.cs 256 1 amiraakj

    Error 2 The name 'ex' does not exist in the current context C:\Users\LENOVO\documents\visual studio 2010\Projects\amiraakj\amiraakj\Form2.cs 295 19 amiraakj

    have error.why?

    ReplyDelete
    Replies
    1. Hi,
      Change the exception variable name "ex" to e.
      Import necessary files for Bitmap processing. Move cursor to the Bitap variable and press Ctrl + . key. It will show you suggestions to fix it.
      Sorry, I didn't see your comments earlier. Somehow missed it.

      Regards,
      Naeem.
      PS I am teaching courses about socket programming and windows service programming. You can watch any of your choice on 50% discount. Coupon links are given below.
      https://www.udemy.com/tcpip-socket-programming-for-coders-using-csharp-net/?couponCode=HALF

      https://www.udemy.com/windows-service-programming/?couponCode=HALF

      Delete
  2. Thank you for this nice example.
    This was exactly what i was looking for, but i use 32bppargb. ;)
    It seems like you are missing the last pixel of each row, or is that on purpose?

    Best regards

    ReplyDelete
  3. Hi,

    I don't remember why I did that. Wrote this post so many years ago. Glad to know that you found the article useful.
    I'm teaching TCP/IP Socket programming and Windows Service programming too. You can take any of those courses if interested. 50% off discount coupons are given below.
    Regards,
    Naeem.

    https://www.udemy.com/tcpip-socket-programming-for-coders-using-csharp-net/?couponCode=HALF

    https://www.udemy.com/windows-service-programming/?couponCode=HALF

    ReplyDelete

Feel free to talk back...