The best practice of FlutterComponent is to choose color and realize it

Building personalized UIs is pretty cool. Your application doesn't need to be the same for everyone. An easy way to customize your application is to extract the color palette from the client profile/cover photo.

It does so.

First, we load an image from a URL into a byte list.

imageBytes = (await NetworkAssetBundle(Uri.parse(photo)).load(photo))
      .buffer
      .asUint8List();
复制代码

Then, we import the Image lib so we can access each pixel without worrying about the format of the image.

In the method below, I access a pixel mesh so I can pick colors from different parts of the image.

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;
}
复制代码

This is what the grid looks like if noOfPixelsPerAxis is 4.

img

In this example, we will extract 16 pixels.

OK, now we have 16 colors, but what can we do with them? We need to sort them somehow so we can extract the palette.

img

Now let's try to sort the colors from light to dark. We use the computeLuminance method, which is computationally expensive, so we probably shouldn't be doing the computations in the sorting method (multiple computations for each color), but for the sake of this example, it's fine.

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

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

  return sorted;
}
复制代码

After sorting, our colors look like this.

img

Brighter image at the beginning (top left, darker at the end, bottom right). I have them displayed in a grid so they can easily fit on the screen.

We don't need all 16 colors in the palette, that's too much, so let's try to extract 4 colors.

To do this, I'm going to split this list of 16 colors into 4 sublists of 4 colors, and in each sublist find the average color that will become the item in our final palette color list.

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);
}
复制代码

The average color is calculated by adding all the red, blue and green components together and dividing the sum by the number of colors added.

img

The first color in the palette (without the 1 on the right) is made up of the first 4 colors (0, 1, 2, 3) in the sorted list, the second color is 4, 5, 6, 7, and the The three colors are 8, 9, 10, 11 and the fourth is 12, 13, 14, 15.

To prevent the UI from being blocked by these heavy computations, I use the compute method, which executes your function on a separate isolate (a new thread with separate memory) and returns your result.

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

img

原文链接:mobileappcircular.com/how-to-extr…

源码地址:github.com/jelenalecic…

向大家推荐下我的网站 xuyisheng.top/ 专注 Android-Kotlin-Flutter 欢迎大家访问

Guess you like

Origin juejin.im/post/7085160195143237640