简体   繁体   中英

How can I test an image to be grayscale?

In the Aforge .net/ Accord .net library, the following test is performed to determine whether an image is grayscale:

public static bool IsGrayscale (Bitmap image)
{
    bool ret = false;

    // check pixel format
    if (image.PixelFormat == PixelFormat.Format8bppIndexed)
    {
        ret = true;
        // check palette
        ColorPalette cp = image.Palette;
        Color c;
        // init palette
        for ( int i = 0; i < 256; i++ )
        {
            c = cp.Entries[i];
            if ((c.R != i) || (c.G != i) || (c.B != i))
            {
                ret = false;
                break;
            }
        }
    }
    return ret;
}

Isn't it fallacious?

As far as the definition goes, a Grayscale image can be of any color depth except 1-bit pp. For instance, the following is a 32-bit grayscale image:

在此输入图像描述
在此输入图像描述

So, my question is, what is the proper way to test a Grayscale image?

Looks like I got my answer in this link .

If the image is a Gray Scale image then

 if(R=G=B) //Grayscale 

For more accurate results you can introduce some thresholds values. ie

 if((abs(RG)< Threshold))// Threshold-> can be greater than zero. eg 0.006 //Grayscale 

By this way you can get pretty good results.

But, I suspect, this procedure would be as slow as hell.

So, anyone with a better idea is welcome to answer.

That code is checking for standard 8-bit grayscale where the pixel values correspond to their brightness. This is more or less a standard for grayscale, but it will indeed not match optimised palettes or anything like that.

I'm not sure why you would exclude 1bpp though. It's an indexed format like any other, and in fact has a colour palette just like 8bpp, meaning it is not even limited to pure black and white. This is a 1bpp grayscale version of that parrot with two gray values in its palette:

1bpp灰​​鹦鹉

The simplest way to check indexed images is indeed to go over the palette and do the R=G=B test, but technically, even then, you could argue that the image is grayscale as long as any non-gray colours on the palette are not actually used on the image.

A sure-fire way is probably just to make LockBits convert the image to 32bppARGB, and then check the R, G and B on that. But even there you'll have to make choices... do 100% transparent pixels that don't match R=G=B make the image "not grayscale" ?

Anyway, here would be the method I'd use:

public static Boolean IsGrayscale(Bitmap cur)
{
    // Indexed format, and no non-gray colours in the images palette: immediate pass.
    if ((cur.PixelFormat & PixelFormat.Indexed) == PixelFormat.Indexed
        && cur.Palette.Entries.All(c => c.R == c.G && c.R == c.B))
        return true;
    // Quick indexed check failed; actually check image data.
    // Get bytes out of the image, converted to 32bpp ARGB 
    BitmapData curBitmapData = cur.LockBits(new Rectangle(0, 0, cur.Width, cur.Height),
        ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
    Int32 stride = curBitmapData.Stride;
    Byte[] data = new Byte[stride * cur.Height];
    Marshal.Copy(curBitmapData.Scan0, data, 0, data.Length);
    cur.UnlockBits(curBitmapData);
    // Go over all bytes per block of four.
    Int32 curRowOffs = 0;
    for (Int32 y = 0; y < cur.Height; y++)
    {
        // Set offset to start of current row
        Int32 curOffs = curRowOffs;
        for (Int32 x = 0; x < cur.Width; x++)
        {
            Byte b = data[curOffs];
            Byte g = data[curOffs + 1];
            Byte r = data[curOffs + 2];
            Byte a = data[curOffs + 3];
            // Increase offset to next colour
            curOffs += 4;
            if (a == 0)
                continue;
            if (r != g || r != b)
                return false;
        }
        // Increase row offset
        curRowOffs += stride;
    }
    return true;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM