private bool CreateLayeredWindowFromImgBuffer(IntPtr pImgBuffer, long cImgBufferLen, bool topMost) { bool bSuccess = false; IntPtr pImagingFactory = IntPtr.Zero; IntPtr pDecoder = IntPtr.Zero; IntPtr pIStream = IntPtr.Zero; IntPtr pDecodedFrame = IntPtr.Zero; IntPtr pBitmapSourceFormatConverter = IntPtr.Zero; IntPtr pBitmapFlipRotator = IntPtr.Zero; try { UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CreateImagingFactory(UnsafeNativeMethods.WIC.WINCODEC_SDK_VERSION, out pImagingFactory)); // Use the WIC stream class to wrap the unmanaged pointer UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CreateStream(pImagingFactory, out pIStream)); UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.InitializeStreamFromMemory(pIStream, pImgBuffer, (uint)cImgBufferLen)); // Create an object that will decode the encoded image Guid vendor = Guid.Empty; UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CreateDecoderFromStream(pImagingFactory, pIStream, ref vendor, 0, out pDecoder)); // Get the frame from the decoder. Most image formats have only a single frame, in the case // of animated gifs we are ok with only displaying the first frame of the animation. UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.GetFrame(pDecoder, 0, out pDecodedFrame)); UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CreateFormatConverter(pImagingFactory, out pBitmapSourceFormatConverter)); // Convert the image from whatever format it is in to 32bpp premultiplied alpha BGRA Guid pixelFormat = UnsafeNativeMethods.WIC.WICPixelFormat32bppPBGRA; UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.InitializeFormatConverter(pBitmapSourceFormatConverter, pDecodedFrame, ref pixelFormat, 0 /*DitherTypeNone*/, IntPtr.Zero, 0, UnsafeNativeMethods.WIC.WICPaletteType.WICPaletteTypeCustom)); // Reorient the image UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CreateBitmapFlipRotator(pImagingFactory, out pBitmapFlipRotator)); UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.InitializeBitmapFlipRotator(pBitmapFlipRotator, pBitmapSourceFormatConverter, UnsafeNativeMethods.WIC.WICBitmapTransformOptions.WICBitmapTransformFlipVertical)); Int32 width, height; UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.GetBitmapSize(pBitmapFlipRotator, out width, out height)); Int32 stride = width * 4; // initialize the bitmap header MS.Win32.NativeMethods.BITMAPINFO bmInfo = new MS.Win32.NativeMethods.BITMAPINFO(width, height, 32 /*bpp*/); bmInfo.bmiHeader_biCompression = MS.Win32.NativeMethods.BI_RGB; bmInfo.bmiHeader_biSizeImage = (int)(stride * height); // Create a 32bpp DIB. This DIB must have an alpha channel for UpdateLayeredWindow to succeed. IntPtr pBitmapBits = IntPtr.Zero; _hBitmap = UnsafeNativeMethods.CreateDIBSection(new HandleRef(), ref bmInfo, 0 /* DIB_RGB_COLORS*/, ref pBitmapBits, null, 0); // Copy the decoded image to the new buffer which backs the HBITMAP Int32Rect rect = new Int32Rect(0, 0, width, height); UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CopyPixels(pBitmapFlipRotator, ref rect, stride, stride * height, pBitmapBits)); _hwnd = CreateWindow(_hBitmap, width, height, topMost); bSuccess = true; } finally { if (pImagingFactory != IntPtr.Zero) { Marshal.Release(pImagingFactory); } if (pDecoder != IntPtr.Zero) { Marshal.Release(pDecoder); } if (pIStream != IntPtr.Zero) { Marshal.Release(pIStream); } if (pDecodedFrame != IntPtr.Zero) { Marshal.Release(pDecodedFrame); } if (pBitmapSourceFormatConverter != IntPtr.Zero) { Marshal.Release(pBitmapSourceFormatConverter); } if (pBitmapFlipRotator != IntPtr.Zero) { Marshal.Release(pBitmapFlipRotator); } if (bSuccess == false) { DestroyResources(); // cleans up _hwnd and _hBitmap } } return(bSuccess); }
private bool CreateLayeredWindowFromImgBuffer(IntPtr pImgBuffer, long cImgBufferLen, bool topMost) { bool bSuccess = false; IntPtr pImagingFactory = IntPtr.Zero; IntPtr pDecoder = IntPtr.Zero; IntPtr pIStream = IntPtr.Zero; IntPtr pDecodedFrame = IntPtr.Zero; IntPtr pBitmapSourceFormatConverter = IntPtr.Zero; IntPtr pBitmapFlipRotator = IntPtr.Zero; try { UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CreateImagingFactory(UnsafeNativeMethods.WIC.WINCODEC_SDK_VERSION, out pImagingFactory)); // Use the WIC stream class to wrap the unmanaged pointer UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CreateStream(pImagingFactory, out pIStream)); UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.InitializeStreamFromMemory(pIStream, pImgBuffer, (uint)cImgBufferLen)); // Create an object that will decode the encoded image Guid vendor = Guid.Empty; UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CreateDecoderFromStream(pImagingFactory, pIStream, ref vendor, 0, out pDecoder)); // Get the frame from the decoder. Most image formats have only a single frame, in the case // of animated gifs we are ok with only displaying the first frame of the animation. UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.GetFrame(pDecoder, 0, out pDecodedFrame)); UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CreateFormatConverter(pImagingFactory, out pBitmapSourceFormatConverter)); // Convert the image from whatever format it is in to 32bpp premultiplied alpha BGRA Guid pixelFormat = UnsafeNativeMethods.WIC.WICPixelFormat32bppPBGRA; UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.InitializeFormatConverter(pBitmapSourceFormatConverter, pDecodedFrame, ref pixelFormat, 0 /*DitherTypeNone*/, IntPtr.Zero, 0, UnsafeNativeMethods.WIC.WICPaletteType.WICPaletteTypeCustom)); // Reorient the image UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CreateBitmapFlipRotator(pImagingFactory, out pBitmapFlipRotator)); UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.InitializeBitmapFlipRotator(pBitmapFlipRotator, pBitmapSourceFormatConverter, UnsafeNativeMethods.WIC.WICBitmapTransformOptions.WICBitmapTransformFlipVertical)); Int32 width, height; UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.GetBitmapSize(pBitmapFlipRotator, out width, out height)); Int32 stride = width * 4; // initialize the bitmap header MS.Win32.NativeMethods.BITMAPINFO bmInfo = new MS.Win32.NativeMethods.BITMAPINFO(width, height, 32 /*bpp*/); bmInfo.bmiHeader_biCompression = MS.Win32.NativeMethods.BI_RGB; bmInfo.bmiHeader_biSizeImage = (int)(stride * height); // Create a 32bpp DIB. This DIB must have an alpha channel for UpdateLayeredWindow to succeed. IntPtr pBitmapBits = IntPtr.Zero; _hBitmap = UnsafeNativeMethods.CreateDIBSection(new HandleRef(), ref bmInfo, 0 /* DIB_RGB_COLORS*/, ref pBitmapBits, null, 0); // Copy the decoded image to the new buffer which backs the HBITMAP Int32Rect rect = new Int32Rect(0, 0, width, height); UnsafeNativeMethods.HRESULT.Check( UnsafeNativeMethods.WIC.CopyPixels(pBitmapFlipRotator, ref rect, stride, stride * height, pBitmapBits)); _hwnd = CreateWindow(_hBitmap, width, height, topMost); bSuccess = true; } finally { if (pImagingFactory != IntPtr.Zero) { Marshal.Release(pImagingFactory); } if (pDecoder != IntPtr.Zero) { Marshal.Release(pDecoder); } if (pIStream != IntPtr.Zero) { Marshal.Release(pIStream); } if (pDecodedFrame != IntPtr.Zero) { Marshal.Release(pDecodedFrame); } if (pBitmapSourceFormatConverter != IntPtr.Zero) { Marshal.Release(pBitmapSourceFormatConverter); } if (pBitmapFlipRotator != IntPtr.Zero) { Marshal.Release(pBitmapFlipRotator); } if (bSuccess == false) { DestroyResources(); // cleans up _hwnd and _hBitmap } } return bSuccess; }