Click here to Skip to main content
Click here to Skip to main content

Drawing lines, shapes, or text on bitmaps

By , 12 Apr 2002
 

Introduction

This article describes the operations needed to draw lines, shapes, or text on bitmaps. The task is quite simple, but a quick reference could be handy for the beginners.

Working with HBITMAPs

As first step we need a background image, referenced by a hbitmap handle. hbitmap can be the result of previous operations, or created with CreateBitmap(), or a resource:

HBITMAP hbitmap = ::LoadBitmap(AfxGetInstanceHandle(),
        MAKEINTRESOURCE(IDB_BITMAP1));

From hbitmap we can extract the basic attributes:

BITMAP bm;
GetObject( hbitmap, sizeof(BITMAP), &bm );
long width=bm.bmWidth;
long height=bm.bmHeight;

Now let's create a memory device context and select a new bitmap.

//prepare the bitmap attributes
BITMAPINFO bmInfo;
memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
bmInfo.bmiHeader.biWidth=width;
bmInfo.bmiHeader.biHeight=height;
bmInfo.bmiHeader.biPlanes=1;
bmInfo.bmiHeader.biBitCount=24;
//create a temporary dc in memory.
HDC pDC = ::GetDC(0);
HDC TmpDC=CreateCompatibleDC(pDC);
//create a new bitmap and select it in the memory dc
BYTE *pbase;
HBITMAP TmpBmp=CreateDIBSection(pDC,
    &bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);

TmpDC is the device context were you can draw lines, text, or images. For example, the next lines draw a string over a background image :

//draw the background
HDC dcBmp=CreateCompatibleDC(TmpDC);
HGDIOBJ TmpObj2 = SelectObject(dcBmp,hbitmap);
BitBlt(TmpDC,0,0,width,height,dcBmp,0,0,SRCCOPY);
SelectObject(TmpDC,TmpObj2);
DeleteDC(dcBmp);

//choose the font
CFont m_Font;
LOGFONT* m_pLF;
m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));
strncpy(m_pLF->lfFaceName,"Times New Roman",31);
m_pLF->lfHeight=64;
m_pLF->lfWeight=600;
m_pLF->lfItalic=1;
m_pLF->lfUnderline=0;
m_Font.CreateFontIndirect(m_pLF);

//select the font in the dc
CDC dc;
dc.Attach(TmpDC);
CFont* pOldFont=NULL;
if (m_Font.m_hObject) 
    pOldFont = dc.SelectObject(&m_Font);
else 
    dc.SelectObject(GetStockObject(DEFAULT_GUI_FONT));

//Set text color
dc.SetTextColor(RGB(60,120,240));
//Set text position;
RECT pos = {40,40,0,0};
//draw the text
dc.SetBkMode(TRANSPARENT);
dc.DrawText("Test",4,&pos,DT_CALCRECT);
dc.DrawText("Test",4,&pos,0);

//cleanup 
if (pOldFont) dc.SelectObject(pOldFont);
m_Font.DeleteObject();
dc.Detach();
free(m_pLF);

At this point there are 2 bitmaps: hbitmap and TmpBmp, you can keep both the old and the new image, or replace hbitmap with TmpBmp:

DeleteObject(hbitmap);
hbitmap=TmpBmp;

Finally, we can delete the temporary device context. Do not delete hbitmap and TmpBmp here, or you'll loose the bitmap.

//final cleanup
SelectObject(TmpDC,TmpObj);
DeleteDC(TmpDC);

Conclusion

The article starts with a background image stored in a HBITMAP, and ends with a new image in a new HBITMAP. This grants a high flexibility on what you can do before, after and in between: you can use all the GDI functions to build your image, and for example you can use CBitmap, or image processing libraries like FreeImage and CxImage, to add effects or save the result in a file.

License

This article, along with any associated source code and files, is licensed under The zlib/libpng License

About the Author

Davide Pizzolato
Italy Italy
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5memberwanggxii19 Jan '13 - 23:13 
It is simple and clear
BugThe codes have an error?memberyiruirui21 Mar '12 - 20:19 
I think
SelectObject(TmpDC,TmpObj2);
DeleteDC(dcBmp);
must move to the end of code,because we still want to draw text in the memory DC before delete the DC.
GeneralMy vote of 5memberRohit Vipin Mathews13 Feb '12 - 1:00 
Good sample codes
GeneralThe source on the page is not working for mememberJJeffrey25 Nov '08 - 21:37 
I kinda assume, by the comments and all that this seems to work for everyone. But I, for the life of me, can't get it to work.
 
I tried the code on the page as is, and then I created a Bitmap object on a dialog box and called
m_BitmapObj.SetBitmap(TmpBmp);
before the cleanup section to make it appear on a dialog box.
 
