有没有一种方法,以了解通过读取映像头一个PNG图像的透明度? [英] Is there a way to find out about a png image transparency by reading the image header?

查看:194
本文介绍了有没有一种方法,以了解通过读取映像头一个PNG图像的透明度?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

这篇关于有没有一种方法,以了解通过读取映像头一个PNG图像的透明度?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