BitmapSource DIBV5ToBitmapSource(byte[] allBytes) { var bmi = BinaryStructHelper.FromByteArray <BITMAPV5HEADER>(allBytes); var imageBytes = GetImageBytesFromAllBytes(allBytes, bmi); var stride = GetStrideFromBitmapHeader(bmi); var reversedImageBytes = ConvertImageBytesFromBottomUpToTopDown(imageBytes, stride); var bmpSource = BitmapSource.Create( bmi.bV5Width, bmi.bV5Height, bmi.bV5XPelsPerMeter, bmi.bV5YPelsPerMeter, GetPixelFormatFromBitsPerPixel(bmi.bV5BitCount), null, reversedImageBytes, stride); return(bmpSource); }
/// <summary> /// A special format 17 bitmap reader /// </summary> /// <param name="clipboardAccessToken">IClipboardAccessToken</param> /// <returns>Bitmap or null</returns> public static Bitmap GetAsFormat17(this IClipboardAccessToken clipboardAccessToken) { var formats = clipboardAccessToken.AvailableFormats().ToList(); if (!formats.Contains("Format17")) { return(null); } var format17Bytes = clipboardAccessToken.GetAsBytes("Format17"); var infoHeader = BinaryStructHelper.FromByteArray <BitmapInfoHeader>(format17Bytes); if (!infoHeader.IsDibV5) { return(null); } // Using special DIBV5 / Format17 format reader // CF_DIBV5 var gcHandle = IntPtr.Zero; try { var handle = GCHandle.Alloc(format17Bytes, GCHandleType.Pinned); gcHandle = GCHandle.ToIntPtr(handle); return (new Bitmap(infoHeader.Width, infoHeader.Height, -(int)(infoHeader.SizeImage / infoHeader.Height), infoHeader.BitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb, new IntPtr(handle.AddrOfPinnedObject().ToInt32() + infoHeader.OffsetToPixels + (infoHeader.Height - 1) * (int)(infoHeader.SizeImage / infoHeader.Height)) )); } catch (Exception ex) { Log.Error().WriteLine(ex, "Problem retrieving Format17 from clipboard."); } finally { if (gcHandle == IntPtr.Zero) { GCHandle.FromIntPtr(gcHandle).Free(); } } return(null); }
/// <summary> /// Place the surface as Format17 bitmap on the clipboard /// </summary> /// <param name="clipboardAccessToken">IClipboardAccessToken</param> /// <param name="surface">ISurface</param> public static void SetAsFormat17(this IClipboardAccessToken clipboardAccessToken, ISurface surface) { // Create the stream for the clipboard using (var dibV5Stream = new MemoryStream()) { var outputSettings = new SurfaceOutputSettings(OutputFormats.bmp, 100, false); bool dispose = ImageOutput.CreateBitmapFromSurface(surface, outputSettings, out var bitmapToSave); // Create the BITMAPINFOHEADER var header = BitmapInfoHeader.Create(bitmapToSave.Width, bitmapToSave.Height, 32); // Make sure we have BI_BITFIELDS, this seems to be normal for Format17? header.Compression = BitmapCompressionMethods.BI_BITFIELDS; var headerBytes = BinaryStructHelper.ToByteArray(header); // Write the BITMAPINFOHEADER to the stream dibV5Stream.Write(headerBytes, 0, headerBytes.Length); // As we have specified BI_COMPRESSION.BI_BITFIELDS, the BitfieldColorMask needs to be added var colorMask = BitfieldColorMask.Create(); // Create the byte[] from the struct var colorMaskBytes = BinaryStructHelper.ToByteArray(colorMask); Array.Reverse(colorMaskBytes); // Write to the stream dibV5Stream.Write(colorMaskBytes, 0, colorMaskBytes.Length); // Create the raw bytes for the pixels only var bitmapBytes = BitmapToByteArray(bitmapToSave); // Write to the stream dibV5Stream.Write(bitmapBytes, 0, bitmapBytes.Length); // Reset the stream to the beginning so it can be written dibV5Stream.Seek(0, SeekOrigin.Begin); // Set the DIBv5 to the clipboard DataObject clipboardAccessToken.SetAsStream("Format17", dibV5Stream); if (dispose) { bitmapToSave.Dispose(); } } }
/// <summary> /// Get a DIB from the Clipboard /// </summary> /// <param name="clipboardAccessToken"></param> /// <returns>Bitmap or null</returns> public static Bitmap GetAsDeviceIndependendBitmap(this IClipboardAccessToken clipboardAccessToken) { var formats = clipboardAccessToken.AvailableFormats().ToList(); if (!formats.Contains(StandardClipboardFormats.Bitmap.AsString())) { return(null); } var format17Bytes = clipboardAccessToken.GetAsBytes(StandardClipboardFormats.Bitmap.AsString()); var infoHeader = BinaryStructHelper.FromByteArray <BitmapInfoHeader>(format17Bytes); if (infoHeader.IsDibV5) { Log.Warn().WriteLine("Getting DIBV5 (format 17) when requesting DIB"); return(null); } // Bitmap version older than 5 var fileHeaderSize = Marshal.SizeOf(typeof(BitmapFileHeader)); var fileHeader = BitmapFileHeader.Create(infoHeader); var fileHeaderBytes = BinaryStructHelper.ToByteArray(fileHeader); using (var bitmapStream = new MemoryStream()) { bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize); bitmapStream.Write(format17Bytes, 0, format17Bytes.Length); bitmapStream.Seek(0, SeekOrigin.Begin); var image = BitmapHelper.FromStream(bitmapStream); if (image != null) { return(image); } } return(null); }