It’s cool to build personalized UIs. Your application doesn’t have to be the same for everyone. An easy way to customize your application is to extract a palette from a customer profile/cover photo.

Here’s how it works.

First, we load the image from a url into a Byte list.

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

Then, we import the Image lib so that 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; }Copy the code

This is what the grid would look like if noOfPixelsPerAxis were 4.

In this example, we will extract 16 pixels.

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

Now let’s try sorting the colors from light to dark. We use the computeLuminance method, which is expensive to calculate, so we probably shouldn’t do it in the sorting method (multiple times for each color), but for the sake of this example, it’s ok.

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

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

  return sorted;
}
Copy the code

Our color looks something like this.

The image is lighter at the beginning (upper left, darker at the end, lower right). I display them in a grid, so they can be easily placed on the screen.

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

To do this, I’ll split the list of 16 colors into 4 sublists of 4 colors, finding average colors in each sublist that will become items 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);
}
Copy the code

The average colour is calculated by adding all the red, blue and green ingredients together and then dividing the sum by the number of colours added.

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

To prevent the user interface from clogging up with these heavy calculations, I use the compute method, which executes your functions on a separate isolate (a new thread with separate memory) and returns your results.

The more pixels you extract from an image, the more time it takes, so find the best number of pixels you want to extract. In addition, the larger the image, the longer it takes to download and decode. It would be best if you could use some thumbnails or images that you know are not very big 🙂 in the video below I extracted 12×12=144 pixels and you can see it takes a second or two.

The original link: mobileappcircular.com/how-to-extr…

Source code address: github.com/jelenalecic…

I would like to recommend my website xuyisheng. Top/focusing on Android-Kotlin-flutter welcome you to visit