如何测试字节数组中的像素是否为白色?

时间:2019-06-14 13:45:22

标签: c# arrays graphics bitmap drawing

我正在尝试根据白色像素修剪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;
}

1 个答案:

答案 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,但该算法只适用于一个特定值,而不适用于阈值。使用上面的代码,您可以适应您的需求。