HighTechTalks DotNet Forums  

memory device context and DIB

Dotnet Framework (Drawing) microsoft.public.dotnet.framework.drawing


Discuss memory device context and DIB in the Dotnet Framework (Drawing) forum.



Reply
 
Thread Tools Search this Thread Display Modes
  #1  
Old   
jonpb
 
Posts: n/a

Default memory device context and DIB - 12-19-2007 , 04:33 PM






Hi,
I am porting some code over from a C++ application that uses OpenGL. I
need to save the current scene to an image file. The steps are quite
simple: create a memory device context, select a DIB into it, draw the
OpenGL scene, create a System.Drawing.Bitmap using FromHBitmap on the
DIB, save the bitmap.

The problem is I get a black bitmap. I'm curious to know if, in the
following code the function signature and parameter passing is correct
for CreateDIBSection. I am not very familiar with using pointers in
unsafe code.

Or, does there seem to be something else I'm missing?

Thanks


[DllImport("gdi32.dll")]
unsafe static extern IntPtr CreateDIBSection(IntPtr hdc, ref BITMAPINFO
bmi, uint Usage, void** bits, IntPtr hSection, uint dwOffset);


public unsafe static Bitmap GetImage(IntPtr dc, Size size, Renderer render)
{
// initialize the bitmap header info.
BITMAPINFO bmi = new BITMAPINFO();
bmi.Init();
bmi.biWidth = size.Width;
bmi.biHeight = size.Height;
bmi.biPlanes = 1;
bmi.biBitCount = 24;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = ((((uint)size.Width * 24U + 15U) & ~15U) / 8U) *
(uint)size.Height; // WORD aligned
bmi.biClrUsed = 0;
bmi.biClrImportant = 0;

// create the DIB
void* bits;
IntPtr dib = CreateDIBSection(dc, ref bmi, DIB_RGB_COLORS, &bits,
IntPtr.Zero, 0);
if (dib == IntPtr.Zero)
throw new Exception("Failed to create DIB section.");
GdiFlush();

// create the memory DC and select the DIB
IntPtr hMemDC = CreateCompatibleDC(dc);
if (hMemDC == IntPtr.Zero)
throw new Exception("Failed to create a compatible device context.");
IntPtr oldDib = SelectObject(hMemDC, dib);

// find the best pixel format descriptor
IntPtr hWnd = render.Owner.Handle;
IntPtr screenDC = GetDC(hWnd);
int pfi = CreateCompatibleBitmapPFD(screenDC, hMemDC);
ReleaseDC(hWnd, screenDC);

// draw the scene
render.DrawScene();

// create a C# Bitmap from the native bitmap selected into the memory
device context
Bitmap bmp = Bitmap.FromHbitmap(dib);
bmp.Save("C:\\ASC\\Test\\viewer.png",
System.Drawing.Imaging.ImageFormat.Png);

// clean up the native resources
SelectObject(hMemDC, oldDib);
DeleteObject(dib);
DeleteDC(hMemDC);

return bmp;
}

Reply With Quote
  #2  
Old   
jonpb
 
Posts: n/a

Default Re: memory device context and DIB - 12-20-2007 , 05:05 PM






On further investigation, after calling CreateDIBSection the bitmap's
nativeImage IntPtr is not zero, but the rawData byte[] member is null.
Has anyone used CreateDIBSection to create an offscreen buffer in C#?
Any help would be much appreciated.

Thanks

jonpb wrote:
Quote:
Hi,
I am porting some code over from a C++ application that uses OpenGL. I
need to save the current scene to an image file. The steps are quite
simple: create a memory device context, select a DIB into it, draw the
OpenGL scene, create a System.Drawing.Bitmap using FromHBitmap on the
DIB, save the bitmap.

The problem is I get a black bitmap. I'm curious to know if, in the
following code the function signature and parameter passing is correct
for CreateDIBSection. I am not very familiar with using pointers in
unsafe code.

Or, does there seem to be something else I'm missing?

Thanks


[DllImport("gdi32.dll")]
unsafe static extern IntPtr CreateDIBSection(IntPtr hdc, ref BITMAPINFO
bmi, uint Usage, void** bits, IntPtr hSection, uint dwOffset);


