Example #1
0
        /// <summary>
        ///     Set an Image to the clipboard
        ///     This method will place images to the clipboard depending on the ClipboardFormats setting.
        ///     e.g. Bitmap which works with pretty much everything and type Dib for e.g. OpenOffice
        ///     because OpenOffice has a bug http://qa.openoffice.org/issues/show_bug.cgi?id=85661
        ///     The Dib (Device Indenpendend Bitmap) in 32bpp actually won't work with Powerpoint 2003!
        ///     When pasting a Dib in PP 2003 the Bitmap is somehow shifted left!
        ///     For this problem the user should not use the direct paste (=Dib), but select Bitmap
        /// </summary>
        public static void SetClipboardData(ISurface surface)
        {
            var dataObject = new DataObject();

            // This will work for Office and most other applications
            //ido.SetData(DataFormats.Bitmap, true, image);

            MemoryStream dibStream    = null;
            MemoryStream dibV5Stream  = null;
            MemoryStream pngStream    = null;
            Bitmap       bitmapToSave = null;
            var          disposeImage = false;

            try
            {
                var outputSettings = new SurfaceOutputSettings(OutputFormats.png, 100, false);
                // Create the image which is going to be saved so we don't create it multiple times
                disposeImage = ImageOutput.CreateBitmapFromSurface(surface, outputSettings, out bitmapToSave);
                try
                {
                    // Create PNG stream
                    if (CoreConfig.ClipboardFormats.Contains(ClipboardFormats.PNG))
                    {
                        pngStream = new MemoryStream();
                        // PNG works for e.g. Powerpoint
                        var pngOutputSettings = new SurfaceOutputSettings(OutputFormats.png, 100, false);
                        ImageOutput.SaveToStream(bitmapToSave, null, pngStream, pngOutputSettings);
                        pngStream.Seek(0, SeekOrigin.Begin);
                        // Set the PNG stream
                        dataObject.SetData(FORMAT_PNG, false, pngStream);
                    }
                }
                catch (Exception pngEx)
                {
                    Log.Error().WriteLine(pngEx, "Error creating PNG for the Clipboard.");
                }

                try
                {
                    if (CoreConfig.ClipboardFormats.Contains(ClipboardFormats.DIB))
                    {
                        using (var tmpBmpStream = new MemoryStream())
                        {
                            // Save image as BMP
                            var bmpOutputSettings = new SurfaceOutputSettings(OutputFormats.bmp, 100, false);
                            ImageOutput.SaveToStream(bitmapToSave, null, tmpBmpStream, bmpOutputSettings);

                            dibStream = new MemoryStream();
                            // Copy the source, but skip the "BITMAPFILEHEADER" which has a size of 14
                            dibStream.Write(tmpBmpStream.GetBuffer(), BITMAPFILEHEADER_LENGTH, (int)tmpBmpStream.Length - BITMAPFILEHEADER_LENGTH);
                        }

                        // Set the DIB to the clipboard DataObject
                        dataObject.SetData(DataFormats.Dib, true, dibStream);
                    }
                }
                catch (Exception dibEx)
                {
                    Log.Error().WriteLine(dibEx, "Error creating DIB for the Clipboard.");
                }

                // CF_DibV5
                try
                {
                    if (CoreConfig.ClipboardFormats.Contains(ClipboardFormats.DIBV5))
                    {
                        // Create the stream for the clipboard
                        dibV5Stream = new MemoryStream();

                        // 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);

                        // Set the DIBv5 to the clipboard DataObject
                        dataObject.SetData(FORMAT_17, true, dibV5Stream);
                    }
                }
                catch (Exception dibEx)
                {
                    Log.Error().WriteLine(dibEx, "Error creating DIB for the Clipboard.");
                }

                // Set the HTML
                if (CoreConfig.ClipboardFormats.Contains(ClipboardFormats.HTML))
                {
                    var tmpFile = ImageOutput.SaveToTmpFile(surface, new SurfaceOutputSettings(OutputFormats.png, 100, false), null);
                    var html    = GetHtmlString(surface, tmpFile);
                    dataObject.SetText(html, TextDataFormat.Html);
                }
                else if (CoreConfig.ClipboardFormats.Contains(ClipboardFormats.HTMLDATAURL))
                {
                    string html;
                    using (var tmpPngStream = new MemoryStream())
                    {
                        var pngOutputSettings = new SurfaceOutputSettings(OutputFormats.png, 100, false)
                        {
                            // Do not allow to reduce the colors, some applications dislike 256 color images
                            // reported with bug #3594681
                            DisableReduceColors = true
                        };
                        // Check if we can use the previously used image
                        if (bitmapToSave.PixelFormat != PixelFormat.Format8bppIndexed)
                        {
                            ImageOutput.SaveToStream(bitmapToSave, surface, tmpPngStream, pngOutputSettings);
                        }
                        else
                        {
                            ImageOutput.SaveToStream(surface, tmpPngStream, pngOutputSettings);
                        }
                        html = GetHtmlDataUrlString(surface, tmpPngStream);
                    }
                    dataObject.SetText(html, TextDataFormat.Html);
                }
            }
            finally
            {
                // we need to use the SetDataOject before the streams are closed otherwise the buffer will be gone!
                // Check if Bitmap is wanted
                if (CoreConfig.ClipboardFormats.Contains(ClipboardFormats.BITMAP))
                {
                    dataObject.SetImage(bitmapToSave);
                    // Place the DataObject to the clipboard
                    SetDataObject(dataObject, true);
                }
                else
                {
                    // Place the DataObject to the clipboard
                    SetDataObject(dataObject, true);
                }

                pngStream?.Dispose();
                dibStream?.Dispose();
                dibV5Stream?.Dispose();
                // cleanup if needed
                if (disposeImage)
                {
                    bitmapToSave?.Dispose();
                }
            }
        }
