Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to paste a transparent image from the clipboard in a C# winforms app?

Note: This question is about pasting from the clipboard, not copying to the clipboard. There are several posts about copying to the clipboard, but couldn't find one that addresses this question.

How can I paste an image with transparency, for example this one, into a winforms app and retain transparency?

I have tried using System.Windows.Forms.GetImage(), but that produces a bitmap with a black background.

I am copying this image from Google Chrome, which supports several clipboard formats, including DeviceIndependentBitmap and Format17.

like image 912
bright Avatar asked Jun 30 '12 11:06

bright


People also ask

How do I copy and paste a transparent image in Photoshop?

png , the Shift + Ctrl + F12 key combination is sent to Photoshop, which I have mapped to a Photoshop Action to place the clip. png file into the currently open document. If the utility did not save the image, the standard Ctrl + V key combo is sent to Photoshop and a standard paste is performed.

How do I paste a transparent image in paint?

With the image selected, click on the down arrow present below the Select option. Choose Transparent selection. Voila!


2 Answers

Chrome copies the image to the clipboard in a 24bpp format. Which turns the transparency into black. You can get a 32bpp format out of the clipboard but that requires handling the DIB format. There's no built-in support for that in System.Drawing, you need a little helper function that make the conversion:

    private Image GetImageFromClipboard() {
        if (Clipboard.GetDataObject() == null) return null;
        if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Dib)) {
            var dib = ((System.IO.MemoryStream)Clipboard.GetData(DataFormats.Dib)).ToArray();
            var width = BitConverter.ToInt32(dib, 4);
            var height = BitConverter.ToInt32(dib, 8);
            var bpp = BitConverter.ToInt16(dib, 14);
            if (bpp == 32) {
                var gch = GCHandle.Alloc(dib, GCHandleType.Pinned);
                Bitmap bmp = null;
                try {
                    var ptr = new IntPtr((long)gch.AddrOfPinnedObject() + 40);
                    bmp = new Bitmap(width, height, width * 4, System.Drawing.Imaging.PixelFormat.Format32bppArgb, ptr);
                    return new Bitmap(bmp);
                }
                finally {
                    gch.Free();
                    if (bmp != null) bmp.Dispose();
                }
            }
        }
        return Clipboard.ContainsImage() ? Clipboard.GetImage() : null;
    }

Sample usage:

    protected override void OnPaint(PaintEventArgs e) {
        using (var bmp = GetImageFromClipboard()) {
            if (bmp != null) e.Graphics.DrawImage(bmp, 0, 0);
        }
    }

Which produced this screen-shot with the form's BackgroundImage property set to a stock bitmap:

enter image description here

like image 190
Hans Passant Avatar answered Sep 22 '22 01:09

Hans Passant


(I can't comment answers)

Answer of Hans Passant is good, but not correct.

Screenshot saved with this code.

You need to replace var ptr = new IntPtr((long)gch.AddrOfPinnedObject() + 40); with var ptr = new IntPtr((long)gch.AddrOfPinnedObject() + 52);

Screenshot saved with correct code.

Also you need flip image vertically

like image 22
Andrey059918 Avatar answered Sep 22 '22 01:09

Andrey059918