# Win32: DIBs Bitmaps and DCs

This topic is 4177 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi all, I'm trying to create a font renderer for my little engine, and I intend to do this by rendering glyphs to a GDI surface, then getting the bits on the GDI surface and copying / converting them onto a D3D texture. Now, I'm wondering what the most efficient way to handle the GDI stuff is. I've currently created a DC compatible with the display, and a bitmap compatible with the DC. However, that gives me a monochrome bitmap. The docs for CreateCompatibleDC say that I can use CreateCompatibleBitmap to specify the width, height and colour of the bitmap. Which is a lie - I can only specify width and height. So, should I use CreateDIBSection instead of CreateCompatibleBitmap? Would that not cause problems or efficiency issues, since it's a device independant bitmap instead of a device dependant bitmap? Also, has anyone done this sort of thing before (font rendering like this), and if so, is there a more efficient way? I'm reasonably confident that this is going to be the best way to do it, but I'd like to hear other ideas too. Cheers, Steve

##### Share on other sites
IDirect3DSurface9::GetDC

Then write the glyphs to this surface and make a texture out of it. I did this once, but I cant remember if I directly drew the text to the backbuffer-surface (this was in directdraw), or used a font texture. Maybe the former.

ch.

##### Share on other sites
Quote:
 Original post by christian hIDirect3DSurface9::GetDCThen write the glyphs to this surface and make a texture out of it. I did this once, but I cant remember if I directly drew the text to the backbuffer-surface (this was in directdraw), or used a font texture. Maybe the former.ch.
I had a look at this method, but I think the GDI method will be faster. To use that, you have to use an offscreen plain surface, which has to be in the default pool. And you have to lock the surface to copy it to a managed texture, which is likely more expensive since you're reading from VRAM. And I'm not convinced that D3D doesn't have to do a lot of work internally to provide you with a DC to a surface (I.e. I think it creates a DC and bitmap internally, copies itself to the bitmap and then gives you the DC, and does the opposite when you call ReleaseDC()).
I could be wrong of course [smile]

##### Share on other sites
Not sure what's the fastest way to render text, but here's how to change a text's color: Link. You need to scroll about halfway down.

Probably not of much use, but I thought I'd drop it just in case.

##### Share on other sites
Quote:
 Original post by Servant of the LordNot sure what's the fastest way to render text, but here's how to change a text's color: Link. You need to scroll about halfway down.Probably not of much use, but I thought I'd drop it just in case.
I'll be pursuading D3D to colour my text for me, GDI will just be drawing a white letter and I'll get D3D to apply diffue colour and texturing.

Thanks anyway

##### Share on other sites
Not 100% here, but when I've converted images to DIB, it converts them into an array of RGBQUAD structures something like:

{
BYTE rgbRed;
BYTE rgbGreen;
BYTE rgbBlue;
BYTE rgbReserved;
};

So you'd not be able to copy this directly into the texture. You'd have to compile each pixel from the RGBQUAD based on the texture pixel format, and manually set the alpha, I guess.

##### Share on other sites
From what I saw, when I get the bits for a DIB/DDB they come to me in whatever format the DIB/DDB is in, and the RGBQUAD stuff is for palettes.
My main issue with DIBs is the "Device Independant" part makes me think that using it will mean GDI has to do some form of conversion, and hence it'll be slower than a DDB...

##### Share on other sites
Not sure about this. When I use GetDIBits on a 24bit colour bitmap, it copies the data into a buffer that is in the format I've posted above.

I thought the whole point of Device Independant Bitmaps was it gave you the data in a standard format rather than the format the DDB was in.

When I was using DirectDraw, I used to load image data in the RGBQUAD format, then use StretchDIBits to put it onto a DirectDraw surface. It would correctly set up the surface regardless of the surface colour depth - it even did the correct colour matching from true colour to 256 colour for me.

Sorry if I'm at cross purposes here.

##### Share on other sites
Quote:
 Original post by EasilyConfusedNot sure about this. When I use GetDIBits on a 24bit colour bitmap, it copies the data into a buffer that is in the format I've posted above.I thought the whole point of Device Independant Bitmaps was it gave you the data in a standard format rather than the format the DDB was in.When I was using DirectDraw, I used to load image data in the RGBQUAD format, then use StretchDIBits to put it onto a DirectDraw surface. It would correctly set up the surface regardless of the surface colour depth - it even did the correct colour matching from true colour to 256 colour for me.Sorry if I'm at cross purposes here.
Ah, I see now. Well, it looks like the only way to get access to the data in a DC is via a DIB, so I'll use that. GetBitmapBits() is deprecated apparently.

I'll investigate now. Thanks for the replies.

