|
|
QA: How can I get bitmap bits?
By Vassili Philippov, July 02, 2001.
Print version
Question
I loaded bitmap using LoadBitmap function. Now I want to read bitmap
bits (color of each point). How can I do it? I have looked at GetDIBits
function but it isn't not implemented under Windows CE.
Answer
Here is a way to read bitmap bits:
-
Create another bitmap using CreateDIBSection, this function will return you
pointer to bits location.
-
Create two device contexts and select your original bitmap into one of
them and just created bitmap (that was created using CreateDIBSection)
into another device context.
-
Call BitBlt to copy original bitmap into just created.
-
See bits of just created bitmap (CreateDIBSection gave your a pointer
to them) there will be copy of original bits
But you should be careful because bits will be in the strange order. Here is
information about bits order (3 bytes per point, from bottom to top, BGR).
-
3 bytes per point.
-
Lines ane from the bottom to the top!
-
Points in the line are from the left to the right
-
Bytes in one point are BGR (blue, green, red) not RGB
But much more easy way is using of STScreenBuffer library that does all this
wotk for you. To get access to bits using CSTScreenBuffer class you have:
-
Create instance of CSTScreenBuffer class.
-
Initialize it with your source bitmap using Create method.
-
Read color of points using GetPoint(int nX, int nY) function.
Source code
Here is a sample code that uses CSTScreenBuffer class. Download
STScreenBuffer library.
void CTestGettingBitsDlg::OnTestGettingBits()
{
HBITMAP hSourceBitmap = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1));
CSTScreenBuffer sb;
sb.Create(hSourceBitmap);
CClientDC dc(this);
//Here we can read colors using sb.GetPoint
DeleteObject(hSourceBitmap);
}
Here is a sample code that doesn't use CSTScreenBuffer class.
struct DIBINFO : public BITMAPINFO
{
RGBQUAD arColors[255]; // Color table info - adds an extra 255 entries to palette
operator LPBITMAPINFO() { return (LPBITMAPINFO) this; }
operator LPBITMAPINFOHEADER() { return &bmiHeader; }
RGBQUAD* ColorTable() { return bmiColors; }
};
void CTestGettingBitsDlg::OnTestGettingBits()
{
//1. Initialize source bitmap. For example load from resources.
HBITMAP hSourceBitmap = LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP1));
//2. Getting bimap size.
BITMAP bm;
GetObject(hSourceBitmap, sizeof(BITMAP), &bm);
//3. Creating new bitmap and receive pointer to it's bits.
HBITMAP hTargetBitmap;
void *pBuffer;
//3.1 Initilize DIBINFO structure
DIBINFO dibInfo;
dibInfo.bmiHeader.biBitCount = 24;
dibInfo.bmiHeader.biClrImportant = 0;
dibInfo.bmiHeader.biClrUsed = 0;
dibInfo.bmiHeader.biCompression = 0;
dibInfo.bmiHeader.biHeight = bm.bmHeight;
dibInfo.bmiHeader.biPlanes = 1;
dibInfo.bmiHeader.biSize = 40;
dibInfo.bmiHeader.biSizeImage = bm.bmWidth*bm.bmHeight*3;
dibInfo.bmiHeader.biWidth = bm.bmWidth;
dibInfo.bmiHeader.biXPelsPerMeter = 3780;
dibInfo.bmiHeader.biYPelsPerMeter = 3780;
dibInfo.bmiColors[0].rgbBlue = 0;
dibInfo.bmiColors[0].rgbGreen = 0;
dibInfo.bmiColors[0].rgbRed = 0;
dibInfo.bmiColors[0].rgbReserved = 0;
//3.2 Create bitmap and receive pointer to points into pBuffer
HDC hDC = ::GetDC(NULL);
ASSERT(hDC);
hTargetBitmap = CreateDIBSection(
hDC,
(const BITMAPINFO*)dibInfo,
DIB_RGB_COLORS,
(void**)&pBuffer,
NULL,
0);
::ReleaseDC(NULL, hDC);
//4. Copy source bitmap into the target bitmap.
//4.1 Create 2 device contexts
CDC memDc;
if (!memDc.CreateCompatibleDC(NULL)) {
ASSERT(FALSE);
}
CDC targetDc;
if (!targetDc.CreateCompatibleDC(NULL)) {
ASSERT(FALSE);
}
//4.2 Select source bitmap into one DC, target into another
HBITMAP hOldBitmap1 = (HBITMAP)::SelectObject(memDc.GetSafeHdc(), hSourceBitmap);
HBITMAP hOldBitmap2 = (HBITMAP)::SelectObject(targetDc.GetSafeHdc(), hTargetBitmap);
//4.3 Copy source bitmap into the target one
targetDc.BitBlt(0, 0, bm.bmWidth, bm.bmHeight, &memDc, 0, 0, SRCCOPY);
//4.4 Restore device contexts
::SelectObject(memDc.GetSafeHdc(), hOldBitmap1);
::SelectObject(targetDc.GetSafeHdc(), hOldBitmap2);
memDc.DeleteDC();
targetDc.DeleteDC();
//Here we can bitmap bits: pBuffer. Note:
// 1. pBuffer contains 3 bytes per point
// 2. Lines ane from the bottom to the top!
// 3. Points in the line are from the left to the right
// 4. Bytes in one point are BGR (blue, green, red) not RGB
// 5. Don't delete pBuffer, it will be automatically deleted
// when delete hTargetBitmap
DeleteObject(hSourceBitmap);
DeleteObject(hTargetBitmap);
}
Related resources:
Discuss
Discuss this article.
Here you can write your comments and read comments of other developers.
|