Is it posible to know the brightness of a picture in Flutter?

0

I am building an application which has a Camera inside.

After I take a photo, I want to analyze it to know the brightness of this picture, if it is bad I have to take again the photo.

This is my code right now, it's a javascript function that I found and writing in Dart:

Thanks to @Abion47

EDIT 1

for (int i = 0; i < pixels.length; i++) {
      int pixel = pixels[i];
      int b = (pixel & 0x00FF0000) >> 16;
      int g = (pixel & 0x0000FF00) >> 8;
      int r = (pixel & 0x000000FF);

      avg = ((r + g + b) / 3).floor();
      colorSum += avg;
    }

    brightness = (colorSum / (width * height)).floor();
}

brightness = (colorSum / (width * height)).round();
// I tried with this other code
//brightness = (colorSum / pixels.length).round();

return brightness;

But I've got less brightness on white than black, the numbers are a little bit weird.

Do you know a better way to know the brightness?

SOLUTION:

Under further investigation we found the solution, we had an error doing the image decoding, but we used a Image function to do it.

Here is our final code:

Image image = decodeImage(file.readAsBytesSync());
    var data = image.getBytes();
    var colorSum = 0;
    for(var x = 0; x < data.length; x += 4) {
      int r = data[x];
      int g = data[x + 1];
      int b = data[x + 2];
      int avg = ((r + g + b) / 3).floor();
      colorSum += avg;
    }
    var brightness = (colorSum / (image.width * image.height)).floor();
    return brightness;

Hope it helps you.

image
flutter
dart
camera
brightness
asked on Stack Overflow Oct 14, 2020 by Nicolas Lucero • edited Nov 3, 2020 by Nicolas Lucero

1 Answer

1

There are several things wrong with your code.

First, you are getting a range error because you are attempting to access a pixel that doesn't exist. This is probably due to width and/or height being greater than the image's actual width or height. There are a lot of ways to try and get these values, but for this application it doesn't actually matter since the end result is to get an average value across all pixels in the image, and you don't need the width or height of the image for that.

Second, you are fetching the color values by serializing the color value into a hex string and then parsing the individual channel substrings. Your substring is going to result in incorrect values because:

  • foo.substring(a, b) takes the substring of foo from a to b, exclusive. That means that a and b are indices, not lengths, and the resulting string will not include the character at b. So assuming hex is "01234567", when you do hex.substring(0, 2), you get "01", and then you do hex.substring(3, 5) you get "34" while hex.substring(6, 8) gets you "67". You need to do hex.substring(0, 2) followed by hex.substring(2, 4) and hex.substring(4, 6) to get the first three channels.
  • That being said, you are fetching the wrong channels. The image package stores its pixel values in ABGR format, meaning the first two characters in the hex string are going to be the alpha channel which is unimportant when calculating image brightness. Instead, you want the second, third, and forth channels for the blue, green, and red values respectively.
  • And having said all that, this is an extremely inefficient way to do this anyway when the preferred way to retrieve channel data from an integer color value is with bitwise operations on the integer itself. (Never convert a number to a string or vice versa unless you absolutely have to.)

So in summary, what you want will likely be something akin to the following;

final pixels = image.data;
double colorSum = 0;

for (int i = 0; i < pixels.length; i++) {
  int pixel = pixels[i];
  int b = (pixel & 0x00FF0000) >> 16;
  int g = (pixel & 0x0000FF00) >> 8;
  int r = (pixel & 0x000000FF);
  avg = (r + g + b) / 3;
  colorSum += avg;
}

return colorSum / pixels.length;
answered on Stack Overflow Oct 14, 2020 by Abion47 • edited Oct 14, 2020 by Abion47

User contributions licensed under CC BY-SA 3.0