Example #1
0
        /// <summary>
        /// the DIB readed should solve the issue reported here: https://sourceforge.net/projects/greenshot/forums/forum/676083/topic/6354353/index/page/1
        /// </summary>
        /// <returns>Image</returns>
        private static Image GetDIBImage(IDataObject dataObejct)
        {
            try {
                // If the EnableSpecialDIBClipboardReader flag in the config is set, use the code from:
                // http://www.thomaslevesque.com/2009/02/05/wpf-paste-an-image-from-the-clipboard/
                // to read the DeviceIndependentBitmap from the clipboard, this might fix bug 3576125
                if (config.EnableSpecialDIBClipboardReader)
                {
                    MemoryStream dibStream = GetFromDataObject(dataObejct, DataFormats.Dib) as MemoryStream;
                    if (isValidStream(dibStream))
                    {
                        LOG.Info("Found valid DIB stream, trying to process it.");
                        byte[] dibBuffer = new byte[dibStream.Length];
                        dibStream.Read(dibBuffer, 0, dibBuffer.Length);
                        BitmapInfoHeader infoHeader = BinaryStructHelper.FromByteArray <BitmapInfoHeader>(dibBuffer);
                        LOG.InfoFormat("Using special DIB format reader for biCompression {0}", infoHeader.biCompression);
                        int  fileHeaderSize = Marshal.SizeOf(typeof(BitmapFileHeader));
                        uint infoHeaderSize = infoHeader.biSize;
                        int  fileSize       = (int)(fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage);

                        BitmapFileHeader fileHeader = new BitmapFileHeader();
                        fileHeader.bfType      = BitmapFileHeader.BM;
                        fileHeader.bfSize      = fileSize;
                        fileHeader.bfReserved1 = 0;
                        fileHeader.bfReserved2 = 0;
                        fileHeader.bfOffBits   = (int)(fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4);

                        byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray <BitmapFileHeader>(fileHeader);

                        using (MemoryStream bitmapStream = new MemoryStream()) {
                            bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
                            bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
                            bitmapStream.Seek(0, SeekOrigin.Begin);
                            using (Image tmpImage = Image.FromStream(bitmapStream)) {
                                if (tmpImage != null)
                                {
                                    return(ImageHelper.Clone(tmpImage));
                                }
                            }
                        }
                    }
                }
                else
                {
                    LOG.Info("Skipping special DIB format reader as it's disabled in the configuration.");
                }
            } catch (Exception dibEx) {
                LOG.Error("Problem retrieving DIB from clipboard.", dibEx);
            }
            return(null);
        }
