FlutterComponent最佳实践之取色我来实现

318 篇文章 18 订阅
9 篇文章 0 订阅

作者:xuyisheng

构建个性化的UI是非常酷的。你的应用程序不需要对每个人都是一样的。一个轻松定制你的应用程序的方法是,从客户资料/封面照片中提取调色板。

它是这样做的。

首先,我们从一个网址上加载图片到byte list中。

imageBytes = (await NetworkAssetBundle(Uri.parse(photo)).load(photo))
      .buffer
      .asUint8List();

然后,我们导入Image lib,这样我们就可以访问每个像素,而不用担心图像的格式问题。

在下面的方法中,我访问了一个像素mesh,所以我可以从图像的不同部分挑选颜色。

List<Color> extractPixelsColors(Uint8List? bytes) {
  List<Color> colors = [];

  List<int> values = bytes!.buffer.asUint8List();
  imageLib.Image? image = imageLib.decodeImage(values);

  List<int?> pixels = [];

  int? width = image?.width;
  int? height = image?.height;

  int xChunk = width! ~/ (noOfPixelsPerAxis + 1);
  int yChunk = height! ~/ (noOfPixelsPerAxis + 1);

  for (int j = 1; j < noOfPixelsPerAxis + 1; j++) {
    for (int i = 1; i < noOfPixelsPerAxis + 1; i++) {
      int? pixel = image?.getPixel(xChunk * i, yChunk * j);
      pixels.add(pixel);
      colors.add(abgrToColor(pixel!));
    }
  }

  return colors;
}

如果noOfPixelsPerAxis是4的话,这个网格看起来就是这样。

在这个例子中,我们将提取16个像素。

好了,现在我们有16种颜色,但我们能用它们做什么呢?我们需要以某种方式对它们进行排序,所以我们可以提取调色板。

现在我们尝试将颜色从浅色到深色排序。我们使用computeLuminance方法,这个方法的计算成本很高,所以我们也许不应该在排序方法中进行计算(对每种颜色进行多次计算),但为了这个例子,这也是可以的。

List<Color> sortColors(List<Color> colors) {
  List<Color> sorted = [];

  sorted.addAll(colors);
  sorted.sort((a, b) => b.computeLuminance().compareTo(a.computeLuminance()));

  return sorted;
}

经过分类,我们的颜色看起来像这样。

开始时图像较亮(左上方,结束时图像较暗,右下方)。我把它们显示在一个网格中,所以它们可以很容易地放在屏幕上。

我们不需要调色板中的所有16种颜色,这太多了,所以让我们试着提取4种颜色。

为了做到这一点,我将把这个16种颜色的列表分成4个4种颜色的子列表,在每个子列表中找到平均颜色,这些平均颜色将成为我们最终调色板颜色列表中的项目。

Color getAverageColor(List<Color> colors) {
  int r = 0, g = 0, b = 0;

  for (int i = 0; i < colors.length; i++) {
    r += colors[i].red;
    g += colors[i].green;
    b += colors[i].blue;
  }

  r = r ~/ colors.length;
  g = g ~/ colors.length;
  b = b ~/ colors.length;

  return Color.fromRGBO(r, g, b, 1);
}

平均颜色的计算方法是将所有的红色、蓝色和绿色成分加在一起,然后将总和除以所加颜色的数量。

调色板中的第一种颜色(右边没有1)是由排序列表中的前4种颜色(0、1、2、3)组成的,第二种颜色是4、5、6、7,第三种颜色是8、9、10、11,第四种是12、13、14、15。

为了防止用户界面被这些繁重的计算所阻塞,我使用了compute方法,它在一个独立的isolate(具有独立内存的新线程)上执行你的函数,并返回你的结果。

你从图像中提取的像素越多,就会花费更多的时间,所以要找到你要提取的最佳像素数。另外,图像越大,下载和解码的时间就越长。如果你能使用一些缩略图或你知道不是很大的图片,那将是最好的 😃 在下面的视频中,我提取了12x12=144像素,你可以看到它需要一两秒钟。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值