How do I get a device context from an indexed bitmap?

J

Joergen Bech

Suppose I have

Dim bm As New Bitmap(16, 16,Imaging.PixelFormat.Format8bppIndexed)

I cannot use

Dim g As Graphics = Graphics.FromImage(bmdest)
Dim hdc As IntPtr = g.GetHdc()

as the FromImage call will fail for indexed bitmaps.

How do I get a device context handle (hdc) to this bitmap so I can
draw on it using GDI (not GDI+) functions, such as RoundRect, etc?

Note: I do *not* want to convert the image to 24-bit, then go the
usual GDI+ route, then convert it back to 8-bit. I want to *stay* in
8-bit mode.

Also note that I am not looking for solutions that create a new
bitmap using GDI functions. One of the things I need to do is to
take to bitmap parameters, obtain hdc's for both, then use those
to draw one of the bitmaps on top of the other using BitBlt or
StretchBlt. The sample bitmap object above is just an example
of the format I need to be able to handle.

TIA,

Joergen Bech
 
A

Armin Zingler

Joergen Bech @ post1.tele.dk> said:
Suppose I have

Dim bm As New Bitmap(16, 16,Imaging.PixelFormat.Format8bppIndexed)

I cannot use

Dim g As Graphics = Graphics.FromImage(bmdest)
Dim hdc As IntPtr = g.GetHdc()

as the FromImage call will fail for indexed bitmaps.

How do I get a device context handle (hdc) to this bitmap so I can
draw on it using GDI (not GDI+) functions, such as RoundRect, etc?

Note: I do *not* want to convert the image to 24-bit, then go the
usual GDI+ route, then convert it back to 8-bit. I want to *stay* in
8-bit mode.

Also note that I am not looking for solutions that create a new
bitmap using GDI functions.

After searching the web, it seems to be impossible with the current release
of GDI+. It's not supported with indexed pixel format.
One of the things I need to do is to
take to bitmap parameters, obtain hdc's for both, then use those to
draw one of the bitmaps on top of the other using BitBlt or
StretchBlt. The sample bitmap object above is just an example of the
format I need to be able to handle.


Maybe microsoft.public.dotnet.framework.drawing has an answer.



Armin
 
M

Michael Phillips, Jr.

How do I get a device context handle (hdc) to this bitmap so I can
draw on it using GDI (not GDI+) functions, such as RoundRect, etc?

The MSDN documentation clearly states that you cannot get a Graphics object
from an Indexed image.

You can use GDI with p-invoke to get the job done. Create your indexed
bitmap with CreateDIBSection.
 
J

Joergen Bech

I had sorta hoped it was possible to get a device context without
going through a Graphics object.

I am not sure how CreateDIBSection could help me, since this
function takes an hdc parameter itself - which is exactly what I was
missing in the first place?!?

/Joergen Bech
 
M

Michael Phillips, Jr.

I am not sure how CreateDIBSection could help me, since this
function takes an hdc parameter itself - which is exactly what I was
missing in the first place?!?

Use a memory device context.

1) IntPtr hdc = GetDC(IntPtr.Zero) ' get the dc of the desktop
2) IntPtr hdcMem = CreateCompatibleDC(hdc) ' memory device context
3) CreateDIBSection(hdcMem,...)
4) Don't forget to release and delete device contexts when you are finished
with them
ReleaseDC(IntPtr.Zero, hdc)
DeleteDC(hdcMem)
 
J

Joergen Bech

Use a memory device context.

1) IntPtr hdc = GetDC(IntPtr.Zero) ' get the dc of the desktop
2) IntPtr hdcMem = CreateCompatibleDC(hdc) ' memory device context
3) CreateDIBSection(hdcMem,...)
4) Don't forget to release and delete device contexts when you are finished
with them
ReleaseDC(IntPtr.Zero, hdc)
DeleteDC(hdcMem)

I still do not get how this is going to solve my original problem:

1. I have a bitmap object, which is an 8-bit, indexed image.
This bitmap might already contain image information.

2. I want to draw on this bitmap using GDI functions.

Where does your sample code above refer to such a bitmap?
What you are illustrating is a way to create an empty,
screen-compatible device context(?)

Regards,

Joergen Bech
 
M

Michael Phillips, Jr.

Where does your sample code above refer to such a bitmap?
What you are illustrating is a way to create an empty,
screen-compatible device context(?)

My code demonstrates how to create an empty canvas to draw on.
It assumes that you do not have an existing DIB surface to render to.
1. I have a bitmap object, which is an 8-bit, indexed image.
This bitmap might already contain image information.

2. I want to draw on this bitmap using GDI functions.

Assuming you already have an indexed bitmap that has been loaded
and created as a DIB with CreateDIBSection then steps 1 and 2 allow to
create a memory device context
which allows your DIB to be selected into it so that it may act as a canvas
for you to render to.

You must select your DIB's handle into this memory device context so that
you may draw on it.
1) IntPtr hOldBitmap = SelectObject(hdcMem, hBitmap)
2) Draw anything you like on your bitmap using any GDI funtion
3) SelectObject(hdcMem, hOldBitmap) ' remove your DIB from the memory device
context
4) Save or display your DIB
 
J

Joergen Bech

I appreciate your effort.

However, I specifically said in the
original post that the destination was an 8-bit, indexed,
System.Drawing.Bitmap object.

In other words, the indexed bitmap was not created by any
CreateDIBSection calls made by me.

I do not know how I can rephrase my original question to
state my intent any clearer.

How about: I need to use an existing, 8-bit, indexed
System.Drawing.Bitmap object as the destination for a GDI BitBlt
operation. How do I bridge the gap between
System.Drawing.Bitmap and hdc?

Regards,

Joergen Bech
 
M

Michael Phillips, Jr.

I do not know how I can rephrase my original question to
state my intent any clearer.

How about: I need to use an existing, 8-bit, indexed
System.Drawing.Bitmap object as the destination for a GDI BitBlt
operation. How do I bridge the gap between
System.Drawing.Bitmap and hdc?

As I previously stated, you cannot get a Graphics context for an indexed
System.Drawing.Bitmap.

This is a Microsoft design decision not mine.

That means that you cannot use an indexed System.Drawing.Bitmap to achieve
your goal.

You can choose to follow my recommendations and solve your problem or choose
not to and fail in your goal.

You can use Lockbits to transfer your System.Drawing.Bitmap to a GDI DIB
created with CreateDIBSection and then
Marshal the bits back to your indexed System.Drawing.Bitmap when you have
finished rendering to it.

Your only other choice is to convert your indexed bitmap to 24bpp and draw
to your heart's content and then recompute a palette and repack
your 8bpp bitmap.
 
J

Joergen Bech

You can choose to follow my recommendations and solve your problem or choose
not to and fail in your goal.

ok. That was the answer I was looking for.

Yes, there are ways of copying the image and work on the
copy, but I was hoping for a solution which did not involve
the additional copying back and forth processes as well as
the memory overhead.

Thanks again. Over & out,

Joergen Bech
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top