I get an image, but there is no changes nor added text on the image. Am I doing something wrong?
 
Forgive me if it's plain obvious to you. I must be blinded by too much coding at the moment.
GeneralRe: The source on the page is not working for mememberddas-edEn9 Feb '12 - 22:44 
I face this same problem. Can someone please help.   WTF | :WTF:
GeneralRe: The source on the page is not working for me [modified]memberddas-edEn9 Feb '12 - 22:48 
Ok here is the fix. Replace the line:
 
SelectObject(TmpDC,TmpObj2);
 
with:
 
SelectObject(dcBmp,TmpObj2);


modified 10 Feb '12 - 4:58.

QuestionCreating Text on bitmap in C# winformsmemberpyar12323 Sep '08 - 20:54 
Hello,could anyone of you give me de soluton to have a text on the bitmap image using C#..I have created 2 parts like pie chart using bitmap class.Now i want the texts on these separate parts.How is this done??
GeneralTEXT OVER BITMAPmemberpelis30 May '07 - 7:09 
Hi all,
 
I have picture loaded on a buffer declared as it follows
 
BYTE *m_pBitmap = (BYTE *) new BYTE [3*theCamera.m_width*theCamera.m_height];
 
The capture image is stored inverted on m_pBitmap. Now before creating a JPG i would like to add a few lines of text in the top of the image (the parameters used by the camera that i have on a string or CString), i don't want to overlap them, I mean, i would like to make the picture bigger and add the text.
 
BYTE *m_pBitmapAUX = (BYTE *) new BYTE [3*theCamera.m_width*(theCamera.m_height+50)];
memset(m_pBitmapAUX,0,3*theCamera.m_width*(theCamera.m_height+50)); //Black Bitmap
memcpy(m_pBitmapAUX,m_pBitmap,3*theCamera.m_height*theCamera.m_width); //
 
Now I have a bitmap with a black part added in the top. My question is, what should I do now to add some text on this black area? I don't have to show it on the screen, just save it I use:
 
CreateJPGFile(file, m_pBitmapAUX, theCamera.m_width, theCamera.m_height+50, true, true);
 
I have been searching but all i found is by means of DC, CDC, Crect, and i didn't make it work fine...
 
Thank you very much before hand

