【问题标题】:Is canvas getImageData method machine/browser dependent?canvas getImageData 方法是否依赖于机器/浏览器?
【发布时间】:2014-12-24 06:51:06
【问题描述】:

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

我能够在 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]);
}

有问题的图片是this(预览如下)。

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

虽然结果很接近,但为什么它们在理想情况下并不完全相同?getImageData 确实因本地设置而异,还是 JPG 数据是在不同的机器上会有不同的解释?

编辑:这张图片不是一次性的。在客户要求处理的一系列图像中发现了这种颜色变化。我和我的客户对同一组图像获得了不同的结果。

【问题讨论】:

  • 这与浏览器应用或不应用颜色配置文件有关,以及哪个。
  • 不依赖于浏览器画布功能的第三方图像处理库可能会有所帮助。例如,this is a good library。
  • 还有其他两种方法可以解决这个问题。一种是使用 WebGL 和 readPixels。 WebGL 可以在上传图片前通过调用gl.pixelStorei(gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE); 关闭颜色校正。然后你会render it 并读回像素。另一种方法是使用ImageBitmap api。不幸的是,看起来只有 Chrome 支持带有忽略颜色空间转换选项的完整规范。

标签: javascript canvas colors getimagedata


【解决方案1】:

是的。这个事实被canvas fingerprinting利用:

同样的 HTML5 Canvas 元素可以 在不同的网络浏览器上产生异常像素,具体取决于 执行它的系统。

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

【讨论】:

  • 谢谢!非常有趣的见解!
  • 我在两台几乎相同的 Windows 8 机器上看到了不同的结果(一台运行 Chrome,另一台运行最新的 Opera [基于 Chromium])。
猜你喜欢
  • 2019-11-17
  • 1970-01-01
  • 1970-01-01
  • 2012-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-06
  • 2019-03-07
相关资源
最近更新 更多