コード例 #1
0
ファイル: ResourceStripper.cs プロジェクト: dotnet/wpf-test
        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);
        }