Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Attempting to access 1 bit bitmap raw pixel data

0 views
Skip to first unread message

Steve...@gmail.com

unread,
Sep 6, 2005, 12:48:35 PM9/6/05
to
I have been reading 20+ articles and news posts on how to obtain access
to a bitmap file's raw pixel data. I have been failing terribly.

My latest attempt(based on several examples online) is failing in a
very strange way(to me).

Here is the code:
<code>
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,
filename,
IMAGE_BITMAP,
0,
0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_CREATEDIBSECTION);

BITMAP bitmap;
memset(&bitmap, 0, sizeof(BITMAP));

BITMAPINFO bitmapinfo;
memset(&bitmapinfo, 0, sizeof(BITMAPINFO));


HDC hdc = ::GetDC(NULL);
GetDIBits(hdc, hBitmap, 0, bitmap.bmHeight, NULL, &bitmapinfo,
DIB_RGB_COLORS);
int errCode = GetLastError();
</code>

errCode is 8 which translates to:
ERROR_NOT_ENOUGH_MEMORY - Not enough storage is available to process
this command.

I don't see that I am supposed to have allocated anything. From the
examples I have seen online, I should make two calls to GetDIBits();
one to get BITMAPINFO filled and another to get the actual data.

The articles I have seen are littered with information about device
context, resolution, color depth, etc. All I want to do is read the
file and find out what the file's pixel data is so that I can convert
it to HEX codes for an LCD driver for an embedded device.


If anyone could clue me into the *clean* and neat way to read a 1 bit
bitmap and get to the data[] that would be great. I would also like to
know why the above code is failing.

Thank for your time,
Steve

Steve...@gmail.com

unread,
Sep 6, 2005, 12:53:28 PM9/6/05
to
Apologies!
It is this line that is setting error code # 8:
<code>

hBitmap = (HBITMAP)LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_CREATEDIBSECTION);
</code>

The call to GetDIBits doesn't raise an error code.
It also doesn't set any of the BITMAPINFO struct members :(

So now I have 2 problems...

Kellie Fitton

unread,
Sep 6, 2005, 1:21:25 PM9/6/05
to
Hi,

Well, when using the API GetDIBits(), it is important to handle the
alignment of the DIB data, DIB data are always DWORD aligned, so you
need to pad each scanLine out to a full DWORD boundary.

Total surface bytes = Y Resolution * DWORD aligned X Resolution

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_7gms.asp

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/gdi/bitmaps_1rw2.asp

Hope these information helps,

Kellie.

Michael Phillips, Jr.

unread,
Sep 6, 2005, 1:40:17 PM9/6/05
to
Try this:

LoadImage will only load bitmaps that have a normal BITMAPINFOHEADER
structure. It will not load BITMAPV4HEADER or BITMAPV5HEADER bitmaps.

#define WORD_ALIGNED_BYTES(width) ((((width-1)>>5)+1)<<2) // WORD aligned
row stride

DWORD dwError;

HBITMAP hBitmap = (HBITMAP)::LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);

if ( hBitmap ) // assume a bitmap created with CreateDIBSection
{
DIBSECTION ds;
::GetObject( hBitmap, sizeof(ds), &ds );

// allocate a buffer to hold the bits (i.e., row stride * height)
// a 1bpp bitmap requires a WORD aligned buffer
// all other bitmaps require a DWORD aligned buffer
PBYTE lpBits = new BYTE[ WORD_ALIGNED_BYTES(ds.Bm.bmWidth) *
ds.Bm.bmHeight ];

// retrieve the bits... assume lpBits buffer created without error
HDC hDC = ::CreateCompatibleDC(NULL);
int iScanlines = ::GetDIBits( hDC, 0, ds.Bm.bmHeight, lpBits, &ds.Bmih,
DIB_RGB_COLORS);
::DeleteDC(hDC);

if ( iScanlines == ds.Bm.bmHeight )
{
// work with raw bits

delete [] lpBits;
::DeleteObject(hBitmap);
}
else
dwError = ::GetLastError();
}
else
dwError = ::GetLastError();