public unsafe static Bitmap GetImage(IntPtr dc, Size size, Renderer render)
{
// initialize the bitmap header info.
BITMAPINFO bmi = new BITMAPINFO();
bmi.Init();
bmi.biWidth = size.Width;
bmi.biHeight = size.Height;
bmi.biPlanes = 1;
bmi.biBitCount = 24;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = ((((uint)size.Width * 24U + 15U) & ~15U) / 8U) *
(uint)size.Height; // WORD aligned
bmi.biClrUsed = 0;
bmi.biClrImportant = 0;

// create the DIB
void* bits;
IntPtr dib = CreateDIBSection(dc, ref bmi, DIB_RGB_COLORS, &bits,
IntPtr.Zero, 0);
if (dib == IntPtr.Zero)
throw new Exception("Failed to create DIB section.");
GdiFlush();

// create the memory DC and select the DIB
IntPtr hMemDC = CreateCompatibleDC(dc);
if (hMemDC == IntPtr.Zero)
throw new Exception("Failed to create a compatible device context.");
IntPtr oldDib = SelectObject(hMemDC, dib);

// find the best pixel format descriptor
IntPtr hWnd = render.Owner.Handle;
IntPtr screenDC = GetDC(hWnd);
int pfi = CreateCompatibleBitmapPFD(screenDC, hMemDC);
ReleaseDC(hWnd, screenDC);

// draw the scene
render.DrawScene();

// create a C# Bitmap from the native bitmap selected into the memory
device context
Bitmap bmp = Bitmap.FromHbitmap(dib);
bmp.Save("C:\\ASC\\Test\\viewer.png",
System.Drawing.Imaging.ImageFormat.Png);

// clean up the native resources
SelectObject(hMemDC, oldDib);
DeleteObject(dib);
DeleteDC(hMemDC);

return bmp;
}

Reply With Quote
  #3  
Old   
Michael Phillips, Jr.
 
Posts: n/a

Default Re: memory device context and DIB - 12-21-2007 , 08:13 AM



Quote:
Has anyone used CreateDIBSection to create an offscreen buffer in C#?
[DllImport("gdi32.dll")]
static extern IntPtr CreateDIBSection([In] IntPtr hdc, [In] ref
BITMAPINFOHEADER pbmi,
[In] uint iUsage, [In][Out] ref IntPtr ppvBits, [In] IntPtr hSection, [In]
uint dwOffset);

The above declaration will produce an empty DIB bitmap of your choice of
pixel format, width, height, etc.

You may render to the offscreen DIB by using any of the GDI BitBlt
variations or render directly to the image's memory.

The ppvBits provides direct memory access to the DIB's bits.

You have many choices as to how you create a managed System.Drawing.Bitmap.

Here is one constructor that will work with a DIB:

public Bitmap(int width, int height, int stride, PixelFormat format, IntPtr
scan0);
"jonpb" <nospam (AT) nospam (DOT) com> wrote

Quote:
On further investigation, after calling CreateDIBSection the bitmap's
nativeImage IntPtr is not zero, but the rawData byte[] member is null. Has
anyone used CreateDIBSection to create an offscreen buffer in C#? Any help
would be much appreciated.

Thanks

jonpb wrote:
Hi,
I am porting some code over from a C++ application that uses OpenGL. I
need to save the current scene to an image file. The steps are quite
simple: create a memory device context, select a DIB into it, draw the
OpenGL scene, create a System.Drawing.Bitmap using FromHBitmap on the
DIB, save the bitmap.

The problem is I get a black bitmap. I'm curious to know if, in the
following code the function signature and parameter passing is correct
for CreateDIBSection. I am not very familiar with using pointers in
unsafe code.

Or, does there seem to be something else I'm missing?

Thanks


[DllImport("gdi32.dll")]
unsafe static extern IntPtr CreateDIBSection(IntPtr hdc, ref BITMAPINFO
bmi, uint Usage, void** bits, IntPtr hSection, uint dwOffset);


