Solved

Displaying a Bitmap Image, where datas are in byte array

Posted on 2003-12-03
8
3,850 Views
Last Modified: 2013-12-03
Hi,

I need to display the BMP image on the screen (dialog based) using VC++. I have the image data in a byte array, so can any one help me out in displaying this image. Is there any API for this?? i m bit new to C++, so please help me out.

Thanks in advance
Ram
0
Comment
Question by:rampriya_sb
8 Comments
 
LVL 44

Expert Comment

by:Karl Heinz Kremer
Comment Utility
Your question is in the wrong area: Even though you are programming in C++, it's about a Windows programming problem. Depending on how you create your application (Windows SDK, MFC, ...) you should post a request in Community Support to move the question.

Does the image have to stay in the byte array, or would it be possible to store the bitmap in a resource file? If that's possible, your problem just got a lot simpler. In case you are using MFC, add your image to the resource file, then place a picture control on your dialog. Bring up preferences for the picture control and select your image.
0
 
LVL 23

Expert Comment

by:Roshan Davis
Comment Utility
Use DIB Functions

SetDIBits, StretchDIBits

Good Luck
0
 
LVL 3

Accepted Solution

by:
RJSoft earned 500 total points
Comment Utility
If you have the bitmap bits chances are that you have access to them by a handle to a bitmap HBITMAP which was given to you by either LoadImage or LoadBitmap.

If so, next thing you need to do is select that handle into a memory device context and then BitBlt it to the screen.

But since you say your app is dialog based here is what you do to display an image.

This assumes your using VC++.

First you create a static text box in your resource editor and place it somewhere within the dialog that you wish to view it. I use the style sunken so that I can see the actual static text box when I am adjusting size.

Give the static text box an Id that is more meaningful than ID_STATIC. Something like ID_PICTURE.

Then in your class view add a new class. Call it MyStatic or whater. Make sure the base class is CStatic.

Then go back to resource editor and choose the classwizard. Add a member variable to the ID ID_PICTURE. Call it MyPic or whatever.

Make sure to include the #include "MyStatic.h" or whatever at the top of your dialogs header file.

Now you have a dialog that has a child static window called MyPic that is an instance of MyStatic.

In the class view go to the class MyStatic and then add a message member function WM_PAINT. This will create the member OnPaint.

Then add another function call it anything you like, to do the actual painting. Call it MyPaint. void MyPaint();

Add the line MyPaint(); in the OnPaint function. That way every time windows request to paint your OnPaint will call MyPaint();

MyPaint simply grabs a dc creates a memory dc and then loads the handle into the memory dc and uses BitBlt to paint to the screen dc.

The below example is how to do it in API because I like doing it this way. It is easy to figure out how to do it in MFC (VC default) if you like but I dont bother.

Since this routine belongs to MyStatic the area calculated is the area of the static window. The calculation is to center the image if it is smaller than the client area (the usable area) of the static window else it simply starts the image in the upper left corner and continues to paint it to the boundries of the static window. The boundries are enforced from the Rect region.

void MyStatic::MyPaint()
{
HBITMAP hbmp=::LoadImage or ::LoadBitmap...
HDC dc=::GetDC(this->m_hWnd);
HDC MemDC=::CreateCompatibleDC(dc);
// get the demensions of the window area
RECT rr; ::GetClientRect(this->m_hWnd,&rr);
// create a rect region so we don't paint out of the window.
HRGN hrgn=CreateRectRegion(rr.left,rr.top,rr.right, rr.bottom);
// select controlling region for output dc ( output dc is screen)
HRGN hOldhrgn=(HRGN)::SelectObject(dc,hrgn);
// get size of bitmap so we can compare sizes
BITMAP bmp; ::GetObject(hbmp,sizeof(BITMAP),&bmp);
//
// center the image in text box
int X,Y;
if(rr.right > bmp.bmpWidth)
X=(rr.right - bmp.bmpWidth) / 2;
else X=rr.left;
//
if(rr.bottom > bmp.bmWidth)
Y=(rr.bottom - bmp.bmHeight) / 2;
else Y=rr.top;
//
// select bitmap into memory device context (MemDC)
HBITMAP hOldBitmap=(HBITMAP)::SelectObject(MemDC,hbmp);
//
// send to screen
::BitBlit(dc,X,Y,bmp.bmWidth,bmp.bmHeight, MemDC,0,0,SRCCOPY);
//
//Clean up memory
//
::SelectObject(hOldhrgn);
::SelectObject(hOldBitmap);
::ReleaseDC(this->m_hWnd);
::DeleteDC(MemDC);
::DeleteObject(hrgn);
}//endfunc

If you want to use StretchBlt you also need to set the stretchblit mode set it to COLORONCOLOR.

Also since StretchBlt has the extra size parametors just simply use values from the BITMAP bmp which has the size width and height.

SetDIBits also is similar except that it has a parametor for the pointer to your bitmap bits. SetDIBits actually copies the bits to the designated dc, so if you use the screen dc (dc) then it will actually paint the image to the screen.

BitBlt is a powerful function. You can also use it to copy your screen.