<Steve...@gmail.com> wrote in message
news:1126025608....@f14g2000cwb.googlegroups.com...

Steve...@gmail.com

unread,
Sep 6, 2005, 2:54:35 PM9/6/05
to
Hi Michael,

Thank you for the reply. One thing that I have noticed from your code.
DIBSECTION::dsBmih is a BITMAPINFOHEADER and ::GetDIBits() wants
LPBITMAPINFO

I will substitute this sectio of code unless you inform me that I am
missing something. I will let you know how things work out.

Thank you also to Kellie for the additional information.

Steve...@gmail.com

unread,
Sep 6, 2005, 3:04:46 PM9/6/05
to
Michael,

I'm still getting the code 8 on LoadImage()

The source bitmap I'm testing with has been saved from Photoshop CS and
I also saved a version from MS Paint

Both throw the same error.


I will past the entire code. It's almost EXACTLY what you pasted save
for the error report macro

<code>
#define CheckAndReportIfError(line) \
{ \
DWORD dwError = GetLastError(); \
if(dwError != 0) \
{ \
char buffer[256]={0}; \
sprintf(buffer, "Line: %d\tError: %d", line, dwError); \
MessageBox(0, buffer, "error", MB_OK); \
} \
} \

void GetBitmapBits(CString& filename)
{
#define WORD_ALIGNED_BYTES(width)((((width-1)>>5)+1)<<2) // word
aligned row stride

DWORD dwError;

HBITMAP hBm = (HBITMAP)::LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION);
CheckAndReportIfError(__LINE__);

if(hBm)
{
DIBSECTION ds;
BITMAPINFO bmi;
::GetObject(hBm, sizeof(ds), &ds);
CheckAndReportIfError(__LINE__);

//


// allocate a buffer to hold the bits

//
PBYTE bits = new
BYTE[WORD_ALIGNED_BYTES(ds.dsBm.bmWidth)*ds.dsBm.bmHeight];
ASSERT(bits && "Allocation failed!");

HDC hDC = ::CreateCompatibleDC(NULL);
CheckAndReportIfError(__LINE__);
int iScanlines = ::GetDIBits(hDC, hBm, 0, ds.dsBm.bmHeight, bits,
&bmi/*&ds.dsBmih*/, DIB_RGB_COLORS);
CheckAndReportIfError(__LINE__);


::DeleteDC(hDC);

if(iScanlines == ds.dsBm.bmHeight)
{
//
// work with the bits
//

//
// all done, clean up
//
delete[] bits;
bits = NULL;

::DeleteObject(hBm);
}
else
{
CheckAndReportIfError(__LINE__);
}
}
else
{
CheckAndReportIfError(__LINE__);
}
}
</code>

Michael Phillips, Jr.

unread,
Sep 6, 2005, 3:42:46 PM9/6/05
to
GetDIBits requires a BITMAPINFO header.

My code works only for 24bpp or greater since it assumes no
color table. That was my mistake.. sorry about that.

Simply allocate room for the color table:
UINT nColors = 1 << ds.dsBm.BmBits; // should be 2 for 1bpp
LPBITMAPINFO pbmi = (BITMAPINFO*)new
BYTE[sizeof(BITMAPINFOHEADER)+nColors*sizeof(RGBQUAD)];
// copy the BITMAPINFOHEADER from the DIBSECTION
::CopyMemory(pbmi, &ds.dsBmih, sizeof(BITMAPINFOHEADER));

// fill in the color table
HDC hDC = ::CreateCompatibleDC(NULL);
// Select the bitmap into the device
HGDIOBJ hOldBitmap = ::SelectObject(hDC, hBitmap);
// retrive the color table from the DIBSection
nColors = ::GetDIBColorTable(hDC, 0, nColors, &pbmi->bmiColors[0]);
::SelectObject(hDC, hOldBitmap);

// Now call GetDIBits with the correct BITMAPINFO pointer

...
delete [] pbmi;


