private MemoryStream SaveBitmapToStream(IntPtr pBits) { MemoryStream memoryStream = new MemoryStream(); IntPtr hdc = IntPtr.Zero; IntPtr hPalette = IntPtr.Zero; try { hdc = User32.GetDC(IntPtr.Zero); if (hdc == IntPtr.Zero) { throw new ExternalException("Call to native API (GetDC) failed"); } // Compute bitmap size and create it if needed int paletteSize = 0; IntPtr structBmpInfoPtr = new IntPtr(pBits.ToInt64() + Marshal.OffsetOf(typeof(GDI32.BITMAPINFOHEADER), "biSize").ToInt64()); int structBmpInfoSize = Marshal.ReadInt32(structBmpInfoPtr); IntPtr bitCountPtr = new IntPtr(pBits.ToInt64() + Marshal.OffsetOf(typeof(GDI32.BITMAPINFOHEADER), "biBitCount").ToInt64()); int bitCount = Marshal.ReadInt32(bitCountPtr); if (bitCount <= 8) { paletteSize = 1 << bitCount; IntPtr colorUsedPtr = new IntPtr(pBits.ToInt64() + Marshal.OffsetOf(typeof(GDI32.BITMAPINFOHEADER), "biClrUsed").ToInt64()); int colorUsed = Marshal.ReadInt32(colorUsedPtr); if (colorUsed > 0) { paletteSize = colorUsed; } paletteSize *= 4; // 4 -> sizeof(RGBQUAD) // Create palette IntPtr palettePtr = IntPtr.Zero; try { int structLogPaletteSize = Marshal.SizeOf(typeof(GDI32.LOGPALETTE)); palettePtr = Marshal.AllocHGlobal(structLogPaletteSize + paletteSize); IntPtr palVersion = new IntPtr(palettePtr.ToInt64() + Marshal.OffsetOf(typeof(GDI32.LOGPALETTE), "palVersion").ToInt64()); IntPtr palNumEntries = new IntPtr(palettePtr.ToInt64() + Marshal.OffsetOf(typeof(GDI32.LOGPALETTE), "palNumEntries").ToInt64()); Marshal.WriteInt16(palVersion, 0x300); Marshal.WriteInt16(palNumEntries, (short)(paletteSize / 4)); for (int t = 0; t < paletteSize; t += 4) { IntPtr pRgbfBits = new IntPtr(pBits.ToInt64() + structBmpInfoSize + t); IntPtr pRgbfPallette = new IntPtr(palettePtr.ToInt64() + structLogPaletteSize + t); Marshal.WriteInt32(pRgbfPallette, Marshal.ReadInt32(pRgbfBits)); // } hPalette = GDI32.CreatePalette(palettePtr); if (hPalette == IntPtr.Zero) { throw new ExternalException("Call to native API (CreatePalette) failed"); } } finally { if (palettePtr != IntPtr.Zero) { Marshal.FreeHGlobal(palettePtr); palettePtr = IntPtr.Zero; } } } // Create hBitmap, create Bitmap from it and save as stream IntPtr offsetToBits = new IntPtr(pBits.ToInt64() + structBmpInfoSize + paletteSize); IntPtr hBitmap = GDI32.CreateDIBitmap(hdc, pBits, GDI32.CBM_INIT, offsetToBits, pBits, GDI32.DIB_RGB_COLORS); if (hBitmap == IntPtr.Zero) { throw new ExternalException("Call to native API (CreateDIBitmap) failed"); } using (Bitmap bmp = (hPalette == IntPtr.Zero) ? Bitmap.FromHbitmap(hBitmap) : Bitmap.FromHbitmap(hBitmap, hPalette)) { bmp.Save(memoryStream, ImageFormat.Png); } // } finally { if (hdc != IntPtr.Zero) { User32.ReleaseDC(IntPtr.Zero, hdc); hdc = IntPtr.Zero; } if (hPalette != IntPtr.Zero) { GDI32.DeleteObject(hPalette); hPalette = IntPtr.Zero; } } return(memoryStream); }