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

How to test whether pixel is white in byte array?

我正在尝试 trim 一个基于白色像素的 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;
}

由于您使用代码请求位图数据 as 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 width = source.Width;

Int32 lineStart = 0;
for (Int32 y = 0; y < height; ++y)
{
    Int32 offset = lineStart;
    for (Int32 x = 0; x < width; ++x)
    {
        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 的值,它决定了要使像素看起来足够接近白色需要所有三个颜色分量上的什么值。

当然,这还不是真正的裁剪代码,但您应该能够从那里弄明白。如果您有兴趣,我发布了一个裁剪算法 ,但该算法适用于一个特定值,而不是阈值。使用上面的代码,您可以根据自己的需要进行调整。