WalterRautenbach
asked on
Create 1 bit bitmap from raw data
Hi there
I am using a 3rd party software sdk to enocde a 2d barcode. The function returns a pointer to the raw image data. The image data is 1 bit per pixel data. Their document also states that the image is 4 byte aligned (what ever that means?) The function returns with the width and height of the image as well (I am not sure if the width and height is that of the image as a 1 byte per pixel image or 1 bit per pixel image). I also see that the function returns with a Palette but I am not sure if this is relevant.
My question is, I want to display the 2D barcode and store it as a Bitmap in the DB. How can I create the 1 bit bitmap?
I am using a 3rd party software sdk to enocde a 2d barcode. The function returns a pointer to the raw image data. The image data is 1 bit per pixel data. Their document also states that the image is 4 byte aligned (what ever that means?) The function returns with the width and height of the image as well (I am not sure if the width and height is that of the image as a 1 byte per pixel image or 1 bit per pixel image). I also see that the function returns with a Palette but I am not sure if this is relevant.
My question is, I want to display the 2D barcode and store it as a Bitmap in the DB. How can I create the 1 bit bitmap?
ASKER
Hi Dan
Thanks for the assistance. I attached the file. The widht = 364 and the height = 212.
You will find that I wrote 52264 bytes to the file. I am not sure if this is correct as the SDK does not say how many bytes is actually returned (I am pretty sure you can calculate it though using width * height / 8 or something??). The way I got to 52264 is it was the first value that did not give me an access violation reading passed the returned image buffer.
Thanks again
bits.txt
Thanks for the assistance. I attached the file. The widht = 364 and the height = 212.
You will find that I wrote 52264 bytes to the file. I am not sure if this is correct as the SDK does not say how many bytes is actually returned (I am pretty sure you can calculate it though using width * height / 8 or something??). The way I got to 52264 is it was the first value that did not give me an access violation reading passed the returned image buffer.
Thanks again
bits.txt
I can't get a reasonable image from that data. But when I use a width of
384
it looks like it might be a barcode. Does the attached look like the image you scannned?
bits1.bmp
384
it looks like it might be a barcode. Does the attached look like the image you scannned?
bits1.bmp
ASKER
Hi Dan
Great work, it looks like it, it just seems swapped. Please find attached what the image should look like.
Regards. Why do you think 384 would work?
2dBarcode.zip
Great work, it looks like it, it just seems swapped. Please find attached what the image should look like.
Regards. Why do you think 384 would work?
2dBarcode.zip
The 384 makes sense... I was doing the 32-bit alignment logic wrong. A 364-pixel wide image must actually be 384 wide so that it is a multiple of 32 (4-byte aligned)
The attached is from an MFC project, but I've avoided use of CBitmap and other MFC objects. You won't be using the CFile object, since you already have a buffer containing the data.
The for() loop copies the bottom line to the top, and so forth. Raw bitmap data is expected to have the scanlines in bottom-to-top order.
The attached is from an MFC project, but I've avoided use of CBitmap and other MFC objects. You won't be using the CFile object, since you already have a buffer containing the data.
The for() loop copies the bottom line to the top, and so forth. Raw bitmap data is expected to have the scanlines in bottom-to-top order.
void CD49Dlg::OnButton2()
{
int nWide= 364;
int nHigh= 212;
// account for line length needing to be 32-bit chunks
int nDwordsPerLine= (nWide + 31)/32;
int nBytesPerLine= nDwordsPerLine * 4;
int nPixelsPerLine= nBytesPerLine * 8;
int nDataLen= nBytesPerLine * nHigh; // amount of data to read from the file
BYTE* pabBitsRaw= new BYTE[nDataLen];
BYTE* pabBits= new BYTE[nDataLen];
CFile cFile("c:\\temp\\bits.txt", CFile::modeRead );
int n= cFile.Read( pabBitsRaw, nDataLen );
cFile.Close();
// raw bitmap data must be set to top-line on the bottom, etc.
//
for (int y=0; y<nHigh; y++ ) {
BYTE* pSrc= &pabBitsRaw[ ((nHigh-1)-y) * nBytesPerLine];
BYTE* pDst= &pabBits [ y * nBytesPerLine];
memmove( pDst, pSrc, nBytesPerLine );
}
HBITMAP hBmp= ::CreateBitmap( nPixelsPerLine, nHigh, 1, 1, pabBits );
m_ctlBmp.SetBitmap( hBmp ); // this lets me display the result
delete pabBits; // cleanup allocations
delete pabBitsRaw;
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Sir, THANK YOU!!!!!! It works perfectly. Thanks again
ASKER
I have one question though:
int nDwordsPerLine= (nWide + 31)/32;
Why 31? Where do you get that from?
Thanks
int nDwordsPerLine= (nWide + 31)/32;
Why 31? Where do you get that from?
Thanks
Quoted from the grading comment:
"Sir, THANK YOU!!!!!! It works perfectly. Thanks again"
You are welcome. I'm glad to help and this type of problem always interests me.
As to:
z= (n+31)/32
What that does is create a number (z) that is the next higher multiple of 32, but if n is already a multiple of 32, then z ends up the same as n. It works perfectly when z is an integer datatype because in integer division, the remainder (what would be the fraction after the decimal point) is discarded.
Any number smaller than 31 would not work correctly in every case.
Note that this is similar to another technique to "round a number" up or down:
z= (n+16)/32
Afterwards, z is the the lext lower multiple of 32 (if it is less than halfway between multiples), but will be the next higher multiple if n is more than halfway to the next multiple. It's a bit easier to understand if using round number decimals, such as 100:
z= (n+50)/100
the result (z) will always be a multiple of 100 (0, 100, 200, 300...) and if n is less than halfway between multiples (e.g., 100, 121, 135, 149, etc) then z will "round down" -- end up as 100). But if n is *more than or exactly* halfway (150, 155, 179, 199) then z will "round up" and be the next higher multiple (200).
"Sir, THANK YOU!!!!!! It works perfectly. Thanks again"
You are welcome. I'm glad to help and this type of problem always interests me.
As to:
z= (n+31)/32
What that does is create a number (z) that is the next higher multiple of 32, but if n is already a multiple of 32, then z ends up the same as n. It works perfectly when z is an integer datatype because in integer division, the remainder (what would be the fraction after the decimal point) is discarded.
Any number smaller than 31 would not work correctly in every case.
Note that this is similar to another technique to "round a number" up or down:
z= (n+16)/32
Afterwards, z is the the lext lower multiple of 32 (if it is less than halfway between multiples), but will be the next higher multiple if n is more than halfway to the next multiple. It's a bit easier to understand if using round number decimals, such as 100:
z= (n+50)/100
the result (z) will always be a multiple of 100 (0, 100, 200, 300...) and if n is less than halfway between multiples (e.g., 100, 121, 135, 149, etc) then z will "round down" -- end up as 100). But if n is *more than or exactly* halfway (150, 155, 179, 199) then z will "round up" and be the next higher multiple (200).
ASKER
Thank you for the explanation. I am pretty sure I understand now. Of course that value (31) will have then to change if the image width increases or decreases.
Thanks again.
Thanks again.
The formula (and the program code) will provide the correct size for any image width. It calculates the width in "4-byte-aligned" units.
ASKER
Oh, ok, thanks, so I did not really understand then. Thanks for your patience.
I'd need the width and height.
The four-byte alignment is standard. It just means that if the width in bytes is not a multiple of four, there are bytes of binary zero added to the right-hand side of the image data matrix.