HDC dc=::GetDC(..);
HDC MemDC=::CreateCompatibleDC(dc);
RECT rr;::GetClientRect(....);
HBITMAP hbmp=::CreateCompatibleBitmap(dc,rr.right,rr.bottom);
HBITMAP hOld=::SelectObject(MemDC,hbmp);
BitBlt(MemDC,rr.left,rr.top,rr.right,rr.bottom,dc,rr.left,rr.top,SRCCOPY);

Now you have a copy of the screen in the handle hbmp.

You can now write the bitmap to file using a BITMAPINFO header. There are pleanty of example code of how to do this. But basically you could do the above with GetDIBits (call twice, once to load the bitmap info structure and a second call to get the bits) then write the file.

Another useful feature of BitBlt is using a mask. A mask allows you to designate areas of your bitmap image that will show up or be invisible.

Example: Say you want to display a ball in the center of your dialog. So you create the ball using resource editor or whatever. Your ball exist within the rectangle that you drew it in. Now you would like to display the ball but not the surrounding rectangle. So you use a mask.

The mask is basically a duplicate image of the real image but it is in black and white only. The black area of the mask is the area that will SHOW. The white area designates the area that you want to be invisible.

All that is required is that you select the mask and blit to the screen using the AND and then you blit the normal image using the INVERT.

::SelectObject(MemDC,hbmpMask);
::BitBlt(dc,x,y,bmp.bmWidth,bmp.bmHeight,MemDC,0,0,SRCAND);
::SelectObject(MemDC,hbmp);
::BitBlt(dc,x,y,bmp.bmHeight,bmp.bmHeight,MemDC,0,0,SRCINVERT);


Knowing this now you can do simple animation. Simply adjust the x and y parms and the image moves. They are called sprites. Animated objects that move.

One problem is that previous image does not dissapear. But that is simple to solve simply paint the background before you paint the sprites.

Think of it as layering. Whatever you want on top you do last. So you could paint a sky then a landscape, then a bunch of trees, then person walking.

Each itteration you have to do in that order to keep things looking right. But since your using GDI (windows graphic device interface) which uses a data base to access the vidio screen driver the animation is slow and flickers.

One way to solve this is to use double buffering technique. This is simply using 2 memory dc to do the gdi commands to. That way your slow gdi commands are done in memory which is faster than to the screen. This reduces flicker. Gdi commands like polygon and rectangle and ellipse are really slow done in the screen but to a MemDC is faster. So basically you wind up doing BitBlit(MemDC,x,y,bmp.bmWidth,bmp.bmHeight,MemDC2,0,0,SRCCOPY);

Then after all your gdi stuff is done do a BitBlt to the screen. Avoid using StretchBlt to the screen because it is slllllooooowwww also. Use StretchBlt from MemDC2 to MemDC and that is reasonably acceptable.

After this, you may want to migrate to DirectDraw. DirectDraw is Microsoft answer to accessing the video buffer directly which is much much faster.

Hope this helps

RJ
 

0
 

Author Comment

by:rampriya_sb
Comment Utility
Hi,

Thanks a lot for the help, This is great. But since i m new to C++, it will be nice if you can send me a small project code regarding this. This will help me a lot. you can mail me at rampriya_sb@yahoo.com

I appreciate it.

Thanks
Ram
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 49

Expert Comment

by:DanRollins
Comment Utility
rampriya_sb,
EE does not work well when Experts and Askers correspond by email.  In fact, it is against the rules except in very rare cases.

You have not responded to the questions posed by the Experts and you must do so in order for anyone to provide code for you.  Please describe the format of the image data that you have.  Then one of us can provide code that will put that image data into a bitmap and show you how to display it.

-- Dan
0
 

Author Comment

by:rampriya_sb
Comment Utility
I m sorry about this, i'll take care not to repeat it again. As i was new to C++, i wanted someone to help me out with this in detail.

Well, i have got my solution solved. Thanks

Ram
0
 
LVL 3

Expert Comment

by:RJSoft
Comment Utility
I was un-aware of that rule also. But it makes sense.

Here is the email coorispondance in reguard to this subject

BEGIN EMAIL/////////////////////////////////////////
Hello Rampriya;

I assume your using VC++ 6.0. We need to establish
this first.

Assuming you are.

All you really need to do is copy these steps I am
going to tell you. It took me about 10 minutes to
write and compile the code. Take these steps.

First create a dialog based application using MFC
Appwizard (exe)

Select whatever directory and name of app you like.

Select Dialog based app.

You can remove the check from About box and ActiveX
controls if you like dont matter. I like to leave the
3d controlls because it looks better.

Press finish and watch as the classes and resource etc
are made for you.

Next if your not already in the resource editor then
open it up by selecting ResourceView.

When you create a Dialog based app the main window is
a dialog. The VC++6.0 version of a basic dialog based
application comes with a static text box, it has the
text "TODO: Place dialog controls here."

"Right Click" on that text because that is going to be
a box where you can display your image. Select
Properties and change the default IDC_STATIC to
IDC_PAINTBOX or whatever you like. Select the tab
Styles and check the box sunken. The sunken property
will help you when your sizing the static text box so
you can see it.

