如何使用JavaScript从图像中获取平均色或主要颜色?

7
我希望能够从一张图片中获取HEX或RGB平均值,并将这个颜色设置为另一个div的背景色。
例如,如果我上传了一张红色的图片,我会得到类似于#FF0000的值。
请告诉我这是否可行 :)
非常感谢。

1
JavaScript 本身无法处理上传的文件。 - alex
你是想要精确的像素颜色,还是在特定的HSV范围内?(我建议后者会更好地为您服务。) - Phrogz
6个回答

13

首先,在canvas上绘制图像:

function draw(img) {
    var canvas = document.createElement("canvas");
    var c = canvas.getContext('2d');
    c.width = canvas.width = img.width;
    c.height = canvas.height = img.height;
    c.clearRect(0, 0, c.width, c.height);
    c.drawImage(img, 0, 0, img.width , img.height);
    return c; // returns the context
}

现在您可以迭代图像的像素。一种天真的颜色检测方法是简单地计算图像中每种颜色的频率。
// returns a map counting the frequency of each color
// in the image on the canvas
function getColors(c) {
    var col, colors = {};
    var pixels, r, g, b, a;
    r = g = b = a = 0;
    pixels = c.getImageData(0, 0, c.width, c.height);
    for (var i = 0, data = pixels.data; i < data.length; i += 4) {
        r = data[i];
        g = data[i + 1];
        b = data[i + 2];
        a = data[i + 3]; // alpha
        // skip pixels >50% transparent
        if (a < (255 / 2))
            continue; 
        col = rgbToHex(r, g, b);
        if (!colors[col])
            colors[col] = 0;
        colors[col]++;
    }
    return colors;
}

function rgbToHex(r, g, b) {
    if (r > 255 || g > 255 || b > 255)
        throw "Invalid color component";
    return ((r << 16) | (g << 8) | b).toString(16);
}

getColors 返回一个颜色名称和数量的映射表。透明像素将被跳过。从这个映射表中获取最常见的颜色应该很容易。

如果您真的想要每个颜色分量的平均值,您也可以从 getColors 的结果中轻松获得,但结果可能不是非常有用。 这个答案 解释了一种更好的方法。

您可以按如下方式使用它:

// nicely formats hex values
function pad(hex) {
    return ("000000" + hex).slice(-6);
}

// see this example working in the fiddle below
var info = document.getElementById("info");
var img = document.getElementById("squares");
var colors = getColors(draw(img));
for (var hex in colors) {
    info.innerHTML += "<li>" + pad(hex) + "->" + colors[hex];
}

查看一个工作示例


4
  • 将图像放置在画布上。
  • 获取2D上下文。
  • 循环遍历像素,并存储每个r、g、b值。如果找到相同的值,则将其递增一次。
  • 循环遍历存储的r、g、b值,并记录最大的r、g、b值。
  • 将r、g、b转换为十六进制

5
将RGB转换为十六进制需要19行代码?现在的孩子们啊。((r << 16) | (g << 8) | b) - Wayne
3
是的,我知道,谷歌可以找到答案,但很少是最好的。这就是为什么这里的人会让我恼火,“你先谷歌了吗?” - alex

3

0
你可以考虑使用 CSS 提供的卷积滤镜来实现你想要的效果(假设你想将其呈现回 HTML 中)。因此,你可以显示两次图像,其中一个是经过卷积处理的。
话虽如此,如果你需要自己获取信息,这种方法并不适用。

0

-1

计算平均颜色的步骤如下:

  1. 将图像放置在画布上
  2. 将图像大小调整为1像素乘1像素
  3. 获取结果像素的颜色(该像素将是计算出的平均值)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接