public unsafe static Bitmap GetImage(IntPtr dc, Size size, Renderer
render)
{
// initialize the bitmap header info.
BITMAPINFO bmi = new BITMAPINFO();
bmi.Init();
bmi.biWidth = size.Width;
bmi.biHeight = size.Height;
bmi.biPlanes = 1;
bmi.biBitCount = 24;
bmi.biCompression = BI_RGB;
bmi.biSizeImage = ((((uint)size.Width * 24U + 15U) & ~15U) / 8U) *
(uint)size.Height; // WORD aligned
bmi.biClrUsed = 0;
bmi.biClrImportant = 0;

// create the DIB
void* bits;
IntPtr dib = CreateDIBSection(dc, ref bmi, DIB_RGB_COLORS, &bits,
IntPtr.Zero, 0);
if (dib == IntPtr.Zero)
throw new Exception("Failed to create DIB section.");
GdiFlush();

// create the memory DC and select the DIB
IntPtr hMemDC = CreateCompatibleDC(dc);
if (hMemDC == IntPtr.Zero)
throw new Exception("Failed to create a compatible device context.");
IntPtr oldDib = SelectObject(hMemDC, dib);

// find the best pixel format descriptor
IntPtr hWnd = render.Owner.Handle;
IntPtr screenDC = GetDC(hWnd);
int pfi = CreateCompatibleBitmapPFD(screenDC, hMemDC);
ReleaseDC(hWnd, screenDC);

// draw the scene
render.DrawScene();

// create a C# Bitmap from the native bitmap selected into the memory
device context
Bitmap bmp = Bitmap.FromHbitmap(dib);
bmp.Save("C:\\ASC\\Test\\viewer.png",
System.Drawing.Imaging.ImageFormat.Png);

// clean up the native resources
SelectObject(hMemDC, oldDib);
DeleteObject(dib);
DeleteDC(hMemDC);

return bmp;
}



Reply With Quote
  #4  
Old   
jonpb
 
Posts: n/a

Default Re: memory device context and DIB - 12-21-2007 , 05:42 PM



Michael Phillips, Jr. wrote:
Quote:
Has anyone used CreateDIBSection to create an offscreen buffer in C#?

[DllImport("gdi32.dll")]
static extern IntPtr CreateDIBSection([In] IntPtr hdc, [In] ref
BITMAPINFOHEADER pbmi,
[In] uint iUsage, [In][Out] ref IntPtr ppvBits, [In] IntPtr hSection, [In]
uint dwOffset);

Thanks for the response. I have not found a way to get this declaration
to compile. My first guess was this:

IntPtr bits;
IntPtr dib = CreateDIBSection(hMemDC, ref bmi, DIB_RGB_COLORS,
ref bits, IntPtr.Zero, 0);

The compiler complains that bits needs to be initialized first. But,
that is the reason the signature is void** in C, it is CreateDIBSection
that allocate the memory not me. I tried a number of other things
without luck. Can you give me an example of how you use this declaration
of CreateDIBSection?

Thanks


Reply With Quote
  #5  
Old   
Michael Phillips, Jr.
 
Posts: n/a

Default Re: memory device context and DIB - 12-21-2007 , 06:26 PM



Quote:
IntPtr bits;
IntPtr dib = CreateDIBSection(hMemDC, ref bmi, DIB_RGB_COLORS,
ref bits, IntPtr.Zero, 0);
Your guess was correct. You forgot to initialize the bits as follows:

IntPtr bits = IntPtr.Zero;
IntPtr hdcMem = CreateCompatibleDC(IntPtr.Zero);
IntPtr hBitmap = CreateDIBSection(hdcMem, ref bmi, DIB_RGB_COLORS, ref bits,
IntPtr.Zero, 0);
DeleteDC(hdcMem);

"jonpb" <nospam (AT) nospam (DOT) com> wrote

Quote:
Michael Phillips, Jr. wrote:
Has anyone used CreateDIBSection to create an offscreen buffer in C#?

[DllImport("gdi32.dll")]
static extern IntPtr CreateDIBSection([In] IntPtr hdc, [In] ref
BITMAPINFOHEADER pbmi,
[In] uint iUsage, [In][Out] ref IntPtr ppvBits, [In] IntPtr hSection,
[In] uint dwOffset);


Thanks for the response. I have not found a way to get this declaration to
compile. My first guess was this:

IntPtr bits;
IntPtr dib = CreateDIBSection(hMemDC, ref bmi, DIB_RGB_COLORS,
ref bits, IntPtr.Zero, 0);

The compiler complains that bits needs to be initialized first. But, that
is the reason the signature is void** in C, it is CreateDIBSection that
allocate the memory not me. I tried a number of other things without luck.
Can you give me an example of how you use this declaration of
CreateDIBSection?

Thanks



Reply With Quote
Reply




Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.4
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.