Flutter如何获取图片主色调
嗨,这里是甜瓜看代码。这篇文章跟大伙唠唠Flutter如何获取图片的主体色。
为什么要获取图片主色调?
在移动应用开发中,颜色是界面设计的重要组成部分。有时候,我们希望根据一张图片的主要颜色来设置整体的配色方案,从而使页面具有统一的风格。而想要获取图片主色调,其实本质就是获取出现最多次的某种色值的像素点,因此我们顺着这个思路展开。
获取图片中颜色最多的像素点的步骤
下面是使用Flutter获取图片中颜色最多的像素点的步骤:
1. 导入必要的库
首先,我们需要导入Flutter的dart:ui
库,它提供了访问底层图像处理功能的接口。在你的Flutter项目中的pubspec.yaml
文件中添加以下依赖项,当然这一般都是默认就有的,在项目创建之初:
dependencies:
flutter:
sdk: flutter
dev_dependencies:
flutter_test:
sdk: flutter
2. 加载图片
接下来,我们需要加载我们想要获取主要颜色的图片。使用Flutter的ImageProvider
类可以轻松实现这一点。以下是加载图片的示例代码:
import 'dart:ui' as ui;
Future<ui.Image> loadImage() async {
final Completer<ui.Image> completer = Completer();
const imageProvider = NetworkImage('url');
imageProvider.resolve(const ImageConfiguration()).addListener(
ImageStreamListener((info, _) async {
completer.complete(info.image);
}),
);
return completer.future;
}
// 使用示例
final image = await loadImage();
3. 分析像素
现在,我们已经成功加载了图片。接下来,我们将分析图片中的像素,并计算每种颜色的出现次数。以下是计算每种颜色出现次数的示例代码:
import 'dart:ui' as ui;
Future<Map<int, int>> countColors(ui.Image image) async {
Uint8List bytes = await image
.toByteData(format: ui.ImageByteFormat.rawRgba)
.then((data) => data!.buffer.asUint8List());
final colorCount = <int, int>{};
for (int i = 0; i < bytes.lengthInBytes; i += 4) {
final alpha = bytes[i];
final red = bytes[i + 1];
final green = bytes[i + 2];
final blue = bytes[i + 3];
final key = (blue << 24) | (red << 16) | (green << 8) | alpha;
if (colorCount.containsKey(key)) {
colorCount[key] = colorCount[key]! + 1;
} else {
colorCount[key] = 1;
}
}
return colorCount;
}
// 使用示例
final colorCounts = countColors(image);
4. 找到颜色最多的像素点
现在,我们已经计算了每种颜色出现的次数。接下来,我们需要找到颜色出现次数最多的像素点。以下是找到颜色最多的像素点的示例代码:
int findMostCommonColor(Map<int, int> colorCounts) {
int mostCommonColor = 0;
int maxCount = 0;
colorCounts.forEach((color, count) {
if (count > maxCount) {
mostCommonColor = color;
maxCount = count;
}
});
return mostCommonColor;
}
// 使用示例
final mostCommonColor = findMostCommonColor(colorCounts);
5. 解析颜色值
最后,我们将解析颜色值并获取其中的红、绿、蓝和透明度分量。以下是解析颜色值的示例代码:
import 'package:flutter/material.dart';
Color parseColor(int color) {
final alpha = (color >> 24) & 0xFF;
final red = (color >> 16) & 0xFF;
final green = (color >> 8) & 0xFF;
final blue = color & 0xFF;
return Color.fromARGB(alpha, red, green, blue);
}
// 使用示例
final mostCommonColorValue = parseColor(mostCommonColor);
现在,mostCommonColorValue
将包含颜色最多的像素点的颜色值。到这里本文应该就结束了,但是使用过后发现这个实现有其局限性,因为它获取的是每个像素点的色值,这会过于精确以至于只能适用主体色调相对单一的情况。那么该如何实现呢?
Android中Palette库的实现
在安卓中使用Palette库获取图像的主体颜色时,Palette库使用了一种基于统计的算法来提取颜色信息。该算法的主要思想是分析图像中的像素分布和颜色频率,以确定主要的颜色。
Palette库的算法主要包括以下步骤:
-
颜色量化:首先,算法会对图像进行颜色量化,将连续的颜色空间分割成离散的颜色桶。这有助于降低计算复杂度并提高效率。
-
颜色统计:接下来,算法会遍历图像中的每个像素,并将每个像素的颜色值分配给相应的颜色桶。通过统计每个颜色桶中的像素数量,算法得到颜色的频率信息。
-
颜色提取:根据颜色频率,算法选择一组主要的颜色作为图像的主体颜色。常见的提取方式包括选择频率最高的几个颜色,或者使用一些启发式规则来选择具有代表性的颜色。
看完这个实现,再掂量了一下自己的能力,我觉的我不可以。不过经过一番周折,我找到了一个库,基本上是能够实现的。
color_thief_dart库实现Flutter获取图片主色调
这里先放上库的链接:color_thief_dart
实现
final Completer<ui.Image> completer = Completer();
const imageProvider = NetworkImage(
'https://img.zcool.cn/community/01a88c5c83d982a801217ce671e935.jpg@1280w_1l_2o_100sh.jpg');
imageProvider.resolve(const ImageConfiguration()).addListener(
ImageStreamListener((info, _) async {
getColorFromImage(info.image);
}),
);
getColorFromImage(info.image)的返回值作者的注释是returns the base color from the largest cluster, represented as R,G,B
,意思就是返回最大簇的基色,表示为R,G,B。通过这个注释合理推测一下,作者通过获取到所有像素点的RGB值,然后通过算法对像素点进行簇类划分,之后将最大簇求RGB的平均值,最后这个返回值即主体色的RGB值。
总结
虽然没有自己实现这个功能,但是这个过程学会了如何获取Flutter中图片的像素点,如何去计算RGB值,也算有所收获。也了解到了安卓中取色器的算法实现思路,最后通过color_thief_dart库实现了目标。
希望这篇文章对你有所帮助。这里是甜瓜看代码,期待你的关注!
转载自:https://juejin.cn/post/7237029359135506469