Click here to Skip to main content
15,881,424 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
Hallo together,
working on my project, I have an new problem. I want to speed up my integration of brightness of a bitmap. Therefor I got two different types of calculation algorithms. The first one is the "classical" slow algorithm by iterating through the pixels and get their color and then their brightness:
C#
private double GET_BRIGHTNESS_SLOW(Bitmap processedBitmap)
        {
            double Result = 0;
            double brg = 0;
            for (int x = 0; x < processedBitmap.Width; x++)
            {
                for (int y = 0; y < processedBitmap.Height; y++)
                {
                    brg = processedBitmap.GetPixel(x, y).GetBrightness();
                    if (brg >= BORDER)
                        Result += brg;
                    counter++;
                }
            }
            return Result;
        }


The second algorithm is using the LockBits method and unsafe code:

C#
private double GET_BRIGHTNESS(Bitmap processedBitmap)
        {
            double Result = 0;
            double brg = 0;
            unsafe
            {
                BitmapData bitmapData = processedBitmap.LockBits(new Rectangle(0, 0, processedBitmap.Width, processedBitmap.Height), ImageLockMode.ReadWrite, processedBitmap.PixelFormat);

                int bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(processedBitmap.PixelFormat) / 8;
                int heightInPixels = bitmapData.Height;
                int widthInBytes = bitmapData.Width * bytesPerPixel;
                byte* PtrFirstPixel = (byte*)bitmapData.Scan0;

                for (int y = 0; y < heightInPixels; y++)
                {
                    byte* currentLine = PtrFirstPixel + (y * bitmapData.Stride);
                    for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
                    {
                        int Blue = currentLine[x];
                        int Green = currentLine[x + 1];
                        int Red = currentLine[x + 2];

                        brg= Color.FromArgb(Red, Green, Blue).GetBrightness();
                        if (brg >= BORDER)
                            Result += brg;

                        counter++;
                    }
                }
                processedBitmap.UnlockBits(bitmapData);
            }
            return Result;
        }


For comparison I wrote the following Code:

C#
Stopwatch sw = new Stopwatch();
            sw.Start();
            double result = GET_BRIGHTNESS(p_BMP);
            sw.Stop();
            MessageBox.Show("Counter: " + counter.ToString() + "\r\nTime: " + sw.ElapsedMilliseconds + " ms \r\nValue: " + Math.Round(result, 2).ToString());
            counter = 0;
            sw.Reset();
            sw.Start();
            double result_sl = GET_BRIGHTNESS_SLOW(p_BMP);
            sw.Stop();
            MessageBox.Show("Counter: "+counter.ToString()+"\r\nTime: " + sw.ElapsedMilliseconds + " ms \r\nValue: " + Math.Round(result_sl, 2).ToString());


The result is for the fast version:

<br />
Counter: 325546<br />
Time: 24 ms<br />
Value: 14437,37<br />


and for the slow version:

<br />
Counter: 325546<br />
Time: 449 ms<br />
Value: 16367,6<br />


The Pictures Size is 659 x 494, so 325546 px, thats correct for both. The results above are for BORDER = 0.25. If i set BORDER = 0 I get:

for the fast version Value: 50220,87 and for the slow version Value: 50239,4

Where does this difference come from? Obviously I want to have to correct value and the fast code... Does anyone have an Idea?
Posted

You are missing the alpha content.
C#
int Blue = currentLine[x];
int Green = currentLine[x + 1];
int Red = currentLine[x + 2];
int alpha = currentLine[x + 3];  //Alpha 

That could be making a difference in your final output.
 
Share this answer
 
v3
Comments
DANIEL_PD 13-Oct-15 3:25am    
Hello and thanks for your answer,
but the alpha value is not making a difference in my result (tried it)
Abhinav S 13-Oct-15 3:32am    
Ok. Check the order of blue green and red to the FromARGB() method once.
DANIEL_PD 13-Oct-15 3:36am    
The method is defined as Color.FromARGB(int alpha, int red, int green, int blue) or as Color.FromARGB(int red, int green, int blue). In addition to that my source picture is grayscale, so red=green=blue and alpha=255
Sergey Alexandrovich Kryukov 13-Oct-15 8:34am    
Sure, a 5.
—SA
Abhinav S 13-Oct-15 12:11pm    
Thank you SA.
I found the answer myself, but Abhinav brought me on the correct path...

C#
for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
                    {
                        int Blue = currentLine[x];
                        int Green = currentLine[x + 1];
                        int Red = currentLine[x + 2];

is the problem. Because of my picture being grayscale, one pixel is only 1 Byte, so by setting green to x+1 and red to x+2 I made an average over 3 pixel...

So I changed that directly to:
C#
for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
{
    brg = ((double)currentLine[x]/255.00);


And now everything is perfectly fine
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900