Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reliable way to check if image is Grey scale

I am currently working on one use case where i need to determine if uploaded image is Grey Scale or RGB. I found couple of ways to identify this, but not sure if they are reliable and can be used collectively to confirm image is grey scale or not.

Part 1: Read Image and get NumberDataElements using Raster.

BufferedImage image = ImageIO.read(file);
        Raster ras = image.getRaster();
        int elem = ras.getNumDataElements();

I observed value of elem is "1" in some cases, but not in all.

Part 2: Check RGB value of each pixel. If R , G, B value is same of given pixel.

BufferedImage image = ImageIO.read(file);
        Raster ras = image.getRaster();

        //Number of Color elements
        int elem = ras.getNumDataElements();

        int width = image.getWidth();
        int height = image.getHeight();

        int pixel,red, green, blue;

        for (int i = 0; i < width; i++)
            for (int j = 0; j < height; j++) {
                //scan through each pixel
                pixel = image.getRGB(i, j);
                red = (pixel >> 16) & 0xff;
                green = (pixel >> 8) & 0xff;
                blue = (pixel) & 0xff;

                //check if R=G=B
                if (red != green || green != blue ) {
                    flag = true;
                    break;
                }


            }

Here i check R, G,B values are same for any given pixel and this behavior is consistent across all pixels.

I am using these 2 approaches, but not sure how accurate they are. Kindly suggest..

like image 791
Dark Knight Avatar asked Oct 19 '22 13:10

Dark Knight


2 Answers

Move your if (flag) { break; } line outside of the inner for loop.

And you only need to check that (red != green || green != blue). Breaking any one of these two equalities ensures that the third MUST be broken, so you only require two checks.

I'd also possibly just set an isGrayscale variable of boolean to true and then set it to false, when the equality logic breaks, rather than setting a flag to true. It should be assumed to be grayscale, until it breaks and becomes false. No problem with what you have here with flag, but this is a little more meaningful and intuitive.

If you want to get really clever, you could allow for a delta of variance to allow for images that are SUFFICIENTLY grayscale for purpose i.e. their deviance from equality is lower than a set barrier. But this works as it is :)

like image 157
ManoDestra Avatar answered Oct 21 '22 04:10

ManoDestra


Below approach is worked for me. Thanks guys for help.

BufferedImage image = ImageIO.read(file);
        Raster ras = image.getRaster();

        //Number of Color elements
        int elem = ras.getNumDataElements();

        int width = image.getWidth();
        int height = image.getHeight();

        int pixel,red, green, blue;

        for (int i = 0; i < width; i++)
            for (int j = 0; j < height; j++) {
                //scan through each pixel
                pixel = image.getRGB(i, j);
                red = (pixel >> 16) & 0xff;
                green = (pixel >> 8) & 0xff;
                blue = (pixel) & 0xff;

                //check if R=G=B
                if (red != green || green != blue ) {
                    flag = true;
                    break;
                }


            }
like image 24
Dark Knight Avatar answered Oct 21 '22 06:10

Dark Knight