获取位图的透明度百分比

Get transparency percentage of a bitmap

更新: Clemens 的解决方案是最快的。我会留下我找到的替代方案以防万一:

在尝试按照 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;
}

基本上,我应该怎么做才能从位图中获得准确的透明像素percentage/count?

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

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

您既不需要 System.Drawing.Bitmap 也不需要 WriteableBitmap 来访问 BitmapSource 中的像素值。

只需调用 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;
}