有没有一种方法,以了解通过读取映像头一个PNG图像的透明度?映像、透明度、图像、方法

由网友(奉旨勾女)分享简介:有没有办法来了解一个PNG图像透明度读取图像头?Is there a way to find out about a png image transparency by reading the image header?推荐答案随着我的评论关于 GetPixel 每个像素的表现不佳,我试着写一个片断它认为,如果有...

有没有办法来了解一个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.

阅读全文

相关推荐

最新文章