If loadimage is your problem, try loading the bitmap the old fashion
way using file io.

A bitmap consists of a BITMAPFILEHEADER followed by a BITMAPINFOHEADER
followed by the color table followed by the image bits.

bitmap.bmp
BITMAPFILEHEADER - must have signature 0x4D42 ('BM')
BITMAPINFOHEADER
RGBQUADS - one for each color
RAW BITS


<Steve...@gmail.com> wrote in message
news:1126032875.3...@g43g2000cwa.googlegroups.com...

Michael Phillips, Jr.

unread,
Sep 6, 2005, 3:49:44 PM9/6/05
to
Since you are loading a monochrome bitmap,
try adding the LR_MONOCHROME flags as follows:

HBITMAP hBm = (HBITMAP)::LoadImage(NULL, filename, IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE|LR_CREATEDIBSECTION|LR_MONOCHROME);

If that fails, try loading the bitmap yourself using file io
and instead of using CreateDIBSection use CreateBitmap because
CreateBitmap was designed for 1bpp monochrome bitmaps.


<Steve...@gmail.com> wrote in message
news:1126033486....@g47g2000cwa.googlegroups.com...

Steve...@gmail.com

unread,
Sep 6, 2005, 4:02:48 PM9/6/05
to
Hi Michael,

Thanks again for the fast reply. Allocating color table enabled the
GetDIBits to execute. That is a good start ;)

I am now trying to determine if I have valid results, which I'm not
sure about.

I create a 2 pixel x 2 pixel bmp with a black pixel in the top right
corner.

So far, this is what I have observed;

- I've allocated 8 bytes to received the data
- GetDIBits returned 2
- the values of the bytes are: 192, 0, 0, 0, 64, 0, 0, 0

to me, those values don't look correct. I'm trying to see some pattern
or something that is logical, but it looks like junk.

I've never worked with bitmaps like this before, so I'm not sure what
to expect.
Does that look correct to you?

Thanks again!

Michael Phillips, Jr.

unread,
Sep 6, 2005, 4:03:34 PM9/6/05
to
If you are still getting the code 8 error, I would assume
that your bitmap is corrupt!

You can verify this by using simple file io and the info in my
post. You must have a valid BITMAPFILEHEADER with
signature bytes('BM')! <---check with a hex editor

If you don't, then LoadImage can't figure out the correct
memory allocation for the bitmap.


"Michael Phillips, Jr." <mphil...@nospam.jun0.c0m> wrote in message
news:uPZhlsxs...@tk2msftngp13.phx.gbl...

Michael Phillips, Jr.

unread,
Sep 6, 2005, 4:32:01 PM9/6/05
to
A 1bpp bitmap is packed.

You must unpack each byte to get at the specific
pixel that you want. The pixel will either be set or unset ( 1 or 0 ).

You can use GetPixel( hDC, x, y ) to get the color of the pixel
that you want. Simply select the hBitmap into a device context.

Also, bitmaps are stored upside down.

If you don't want to use GetPixel, you can unpack the bytes
yourself as follows:

// Find the byte on which this scanline begins
DWORD ByteIndex = (bmHeight - y - 1) * WIDTH_ALIGNED_BYTES(bmWidth);
// Find the byte containing this pixel
ByteIndex += (x >> 3);
// Which byte is it?
BYTE BitNumber = (BYTE)( 7 - (x % 8) );
// get the color index
int Index = (lpBits[ByteIndex] << BitNumber) & 0x80 ? 1 : 0;

In the color table you have two colors, selext the matching Index
COLORREF color = RGB(pbmi->bmiColors[Index].rgbRed,
pbmi->bmiColors[Index].rgbGreen, pbmi->bmiColors[Index].rgbBlue);


<Steve...@gmail.com> wrote in message
news:1126036968....@g47g2000cwa.googlegroups.com...

Steve...@gmail.com

unread,
Sep 6, 2005, 4:39:30 PM9/6/05
to
I threw the buffer into a PBITMAPFILEHEADER and everything looks good
type is BF, well, it's 19778 or 4d42 or BM

