Example #1
0
        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);
        }