检查 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
?
虽然我知道之前有人问过这个问题,但我一定是做错了什么,因为这个简单的例子不起作用?它们也很旧,所以也许有一种新的更好的方法?除了这些,我还试图找到其他解决方案:
- Detecting if a PNG image file is a Transparent image?
- Check to see if image is transparent
.. 还有更多不是来自 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;
}
至少这对我有用:-)
我想我有一个简单的问题,我似乎很难弄清楚 - 如何检查我从 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
?
虽然我知道之前有人问过这个问题,但我一定是做错了什么,因为这个简单的例子不起作用?它们也很旧,所以也许有一种新的更好的方法?除了这些,我还试图找到其他解决方案:
- Detecting if a PNG image file is a Transparent image?
- Check to see if image is transparent
.. 还有更多不是来自 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;
}
至少这对我有用:-)