the bfOffBits is 62 and the total size is 70 which leaves 8 for the
data.

Everything looks fine.
if I take a look at the bit data, I see: -64, 0, 0, 0, 64, 0, 0, 0

Which also looks like junk, but like I said, I don't know what I'm
looking for either.

working with the raw data sure is easier than using all the other
methods ;) Granted, it's far from reliable...

Michael Phillips, Jr.

unread,
Sep 6, 2005, 5:03:05 PM9/6/05
to
Let's see... sizeof(BITMAPFILEINFO) = 14 +
sizeof(BITMAPINFOHEADER) = 40 +
2*sizeof(RGBQUAD) = 8
Total = 62 ... So far, so good!

A 2x2 bitmap would consist of 8 bytes of raw data
(((2-1)>>5)+1)<<2 = 4 * height(2) = 8 bytes

Your bitmap looks good!

Now you have to unpack the 8 bytes to get at the
individual pixels.


<Steve...@gmail.com> wrote in message
news:1126039170.7...@g47g2000cwa.googlegroups.com...

Steve...@gmail.com

unread,
Sep 7, 2005, 1:12:15 PM9/7/05
to
OK, making progress, but still not there. This could be the last ?
though(I hope).

After looping through and checking each pixel of the 4 pixel bitmap, I
expected to see only 1 of the 4 pixels to be different(my bitmap looks
like this:
[X][ ]
[ ][ ]
Where the X is a black pixel)

But instead, 2 seem to be black. Anyway, I'm stuck(again) and hoped to
paste code so that someone might point out my error.

<code>
void GetBitmapBitsUglyVersion(CString& filename)
{
#define WORD_ALIGNED_BYTES(width)((((width-1)>>5)+1)<<2)


CFile file(filename, CFile::modeRead);
unsigned long long length = file.GetLength();

char* pBuffer = new char[length+1];
char* pDataPtr = pBuffer;

file.Read(pBuffer, length);
file.Close();

PBITMAPFILEHEADER fileHeader = (PBITMAPFILEHEADER)pDataPtr;
pDataPtr += sizeof(BITMAPFILEHEADER);

PBITMAPINFOHEADER infoHeader = (PBITMAPINFOHEADER)pDataPtr;
unsigned int width = infoHeader->biWidth;
unsigned int height = infoHeader->biHeight;
unsigned int bitCount = infoHeader->biBitCount;
unsigned short numPlanes = infoHeader->biPlanes;

pDataPtr+= sizeof(BITMAPINFOHEADER);
pDataPtr+=(numPlanes+1)*sizeof(RGBQUAD); // skip the color table
(it's B&W)

char* pBits = pDataPtr;


char buffer[128];

for(int i=0; i < width; i++)
{
for(int j=0; j < height; j++)
{


// Find the byte on which this scanline begins

DWORD ByteIndex = (height - j - 1) * WORD_ALIGNED_BYTES(width);


// Find the byte containing this pixel

ByteIndex += (i >> 3);


// Which byte is it?

BYTE BitNumber = (BYTE)( 7 - (i % 8) );


// get the color index

int Index = (pBits[ByteIndex] << BitNumber) & 0x80 ? 1 : 0;
if(Index)
{
sprintf(buffer, "x:%d, y:%d is high\r\n", i, j);
OutputDebugString(buffer);
}
}
}

if(pBuffer)
delete[] pBuffer;
}
</code>

Hopefully someone will see the problem and hopefully it will be a basic
one ;)

Thanks for the help!
-Steve

Michael Phillips, Jr.

unread,
Sep 7, 2005, 2:09:18 PM9/7/05
to
1) Per the docs the bits are located as follows:
char* pBits = (char*)((PBYTE)infoHeader + infoHeader.bfOffBits);

2) You need to read the color table.
When you unpack the byte, you get an index
into the color table that represents the color.
The colors are not mandated to be black and white.
And they don't have to be packed as index[0] = black
and index[1] = white.

