Detecting if image taken by camera is too dark I am trying to build functionality to check if an image taken by the camera is too dark. So I added the following 2 functions to a utility class: 

public static boolean checkIfImageIsTooDark(BitmapRegionDecoder bitmapRegionDecoder)
{
    if(bitmapRegionDecoder == null) {
        Timber.e("Expected bitmapRegionDecoder was null");
        return false;
    }

    int loadingBitmapHeight = bitmapRegionDecoder.getHeight();
    int loadingBitmapWidth = bitmapRegionDecoder.getWidth();

    boolean isImageTooDark = true;

    int checkBitmapWidth = loadingBitmapWidth / 10;
    int checkBitmapHeight = loadingBitmapHeight / 10;
    int topBitmapPosition = 0;
    int leftBitmapPosition = 0;

    while((checkBitmapWidth &lt;= loadingBitmapWidth) &amp;&amp; (leftBitmapPosition &lt; checkBitmapWidth)) {
        while((checkBitmapHeight &lt;= loadingBitmapHeight) &amp;&amp; (topBitmapPosition &lt; checkBitmapHeight)) {
            Rect bitmapRect = new Rect(leftBitmapPosition,topBitmapPosition,checkBitmapWidth,checkBitmapHeight);
            Timber.d("left: " + leftBitmapPosition + " right: " + checkBitmapWidth + " top: " + topBitmapPosition + " bottom: " + checkBitmapHeight);

            Bitmap processBitmap = bitmapRegionDecoder.decodeRegion(bitmapRect,null);

            if(!checkIfImageIsTooDark(processBitmap)) {
                isImageTooDark = false;
                break;
            }

            topBitmapPosition = checkBitmapHeight;
            checkBitmapHeight += (checkBitmapHeight &lt; (loadingBitmapHeight - checkBitmapHeight)) ? checkBitmapHeight : (loadingBitmapHeight - checkBitmapHeight);
        }

        if(!isImageTooDark) {
            break;
        }

        topBitmapPosition = 0; 
        checkBitmapHeight = loadingBitmapHeight / 10; 
        leftBitmapPosition = checkBitmapWidth;
        checkBitmapWidth += (checkBitmapWidth &lt; (loadingBitmapWidth - checkBitmapWidth)) ? checkBitmapWidth : (loadingBitmapWidth - checkBitmapWidth);
    }

    return isImageTooDark;
}

public static boolean checkIfImageIsTooDark(Bitmap bitmap) {
    if(bitmap == null)
    {
        Timber.e("Expected bitmap was null");
        return false;
    }

    int[] brightnessHistogram = new int[256];

    for(int i = 0; i &lt; bitmap.getHeight(); i++) {
        for(int j = 0; j &lt; bitmap.getWidth(); j++) {
            int pixel = bitmap.getPixel(j,i);

            int r = Color.red(pixel);
            int g = Color.green(pixel);
            int b = Color.blue(pixel);

            int brightness = (int)(0.2126 * r + 0.7152 * g + 0.0722 * b);
            brightnessHistogram[brightness]++;
        }
    }

    int allPixelsCount = bitmap.getWidth() * bitmap.getHeight();

    //counting pixels with brightness less than 10
    int darkPixelCount = 0;
    for(int i = 0; i &lt; 10; i++)
    {
        darkPixelCount += brightnessHistogram[i];
    }

    //if more than 70% pixels are too dark then image is too dark
    return darkPixelCount &gt; allPixelsCount * 0.70;
}


The brightness histogram approach I found over here -> https://stackoverflow.com/a/35914745/3287853. And it works quite well. 

The only problem however is that processing an image takes way too much time. I tried it on my phone which produces 4160x3120 and it takes close to a minute to get a result off it. Also, the 4 loops don't look great and I think there should be a better way to make this work, personally. 

I am using an AsyncTask to do this in the background so one improvement that I could think of is to break up the task across multiple threads.

I could also compress the image initially bringing it down to a certain limit of width and height while attempting to maintain its aspect ratio and then process the image. However I wonder if that would actually help in reducing the amount of time taken at all.
Sampling: Don't process ALL pixels

The speed mainly depend on the number of operations, in our case, pixels. And a lot of pixels. This means that the larger the image is, the slower your code will run.

You probably don't need to process all pixels, just a representative subset of them.

Taking this subset is called sampling. You can for example only process every 100th pixel. 

If you want to go more fancy, try Monte Carlo sampling.

If you really need all the pixels, check OpenCV, that is optimized for image processing.