![]() | |
![]() |
| | Thread Tools | Search this Thread | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
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; } |
#3
| |||
| |||
|
|
Has anyone used CreateDIBSection to create an offscreen buffer in C#? |
|
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; } |
#4
| |||
| |||
|
|
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); |
#5
| |||
| |||
|
|
IntPtr bits; IntPtr dib = CreateDIBSection(hMemDC, ref bmi, DIB_RGB_COLORS, ref bits, IntPtr.Zero, 0); |
|
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 |
![]() |
| Thread Tools | Search this Thread |
| Display Modes | |
| |