3) Your buffer needs to hold WORD_ALIGNED_BYTES(width) * height bytes
For your 2x2 bitmap that's 8 bytes.

4) You loop through each scanline
for ( int i = 0; i < height; i++ ) // 2 scan lines


{
// Find the byte on which this scanline begins

DWORD ByteIndex = (height - i - 1) * WORD_ALIGNED_BYTES(width);
// loop through one WORD aligned scanline
for ( int j = 0; j < WORD_ALIGNED_BYTES(width); j++ ) // rowstride
= 4bytes
for ( int k = 0; k < 8; k++ ) // packed as 8 pixels per byte
{
// locate the bit
BYTE BitNumber = (BYTE)( 7 - (k % 8) );


// get the color index

int Index = (pBits[j] << BitNumber) & 0x80 ? 1 : 0;
// look up the color in the color table


COLORREF color = RGB(pbmi->bmiColors[Index].rgbRed,
pbmi->bmiColors[Index].rgbGreen,
pbmi->bmiColors[Index].rgbBlue);
}
}

<Steve...@gmail.com> wrote in message
news:1126113135.1...@g43g2000cwa.googlegroups.com...

Michael Phillips, Jr.

unread,
Sep 7, 2005, 2:22:05 PM9/7/05
to
Correction

> 1) Per the docs the bits are located as follows:
> char* pBits = (char*)((PBYTE)infoHeader + infoHeader.bfOffBits);

Should be


1) Per the docs the bits are located as follows:

char* pBits = (char*)((PBYTE)fileHeader + fileHeader.bfOffBits);

Sorry about that.


"Michael Phillips, Jr." <mphil...@nospam.jun0.c0m> wrote in message

news:Om0VBd9s...@TK2MSFTNGP15.phx.gbl...

Michael Phillips, Jr.

unread,
Sep 7, 2005, 4:12:26 PM9/7/05
to
I am not having a good day.

The loop needs to look like this:

for ( int i = 0; i < height; i++ ) // 2 scan lines
{
// Find the byte on which this scanline begins

PBYTE pByte = (PBYTE)pBits + (height - i - 1) *

WORD_ALIGNED_BYTES(width);
// loop through one WORD aligned scanline
for ( int j = 0; j < WORD_ALIGNED_BYTES(width); j++ ) // rowstride
= 4bytes
for ( int k = 0; k < 8; k++ ) // packed as 8 pixels per byte
{
// locate the bit
BYTE BitNumber = (BYTE)( 7 - (k % 8) );
// get the color index

int Index = (pByte[j] << BitNumber) & 0x80 ? 1 : 0;


// look up the color in the color table
COLORREF color = RGB(pbmi->bmiColors[Index].rgbRed,
pbmi->bmiColors[Index].rgbGreen,
pbmi->bmiColors[Index].rgbBlue);
}
}

"Michael Phillips, Jr." <mphil...@nospam.jun0.c0m> wrote in message
news:%23TeSKk9...@TK2MSFTNGP14.phx.gbl...

Steve...@gmail.com

unread,
Sep 8, 2005, 9:15:41 AM9/8/05
to
That's OK, I end up in the correct place by just advancing my pointer
past each header. I just tested this by using the bfOffBits in the
file header and it indicates the same location that pDataPtr was
already at. So that is good ;)

Now I'm on to review your loop code. I've read the color tables, they
are;
[0] = 0,0,0
[1] = 255,255,255

that looks correct.

Steve...@gmail.com

unread,
Sep 8, 2005, 9:43:13 AM9/8/05
to
I'm sorry to say, it still doesn't work as I would expect. For a
moment, it appeared to behave, but then I realized it was indeed wrong.

Using the loop that you posted, I'm getting indices of 0 and 1 even
when reading an all white 2x2 bitmap.

I haven't been able to find a relationship between the results I'm
seeing.
Once again, for your review, here is the code that I'm using:


<code>
void GetBitmapBitsUglyVersion(CString& filename)
{
#define WORD_ALIGNED_BYTES(width)((((width-1)>>5)+1)<<2)


CFile file(filename, CFile::modeRead);
unsigned long long length = file.GetLength();

char* pBuffer = new char[length+1];
char* pDataPtr = pBuffer;

file.Read(pBuffer, length);
file.Close();

PBITMAPFILEHEADER fileHeader = (PBITMAPFILEHEADER)pDataPtr;
int offset = fileHeader->bfOffBits;
pDataPtr += sizeof(BITMAPFILEHEADER);

PBITMAPINFOHEADER infoHeader = (PBITMAPINFOHEADER)pDataPtr;
unsigned int width = infoHeader->biWidth;
unsigned int height = infoHeader->biHeight;
unsigned int bitCount = infoHeader->biBitCount;
unsigned short numPlanes = infoHeader->biPlanes;

pDataPtr+= sizeof(BITMAPINFOHEADER);

// read the color table
RGBQUAD* colorTables = new RGBQUAD[numPlanes+1];
memcpy(colorTables, pDataPtr, sizeof(RGBQUAD)*(numPlanes+1));


pDataPtr+=(numPlanes+1)*sizeof(RGBQUAD); // skip the color table
(it's B&W)

char* pBits = pDataPtr;

char buffer[128];
int lineCount=0;
for(int i = 0; i < height; i++) // 2 scan lines


{
// Find the byte on which this scanline begins

PBYTE pByte = (PBYTE)pBits + (height - i - 1) *


WORD_ALIGNED_BYTES(width);
// loop through one WORD aligned scanline

for(int j = 0; j < WORD_ALIGNED_BYTES(width); j++) // rowstride=
4bytes
{
for(int k = 0; k < 8; k++) // packed as 8 pixels per byte


{
// locate the bit
BYTE BitNumber = (BYTE)( 7 - (k % 8) );
// get the color index

int Index = (pByte[j] << BitNumber) & 0x80 ? 1 : 0;


// look up the color in the color table


COLORREF color = RGB(colorTables[Index].rgbRed,
colorTables[Index].rgbGreen, colorTables[Index].rgbBlue);
if(color==RGB(0,0,0))
{
// black pixel
lineCount++;
sprintf(buffer, "[%d]\t:x:%d, y:%d is black\r\n", lineCount, i,
j);
OutputDebugString(buffer);
}
}
}
}

if(colorTables)
delete[] colorTables;

if(pBuffer)
delete[] pBuffer;
}
</code>


I will look it over a couple more times and see if I can find the
problem.

Thanks again for your continued involvement, I can't beleive what a
pain this is to solve! ;)

-Steve

Michael Phillips, Jr.

unread,
Sep 8, 2005, 1:02:05 PM9/8/05
to
It's my fault. I forgot to test the code before
I posted it.

No problem. Just changed to following line:

From ------> int Index = (pByte[j] << BitNumber) & 0x80 ? 1 : 0;

To ---------> int Index = (pByte[j] >> BitNumber) & 0x03 ? 1 : 0;

One more correction.

The color table is composed of nColors * sizeof(RGBQUAD)
where nColors = (1 << bitcount), not numPlanes+1.


Here is my code:
<code>

#include <afx.h>

