Having difficulty writing text on a bitmap
-
I am facing problems trying to write text onto a bitmap in the hopes of getting pixelated text on it. I have looked at the code shown here: http://www.codeproject.com/KB/GDI/gdionbitmaps.aspx\[[^](http://www.codeproject.com/KB/GDI/gdionbitmaps.aspx "New Window")] but I can't seem to get it to work right. Here's my code, I am using the code shown on the above site and triggering it to run on a button click form a dialog:
void CCaptureAndDisplayDlg::OnTest()
{HBITMAP hbitmap = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB\_BITMAP1)); BITMAP bitm; GetObject( hbitmap, sizeof(BITMAP), &bitm ); long width=bitm.bmWidth; long height=bitm.bmHeight; 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); //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=400; m\_pLF->lfItalic=0; 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(0,0,0)); //Black Pen //Set text position; RECT pos = {40,40,0,0}; //draw the text dc.SetBkMode(TRANSPARENT); dc.DrawText(strTxt,TxtLen,&pos,DT\_CALCRECT); dc.DrawText(strTxt,TxtLen,&pos,0); m\_Placemat.SetBitmap(TmpBmp); //cleanup if (pOldFont) dc.SelectObject(pOldFont); m\_Font.DeleteObject(); dc.Detach(); free(m\_pLF); DeleteObject(hbitmap); hbitmap=TmpBmp; //final cleanup SelectObject(TmpDC,TmpObj); DeleteDC(TmpDC);
}
-
I am facing problems trying to write text onto a bitmap in the hopes of getting pixelated text on it. I have looked at the code shown here: http://www.codeproject.com/KB/GDI/gdionbitmaps.aspx\[[^](http://www.codeproject.com/KB/GDI/gdionbitmaps.aspx "New Window")] but I can't seem to get it to work right. Here's my code, I am using the code shown on the above site and triggering it to run on a button click form a dialog:
void CCaptureAndDisplayDlg::OnTest()
{HBITMAP hbitmap = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB\_BITMAP1)); BITMAP bitm; GetObject( hbitmap, sizeof(BITMAP), &bitm ); long width=bitm.bmWidth; long height=bitm.bmHeight; 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); //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=400; m\_pLF->lfItalic=0; 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(0,0,0)); //Black Pen //Set text position; RECT pos = {40,40,0,0}; //draw the text dc.SetBkMode(TRANSPARENT); dc.DrawText(strTxt,TxtLen,&pos,DT\_CALCRECT); dc.DrawText(strTxt,TxtLen,&pos,0); m\_Placemat.SetBitmap(TmpBmp); //cleanup if (pOldFont) dc.SelectObject(pOldFont); m\_Font.DeleteObject(); dc.Detach(); free(m\_pLF); DeleteObject(hbitmap); hbitmap=TmpBmp; //final cleanup SelectObject(TmpDC,TmpObj); DeleteDC(TmpDC);
}
It's no biggie, really. I think you'll find the problem to lie in the fatc that you deselect your loaded bitmap from the DC before you draw the text on it. Here's some plain win32 code that hacks togeter a result.
// draws text on a bitmap
void DrawOnBitmap(HBITMAP hBmp)
{
HFONT oldFnt, font1;
HDC memDC;
HBITMAP oldBM;
char *myText = "CrackerJack";// create a mem dc memDC = CreateCompatibleDC(NULL); // select bitmap into it oldBM = (HBITMAP)SelectObject(memDC, hBmp); //create the font font1 = CreateFont(-13, 0, 0, 0, 400, FALSE, FALSE, FALSE, 1, 400, 0, 0, 0, "Tahoma Bold"); oldFnt = (HFONT)SelectObject(memDC, font1); // show text at arbitrary position TextOut(memDC, 30, 30, myText, strlen(myText)); // clean-up time! SelectObject(memDC, oldBM); SelectObject(memDC, oldFnt); DeleteObject(font1); DeleteDC(memDC);
}
simon
modified on Thursday, November 27, 2008 12:52 AM
-
It's no biggie, really. I think you'll find the problem to lie in the fatc that you deselect your loaded bitmap from the DC before you draw the text on it. Here's some plain win32 code that hacks togeter a result.
// draws text on a bitmap
void DrawOnBitmap(HBITMAP hBmp)
{
HFONT oldFnt, font1;
HDC memDC;
HBITMAP oldBM;
char *myText = "CrackerJack";// create a mem dc memDC = CreateCompatibleDC(NULL); // select bitmap into it oldBM = (HBITMAP)SelectObject(memDC, hBmp); //create the font font1 = CreateFont(-13, 0, 0, 0, 400, FALSE, FALSE, FALSE, 1, 400, 0, 0, 0, "Tahoma Bold"); oldFnt = (HFONT)SelectObject(memDC, font1); // show text at arbitrary position TextOut(memDC, 30, 30, myText, strlen(myText)); // clean-up time! SelectObject(memDC, oldBM); SelectObject(memDC, oldFnt); DeleteObject(font1); DeleteDC(memDC);
}
simon
modified on Thursday, November 27, 2008 12:52 AM
Thanks for the quick reply. I appreciate it. I have put your function as such:
void DrawOnBitmap(HBITMAP hBmp)
{
HFONT oldFnt, font1;
HDC memDC;
HBITMAP oldBM;
// some arbitrary junk text
char *myText = "Testing";// create a mem dc memDC = CreateCompatibleDC(NULL); // select bitmap into it oldBM = (HBITMAP)SelectObject(memDC, hBmp); //create the font font1 = CreateFont(-13, 0, 0, 0, 400, FALSE, FALSE, FALSE, 1, 400, 0, 0, 0, "Tahoma Bold"); oldFnt = (HFONT)SelectObject(memDC, font1); // print text at an arbitrary position TextOut(memDC, 30, 30, myText, strlen(myText)); m\_Placemat.SetBitmap(oldBM); //Output Bitmap into Dialog Box CStatic object // clean-up time! SelectObject(memDC, oldBM); SelectObject(memDC, oldFnt); DeleteObject(oldBM); DeleteObject(oldFnt); DeleteDC(memDC);
}
void OnTest()
{
HBITMAP hbitmap = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP3));
DrawOnBitmap(hbitmap);
}What I get back is a black BMP. The point when oldBM = (HBITMAP)SelectObject(memDC, hBmp); was executed, the BMP turned entirely black (when i tried to output at that point). I think when the CreateCompatibleDC is executed with a null, there creates a problem. I tried passing in the DC I used previously but it doesn't make a difference. When I run m_Placemat.SetBitmap(hBmp); instead, I get a black box with a smaller grey box in the centre. I have tried integrating your Font section into mine:
void CCaptureAndDisplayDlg::OnTest()
{HBITMAP hbitmap = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB\_BITMAP3)); BITMAP bitm; GetObject( hbitmap, sizeof(BITMAP), &bitm ); long width=bitm.bmWidth; long height=bitm.bmHeight; BITMAPINFO bmInfo; CBitmap FinalBMP; int rtn=0; 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); //draw the background HDC dcBmp=CreateCompatibleDC(TmpD
-
Thanks for the quick reply. I appreciate it. I have put your function as such:
void DrawOnBitmap(HBITMAP hBmp)
{
HFONT oldFnt, font1;
HDC memDC;
HBITMAP oldBM;
// some arbitrary junk text
char *myText = "Testing";// create a mem dc memDC = CreateCompatibleDC(NULL); // select bitmap into it oldBM = (HBITMAP)SelectObject(memDC, hBmp); //create the font font1 = CreateFont(-13, 0, 0, 0, 400, FALSE, FALSE, FALSE, 1, 400, 0, 0, 0, "Tahoma Bold"); oldFnt = (HFONT)SelectObject(memDC, font1); // print text at an arbitrary position TextOut(memDC, 30, 30, myText, strlen(myText)); m\_Placemat.SetBitmap(oldBM); //Output Bitmap into Dialog Box CStatic object // clean-up time! SelectObject(memDC, oldBM); SelectObject(memDC, oldFnt); DeleteObject(oldBM); DeleteObject(oldFnt); DeleteDC(memDC);
}
void OnTest()
{
HBITMAP hbitmap = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP3));
DrawOnBitmap(hbitmap);
}What I get back is a black BMP. The point when oldBM = (HBITMAP)SelectObject(memDC, hBmp); was executed, the BMP turned entirely black (when i tried to output at that point). I think when the CreateCompatibleDC is executed with a null, there creates a problem. I tried passing in the DC I used previously but it doesn't make a difference. When I run m_Placemat.SetBitmap(hBmp); instead, I get a black box with a smaller grey box in the centre. I have tried integrating your Font section into mine:
void CCaptureAndDisplayDlg::OnTest()
{HBITMAP hbitmap = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB\_BITMAP3)); BITMAP bitm; GetObject( hbitmap, sizeof(BITMAP), &bitm ); long width=bitm.bmWidth; long height=bitm.bmHeight; BITMAPINFO bmInfo; CBitmap FinalBMP; int rtn=0; 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); //draw the background HDC dcBmp=CreateCompatibleDC(TmpD
Hi there. Just looking at your implementation of
void DrawOnBitmap(HBITMAP hBmp)
, I notice that you set the bitmap image of the m_Placemat to be the image that _was_ originally selected into the temporary DC - This image has had nothing done to it, so it should be black. ;P Following selecting this empty bitmap, you still do the call to DeleteObject(oldBM)... I suggest you try changingm_Placemat.SetBitmap(oldBM); //Output Bitmap into Dialog Box CStatic object
to
m_Placemat.SetBitmap(hBmp); //Output Bitmap into Dialog Box CStatic object
Since you want to display the loaded bitmap with the added text in your program, and not the (since deleted) empty bitmap that belonged to the temporary DC we created. Please, let me know if I've been unclear/it doesn't work for you.
-
Hi there. Just looking at your implementation of
void DrawOnBitmap(HBITMAP hBmp)
, I notice that you set the bitmap image of the m_Placemat to be the image that _was_ originally selected into the temporary DC - This image has had nothing done to it, so it should be black. ;P Following selecting this empty bitmap, you still do the call to DeleteObject(oldBM)... I suggest you try changingm_Placemat.SetBitmap(oldBM); //Output Bitmap into Dialog Box CStatic object
to
m_Placemat.SetBitmap(hBmp); //Output Bitmap into Dialog Box CStatic object
Since you want to display the loaded bitmap with the added text in your program, and not the (since deleted) empty bitmap that belonged to the temporary DC we created. Please, let me know if I've been unclear/it doesn't work for you.
I've tried that. Running
m_Placemat.SetBitmap(hBmp);
results in a black image with an grey centre (the grey of a standard Dialog window, so i think it's hollow) I can output text on a blank window like this:
void CGDITest::OnDraw(CDC* pDC)
{
CGDITestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);pDC->TextOut(50, 42, "Testing", 13);
}
so I don't think it's my VC 6's SDK, I must be doing something wrong... Can I use the plain
pDC->TextOut
to get an array of bits that make up the string? Without trying to write it on a standard white bitmap? I'm really lost now. And Thank you again for replying. -
I've tried that. Running
m_Placemat.SetBitmap(hBmp);
results in a black image with an grey centre (the grey of a standard Dialog window, so i think it's hollow) I can output text on a blank window like this:
void CGDITest::OnDraw(CDC* pDC)
{
CGDITestDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);pDC->TextOut(50, 42, "Testing", 13);
}
so I don't think it's my VC 6's SDK, I must be doing something wrong... Can I use the plain
pDC->TextOut
to get an array of bits that make up the string? Without trying to write it on a standard white bitmap? I'm really lost now. And Thank you again for replying.JJeffrey wrote:
I've tried that.
Oops! Sorry i missed that the first time round. Hmmmm, I've no idea about pDC->TextOut as I'm away from my other pc. Something else to consider, are the loaded and created bitmaps of comparable bits/pixel - sorry, it's all i can think of right now.
-
JJeffrey wrote:
I've tried that.
Oops! Sorry i missed that the first time round. Hmmmm, I've no idea about pDC->TextOut as I'm away from my other pc. Something else to consider, are the loaded and created bitmaps of comparable bits/pixel - sorry, it's all i can think of right now.
Thanks for your time. I appreciate it. Maybe I should try from a different angle or something. I don't see how, personally, the bits/pixel ratio could affect the writing of the text. If I use a smaller resolution picture (less colour palette size), I don't see why text would suddenly be able to be written. Anyway, thanks. Hope my boss doesn't kill me for not getting this.... :p
-
Thanks for your time. I appreciate it. Maybe I should try from a different angle or something. I don't see how, personally, the bits/pixel ratio could affect the writing of the text. If I use a smaller resolution picture (less colour palette size), I don't see why text would suddenly be able to be written. Anyway, thanks. Hope my boss doesn't kill me for not getting this.... :p
Have a look at http://www.codeproject.com/KB/applications/imageviewer.aspx[^]. It is a tool I wrote to help debug graphics problems. It may help you figure this out.
You may be right I may be crazy -- Billy Joel -- Within you lies the power for good - Use it!
-
Have a look at http://www.codeproject.com/KB/applications/imageviewer.aspx[^]. It is a tool I wrote to help debug graphics problems. It may help you figure this out.
You may be right I may be crazy -- Billy Joel -- Within you lies the power for good - Use it!
Thank you, Thank you... THANK. YOU! Your program is fantastic. I see where it went wrong now, the
SelectObject
s were causing theHDC
s to overwrite with old images as they weren't done properly (I think...). I delayed it till later in the code. For the record, this code works:void CCaptureAndDisplayDlg::OnTest()
{HBITMAP hbitmap = ::LoadBitmap(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB\_BITMAP1)); BITMAP bitm; GetObject( hbitmap, sizeof(BITMAP), &bitm ); long width=bitm.bmWidth; long height=bitm.bmHeight; BITMAPINFO bmInfo; int rtn=0; 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); //draw the background HDC dcBmp=CreateCompatibleDC(TmpDC); HGDIOBJ TmpObj2 = SelectObject(dcBmp,hbitmap); BitBlt(TmpDC,0,0,width,height,dcBmp,0,0,SRCCOPY); char \*myText = "Testing"; HFONT oldFnt, font1; font1 = CreateFont(-13, 0, 0, 0, 400, FALSE, FALSE, FALSE, 1, 400, 0, 0, 0, "Tahoma Bold"); oldFnt = (HFONT)SelectObject(TmpDC, font1); // print text at an arbitrary position TextOut(TmpDC, 30, 30, myText, strlen(myText)); SelectObject(TmpDC,TmpObj2); m\_Placemat.SetBitmap(TmpBmp); SelectObject(TmpDC, oldFnt); DeleteObject(oldFnt); DeleteDC(TmpDC); DeleteDC(dcBmp);
}
Great Program you have there.... Jeffrey
modified on Friday, November 28, 2008 1:40 AM