C# 获取位图的透明度百分比

C# 获取位图的透明度百分比,c#,wpf,bitmap,transparency,bitmapimage,C#,Wpf,Bitmap,Transparency,Bitmapimage,更新:克莱门斯的解决方案是最快的。我会留下我找到的备选方案,以防万一: 正如Peter Duniho在评论中所建议的那样,尝试创建一个最小的可复制示例时,我发现错误的透明度值来自BitmapImageToBitmapConverter() 这把整个形象搞砸了。现在,我将png直接加载到位图并扫描它,它会给出准确的结果: Bitmap bmp = new Bitmap("icon.png"); Console.WriteLine(TransparencyPercentageInImage(bmp)

更新:克莱门斯的解决方案是最快的。我会留下我找到的备选方案,以防万一:

正如Peter Duniho在评论中所建议的那样,尝试创建一个最小的可复制示例时,我发现错误的透明度值来自
BitmapImageToBitmapConverter()
这把整个形象搞砸了。现在,我将png直接加载到位图并扫描它,它会给出准确的结果:

Bitmap bmp = new Bitmap("icon.png");
Console.WriteLine(TransparencyPercentageInImage(bmp));
问题是:

我在列表中有几个图像控件:

imagesList[index].Source = ReloadIcon(index);
它们从“.png”文件加载图像,如下所示:

public BitmapImage ReloadIcon(int index)
        {
            var image = new BitmapImage();
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.CreateOptions = BitmapCreateOptions.IgnoreImageCache;
            image.UriSource = new Uri(iconPaths[index], UriKind.Absolute);
            image.EndInit();
            return image;
        }
然后,我使用此转换器将其转换为位图:

private Bitmap BitmapImageToBitmapConverter(BitmapImage bitmapImage)      
{
    using (MemoryStream outStream = new MemoryStream())
    {
        BitmapEncoder enc = new BmpBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(bitmapImage));
        enc.Save(outStream);
        System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(outStream);

        return new Bitmap(bitmap);
    }
}
要稍后使用此代码扫描每个像素的透明度,请执行以下操作:

private double TransparencyPercentageInImage(Bitmap image)
{
    double transpPercentage;
    double transpPixelCount = 0;
    double totalPixelCount = image.Height * image.Width;
    Console.WriteLine("Total pixel count: " + totalPixelCount);

    for (int y = 0; y < image.Height; ++y)
    {
        for (int x = 0; x < image.Width; ++x)
        {
            if (image.GetPixel(x, y).A == 0) //or !=255
            {
                transpPixelCount++;
            }
        }
    }

    transpPercentage = transpPixelCount / totalPixelCount * 100;
    return transpPercentage;
}
private双透明图像(位图图像)
{
双百分比;
双像素计数=0;
double totalPixelCount=image.Height*image.Width;
Console.WriteLine(“总像素计数:+totalPixelCount”);
对于(int y=0;y
基本上,如何从位图中获得准确的透明像素百分比/计数

我在寻找绝对透明像素的计数,而不是半透明像素


我并不是真的在寻找速度,所以任何解决方案都是可行的。我已经在使用不安全的代码,所以也欢迎使用。

您既不需要
系统.Drawing.Bitmap
也不需要
可写位图来访问位图源中的像素值

只需调用
CopyPixels
即可获得像素缓冲区,并使用alpha值0对像素进行计数。首先确保以所需格式访问缓冲区:

private double GetTransparentPixelsPercentage(BitmapSource bitmap)
{
    if (bitmap.Format != PixelFormats.Bgra32)
    {
        bitmap = new FormatConvertedBitmap(bitmap, PixelFormats.Bgra32, null, 0);
    }

    var pixelCount = bitmap.PixelWidth * bitmap.PixelHeight;
    var pixels = new byte[4 * pixelCount];

    bitmap.CopyPixels(pixels, 4 * bitmap.PixelWidth, 0);

    var transparentPixelCount = 0;

    for (var i = 3; i < 4 * pixelCount; i += 4) // start at first alpha value
    {
        if (pixels[i] == 0)
        {
            transparentPixelCount++;
        }
    }

    return (double)transparentPixelCount / pixelCount;
}
private double getTransparentPixelPercentage(位图源位图)
{
if(bitmap.Format!=PixelFormats.Bgra32)
{
位图=新格式转换位图(位图,PixelFormats.Bgra32,null,0);
}
var pixelCount=bitmap.PixelWidth*bitmap.PixelHeight;
var像素=新字节[4*像素计数];
位图.CopyPixels(像素,4*bitmap.PixelWidth,0);
var transparentPixelCount=0;
对于(var i=3;i<4*pixelCount;i+=4)//从第一个alpha值开始
{
如果(像素[i]==0)
{
透明像素计数++;
}
}
返回(双)透明像素计数/像素计数;
}

为什么不将图像转换为32bpp位图并扫描alpha通道?如果我理解正确,我会将图像转换为32bpp,然后使用
image.GetPixel
以与我相同的方式扫描?我是否仍应使用
MakeTransparent()
?如果可能的话,还可以为我提供一些关于32bpp转换的参考资料或代码,以及您的总体建议。我明天就试试。
GetPixel
太慢了。最好将图像转换为
WriteableBitmap
,并直接访问图像数据。例如,请参阅。如果您需要堆栈溢出的帮助,您需要改进您的问题。提供一个很好的例子。另一方面,你需要更好地解释你的目标。PNG文件上下文中的“透明度”不是二进制内容。每个像素的alpha值范围从0%透明到100%透明。您似乎想要一个“平均透明度”结果,但这需要平均每个像素的所有alpha分量,而不仅仅是寻找0个alpha值。也不清楚为什么你们都要创建
transpColorValue
;你只会给它添加值,而不会像直接从位图图像中使用符咒一样使用这些值。非常感谢。