当前位置:网站首页>Deep exploration image theme color extraction

Deep exploration image theme color extraction

2022-06-26 06:58:00 Code Taoist

logo

The idea comes from 「 performance optimization 」 Skeleton screen in :

In the sites with most pictures , It will be very nice Experience —— Image loading is usually uncomfortable , A good skeleton is usually a low pixel image , That is, the general color matching and changes are consistent with the actual content .

Sometimes, for example, the picture is not fixed , Then you can use an algorithm to get the main color of the picture ( At least it must be of the same color ), Use solid color blocks to occupy space .

Think further , In some “ Relaxed ” In the scene of , We can make the background color / The theme color of the page changes with the rotation chart . As for the effect ...... You can think of the background effect when Netease cloud music slides and cuts songs .

Because it is not a fixed picture , So I thought of four ways :

  • tensorflow.js Image color analysis
  • canvas Analyze the main tone of the picture , Take approximate value
  • css Gaussian blur
  • When uploading pictures, the back end analyzes and processes the pictures , Returns a low pixel image directly

The first method is still in my practice , I will write a separate article in the future ; The last method is not recommended to be preferred : First, back-end processing also takes time , On the other hand, it is also transmitted by pictures ...yee~( And the back-end may not recommend you to choose )

If you want to see the actual effect, it is recommended to try it yourself , Because I found that in this article QQ Why are the screenshots so dark , The actual display is very beautiful .

The third way seems to be pure css Realized , How to get it ? This is to say css Medium filter: blur(); Simply speaking , Using a blur filter and further stretching , You can approximately get the theme color of a picture :

<div></div>

div {

    background: url( Picture address );

    background-size: cover;

    filter: blur(50px);

}

You see , Through a larger blur filter , Gaussian blur the picture 50px, Is the blurred picture a bit of an inside flavor ,

1

The picture is taken from the wechat store APP- Self owned brand of wechat store rua Baby - Cotton doll , Welcome to play ( ̄▽ ̄)"

But not yet , There are some fuzzy edges , We can use overflow Cut .

Next , We need to get rid of the blurry edges , And by transform: scale() Zoom in , Focus the color further :

Here, it is recommended to use pseudo elements for operations

div {
    position: relative;
    width: xx;
    height: xx;
    overflow: hidden;
}

div::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: url( Picture address );
    background-size: cover;
    filter: blur(50px);
    transform: scale(2); // To change the 
    transform-origin: center center;
}

2

So you get the main color of the picture . Of course, it is necessary to carry out other processing .

Let's talk about the second method —— canvas. In fact, it is not recommended , Because it is JS operation , And in the case that the picture is not fixed and there are many, the single thread js Deal with this “ First level events ” The loss of performance and experience is unimaginable . But the author of this article still wants to share , Because this is the first applied result of my original research ( Have feelings hey hey )

First ,canvas Medium getImageData() Method to get the pixel set of the picture :

function getImagePixel(canvas, img) {
    const context = canvas.getContext("2d");
    context.drawImage(img, 0, 0);
    return context.getImageData(0, 0, canvas.width, canvas.height).data;
}

Here's how to use canvas Let's wake up for those unfamiliar students :img It's loaded asynchronously , All operations on the picture should be placed in img Of onload In the middle of —— You can think about using promise Do it .

3

Calling this function will get an array —— It is rgba value , in other words , When processing, the four data are “ A group of ”, More colloquially ,for In circulation i+=4! To process the data :

function getCountArr(pData) {
    let colorList = [], rgba = [], rgbaStr = '';

    for(let i=0; i<pData.length; i+=4) {
        rgba[0] = pData[i];
        rgba[1] = pData[i+1];
        rgba[2] = pData[i+2];
        rgba[3] = pData[i+3];

        if(rgba.indexOf(undefined)!==-1 || pData[i+3] === 0) {
            continue;
        }

        rgbaStr = rgba.join(',');

        if(rgbaStr in colorList) {
            ++colorList[rgbaStr];
        }else {
            colorList[rgbaStr] = 1;
        }
    }

    return colorList;

}

This is the time , What you get is each set of data ( Color value ) The number of times .

Then rewrite what just happened getImagePixel function :

function getImagePixel(canvas, img) {

    const context = canvas.getContext("2d");

    context.drawImage(img, 0, 0);

    let pixelData = context.getImageData(0, 0, canvas.width, canvas.height).data;

    return getCountArr(pixelData);

}

thus , We sort them and take the first value / Or take the average value of some flag items , Basically, it can be regarded as background It's worth it :

for(let prop in colorList) {

    arr.push({
        color: `rgba(${prop})`,
        count: colorList[prop]
    })

}

arr.sort((a, b)=>{return a.count - b.count;});

that will do !

「 the path winds along mountain ridges !」

Do you really think canvas This method is just chicken ribs ? Imagine such a scenario : In the case of weak networks , Pictures must be slow to load . At this time we pass through js Get the main color of the picture and fill it in the position of the picture . This is not a “ Blur gradient loading ” A great scene !

原网站

版权声明
本文为[Code Taoist]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202171318130381.html