Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
635 views
in Technique[技术] by (71.8m points)

Check if Clipboard.GetImage() is transparent in C#

I think I have a simple problem that seems very hard for me to figure out - how to check if an image I get from Clipboard.GetImage() uses transparency. If it does then I will show it in a PictureBox with the transparent background.

I copy the picture directly from the application - e.g. the browser or one of the Windows image viewers. Pasting the picture to e.g. Word will get the transparent background.

I am using this code:

// Check if the picture in clipboard has any transparency (alpha channel != 255)
Bitmap img = new Bitmap(Clipboard.GetImage());
for (int y = 0; y < img.Height; ++y)
{
    for (int x = 0; x < img.Width; ++x)
    {
        if (img.GetPixel(x, y).A != 255)
        {
            Debug.WriteLine("Picture is transparent - set breakpoint here");
        }
    }
}
...

// Show the picture with transparent background - this works fine
img.MakeTransparent(img.GetPixel(0,0));
myPictureBox.Image = (Image)img;

I am trying with various pictures found on the net and I can copy/paste those pictures with the transparent background so I know they are transparent but no pictures will trigger the Debug.WriteLine and all values equals 255?

Though I recognize this has been asked before then I must be doing something wrong since this simple example does not work? Also they are old so maybe there is a new and better way? I have tried to find other solutions besides these:

.. and more also not from StackOverflow. I have seen both really simple solutions and horrofying complex ones - but still none of them seems to work.

is this because the clipboard object cannot see the transparency or .. ?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I ended up this solution, based on the comment from @Jeff, CopyTransparentImages. This will get the (real?) image from the clipboard (which will also include the alpha channel) and then I will check if the image contains any transparency afterwards. If it does then I will make the image background color transparent, according to my original question, before I show it in a PictureBox.

// Get the image formats from clipboard and check if it is transparent
Image imgCopy = GetImageFromClipboard();
bool isClipboardImageTransparent = IsImageTransparent(imgCopy);
if (isClipboardImageTransparent)
{
    ...
}

// Get the real image from clipboard (this supports the alpha channel)
private Image GetImageFromClipboard()
{
    if (Clipboard.GetDataObject() == null) return null;
    if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Dib))
    {

        // Sometimes getting the image data fails and results in a "System.NullReferenceException" error - probably because clipboard handling also can be messy and complex
        byte[] dib;
        try
        {
            dib = ((System.IO.MemoryStream)Clipboard.GetData(DataFormats.Dib)).ToArray();
        }
        catch (Exception ex)
        {
            return Clipboard.ContainsImage() ? Clipboard.GetImage() : null;
        }

        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;
}

// Check if the image contains any transparency
private static bool IsImageTransparent(Image image)
{
    Bitmap img = new Bitmap(image);
    for (int y = 0; y < img.Height; ++y)
    {
        for (int x = 0; x < img.Width; ++x)
        {
            if (img.GetPixel(x, y).A != 255)
            {
                return true;
            }
        }
    }
    return false;
}

At least this is working for me :-)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...