Example #2
0
        /// <summary>
        ///     Helper method to try to get an image in the specified format from the dataObject
        ///     the DIB reader should solve some issues
        ///     It also supports Format17/DibV5, by using the following information: http://stackoverflow.com/a/14335591
        /// </summary>
        /// <param name="format">string with the format</param>
        /// <param name="dataObject">IDataObject</param>
        /// <returns>Bitmap or null</returns>
        private static Bitmap GetBitmapForFormat(string format, IDataObject dataObject)
        {
            var clipboardObject = GetFromDataObject(dataObject, format);
            var imageStream     = clipboardObject as MemoryStream;

            if (!IsValidStream(imageStream))
            {
                // TODO: add "HTML Format" support here...
                return(clipboardObject as Bitmap);
            }
            if (CoreConfig.EnableSpecialDIBClipboardReader)
            {
                if (format == FORMAT_17 || format == DataFormats.Dib)
                {
                    Log.Info().WriteLine("Found DIB stream, trying to process it.");
                    try
                    {
                        if (imageStream != null)
                        {
                            var dibBuffer = new byte[imageStream.Length];
                            imageStream.Read(dibBuffer, 0, dibBuffer.Length);
                            var infoHeader = BinaryStructHelper.FromByteArray <BitmapInfoHeader>(dibBuffer);
                            if (!infoHeader.IsDibV5)
                            {
                                Log.Info().WriteLine("Using special DIB <v5 format reader with biCompression {0}", infoHeader.Compression);
                                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(dibBuffer, 0, dibBuffer.Length);
                                    bitmapStream.Seek(0, SeekOrigin.Begin);
                                    var image = BitmapHelper.FromStream(bitmapStream);
                                    if (image != null)
                                    {
                                        return(image);
                                    }
                                }
                            }
                            else
                            {
                                Log.Info().WriteLine("Using special DIBV5 / Format17 format reader");
                                // CF_DIBV5
                                var gcHandle = IntPtr.Zero;
                                try
                                {
                                    var handle = GCHandle.Alloc(dibBuffer, 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();
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception dibEx)
                    {
                        Log.Error().WriteLine(dibEx, "Problem retrieving DIB from clipboard.");
                    }
                }
            }
            else
            {
                Log.Info().WriteLine("Skipping special DIB format reader as it's disabled in the configuration.");
            }
            try
            {
                if (imageStream != null)
                {
                    imageStream.Seek(0, SeekOrigin.Begin);
                    var tmpImage = BitmapHelper.FromStream(imageStream);
                    if (tmpImage != null)
                    {
                        Log.Info().WriteLine("Got image with clipboard format {0} from the clipboard.", format);
                        return(tmpImage);
                    }
                }
            }
            catch (Exception streamImageEx)
            {
                Log.Error().WriteLine(streamImageEx, $"Problem retrieving {format} from clipboard.");
            }
            return(null);
        }