##### Share on other sites
Quote:
 Original post by Evil SteveI've currently created a DC compatible with the display, and a bitmap compatible with the DC. However, that gives me a monochrome bitmap. The docs for CreateCompatibleDC say that I can use CreateCompatibleBitmap to specify the width, height and colour of the bitmap. Which is a lie - I can only specify width and height.

Can't you just create bitmap compatible with the display (instead of memory DC, that you probably are doing at the moment)? That way you can get true color bitmaps. That's what I'm doing on my simple off-screen painting and so far I'm getting very good performance.
Edit: Actually MSDN is pretty clear on this:
Quote:
 From: MSDN CreateCompatibleDC"A memory DC exists only in memory. When the memory DC is created, its display surface is exactly one monochrome pixel wide and one monochrome pixel high."

Quote:
 From: MSDN CreateCompatibleBitmap"The color format of the bitmap created by the CreateCompatibleBitmap function matches the color format of the device identified by the hdc parameter."

[Edited by - VHL on August 10, 2006 11:43:37 AM]

##### Share on other sites
C&P from your journal, just in case:

Use GetScreenDC and feed that into CreateCompatibleDC to get a memory device context in the same bit-depth and such as the screen device. Be warned that you should pay attention to resolution/color depth change events (you will get a Windows message IIRC) as these may invalidate your device contexts and require you to recreate them, in certain cases.

##### Share on other sites
I think using a DIB is the way to go now. I got some stuff during my lunch break that seems to work (But I haven't tested properly). Using CreateDIBSection() gives me constant access to the bits, and lets me create a 32-bit DIB too, which makes texture conversion easy.

##### Share on other sites
Quote:
 Original post by Evil SteveI've currently created a DC compatible with the display, and a bitmap compatible with the DC. However, that gives me a monochrome bitmap.

Sounds like you're doing this:
HDC memdc = CreateCompatibleDC(displaydc);HBITMAP bitmap = CreateCompatibleBitmap(memdc, x, y);

HDC memdc = CreateCompatibleDC(displaydc);HBITMAP bitmap = CreateCompatibleBitmap(displaydc, x, y);

At any rate using DIB's instead of compatible bitmaps is a lot more convienent as you've find so the question is kind of moot.

##### Share on other sites
I've actually been working on some screen capturing code lately, this is how I approach it:

1. Create a BITMAPINFO structure
2. Get the DC for the surface you want to capture
3. Create a compatible DC for this surface
4. Create a compatible bitmap from the original surface
5. Select the bitmap into into the compatible DC
6. Blit from the original DC to the compatible DC
7. Call GetDIBits to extract the bitmap info from the compatible DC to some raw buffer

I'm not sure if this is the most efficient way (it probably isn't), but it definitely works. Most of the steps can only be done once however, only 6 and 7 need to be done every time you want to render text, I believe.

Hope this helps

##### Share on other sites
Quote:
Original post by Anon Mike
Quote:
 Original post by Evil SteveI've currently created a DC compatible with the display, and a bitmap compatible with the DC. However, that gives me a monochrome bitmap.

Sounds like you're doing this:
HDC memdc = CreateCompatibleDC(displaydc);HBITMAP bitmap = CreateCompatibleBitmap(memdc, x, y);

HDC memdc = CreateCompatibleDC(displaydc);HBITMAP bitmap = CreateCompatibleBitmap(displaydc, x, y);

At any rate using DIB's instead of compatible bitmaps is a lot more convienent as you've find so the question is kind of moot.
Ahh, that is indeed what I was doing.

Using a DIB secion seems to work perfectly, thanks.

For reference, I do it like this:
// Setup codeHDC m_hDC = CreateCompatibleDC(NULL);HFONT m_hFont = CreateFont(...);HBITMAP m_hBmp = CreateDIBSection(..., &m_pBits, ...); // 32-bit, and big enough to hold one glyphHBITMAP m_hBmpOld = (HBITMAP)SelectObject(hDC, hBmp);HFONT m_hFontOld = (HFONT)SelectObject(hDC, hFont);// Render code:DrawText(...); // Draw 1 letter to the DIB sectionGdiFlush();// Lock the D3D texture and copy bits in from m_pBits (From CreateDIBSection())

And it seems to work at a pretty decent speed.

Thanks to again to everyone.

##### Share on other sites
whops, sorry it seems youv'e got it sorted out, I was just going to say d3dfont.h & d3dfont.cpp pretty much cover what you were asking;

d3dfont.h
http://www.koders.com/cpp/fid93360BE68DA707918ACDBD81C9FDCC513EBFA34C.aspx

d3dfont.cpp
http://www.koders.com/cpp/fid45658CAFEED5C5456101A0F231836C1C1B639BB4.aspx?s=d3dfont.cpp

edited.

[Edited by - Stevieboy on August 10, 2006 4:59:12 PM]