canvas getImageData 方法是否依赖于机器/浏览器?

IT技术 javascript canvas colors getimagedata
2021-02-19 14:54:40

一位客户需要有关提取产品图像主色的程序的帮助。

我能够在 Javascript 中快速实现这一点;下面的算法仅对图像上 3x3 网格的中心正方形进行采样,以快速估计图像中的 T 恤颜色。

var image = new Image();
image.onload = function() {
    try {
        // get dominant color by sampling the central square of a 3x3 grid on image
        var dominantColor = getDominantColor();

        // output color
        $("#output").html(dominantColor);
    }
    catch(e) {
        $("#output").html(e);
    }
};
image.src = "sample_image.jpg";

function getDominantColor() {

    // Copy image to canvas
    var canvas = $("<canvas/>")[0];
    canvas.width = image.width;
    canvas.height = image.height;
    canvas.getContext("2d").drawImage(image, 0, 0);

    // get pixels from the central square of a 3x3 grid
    var imageData = canvas.getContext("2d").getImageData(canvas.width/3, canvas.height/3, canvas.width/3, canvas.height/3).data;

    var colorOccurrences = {};
    var dominantColor = "";
    var dominantColorOccurrence = 0;

    for(var i = 0; i < imageData.length; i += 4) {
        var red = imageData[i];
        var green = imageData[i+1];
        var blue = imageData[i+2];
        //var alpha = imageData[i+3]; // not required for this task

        var color = RGBtoHEX({"red": red, "green": green, "blue": blue});

        if(colorOccurrences[color] == undefined) {
            colorOccurrences[color] = 1;
        }
        else {
            colorOccurrences[color] ++;

            if(colorOccurrences[color] > dominantColorOccurrence) {
                dominantColorOccurrence = colorOccurrences[color];
                dominantColor = color;
            }
        }
    }

    return dominantColor;
}

function RGBtoHEX(rgb) {
    var hexChars = "0123456789ABCDEF";
    return "#"
            + (hexChars[~~(rgb.red/16)] + hexChars[rgb.red%16])
            + (hexChars[~~(rgb.green/16)] + hexChars[rgb.green%16])
            + (hexChars[~~(rgb.blue/16)] + hexChars[rgb.blue%16]);
}

有问题的图像是这个(预览如下)。

样品产品

但是,在上面的代码中处理此图像时的结果因机器/浏览器而异:这#FF635E是我在我的机器上看到的,运行 Windows7 并使用 Firefox 32。我的客户端运行 Mac 获得#FF474B在 Safari 和#FF474CFirefox 33的结果

尽管结果很接近,但为什么理想情况下它们不完全相同?是否getImageData确实取决于当地的设置,或者是JPG数据被不同的解释在不同的机器?

编辑:此图像不是一次性案例。在客户要求处理的图像范围内注意到了这种颜色变化。我和我的客户对同一组图像获得了不同的结果。

1个回答

是的。这个事实被画布指纹利用

相同的 HTML5 Canvas 元素可以在不同的 Web 浏览器上产生特殊的像素,具体取决于执行它的系统。

发生这种情况有几个原因:在图像格式级别——Web 浏览器使用不同的图像处理引擎、导出选项、压缩级别,即使它们是像素完美的,最终图像也可能获得不同的哈希值;在像素图级别——操作系统使用不同的算法和设置来进行抗锯齿和亚像素渲染。我们不知道所有的原因,但我们已经收集了超过一千个独特的签名。

我在两台几乎相同的 Windows 8 机器上看到了不同的结果(一台运行 Chrome,另一台运行最新的 Opera [基于 Chromium])。
2021-04-26 14:54:40
谢谢!非常有趣的见解!
2021-05-16 14:54:40