Talk about how to extract the theme color of the picture from the background of Netease cloud music

Time:2021-10-17

Netease cloud

Netease cloud music must be a familiar app. After all, everyone will be late at nightthe NetEase's cloud music
Talk about how to extract the theme color of the picture from the background of Netease cloud music
I’m kidding. I found an interesting special effect when listening to songs on Netease cloud recently:

When switching songs, the background color will be replaced according to the current cover. As a senior cut figure, I can’t hold my damn curiosity. No, I’m going to find out.
Talk about how to extract the theme color of the picture from the background of Netease cloud music
First of all, I have conceived many possible ways to realize it:

  • Machine learning color analysis of pictures
  • The front end extracts the main color of the picture and makes gradient processing
  • Gaussian blur of cover background

For the first, it is not within my knowledge, so I won’t explain it here.

In the second case, it is generally usedcanvasTo achieve.

The third is relatively speaking, from the technical level, the implementation is the simplest.

After making a guess and analysis, I silently opened the familiar chrome console and opened the source code of Netease cloud music:
Talk about how to extract the theme color of the picture from the background of Netease cloud music

Good guy, it’s really the third way to realize it.

This article should have ended here. But a friend asked me beforeHow to extract the theme color of the front-end pictureSimilar requirements have been made just before. Let’s expand and explain here.

Here we take a picture website as an example to show the scenarios widely used in actual business:
Talk about how to extract the theme color of the picture from the background of Netease cloud music
In the weak network, the picture loading speed is slow. At this time, before the picture is fully loaded, the main color of the picture is extracted and then filled as the background color. In this way, the user experience can be greatly improved.

How did that happen?

We use it herecanvasIt can be realized in three steps:

  • Get picture data
  • Process picture data
  • Sort color list

The test images we use here are:
Talk about how to extract the theme color of the picture from the background of Netease cloud music

Relatively speaking, the main tone is obvious and easy to test ~

Get picture data

We know that the picture is composed of pixels. Through canvasgetImageData()Method can just obtain the pixel data of the picture:

let imgObj = document.getElementById('yourId');

//Create canvas
let canvas = document.createElement('canvas');
canvas.setAttribute('width', imgObj.width);
canvas.setAttribute('height', imgObj.height);
let context = canvas.getContext('2d');
//Draw the picture on the canvas
context.drawImage(imgObj, 0, 0);
//Get pixel data
let imgData = context.getImageData(0, 0, imgObj.width, imgObj.height);
let pixelData = imgData.data;

But then you printpixelData, you will find that:
Talk about how to extract the theme color of the picture from the background of Netease cloud music
Good guy, it’s all 0,,,

I can’t think of the reason: is it because canvas’s API is not proficient?

Talk about how to extract the theme color of the picture from the background of Netease cloud music
staystackoverflowThe above answer is found on:
Talk about how to extract the theme color of the picture from the background of Netease cloud music
But I still can’t do it after modification.

At this time, I think that image loading is asynchronous. It may be that the image data is read from the canvas before the image is loaded. Obviously, this is wrong. So I made some adjustments to the original code:

getMainColor("./test.jpeg");
function getMainColor(image) {
  return new Promise((resolve, reject) => {
    try {
      const canvas = document.createElement("canvas");
      const img = new Image(); //  Create img element
      img.src = image; //  Set picture source address
      img.onload = () => {
        let color = getImageColor(canvas, img);
        resolve(color);
      };
    } catch (e) {
      reject(e);
    }
  });
}
function getImageColor(canvas, img) {
  const context = canvas.getContext("2d");
  context.drawImage(img, 0, 0);

  //Get pixel data
  let pixelData = context.getImageData(
    0,
    0,
    canvas.width,
    canvas.height
  ).data;
  console.log("pixelData", pixelData);
  return pixelData;
}

Facts have proved that it’s true
Talk about how to extract the theme color of the picture from the background of Netease cloud music

After obtaining the picture data, the next step is to process it accordingly.

Process picture data

Expand the data obtained in the previous step:
Talk about how to extract the theme color of the picture from the background of Netease cloud music
What does the data here mean? Actuallyrgba, distribution representativeRed (red)GreenBlueandTransparency (alpha)rgbaEach pixel of the picture is represented by the above four values. That is, every four are in a group.

Knowing the rules, let’s clean the data: mainly grouping colors and counting the occurrence times of each color:

function getImageColor(canvas, img) {
  const context = canvas.getContext("2d");
  context.drawImage(img, 0, 0);

  //Get pixel data
  let pixelData = context.getImageData(
    0,
    0,
    canvas.width,
    canvas.height
  ).data;
  console.log("pixelData", pixelData);
  return getCountsArr(pixelData);
}
function getCountsArr(pixelData) {
  let colorList = [];
  let rgba = [];
  let rgbaStr = "";
  //Grouping cycle
  for (let i = 0; i < pixelData.length; i += 4) {
    rgba[0] = pixelData[i];
    rgba[1] = pixelData[i + 1];
    rgba[2] = pixelData[i + 2];
    rgba[3] = pixelData[i + 3];

    if (rgba.indexOf(undefined) !== -1 || pixelData[i + 3] === 0) {
      continue;
    }
    // console.log("rgba", rgba);
    rgbaStr = rgba.join(",");
    if (rgbaStr in colorList) {
      ++colorList[rgbaStr];
    } else {
      colorList[rgbaStr] = 1;
    }
  }
  console.log("colorList", colorList);

  return colorList;
}

PrintcolorListThe result is:
Talk about how to extract the theme color of the picture from the background of Netease cloud music

Here, we get the number of occurrences of each data.

Sort color list

The last step is to sort the color value objects obtained above:

for (let prop in colorList) {
  arr.push({
    //If only RGB is obtained, ` RGB (${prop})`
    color: `rgba(${prop})`,
    count: colorList[prop],
  });
}
//Array sorting
arr.sort((a, b) => {
  return b.count - a.count;
});

console.log("arr", arr);

After sorting, the following results are obtained:
Talk about how to extract the theme color of the picture from the background of Netease cloud music

Here we get the sorted array of the occurrence times of image color values from large to small. Let’s look at the first onergba(206,205,201,255)
Talk about how to extract the theme color of the picture from the background of Netease cloud music
Then paste the test picture:
Talk about how to extract the theme color of the picture from the background of Netease cloud music
The theme color visible to the naked eye has been extracted!

reflect

Finally, go back to the player special effects of Netease cloud music mentioned at the beginning of the article. No matter how it is implemented, its product creativity is worth learning.

When we browse some websites at home and abroad or use some apps, we can always encounter some effects that make you applaud. These special effects are often inseparable from our front end.

it is said that:The front end is the development engineer closest to the product, have you encountered any amazing or thoughtful effects recently? Please leave a message in the comment area

❤️ Love Sanlian

1. If you think this article is good, give it a tryShare, like and watchThree times, let more people see ~

2. pay attention to the official account.Front end forest, regularly push fresh and dry goods and good articles for you.

3. Wear masks and personal protection at special stages.