Example #2
0
        public static void SetClipboardData(ISurface surface)
        {
            DataObject 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;
            Image        imageToSave  = null;
            bool         disposeImage = false;

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

                try
                {
                    if (config.ClipboardFormats.Contains(ClipboardFormat.DIB))
                    {
                        using (MemoryStream tmpBmpStream = new MemoryStream())
                        {
                            // Save image as BMP
                            SurfaceOutputSettings bmpOutputSettings = new SurfaceOutputSettings(OutputFormat.bmp, 100, false);
                            ImageOutput.SaveToStream(imageToSave, 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("Error creating DIB for the Clipboard.", dibEx);
                }

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

                        // Create the BITMAPINFOHEADER
                        BITMAPINFOHEADER header = new BITMAPINFOHEADER(imageToSave.Width, imageToSave.Height, 32);
                        // Make sure we have BI_BITFIELDS, this seems to be normal for Format17?
                        header.biCompression = BI_COMPRESSION.BI_BITFIELDS;
                        // Create a byte[] to write
                        byte[] headerBytes = BinaryStructHelper.ToByteArray <BITMAPINFOHEADER>(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
                        BitfieldColorMask colorMask = new BitfieldColorMask();
                        // Make sure the values are set
                        colorMask.InitValues();
                        // Create the byte[] from the struct
                        byte[] colorMaskBytes = BinaryStructHelper.ToByteArray <BitfieldColorMask>(colorMask);
                        Array.Reverse(colorMaskBytes);
                        // Write to the stream
                        dibV5Stream.Write(colorMaskBytes, 0, colorMaskBytes.Length);

                        // Create the raw bytes for the pixels only
                        byte[] bitmapBytes = BitmapToByteArray((Bitmap)imageToSave);
                        // 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("Error creating DIB for the Clipboard.", dibEx);
                }

                // Set the HTML
                if (config.ClipboardFormats.Contains(ClipboardFormat.HTML))
                {
                    string tmpFile = ImageOutput.SaveToTmpFile(surface, new SurfaceOutputSettings(OutputFormat.png, 100, false), null);
                    string html    = getHTMLString(surface, tmpFile);
                    dataObject.SetText(html, TextDataFormat.Html);
                }
                else if (config.ClipboardFormats.Contains(ClipboardFormat.HTMLDATAURL))
                {
                    string html;
                    using (MemoryStream tmpPNGStream = new MemoryStream())
                    {
                        SurfaceOutputSettings pngOutputSettings = new SurfaceOutputSettings(OutputFormat.png, 100, false);
                        // Do not allow to reduce the colors, some applications dislike 256 color images
                        // reported with bug #3594681
                        pngOutputSettings.DisableReduceColors = true;
                        // Check if we can use the previously used image
                        if (imageToSave.PixelFormat != PixelFormat.Format8bppIndexed)
                        {
                            ImageOutput.SaveToStream(imageToSave, 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 (config.ClipboardFormats.Contains(ClipboardFormat.BITMAP))
                {
                    dataObject.SetImage(imageToSave);
                    // Place the DataObject to the clipboard
                    SetDataObject(dataObject, true);
                }
                else
                {
                    // Place the DataObject to the clipboard
                    SetDataObject(dataObject, true);
                }

                if (pngStream != null)
                {
                    pngStream.Dispose();
                    pngStream = null;
                }

                if (dibStream != null)
                {
                    dibStream.Dispose();
                    dibStream = null;
                }
                if (dibV5Stream != null)
                {
                    dibV5Stream.Dispose();
                    dibV5Stream = null;
                }
                // cleanup if needed
                if (disposeImage && imageToSave != null)
                {
                    imageToSave.Dispose();
                }
            }
        }
Example #3
0
        /// <summary>
        /// Helper method to try to get an image in the specified format from the dataObject
        /// the DIB readed should solve the issue reported here: https://sourceforge.net/projects/greenshot/forums/forum/676083/topic/6354353/index/page/1
        /// 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>Image or null</returns>
        private static Image GetImageForFormat(string format, IDataObject dataObject)
        {
            object       clipboardObject = GetFromDataObject(dataObject, format);
            MemoryStream imageStream     = clipboardObject as MemoryStream;

            if (!isValidStream(imageStream))
            {
                // TODO: add "HTML Format" support here...
                return(clipboardObject as Image);
            }
            else
            {
                if (config.EnableSpecialDIBClipboardReader)
                {
                    if (format == FORMAT_17 || format == DataFormats.Dib)
                    {
                        LOG.Info("Found DIB stream, trying to process it.");
                        try
                        {
                            byte[] dibBuffer = new byte[imageStream.Length];
                            imageStream.Read(dibBuffer, 0, dibBuffer.Length);
                            BITMAPINFOHEADER infoHeader = BinaryStructHelper.FromByteArray <BITMAPINFOHEADER>(dibBuffer);
                            if (!infoHeader.IsDibV5)
                            {
                                LOG.InfoFormat("Using special DIB <v5 format reader with biCompression {0}", infoHeader.biCompression);
                                int  fileHeaderSize = Marshal.SizeOf(typeof(BITMAPFILEHEADER));
                                uint infoHeaderSize = infoHeader.biSize;
                                int  fileSize       = (int)(fileHeaderSize + infoHeader.biSize + infoHeader.biSizeImage);

                                BITMAPFILEHEADER fileHeader = new BITMAPFILEHEADER();
                                fileHeader.bfType      = BITMAPFILEHEADER.BM;
                                fileHeader.bfSize      = fileSize;
                                fileHeader.bfReserved1 = 0;
                                fileHeader.bfReserved2 = 0;
                                fileHeader.bfOffBits   = (int)(fileHeaderSize + infoHeaderSize + infoHeader.biClrUsed * 4);

                                byte[] fileHeaderBytes = BinaryStructHelper.ToByteArray <BITMAPFILEHEADER>(fileHeader);

                                using (MemoryStream bitmapStream = new MemoryStream())
                                {
                                    bitmapStream.Write(fileHeaderBytes, 0, fileHeaderSize);
                                    bitmapStream.Write(dibBuffer, 0, dibBuffer.Length);
                                    bitmapStream.Seek(0, SeekOrigin.Begin);
                                    using (Image tmpImage = Image.FromStream(bitmapStream))
                                    {
                                        if (tmpImage != null)
                                        {
                                            return(ImageHelper.Clone(tmpImage));
                                        }
                                    }
                                }
                            }
                            else
                            {
                                LOG.Info("Using special DIBV5 / Format17 format reader");
                                // CF_DIBV5
                                IntPtr gcHandle = IntPtr.Zero;
                                try
                                {
                                    GCHandle handle = GCHandle.Alloc(dibBuffer, GCHandleType.Pinned);
                                    gcHandle = GCHandle.ToIntPtr(handle);
                                    return(new Bitmap(infoHeader.biWidth, infoHeader.biHeight, -(int)(infoHeader.biSizeImage / infoHeader.biHeight),
                                                      infoHeader.biBitCount == 32 ? PixelFormat.Format32bppArgb : PixelFormat.Format24bppRgb,
                                                      new IntPtr(handle.AddrOfPinnedObject().ToInt32() + infoHeader.OffsetToPixels + (infoHeader.biHeight - 1) * (int)(infoHeader.biSizeImage / infoHeader.biHeight))));
                                }
                                catch (Exception ex)
                                {
                                    LOG.Error("Problem retrieving Format17 from clipboard.", ex);
                                }
                                finally
                                {
                                    if (gcHandle == IntPtr.Zero)
                                    {
                                        GCHandle.FromIntPtr(gcHandle).Free();
                                    }
                                }
                            }
                        }
                        catch (Exception dibEx)
                        {
                            LOG.Error("Problem retrieving DIB from clipboard.", dibEx);
                        }
                    }
                }
                else
                {
                    LOG.Info("Skipping special DIB format reader as it's disabled in the configuration.");
                }
                try
                {
                    imageStream.Seek(0, SeekOrigin.Begin);
                    using (Image tmpImage = Image.FromStream(imageStream, true, true))
                    {
                        if (tmpImage != null)
                        {
                            LOG.InfoFormat("Got image with clipboard format {0} from the clipboard.", format);
                            return(ImageHelper.Clone(tmpImage));
                        }
                    }
                }
                catch (Exception streamImageEx)
                {
                    LOG.Error(string.Format("Problem retrieving {0} from clipboard.", format), streamImageEx);
                }
            }
            return(null);
        }