Flutter可以知道一张图片的亮度吗?
Is it posible to know the brightness of a picture in Flutter?
我正在构建一个内置摄像头的应用程序。
拍完照片后,我想分析一下这张照片的亮度,如果不好就得重拍。
这是我现在的代码,它是我在 Dart 中找到并编写的 javascript 函数:
感谢@Abion47
编辑 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;
但我的白色亮度比黑色低,数字有点奇怪。
你知道更好的了解亮度的方法吗?
解决方案:
经过进一步调查,我们找到了解决方案,我们在进行图像解码时出错,但我们使用了图像函数来完成它。
这是我们的最终代码:
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;
希望对你有帮助。
您的代码有几处错误。
首先,您收到范围错误,因为您试图访问不存在的像素。这可能是由于 width
and/or height
大于图像的实际宽度或高度。有很多方法可以尝试获取这些值,但对于这个应用程序,它实际上并不重要,因为最终结果是获取图像中所有像素的平均值,而您不需要宽度或高度的图像。
其次,您通过将颜色值序列化为十六进制字符串然后解析各个通道子字符串来获取颜色值。您的 substring
将导致不正确的值,因为:
foo.substring(a, b)
取foo
的子串从a
到b
,互斥。这意味着 a
和 b
是索引,而不是长度,并且生成的字符串将不包含 b
处的字符。所以假设 hex
是“01234567”,当你做 hex.substring(0, 2)
时,你得到“01”,然后你做 hex.substring(3, 5)
得到“34”,而 hex.substring(6, 8)
得到你“ 67"。您需要执行 hex.substring(0, 2)
,然后执行 hex.substring(2, 4)
和 hex.substring(4, 6)
以获得前三个频道。
- 话虽如此,您获取的频道有误。
image
包以 ABGR 格式存储其像素值,这意味着十六进制字符串中的前两个字符将成为 alpha 通道,这在计算图像亮度时并不重要。相反,您需要分别用于蓝色、绿色和红色值的第二个、第三个和第四个通道。
- 话虽如此,当从整数颜色值检索通道数据的首选方法是对整数本身进行按位运算时,无论如何这是一种非常低效的方法。 (除非万不得已,否则切勿将数字转换为字符串,反之亦然。)
所以总而言之,您想要的可能类似于以下内容;
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;
我正在构建一个内置摄像头的应用程序。
拍完照片后,我想分析一下这张照片的亮度,如果不好就得重拍。
这是我现在的代码,它是我在 Dart 中找到并编写的 javascript 函数:
感谢@Abion47
编辑 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;
但我的白色亮度比黑色低,数字有点奇怪。
你知道更好的了解亮度的方法吗?
解决方案:
经过进一步调查,我们找到了解决方案,我们在进行图像解码时出错,但我们使用了图像函数来完成它。
这是我们的最终代码:
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;
希望对你有帮助。
您的代码有几处错误。
首先,您收到范围错误,因为您试图访问不存在的像素。这可能是由于 width
and/or height
大于图像的实际宽度或高度。有很多方法可以尝试获取这些值,但对于这个应用程序,它实际上并不重要,因为最终结果是获取图像中所有像素的平均值,而您不需要宽度或高度的图像。
其次,您通过将颜色值序列化为十六进制字符串然后解析各个通道子字符串来获取颜色值。您的 substring
将导致不正确的值,因为:
foo.substring(a, b)
取foo
的子串从a
到b
,互斥。这意味着a
和b
是索引,而不是长度,并且生成的字符串将不包含b
处的字符。所以假设hex
是“01234567”,当你做hex.substring(0, 2)
时,你得到“01”,然后你做hex.substring(3, 5)
得到“34”,而hex.substring(6, 8)
得到你“ 67"。您需要执行hex.substring(0, 2)
,然后执行hex.substring(2, 4)
和hex.substring(4, 6)
以获得前三个频道。- 话虽如此,您获取的频道有误。
image
包以 ABGR 格式存储其像素值,这意味着十六进制字符串中的前两个字符将成为 alpha 通道,这在计算图像亮度时并不重要。相反,您需要分别用于蓝色、绿色和红色值的第二个、第三个和第四个通道。 - 话虽如此,当从整数颜色值检索通道数据的首选方法是对整数本身进行按位运算时,无论如何这是一种非常低效的方法。 (除非万不得已,否则切勿将数字转换为字符串,反之亦然。)
所以总而言之,您想要的可能类似于以下内容;
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;