Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 7425
  • Last Modified:

Getting RGB values from a 24-bit Bitmap

I have been going through this site and there are clearly several ways in which this can be done, I am looking for the simplest in terms of understanding, as I am really new to C++.

I am using Windows XP, Visual C++ 6.0, and am dealing with 24-bit uncompressed bitmaps.

I wish to be able to create an application (be it command based or window gui based), that can load a bitmap file, and be able to retrieve the RGB values from each pixel. I hope to look for errors in the bitmap, at first starting to look for large areas of green and black. To do this I will need to be able to create an algorithm to loop and search through each pixel. I will also need to be able to note the location of the pixel, as I will need to compare its value with those of the pixels around it.

From what I understand, the structure of a 24-bit bitmap uses 1 byte for each value, thus 3 bytes to store the RGB. How would one get these values in number form to say be checked if it is inbetween say 230-255?

If this question is not entirely worded well, I apologise, I am new to this forum and C++.

Any help or reading material links appreciated, and there is a large urgency as I need this information ASAP, although I dont have the points to offer...

Thanks in advance,
Graham
0
PoD
Asked:
PoD
  • 6
  • 4
  • 3
  • +2
2 Solutions
 
nietodCommented:
The simplist way is not necessarily the most efficient way.  The simplist way is to load the bitmap into a device context (DC) and then use GetPixel() repeatedly to get the value of each pixel.

example follows
0
 
fl0ydCommented:
So do you have a pointer to the bitmap-data already? If so, there is only one thing to pay special attention to, well, two things:
* bitmaps are usually stored upside-down, i.e., the first row in the array is the one at the bottom of the bitmap
* the beginning of each line is aligned at DWORD boundaries with 0-3 padding bytes at the end each row. So the width in memory isn't necessarily the same as bitmap_width * 3
Retrieving the data is simple. Let's assume your pointer to the bitmap-data is called pBits and of type 'unsigned char*':

unsigned char red = *pBits;
++pBits;
unsigned char green = *pBits;
++pBits;
unsigned char blue = *pBits;
++pBits;

Now, red, green, and blue are the color values of the first pixel of the last row (bottom-up!) in the bitmap.

Calculating the pitch (memory stride from one row to the next) you can use this formula:

long lPitch = ( ( bitmap_width * 3 ) + 3 ) & ~3 );

Thus, the pointer to the first row would be:

unsigned char* pFirstRow = pBits + ( bitmap_height - 1 ) * lPitch;

If anything is still unclear [which is very likely] feel free to come back and ask.

.f
0
 
nietodCommented:
HBITMAP BitMapHnd =               LoadImage(hInstance,"c:\\filename.bmp",IMAGE_BOTMAP,
                                  LR_DEFAULTSIZE,LR_DEFAULTSIZE,
                                   LR_CREATEDIBSECTION | LR_LOADFROMFILE);

HDC MemDCHnd = CreateCompatibleDC(NULL); // Create a DC to work in
HBITMAP OldBmpHnd = SelectObject(MemDCHnd,BitMapHnd); // Select in the new bitmap.

// here you will want to loop through all the pixels.

COLORREF Pixel = GetPixel(MemDCHnd,0,0); // Get the pixel at 0,0.
int RedValue = GetRValue(Pixel); // Extract he value of the Red component of this pixel.

SelectObject(MemDCHnd,OldBmpHnd); //IMPORTANT must return the original bitmap to the DC.
DeleteDC(MemDCHnd); // Delete the memory DC.
DeleteOjbect(BitMapHnd); // Delete the bitmap.
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
fl0ydCommented:
@ nietod:
No, this method is likely to alter the color values. Assume you have set your display color depth to 16 bits....

.f
0
 
frogger1999Commented:
you should also check out the function

int GetDIBits(
  HDC hdc,           // handle to device context
  HBITMAP hbmp,      // handle to bitmap
  UINT uStartScan,   // first scan line to set in destination bitmap
  UINT cScanLines,   // number of scan lines to copy
  LPVOID lpvBits,    // address of array for bitmap bits
  LPBITMAPINFO lpbi, // address of structure with bitmap data
  UINT uUsage        // RGB or palette index
);

I don't have the time at this moment to write an example but I will later on when I get a chance and you need it.
0
 
nietodCommented:
If you use CREATEDIBSECTION it should not convert the bitmap to display format.   I say shoudl because I;ve never used it.  I load bitmaps more "manually":
0
 
fl0ydCommented:
@ nietod:

To tell you the truth, after skimming through the MSDN I have more questions than I had before. Actually, I'm more inclined to believe that it does work the way you described it. However, opinions are rather weak compared to validated information. If I find the time I'll test it later.

.f
0
 
