如何获取图片的主色、辅色以及颜色统计

最近遇到一个不太常见的需求,希望我一个页面图片的背景色,能够随着图片的变化而变化,而且看上去要和谐。和谐这个词就比较抽象了,思索再三,也许使用图片的主色调,就会使得整个页面比较和谐了。而前端的canvas正好可以满足我们的需求。

获取图片数据

对于位图而言,图片是由一个个像素点组成的,而像素数据则由红、绿、蓝和alpha分量的位数四个元素组成。通过cavas的getImageData()方法,恰好可以获取图片的像素数据,具体数据格式为{data: [r, g, b, a, r, g, b, a…]}。

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

// 创建画布
let canvas = document.createElement('canvas');
canvas.setAttribute('width', imgObj.width);
canvas.setAttribute('height', imgObj.height);
let context = canvas.getContext('2d');
// 将图片画在画布上
context.drawImage(imgObj, 0, 0);
// 获取像素数据
let imgData = context.getImageData(0, 0, imgObj.width, imgObj.height);
let pixelData = imgData.data;

对图片数据进行处理

此时获取到了像素数据,因像素数据的特性,可以对这个数组进行分组,rgba四个为一组。而且在分组的同时,可以考虑对重复出现的颜色进行计数了。我们可以构建如下数据格式来完成分组与计数的需求。

// '像素数据': 数量
const COLORLIST = {
    'rgba1': 10,
    'rgba2': 22,
    ...
}

主要代码如下

let colorList = {};
let rgba = [];
let rgbaSt = '';

// 分组循环
for (let i = 0; i < pixelData.length; i += 4) {
    rgba[0] = pixelData[i];
    rgba[1] = pixelData[i + 1];
    rgba[2] = pixelData[i + 2];
    // 如果主色只要r,g,b不要a,请注释掉这句
    rgba[3] = pixelData[i + 3];

    // 避免undefined数据和alpha为0的数据
    if (rgba.indexOf(undefined) !== -1 || pixelData[i + 3] === 0) {
        continue;
    }
    // 转为字符串
    rgbaSt = rgba.join(',');

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

对颜色列表进行排序处理

至此已经获得了颜色的统计数据,我们只需要进行一下排序,就大功告成了!

let arr = [];

for (let prop in colorList) {
    arr.push({
        // 如果只获取rgb,则为`rgb(${prop})`
        color: `rgba(${prop})`,
        count: colorList[prop]
    });
}
// 数组排序
arr.sort((a, b) {
        return b.count - a.count;
});

好了,大功告成,arr就是我们排好顺序的颜色列表啦,你可以随便取里面你想取的颜色了。arr[0]和arr[1]肯定是我们需要的主辅色了。

注意:要考虑cavans处理的图片的跨域问题。
1.添加属性crossOrigin=”anonymous”。
2.转为base64

发表评论