获取位图的透明度百分比
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;
}
更新: 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;
}