Creating a bitmap object from a BMP file
Although we needn't really create a bitmap object to draw the image, the benefit of doing so is that the bitmap we create is a device dependent bitmap (DDB) as apposed to the device independent bitmap (DIB) help in the BMP file. This reduces the time it takes to render the bitmap onto the device.
The BMP file holds a device independent bitmap and sometimes uses the extension DIB. It is composed of four sections. The first is BITMAPFILEHEADER. This contains the bitmap file signature, the size of the bitmap and the offset to the array of bits that define the bitmap image. The next section is the BITMAPINFOHEADER. This contains information such as the height and widht of the bitmap and the number of colors used. This section is followed by the color table. The color table contains two or more RGBQUAD structures The final section is the actual bits that define the bitmap image.
Step 1: Create the bitmap object
The LoadBMPImage() function given below will read in a BMP file, create a device dependent bitmap of it and attach it to the CBitmap object passed in as an argument. It can also create a logical palette if a pointer to a CPalette object is supplied.This function basically reads in the BMP file, creates a logical palette and calls CreateDIBitmap() to create the GDI bitmap object. Note that when you supply a pointer to a CPalette object, the function creates a logical palette and uses the palette when creating the bitmap object.
// LoadBMPImage - Loads a BMP file and creates a bitmap GDI object
// also creates logical palette for it.
// Returns - TRUE for success
// sBMPFile - Full path of the BMP file
// bitmap - The bitmap object to initialize
// pPal - Will hold the logical palette. Can be NULL
BOOL LoadBMPImage( LPCTSTR sBMPFile, CBitmap& bitmap, CPalette *pPal )
{
CFile file;
if( !file.Open( sBMPFile, CFile::modeRead) )
return FALSE;
BITMAPFILEHEADER bmfHeader;
// Read file header
if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
return FALSE;
// File type should be 'BM'
if (bmfHeader.bfType != ((WORD) ('M' << 8) | 'B'))
return FALSE;
// Get length of the remainder of the file and allocate memory
DWORD nPackedDIBLen = file.GetLength() - sizeof(BITMAPFILEHEADER);
HGLOBAL hDIB = ::GlobalAlloc(GMEM_FIXED, nPackedDIBLen);
if (hDIB == 0)
return FALSE;
// Read the remainder of the bitmap file.
if (file.ReadHuge((LPSTR)hDIB, nPackedDIBLen) != nPackedDIBLen )
{
::GlobalFree(hDIB);
return FALSE;
}
BITMAPINFOHEADER &bmiHeader = *(LPBITMAPINFOHEADER)hDIB ;
BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
// If bmiHeader.biClrUsed is zero we have to infer the number
// of colors from the number of bits used to specify it.
int nColors = bmiHeader.biClrUsed ? bmiHeader.biClrUsed :
1 << bmiHeader.biBitCount;
LPVOID lpDIBBits;
if( bmInfo.bmiHeader.biBitCount > 8 )
lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors + bmInfo.bmiHeader.biClrUsed) +
((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
else
lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);
// Create the logical palette
if( pPal != NULL )
{
// Create the palette
if( nColors <= 256 )
{
UINT nSize = sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * nColors);
LOGPALETTE *pLP = (LOGPALETTE *) new BYTE[nSize];
pLP->palVersion = 0x300;
pLP->palNumEntries = nColors;
for( int i=0; i < nColors; i++)
{
pLP->palPalEntry[i].peRed = bmInfo.bmiColors[i].rgbRed;
pLP->palPalEntry[i].peGreen = bmInfo.bmiColors[i].rgbGreen;
pLP->palPalEntry[i].peBlue = bmInfo.bmiColors[i].rgbBlue;
pLP->palPalEntry[i].peFlags = 0;
}
pPal->CreatePalette( pLP );
delete[] pLP;
}
}
CClientDC dc(NULL);
CPalette* pOldPalette = NULL;
if( pPal )
{
pOldPalette = dc.SelectPalette( pPal, FALSE );
dc.RealizePalette();
}
HBITMAP hBmp = CreateDIBitmap( dc.m_hDC, // handle to device context
&bmiHeader, // pointer to bitmap size and format data
CBM_INIT, // initialization flag
lpDIBBits, // pointer to initialization data
&bmInfo, // pointer to bitmap color-format data
DIB_RGB_COLORS); // color-data usage
bitmap.Attach( hBmp );
if( pOldPalette )
dc.SelectPalette( pOldPalette, FALSE );
::GlobalFree(hDIB);
return TRUE;
}
Step 2: Drawing the bitmap
The DrawBitmap() function given below is a very simple function that will draw the given bitmap to the top left corner of the device context. It will also use a logical palette to draw the image if you supply one. You can easily extend this function to specify where to draw the bitmap or even whether to tile the bitmap or extend it to cover the device context.void DrawBitmap(CDC* pDC, CBitmap& bitmap, CPalette *pPal )
{
// Create a compatible memory DC
CDC memDC;
memDC.CreateCompatibleDC( pDC );
memDC.SelectObject( &bitmap );
// Select and realize the palette
if( pPal != NULL && pDC->GetDeviceCaps(RASTERCAPS) & RC_PALETTE )
{
pDC->SelectPalette( pPal, FALSE );
pDC->RealizePalette();
}
BITMAP bm;
bitmap.GetBitmap( &bm );
pDC->BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memDC, 0, 0,SRCCOPY);
}