#pragma comment ( lib, "libcmtd.lib")
void GetBitmapBitsUglyVersion(char *filename)
{
#define WORD_ALIGNED_BYTES(width)((((width-1)>>5)+1)<<2)


CFile file(filename, CFile::modeRead);
unsigned long long length = file.GetLength();

char* pBuffer = new char[length+1];
char* pDataPtr = pBuffer;

file.Read(pBuffer, length);
file.Close();

PBITMAPFILEHEADER fileHeader = (PBITMAPFILEHEADER)pDataPtr;
int offset = fileHeader->bfOffBits;
pDataPtr += sizeof(BITMAPFILEHEADER);

PBITMAPINFOHEADER infoHeader = (PBITMAPINFOHEADER)pDataPtr;
unsigned int width = infoHeader->biWidth;
unsigned int height = infoHeader->biHeight;
unsigned int bitCount = infoHeader->biBitCount;
unsigned short numPlanes = infoHeader->biPlanes;

pDataPtr+= sizeof(BITMAPINFOHEADER);

// read the color table

RGBQUAD* colorTables = new RGBQUAD[1 << infoHeader->biBitCount];
memcpy(colorTables, pDataPtr, sizeof(RGBQUAD)*(1 <<
infoHeader->biBitCount));
pDataPtr+=(1 << infoHeader->biBitCount)*sizeof(RGBQUAD); // skip the color
table(it's B&W)

unsigned char* pBits = (PBYTE)fileHeader + offset;

// allocate buffer for 32bpp bitmap
int widthBytes = ((((width + 3)&~3)*32) >> 3);
int imageSize = widthBytes * height;
PBYTE pDibBits = new BYTE[imageSize];

int scanlineWidth = WORD_ALIGNED_BYTES(width);

char buffer[128];
int lineCount=0;


for(int i = 0; i < height; i++) // 2 scan lines
{
// Find the byte on which this scanline begins

char *pByte = (char*)((PBYTE)pBits + (height - i - 1) *scanlineWidth);

DWORD *pdwBits = (DWORD*)((PBYTE)pDibBits + (height - i - 1) *
widthBytes);
int l = 0;

// loop through one WORD aligned scanline

for(int j = 0; j < scanlineWidth; j++) // rowstride=4bytes


{
for(int k = 0; k < 8; k++) // packed as 8 pixels per byte
{
// locate the bit
BYTE BitNumber = (BYTE)( 7 - (k % 8) );
// get the color index

int Index = (pByte[j] >> BitNumber) & 0x03 ? 1 : 0;


// look up the color in the color table
COLORREF color = RGB(colorTables[Index].rgbRed,
colorTables[Index].rgbGreen, colorTables[Index].rgbBlue);

pdwBits[l++] = color;


if(color==RGB(0,0,0))
{
// black pixel
lineCount++;
sprintf(buffer, "[%d]\t:x:%d, y:%d is black\r\n", lineCount, i,j);
OutputDebugString(buffer);
}

}

}
}

if (colorTables)
delete[] colorTables;

if(pBuffer)
delete[] pBuffer;

// save 32bpp bitmap
// Try to open the file for write access
CFile outfile;
outfile.Open("test32bpp.bmp",
CFile::modeReadWrite
| CFile::modeCreate
| CFile::shareExclusive);

BITMAPFILEHEADER bfh;

int sizeofColorTable = 0; //32bpp bitmap

int sizeofImage = imageSize;

// construct the file header
bfh.bfType = 0x4D42; // 'BM'
bfh.bfSize =
sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) +
sizeofColorTable +
sizeofImage;
bfh.bfReserved1 = 0;
bfh.bfReserved2 = 0;
bfh.bfOffBits =
sizeof(BITMAPFILEHEADER) +
sizeof(BITMAPINFOHEADER) +
sizeofColorTable;

// write the file header
int iSize = sizeof(bfh);
// write bitmapfileheader
outfile.Write(&bfh, iSize);
iSize = sizeof(BITMAPINFOHEADER) + sizeofColorTable;
infoHeader->biBitCount = 32;
infoHeader->biSizeImage = sizeofImage;
infoHeader->biClrUsed = 0;
infoHeader->biClrImportant = 0;
// write bitmapinfoheader
outfile.Write(infoHeader, iSize);
// write the bits
iSize = sizeofImage;

outfile.Write(pDibBits, iSize);

outfile.Close();
delete [] pDibBits;
}


int main ( int argc, char *argv[] )
{
GetBitmapBitsUglyVersion(argv[2]);
return 0;
}

<code>
I tested the code and it works!

I read in a 1bpp bitmap then unpacked it and created
a 32bpp bitmap.

I saved the bitmap and compared it to the original
in a bitmap viewer.

Both bitmaps look identical except for the bit depth.


<Steve...@gmail.com> wrote in message
news:1126186993....@g43g2000cwa.googlegroups.com...

0 new messages