检查 Clipboard.GetImage() 在 C# 中是否透明

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

我想我有一个简单的问题,我似乎很难弄清楚 - 如何检查我从 Clipboard.GetImage() 获得的图像是否使用透明度 。如果是,那么我将在具有透明背景的 PictureBox 中显示它。

我直接从应用程序复制图片 - 例如浏览器或 Windows 图片查看器之一。将图片粘贴到例如Word 将获得透明背景。

我正在使用此代码:

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

我正在尝试使用在网上找到的各种图片,我可以 copy/paste 那些具有透明背景的图片,所以我知道它们是透明的,但没有图片会触发 Debug.WriteLine 并且所有值都等于255?

虽然我知道之前有人问过这个问题,但我一定是做错了什么,因为这个简单的例子不起作用?它们也很旧,所以也许有一种新的更好的方法?除了这些,我还试图找到其他解决方案:

.. 还有更多不是来自 Whosebug。我已经看到了非常简单的解决方案和可怕的复杂解决方案 - 但其中 none 似乎仍然有效。

这是因为剪贴板对象看不到透明度还是..?

根据@Jeff CopyTransparentImages 的评论,我最终得出了这个解决方案。这将从剪贴板获取(真实的?)图像(其中还将包括 alpha 通道),然后我将检查图像是否包含任何透明度。如果是这样,那么根据我最初的问题,在 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;
}

至少这对我有用:-)