We help IT Professionals succeed at work.

# Calculating 'brightness' of a bitmap

on
Medium Priority
1,188 Views
I am trying to create a self-adjusting brightness feature for a videophone.  I can take a 'snapshot' of the video in .bmp format.  I need to  somehow measure the brightness of that bitmap.  Open to any ideas.  Here is how I plan to do it:
1.  convert the bitmap to grayscale.
2.  Average the grayscale for each pixel, giving me an average "grayness" for the whole bitmap.

Q:  How do I convert the bitmap to grayscale?
How do I access the individual bits of a bitmap.

BTW, I'm using VB 5.0 Enterprise Edition.

TIA
Comment
Watch Question

## View Solution Only

Commented:
First, converting R(ed)G(reen)B(lue) values to grayscale:

Gray = 0.3*Red + 0.59*Green + 0.11*Blue

Averaging these gives you one estimate of "brightness"

For getting these RGB values, use GetPixel API function

Declare Function GetPixel Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long) As Long

From this extract individual RGB values. If you want example code, let me know.

For any bigger BMP this will be quite slow process, so my suggestion is that you randomly sample the BMP and evaluate the average brigthness from those values. You can even weigh certain areas of your picture if necessary.

Hope this gets you started.

Not the solution you were looking for? Getting a personalized solution is easy.

Commented:
Rantanen- Looks very useful.  Yes, sample code would be much appreciated, specifically how the RGB values are stored in the return (long) from GetPixelLib().  If its its too long to post on the 'xchange, you can email it to 'nichols@teleport.com'

Commented:
Clay -
Note that the GetPixel function will just be reading the screen and not the actual values of the bitmap.
If the user has their color depth set to 16 colors, you are going to get incorrect results.  You also have be carefull of 256 color modes, where palette flash can corrupt the bitmap colors.

You'd probably want to open the BitMap as a binary file, and read what the bitmap actually is storing for it's pixels.  Then use rantanen's Greyscale conversion (great code... didn't know it was so simple!)

Chris

Commented:
clay,

he's talking about videophone and I understand he wants to adjust what is seen on the screen, If we were talking about manipulating "still pictures" - yes, I agree with you.

Palette flash is a fact of life, but anyway the control must be quite heavily damped (=slow) in this case, so I wouldn't be too concerned about this. There are many more fast disturbances possible in this kind of application which must be damped away - like somebody lighting a cigarette just in front of the camera. Luckily they are banning smoking in more and more places, so this also is not so big problem :-)

Commented:
Clay,

Commented:
Clay & Rantanen -

What I was refering to was nothing to do with Videophone or still images.  What I'm refering to is what Windows does when you try to display a 24 bit color image on a system that is set up for 16 bit, 8 bit or 4 bit.  Windows uses a system palette, which is totaly different from the bitmap/GIF/JPEG palette.

What happens is best described with 256 color systems.  If your bitmap is a 24 bit color (8 bits RGB), the bitmap can contain up to 16.7 million different colors, each pixel being described by three numbers from 0 to 255, one in each primary color (red, green, & blue).  In a 256 color system, Windows can only display 256 colors at a time.  When it loads the bitmap, if the color is in it's current system palette of 256 colors, it displays the pixel normally.  If it's not in the current system palette, it picks a color that is close to the color in the bitmap.  This will result in some of the pixels that are being displayed not having the same color value as is stored in the bitmap.

Easy way to see this is to change your display to either 16 colors or 256 colors, then load a 24 bit color bitmap in Paint, and look at it.  It will appear slightly different from what it appears when your monitor is set to 24 bit (true color).  To see "palette flash", set your display to 256 colors, and open two instances of paint.  Load two different images (pick ones with different colors :) and make each one active.  As a different Paint becomes active, Windows will change the current palette to one that better fits the active window.

Now, as to how to deal with this for your problem.  I would open the Bitmap that you are using as a binary file, and read each pixel that way.  By doing so, you get a representation of what is in the bitmap, not what Windows is displaying.

Hope this clears things up,

Chris

Commented:
Chris,

what you say is true when you are writing e.g. a photo manipulation program, but in my opinion it is not relevant in this situation.

I don't think Clay is trying to manipulate the bitmaps on the fly with VB (!!!), he's trying to control the hardware and that is totally different thing.

If I'm wrong when doing this assumption my advice to Clay would be forget VB. But ifmy assumption is correct, then even these 16 or 256 color pictures shown on screen react to lighting condition changes and these can be adjusted changing hardware settings (I don't know the technology here to be more specific). 16 color pictures react less, 256 color pictures somewhat more and so on.

That is how I have understood this question here,.

Commented:
My interest is in the colors actually displayed on the screen.  The video is 256 colors (8-bit) and the PC is set for at least 16-bit color.  That avoids palette flash.  (We have only one other application on the screen and its only got 256-colors).

I haven't been able to find out how to decode the long value returned, into R G B colors.  Any ideas?

Commented:
Clay,
maybe the source I sent to you was not clear enough because I had tried to optimize it a little bit.

To find out R,G and B components from the long value returned by GetPixel do

nRed = nRed + Int(nRGB / &H10000 And &HFF)
nGreen = nGreen + Int(nRGB / &H100 And &HFF)
nBlue = nBlue + Int(nRGB And &HFF)

HTH

Commented:
Thanks for the detail.  One question:
With nRed = nRed + Int(nRGB / &H10000 And &HFF)
Where does   ^^^ get defined?  Or is this a cummulative count you are keeping (summing the red in all the pixels?  I.e. are you keeping a running total here?

BTW, the only source code I got was what you posted to the 'exchange here, unless you emailed it to me at work (nichols@murphysw.com).  I'll check there tomorrow.

Commented:
Clay,

oops - yes it was a code snippet from the sub below and as you said, a cumulative count.

Private Function GetBrightness(picX As PictureBox, nSamples As Integer, nX As Integer, nY As Integer) As Single
Dim I As Integer
Dim nRGB As Long
Dim nRed As Integer
Dim nGreen As Integer
Dim nBlue As Integer
Dim nGray As Integer
Dim nRedSum As Long
Dim nGreenSum As Long
Dim nBlueSum As Long
Dim nSum As Long

For I = 1 To nSamples
nRGB = GetPixel(picX.hdc, Int(Rnd() * nX), Int(Rnd() * nY))
nRedSum = nRedSum + Int(nRGB / &H10000 And &HFF)
nGreenSum = nGreenSum + Int(nRGB / &H100 And &HFF)
nBlueSum = nBlueSum + Int(nRGB And &HFF)
Next I
nSum = (0.3 * nRedSum + 0.59 * nGreenSum + 0.11 * nBlueSum) / nSamples
GetBrightness = 100 * nSum / 255
End Function

I posted my sample to  'nichols@teleport.com'  which address you gave in an earlier note.

Commented:
Opps.  Gave you the wrong address.  its cnichols@teleport.com, note the 'c'.
Thanks for all the help!

Commented:
Lasse,
Please resubmit any answer so I can credit you with the answer.  Sorry I didn't get back to this sooner.
##### Thanks for using Experts Exchange.

• View three pieces of content (articles, solutions, posts, and videos)
• Ask the experts questions (counted toward content limit)
• Customize your dashboard and profile