首页 > 解决方案 > 检查 Clipboard.GetImage() 在 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;

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

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

.. 还有更多也不是来自 StackOverflow。我见过非常简单的解决方案和可怕的复杂解决方案——但它们似乎都不起作用。

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

标签: c#clipboard

解决方案


根据@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;
}

至少这对我有用:-)


推荐阅读