Next size the static text box so that it is a few
inches square. Whatever size you want but make it a
little larger than a text box so you can see the
picture when it is displayed in the box.

Now you have a static box with the ID of IDC_PAINTBOX
if you copied me. Next you need to assign a variable
to it. But before you do that you need to create your
own personalized static class with the base class
CStatic. Dont worry it's easy.

In Classview (use tab at bottom left of VC) add a new
class by "right clicking" the first class on the top
of your class listing. Select New class.

In the Name box name the class MyStatic. Then for the
base class scroll down and choose CStatic. Automation
leave as none. Press Ok.

Now you have your customized Static class it is called
MyStatic.

Now go back to Resource View (bottom left tabs of VC)
so you can see your Dialog box with the static
control.

Right click anywhere on the Dialog (not control)
Select ClassWizard.

BTW, ClassWizard IS GREAT! Once you get the hang of it
I know you will love it.

Once in Classwizard select the Members Variable tab.
Then select your static control ID and add a variable.

I like to keep the leading m_ because it is the
default and later it helps you see your control
variables quickly.

Now your in the dialog of Add Member Variable. You
want to create a control type variable. Name your
varialbe something like m_PaintBox. Use Control and
scroll down to you see your customized class MyStatic.
Press Ok.

A dialog comes up that says you screeweed up!!!! No
only joking. It is only a warning to remind you to
include your "MyStatic.h" file which you have to do
manually.

So I go to file view and open up the main window
dialog header file. ( A .h file with the name of your
application and a Dlg in it) So if you named your app
JuneBug then it would be JuneBugDlg.h

You can add your include at the top of the .h file
#include "MyStatic.h"

Now you have a class called MyStatic which is your
customizable subclass of the base class CStatic and
you have an instance variable called m_PaintBox that
is owned by your main window dialog. This object
m_PaintBox is also tied to your dialog by the resource
Id IDC_PAINTBOX.

Now you need to add your customization to your
customized static class MyStatic. So back in class
view (bottom left of VC tab). Select Class View.

Open up your MyStatic Class so we can add a function
to it.

"Right Click" on the top MyStatic and select Add
Member Function.

For the function type you want to type in the word
void. I know this is a little goofy because they imply
that the function is a void type, but what they mean
to say is what type of return is it. Next type in the
name of your function MyPaint() and press enter. You
should keep the function as public. (Dont worry about
that for now dont matter, private is just for big
projects where multiple persons are programming using
your class so you might not want to share a varible or
two. This way you have what you have and the other guy
cant f you up.

So now your class has a function that you can call up.
If you want you can paste the code in from the
previous post I sent you which has the same name.

But you need to somehow call that function up during
the windows processing. What do I mean. Well windows
and that includes your dialog based app which is a
windows based app recieves and sends messages to the
windows message que.

All visible objects in a windows application is a
window. Your dialogs static member m_PaintBox is a
handle to a window. It also recieves messages. One of
the messages you can capture is WM_PAINT.

So to call MyPaint() you can call it from a message
that you know comes to your static. The WM_PAINT
message comes when the static box paints itself.

To capture the WM_PAINT message is easy.

Go back to the bottom left of VC and select tab
ClassView. Then select your class MyStatic. "Right
Click" and select Add Window Message Handler. Scroll
down untill you see WM_PAINT. Choose Add and Edit.

Then simply add the line MyPaint(); like so...

void MyStatic::OnPaint()
{
      CPaintDC dc(this);       
      // TODO: Add your message handler code here
      MyPaint();
      
}

Now next thing to do is create a bitmap. Go to the
Resource View and "right click" the top resource
entry.
Select option "insert" and then new and then create
your bitmap. Just draw any simple shape.

Note that the default id is IDB_BITMAP1 that is what I
used in my code to display a bitmap for your example.
Keep the Id the same or change both in the resource
and my MyPaint code to the same thing (otherwize the
bitmap wont show).

Compile and run. Your done.

RJ
 

END EMAIL  /////////////////////////////////////////
RJ
0
 
LVL 3

Expert Comment

by:RJSoft
Comment Utility
Heres the MyPaint() (api style)

void MyStatic::MyPaint()
{
      HDC dc=::GetDC(this->m_hWnd);
      HDC MemDC=::CreateCompatibleDC(dc);
      RECT rr;::GetClientRect(this->m_hWnd,&rr);
      
      HBITMAP hbmp=::LoadBitmap(::AfxGetInstanceHandle(),MAKEINTRESOURCE(IDB_BITMAP1));
      HBITMAP hOld=(HBITMAP)::SelectObject(MemDC,hbmp);

      BITMAP bmp; ::GetObject(hbmp,sizeof(BITMAP),&bmp);
      
      ::BitBlt(dc,0,0,bmp.bmWidth,bmp.bmHeight,MemDC,0,0,SRCCOPY);


      ::ReleaseDC(this->m_hWnd,dc);
      ::DeleteDC(MemDC);
      ::DeleteObject(hbmp);

}//endfunc
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now