views:

205

answers:

1

I'd like to use OpenGL to draw directly to a .NET System::Drawing::Bitmap (C++/CLI). It seems like it should work like this:

char buf[48];
ZeroMemory( &buf, sizeof(buf));
System::Drawing::Bitmap bmp(
    4,
    4,
    12,
    Imaging::PixelFormat::Format24bppRgb,
    (System::IntPtr)buf);
Graphics^ g = Graphics::FromImage(%bmp);
HDC local_hdc = (HDC)((void*)g->GetHdc());
HGLRC local_hrc = wglCreateContext( local_hdc );
if(!wglMakeCurrent( local_hdc, local_hrc ))
    ShowError();

//Draw something with OpenGL ...

g->ReleaseHdc((IntPtr)((void*)local_hdc));

//Do something with the bitmap ...

But wglMakeCurrent fails with "The pixel format is invalid".

"Of course!" I think. "I just need to set the pixel format of the bitmap in such a way that OpenGL can render to it!"

Sadly, if I use the above Bitmap constructor, I'm limited to an enum of canned pixelformats, rather than a struct holding a bunch of attributes that I can OR together. And I don't think it's possible to set the pixel format after the fact.

Anyway, this way of doing things would be prettier than using a bunch of Win32 calls to make a Device-Independent Bitmap, but the canned pixel formats seem to omit any sort of GL-enabled anything, and I just fail. Can you succeed?

A: 

You probably don't want to draw directly into your buffer anyway, you'd lose all hardware acceleration which is the advantage of OpenGL to begin with. Instead:

  • Set up an OpenGL context as usual, using video RAM.
  • Draw into it, fully accelerated.
  • Create a Bitmap.
  • Call Bitmap::LockBits to get the pointer to the raw pixel memory.
  • Use glCopyImage to read the results from video RAM into the Bitmap.

The PixelFormat passed to LockBits and glCopyImage in the last two steps need to match of course.

Ben Voigt
Ah, but I do want to draw directly into my bitmap buffer! That's because I'm trying to get a bitmap ready to send to a printer. This means I only have to draw once, so speed isn't a big issue, and if I can draw directly to the buffer I avoid duplicating a really big bitmap in memory.
Matthew Lowe
The method I suggested won't use any additional system RAM, only video RAM. How big is this bitmap? I guess if you're trying to render an 8.5"x11" at 1200 dpi (that's 400MB) it might not fit in video RAM but... I don't know if OpenGL would support a rendering surface that large anyway.Why are you wanting OpenGL for this? 3-D rendering? Lots of textured quads? Reuse of existing render routines already needed for screen display?
Ben Voigt
Hm, sorry to let this hang for, like, ever. The image is likely to be that large, and larger for larger paper sizes. I want to use OpenGL for this because I am using OpenGL for rendering the view on screen, and the printout needs to match the screen view as exactly as possible ... just at a higher resolution. So basically, what I want to do is when the user says "print", I want to draw once, directly into the buffer of a .NET bitmap (in my .NET client at least), which can then be easily sent to the printer.
Matthew Lowe