Comments
raw image data -> picturebox in vb6
Posted by Legacy on 01/27/2004 12:00amOriginally posted by: Defcon31
I receive a the address of a pointer to my image data from a dll. how do i display raw image data (1 byte per grayscale pixel) in a picturebox in visual basic.
-
-
ReplyI receive my image data as BYTE array from a VC++ dll. how do i display raw image data (1 byte per grayscale pixel) in a picturebox in visual basic.
Posted by billy_bill on 09/19/2007 08:34amI tried above mentioned solution but unable to show image. Can please some-one help me.
ReplyUse SetDIBits API
Posted by weizhen77 on 10/30/2004 11:30pmBelow is a sample code. The code read a 24-bit BMP file, store the raw data into a memory block "bp" and display onto the PictureBox. For your case instead of 24-bit pixel data, change the code to 8-bit data per pixel. Option Explicit Private Declare Function SetDIBits Lib "gdi32" (ByVal hdc As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long Private Type BITMAPINFOHEADER '40 bytes biSize As Long biWidth As Long biHeight As Long biPlanes As Integer biBitCount As Integer biCompression As Long biSizeImage As Long biXPelsPerMeter As Long biYPelsPerMeter As Long biClrUsed As Long biClrImportant As Long End Type Private Type RGBQUAD '4 bytes rgbBlue As Byte rgbGreen As Byte rgbRed As Byte rgbReserved As Byte End Type Private Type BITMAPINFO '44 bytes bmiHeader As BITMAPINFOHEADER bmiColors As RGBQUAD End Type Private Const DIB_RGB_COLORS = 0& Private Const BI_RGB = 0& Private Sub Command1_Click() Dim i As Long Dim bp() As Byte Dim bmppath As String Dim bm As BITMAPINFO bm.bmiHeader.biSize = Len(bm.bmiHeader) bmppath = App.Path & "\test.bmp" Open bmppath For Binary As #1 Get #1, 3, bm.bmiHeader.biSizeImage 'Not a reliable data Get #1, 19, bm.bmiHeader.biWidth 'Use negative height to scan top-down. Get #1, 23, bm.bmiHeader.biHeight Get #1, 27, bm.bmiHeader.biPlanes Get #1, 29, bm.bmiHeader.biBitCount 'Bits per pixel Get #1, 31, bm.bmiHeader.biCompression 'BI_RGB ReDim bp(bm.bmiHeader.biSizeImage - 1) As Byte Get #1, 55, bp Close #1 Picture1.Width = bm.bmiHeader.biWidth Picture1.Height = bm.bmiHeader.biHeight i = SetDIBits(Picture1.hdc, _ Picture1.Image, _ 0, _ bm.bmiHeader.biHeight, _ bp(0), _ bm, _ DIB_RGB_COLORS) Debug.Print i Picture1.Visible = True Picture1.Refresh End SubReplyHOW DO I USE THIS WITH HDC OR LPCSTR
Posted by Legacy on 03/13/2003 12:00amOriginally posted by: Lloyd
Replysource code for displaying BMP 256-bits colour 640x480 in windows mode using C++
Posted by Legacy on 12/23/2002 12:00amOriginally posted by: hewcm
ReplyRead Pixel by Piexl
Posted by Legacy on 11/04/2002 12:00amOriginally posted by: Hubert
I want to read the RGB value of a bitmap file pixel by pixel. Are there any simple solution? Do I neccessart load the file into a piettle? Thanks.
Reply
I use Borland c++ compiler. CFile - ???
Posted by Legacy on 08/30/2002 12:00amOriginally posted by: ILYA
My compiler can not create CFile object.
ReplyI do not have h-file with defenishen of CFile.
I use CreateFile, ReadFile ....
What must I do read BitMap with shuch function?
(sorry for my Engl.)
Memory leak ???
Posted by Legacy on 06/28/2002 12:00amOriginally posted by: Loan Ng.
Does anyone have memory leak when try using this code?
ReplyProblem using DrawBitmap to the printer device context
Posted by Legacy on 06/11/2002 12:00amOriginally posted by: Pablo
I tried to use DrawBitmap but it is no working. It showed the printer dialog, It said it was printing all the pages but all I obtained was white pages, only my header in them.
There is something else to do in order to use this function for printing?
Thanks,
Pablo
ReplyHow do I add a bmp image through a file to a list control?
Posted by Legacy on 05/20/2002 12:00amOriginally posted by: Dj
I want to add a bmp image after reading from a file, onto the list control.
I am using LoadImage() and able to load a bmp from a file. After that I am even able to draw in OnDraw() using memory device context.
However, How do I go about doing the same in my List Control?
ReplyI made it working several times without problem
Posted by Legacy on 05/16/2002 12:00amOriginally posted by: PJ
I'd obtained Assert messages every second time I invoked "LoadBMPImage" in the "bitmap.Attach( hBmp );" instruction.
I don�t know what exactly means the CBitmap.Attach definition ("Attaches a Windows GDI object to a CGdiObject object."). But if I have problem with "Attach" may be I can solve it with "Detach".
So, I inserted "bitmap.Detach();" just before the "bitmap.Attache( hBmp );" instruction and it seems to be working Ok.
The problem is, Do you know if this "solution" may produce side effects in memory, pointers, etc.?
Thanks,
PJ
Replyhow to load a 256 color bitmap file in simple SDI application
Posted by Legacy on 05/02/2002 12:00amOriginally posted by: aaqib sharif
if any body could help me in this manner. plz do help me. i want to load the bitmap file through Loadbitmap() and then i have to use Getpixel() function for my OCR project.
ReplyLoading, Please Wait ...