有没有办法来了解一个PNG图像透明度读取图像头?
Is there a way to find out about a png image transparency by reading the image header?
推荐答案
随着我的评论关于 GetPixel
每个像素的表现不佳,我试着写一个片断它认为,如果有透明的像素或不图像(包括PNG )。在这里,它是。
Binary access
Following my comment about the poor performance of GetPixel
for each pixel, I tried to write a snippet which finds if there are transparent pixels or not in an image (including PNG). Here it is.
public static bool IsImageTransparent(string fullName)
{
using (Bitmap bitmap = Bitmap.FromFile(fullName) as Bitmap)
{
bool isTransparent;
// Not sure if the following enumeration is correct. Maybe some formats do not actually allow transparency.
PixelFormat[] formatsWithAlpha = new[] { PixelFormat.Indexed, PixelFormat.Gdi, PixelFormat.Alpha, PixelFormat.PAlpha, PixelFormat.Canonical, PixelFormat.Format1bppIndexed, PixelFormat.Format4bppIndexed, PixelFormat.Format8bppIndexed, PixelFormat.Format16bppArgb1555, PixelFormat.Format32bppArgb, PixelFormat.Format32bppPArgb, PixelFormat.Format64bppArgb, PixelFormat.Format64bppPArgb };
if (formatsWithAlpha.Contains(bitmap.PixelFormat))
{
// There might be transparency.
BitmapData binaryImage = bitmap.LockBits(new Rectangle(Point.Empty, bitmap.Size), ImageLockMode.ReadOnly, PixelFormat.Format64bppArgb);
unsafe
{
byte* pointerToImageData = (byte*)binaryImage.Scan0;
int numberOfPixels = bitmap.Width * bitmap.Height;
isTransparent = false;
// 8 bytes = 64 bits, since our image is 64bppArgb.
for (int i = 0; i < numberOfPixels * 8; i += 8)
{
// Check the last two bytes (transparency channel). First six bytes are for R, G and B channels. (0, 32) means 100% opacity.
if (pointerToImageData[i + 6] != 0 || pointerToImageData[i + 7] != 32)
{
isTransparent = true;
break;
}
}
}
bitmap.UnlockBits(binaryImage);
}
else
{
// No transparency available for this image.
isTransparent = false;
}
return isTransparent;
}
}
优点:
在二进制访问,比 GetPixel
快得多,
在不需要额外的库也不是WPF,
工作与GDI支持任何格式+:BMP,GIF,JPEG,PNG,TIFF的EXIF,WMF,EMF和
Binary access, much faster than GetPixel
,
Does not require additional libraries nor WPF,
Works with any format supported by GDI+: BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF.
缺点:
需要不安全
,
比直接读取PNG文件时速度较慢。
一个减少人工的方法是使用调色板。可能有可能存在着一些.NET框架或让你这么做的第三方库。我尝试了以下(使用WPF):
A less manual approach would be to use palettes. There might probably exist some .NET Framework or third party libraries which let you do that. I tried the following (using WPF):
using (Stream imageStreamSource = new FileStream(fullName, FileMode.Open, FileAccess.Read, FileShare.Read))
{
PngBitmapDecoder decoder = new PngBitmapDecoder(imageStreamSource, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource = decoder.Frames[0];
return bitmapSource.Palette.Colors.Any(c => c.A != 0);
}
但是我不能正常工作,因为 bitmapSource.Palette
是空
最时间。此外,使用调色板将在很大程度上降低性能,相比第一片段,因为每个颜色都必须加载到颜色列表,然后再继续。
but I does not work, since bitmapSource.Palette
is null
most of the time. Further, using palettes will heavily decrease performance, compared to the first snippet, since every color must be loaded into a list of colors before proceeding.
相关推荐
最新文章