我正在尝试根据白色像素修剪Bitmap
。我想高效地做到这一点,所以避免使用.GetPixel
我正在实施this question中标记为正确的答案。在答案中,它们检测字节数组中的像素是否透明。我想用一个阈值来检测像素是否为白色(因此,如果白色小于阈值,则foundPixel=true;
。
我在这里提取了相关代码:
static Bitmap TrimBitmap(Bitmap source)
{
BitmapData data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] buffer = new byte[data.Height * data.Stride];
Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);
...
}
检测alpha像素代码(这是我需要的帮助):
byte alpha = buffer[y * data.Stride + 4 * x + 3];
if (alpha != 0)
{
foundPixel = true;
break;
}
答案 0 :(得分:0)
由于您要使用代码请求位格式为Format32bppArgb的位图数据,因此生成的字节将始终为4字节ARGB格式。由于这是指小尾数Uint32
,因此字节中的实际颜色分量按B,G,R,A的顺序排列。
要检查白色,您只需要检查B,G,R字节,而不是A:
BitmapData data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
byte[] buffer = new byte[data.Height * data.Stride];
Marshal.Copy(data.Scan0, buffer, 0, buffer.Length);
Int32 stride = data.Stride;
source.UnlockBits(data);
Int32 height = source.Height;
Int32 lineStart = 0;
for (Int32 y = 0; y < height; ++y)
{
Int32 offset = lineStart;
for (Int32 x = 0; x < stride; x += 4)
{
byte blue = buffer[offset + 0];
byte green = buffer[offset + 1];
byte red = buffer[offset + 2];
//byte alpha = buffer[offset + 3];
if (blue > threshold && green > threshold && red > threshold)
{
// is white pixel.
}
offset += 4;
}
lineStart += stride;
}
threshold
的值接近于255,该值确定像素在所有三种颜色分量上都应与白色足够接近的值。
当然,这还不是真正的裁剪代码,但是您应该可以从那里弄清楚。如果您有兴趣,我发布了一种裁剪算法here,但该算法只适用于一个特定值,而不适用于阈值。使用上面的代码,您可以适应您的需求。