Perhaps the hardest part of working with bitmap image data is that while doing the programming, it looks like random bytes rather than people or houses.
Here at Experts-Exchange, I've worked on a number of questions along the lines of "I have binary image data from source X, and I need to do Y with it." Finding a solution often requires intermediate steps: Tweak the data and look at the result as an image to see if the tweaks went the right way.
This talks about that problem, but it also describes a simple way to display any bitmap in your MFC programs.
Example:
I am getting a stream of binary data from a barcode reader, and I want to display it. I'm told that it is monochrome image data -- 1 bit per pixel (bpp) -- but I don't know how to turn it into a usable HBITMAP. Can you help?
The asker posted a binary file containing the raw data. I was told that the image was 364 wide by 212 high.
As a starting point, I did what I always do: Create a dialog-based Win32 Application with MFC support. I added a button and an OnClick handler, and pounded out some code to read the data into memory:
I can breakpoint on line 12 and use the Visual Studio memory-viewing window to see:
...which actually looks promising: It looks like it could be monochrome bitmap data. I know that the ff values are each a set of eight black (foreground color) pixels. A 00 value is a set of eight white (background color) pixels and other values will be a sequence of eight pixels, some black and some white.
But where do I go from here? I need to see the image before I can make any progress. Here's how I proceed:
- 1
Add a Static Picture Control
In the dialog editor, I added a Picture control:
- 2
Set Control Properties
Right-click the control, choose Properties, and set them to:
ID: IDC_Image
Type: Bitmap
- 3
Create a Control-type Variable
Right-click on the control (the little cactus icon) and select Add Variable..... Set:
Variable name: m_ctlBmp
Leave all of the other settings at their defaults.
Click [Finish]
If you look into the .H file, you'll now see the new object declaration:
CStatic m_ctlBmp;
and the top of the CPP files has a new element in the DoDataExchange() function:
DDX_Control(pDX, IDC_Image, m_ctlBmp);
Thus, we now have a member variable that gives us access to CStatic member functions. One of them is SetBitmap(). So...
- 4
Modify the Program to Display the Bitmap
In the above code snippet, replace the
// NOW what?!??!?!?
line with
Run the program, click [Button1] and see this result:
Now I can see the problem that needs to be solved:
The diagonal characteristic is symptomatic of horizontal misalignment.
The width must be wrong.
So I use my "programming by debugger" technique -- tweak the code and run it -- trying different widths. (Note: There was a time when a rebuild used to take minutes or even hours, but these days. a program like this is running by the time you lift your finger from the mouse button :-).
I could see that I was getting closer as I increased the width, but I had to go way wide -- to 384 -- before the scanlines would resolve into a clean image. Eventually, I remembered that bitmap scanlines are always a multiple of four bytes (DWORD) in length. I had been told that the width was 364 pixels, and 364 looks like a nice multiple of four, but it is not! (at least when counting by 8s -:) That would make each line 45.5 bytes wide. The next multiple of four above 45.5 is 48, so I know that each scanline will contain 48 bytes of data. I add-in some generic code to calculate the needed values (in multiple steps rather than all in one confusing formula, just because that's the way I roll at EE). Modify the code like so:
And the problem is clearly solved!
(Well, almost! That image turned out to be upside down, but changing that was a minor issue. See the EE question for the fix or if you want to download the binary image data file).
Review:
- To quickly begin writing program testing code, create a dialog-based application with MFC support.
- The memory-viewing window can be used as a starting point to see the data as a series of bytes, but that's not enough!
- To quickly be able to see a bitmap during your testing: Add a STATIC Picture Control to the dialog and a control-type variable. Then you can view any bitmap (including one you create from raw data) by using that control's SetBitmap() function.
References:
CreateBitmap Function
http://msdn.microsoft.com/
CStatic::SetBitmap
http://msdn.microsoft.com/
Bitmaps (Overview)
http://msdn.microsoft.com/
=-=-=-=-=-=-=-=-=-=-=-=-=-
If you liked this article and want to see more from this author, please click the Yes button near the:
Was this article helpful?
label that is just below and to the right of this text. Thanks!
=-=-=-=-=-=-=-=-=-=-=-=-=-
by: kk8 on 2009-08-05 at 14:58:15ID: 2529
CImage MFC seems more straightforward