PoDAuthor Commented:
Ok well, first off thanks for the major fast responses. At the time I have only basic code to load and display bitmaps from using the appwizard in VisualC++. So I would rather start a small basic application from scratch as the less code needed the better.

@fl0yd: I dont have a pointer at the mo, I have seen many different methods of loading the bitmap from file, I would guess which one to choose would depend on what functions the rest of the program uses?

@nietod: This is looking like the best way todo it. As I can loop through each pixel, and store the values in integer variables for comparison in a function.

Although you two guys are now worrying me as you dont seem to agree :) I will wait a little more to see what other answers there are.
0
 
nietodCommented:
>> @nietod: This is looking like the best way todo it.
If speed is not an issue, or if the bitmap is fairly small.  That method is probably 100s of times slower than accessing the pixel values directly in memory, as floyd suggested.  That is why I said the simplist way is not necessarily the most efficient way  You might start with that and if its is too slow, move on to some more advanced way.  Like accessing the values from the DIB section yourself.
0
 
PoDAuthor Commented:
Well since I plan to be probably be comparing a lot of bitmaps, I would probably want the fastest one. Any chance of trying to explain the more advanced way in gentle dummy terms :)
0
 
nietodCommented:
>>  I would probably want the fastest one.
You didn't ask for that before!  Its going to get harder now

I think your best bet (there are lots of ways to do this) will be to load the bitmap  as I suggested bfore.  but then use GetDIBits() to extract the pixel information to an array.  

Like

HBITMAP BitMapHnd =               LoadImage(hInstance,"c:\\filename.bmp",IMAGE_BOTMAP,
                                            LR_DEFAULTSIZE,LR_DEFAULTSIZE,
                                             LR_CREATEDIBSECTION | LR_LOADFROMFILE);

HDC MemDCHnd = CreateCompatibleDC(NULL); // Create a DC to work in

DIBSECTION DIBInf; // DIB bitmap information structure.
GetObject(BitMapHnd,sizeof(DIBSECTION),&DIBInf); // Fill in the DIB bitmap information.  

// You might need to swithc top and bottom line if the information is coming out
// flipped upside down..
const int TopLin = 0; // Top line.
const int BtmLin = DIBInf.dsBm.bmHeight; // Bottom line

BITMAPINFO BtmInf;

BmpInf.bmiHeader = DIBInf.dsBmih; // Copy all the format information from the source bitmap.

BmpInf.bmiHeader.biPlanes = 1; // Almost certainly was 1, but just be sure.
BmpInf.bmiHeader.biBitCount = 32; // Specify 32 bits per pixel.
BmpInf.bmiHeader.bicompression = BI_RGB; // Uncompressed
BmpInf.bmiHeader.biSizeImage = 0; // Let windows calculate this.
.
const int PixCnt = DIBInf.dsBmih.biwidth*DIBInf.dsBmih.biHeight; // Number of pixels.
COLORREF PixPtr = new COLORREF[PixCnt];

GetDIIBts(MemDCHnd,BitMapHnd,TopLin,BtmLin,PixPtr,&BtmInf,DIB_RGB_COLORS);

// Now PixPtr shoudl point to an array of 32 bit color values.  Just extract the components from the as I had above.

DeleteDC(MemDCHnd); // Delete the memory DC.
DeleteOjbect(BitMapHnd); // Delete the bitmap.


This code is probably only approximate.  You will need to fool with it to get it to compile and probably it will need other fixes as well.
0
 
PoDAuthor Commented:
Thanks for the major effort nietod. Probably stuck my foot in it when I asked for the better method. I don't even know what a DC is! I would very much like to get that method implemented, so any further quicklinks, or what classes etc, I need to look at to learn how to work with that method would be appreciated.
0
 
fl0ydCommented:
I don't mean to discourage you, but the bitmap-format is an extremely complex beast. Since it was 'invented' by Microsoft I'll give you a link to one of their pages for further information: http://msdn.microsoft.com/library/en-us/gdi/bitmaps_99ir.asp . I suggest that you work with the raw data stored in the file without using device contexts (DC). You have to understand the entire bitmap header though, before you can interpret the data correctly. Chances are, that you don't even find the raw bitmap data if you do not understand the header information.

I hope, this information will get you going. It is a long and winding road, but don't let that get in your way.

.f
0
 
nietodCommented:
>> I don't even know what a DC
Its a device context.  it repredents a graphical device, like a screen or printer.  memory DCs draw on bitmaps in memory, rather than on a physical device.

>>! suggest that you work with the raw data stored
>> in the file without using device contexts (DC)
That's faster again, but I think its even harder.  
0
 
bcladdCommented:
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this question is:

Split: nietod, fl0yd

Please leave any comments here within the next seven days. Experts: Silence
means you don't care.

PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER!

-bcl (bcladd)
EE Cleanup Volunteer
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 6
  • 4
  • 3
  • +2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now