JRF
Question[C#] How to move a line using the mouse after drawing it ?memberaliaamonier22 Apr '07 - 14:56 
hi,I drew a line using the mouse, but i want to move the drawn line to any position i want, how can i do that in C# ?
thnx in advance
GeneralRe: [C#] How to move a line using the mouse after drawing it ?memberHamid.3 Jan '08 - 18:53 
It was better you asked on the C# forum.
QuestionWhere is the code source ??membermccool28 Mar '06 - 1:06 
Where is the code source ??
AnswerRe: Where is the code source ??memberHamid.3 Jan '08 - 18:53 
Source code is at the page.
QuestionDrawing shapes or bitmaps on bitmapsmemberAssaf Koren21 Jan '06 - 1:14 
Is there anyone here knows how to do it in C# ?Sigh | :sigh:
 
don't worry, be happy!
AnswerRe: Drawing shapes or bitmaps on bitmapsmemberStan Shannon21 Jan '06 - 2:23 
GDI+ actually provides a fairly simple mechanism to do that....
 
 
    Graphics g = Graphics.FromImage( YourBitmap );
    g.DrawLine( ...
    etc

 
-- modified at 8:24 Saturday 21st January, 2006
GeneralRe: Drawing shapes or bitmaps on bitmapsmemberAssaf Koren21 Jan '06 - 16:54 
Hi Stan,
 
Thanks... great coding.
Loved the project... and your response.
 
Its work perfectly fine Smile | :)
 
don't worry, be happy!
GeneralBUGmembernavratil10 Aug '04 - 6:00 
It didn't work for long time. At last I found out that author changed the code to fix a bug (as he described in thread "Some issue") but new created.
 
HDC dcBmp = CreateCompatibleDC(TmpDC);
HGDIOBJ TmpObj2 = SelectObject( dcBmp, hbitmap);
BitBlt(TmpDC,0,0,width,height,dcBmp,0,0,SRCCOPY);
//SelectObject(TmpDC,TmpObj2); this is the bug!!!
SelectObject(dcBmp,TmpObj2);
DeleteDC(dcBmp);
Generalresizing of images and shapes as in word artmembersreemail15 Dec '02 - 1:23 
Hi, Thanks a lot for the information on drawing images on Bitmaps.
Can you guide me on how to resize images and basic shapes as in Word Art.
Thanks again
-Sreemail
GeneralRe: resizing of images and shapes as in word artmemberDavide Pizzolato15 Dec '02 - 1:48 
I suppose that WordArt uses the WMF format
Generaltext rendering with cximagememberDavide Pizzolato13 Apr '02 - 23:24 
 image = new CxImage("image2.bmp",CXIMAGE_FORMAT_BMP);
 
 if (image){
  //Preparing Bitmap Info
  long width=image->GetWidth();
  long height=image->GetHeight();
  BITMAPINFO bmInfo;
  memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
  bmInfo.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
  bmInfo.bmiHeader.biWidth=width;
  bmInfo.bmiHeader.biHeight=height;
  bmInfo.bmiHeader.biPlanes=1;
  bmInfo.bmiHeader.biBitCount=24;
 
  BYTE *pbase; //points to the final dib
  //get the background
  HDC pDC = ::GetDC(0);
  HDC TmpDC=CreateCompatibleDC(pDC);
  HBITMAP TmpBmp=CreateDIBSection(pDC,&bmInfo,DIB_RGB_COLORS,(void**)&pbase,0,0);
  HGDIOBJ TmpObj=SelectObject(TmpDC,TmpBmp);
  //draw the background
  image->Draw(TmpDC);
  //choose the font
  CFont m_Font;
  LOGFONT* m_pLF;
  m_pLF=(LOGFONT*)calloc(1,sizeof(LOGFONT));
  strncpy(m_pLF->lfFaceName,"Times New Roman",31);
  m_pLF->lfHeight=64;
  m_pLF->lfWeight=600;
  m_pLF->lfItalic=1;
  m_pLF->lfUnderline=0;
  m_Font.CreateFontIndirect(m_pLF);
 
  //select the font in the dc
  CDC dc;
  dc.Attach(TmpDC);
  CFont* pOldFont=NULL;
  if (m_Font.m_hObject) pOldFont = dc.SelectObject(&m_Font);
  else dc.SelectObject(GetStockObject(DEFAULT_GUI_FONT));
 
  //Set text color
  dc.SetTextColor(RGB(60,120,240));
  //Set text position;
  RECT pos = {40,40,0,0};
  //draw the text
  dc.SetBkMode(TRANSPARENT);
  dc.DrawText("Test",4,&pos,DT_CALCRECT);
  dc.DrawText("Test",4,&pos,0);
 
  //cleanup 
  if (pOldFont) dc.SelectObject(pOldFont);
  m_Font.DeleteObject();
  dc.Detach();
  free(m_pLF);
 
  //transfer the result in the image
  CxImage tmpimage;
  tmpimage.CreateFromHBITMAP(TmpBmp);
  tmpimage.DecreaseBpp(image->GetBpp(),0,image->GetPalette());
  image->Transfer(tmpimage);
 
  //cleanup
  DeleteObject(SelectObject(TmpDC,TmpObj));
  DeleteDC(TmpDC);
 }

GeneralRe: text rendering with cximagememberAnonymous23 Apr '02 - 6:54 
Thanks for the help but all i seem to get are black boxes.
any ideas?

GeneralRe: text rendering with cximagememberAnonymous23 Apr '02 - 9:18 
BYTE *pbase; //points to the final dib
what is this line for?
GeneralRe: text rendering with cximagememberAnonymous23 Apr '02 - 9:17 
what is this line for???
 
BYTE *pbase; //points to the final dib
GeneralRe: text rendering with cximagememberDavide Pizzolato25 Apr '02 - 5:42 
CreateDIBSection sets this pointer to the image bytes in memory
GeneralSome issuesmemberChristian Graus11 Apr '02 - 14:39 
HDC dcBmp=CreateCompatibleDC(TmpDC);
SelectObject(dcBmp,hbitmap);
BitBlt(TmpDC,0,0,width,height,dcBmp,0,0,SRCCOPY);
DeleteDC(dcBmp);
 
This will leak memory, because you did not catch the bitmap already in the HDC, nor did you select it back before deleting it. I've not looked over your other code to see if you leak other resources in the same way, but any pen/brush/bitmap/etc that gets selected into a DC returns the object there prior, and the initial objects must be restored before deleting the DC or you will run out of GDI resources fairly quickly.

 
Christian
 
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
 
"I'm somewhat suspicious of STL though. My (test,experimental) program worked first time. Whats that all about??!?!
- Jon Hulatt, 22/3/2002

GeneralRe: Some issuesmemberKarstenK11 Apr '02 - 23:26 
This is a tricky question. I think if you create a DC it is empty. (You can test the returned hbm with GetObject). Thats why with returned hbm from "selectobject" is empty. -> no leak/problem.
But I wouldn´t code so, I also would restore the returned hbm, its clearer its better.
If you have real dc with selected bitmaps you must restore carefully all objects.
 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 13 Apr 2002
Article Copyright 2002 by Davide Pizzolato
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid