【问题标题】:getImageData always returning 0getImageData 总是返回 0
【发布时间】:2011-04-17 16:04:54
【问题描述】:

我一直在尝试制作一个脚本来比较 HTML5 和 Javascript 中的两个图像。但由于某些奇怪的原因,它总是返回图像完全相同。

当查看问题可能是什么时,我发现每个像素的每个数据值都返回,出于某种奇怪的原因,“0”。

那么,知道我做错了什么吗? :)

出于某种原因,我觉得这很简单,但我刚刚了解了画布元素,所以是的。

这是我的代码:

function compareImg() {
    var c1 = document.getElementById("c");
    var ctx1 = c1.getContext("2d");
    var c2 = document.getElementById("c2");
    var ctx2 = c2.getContext("2d");

    var match = 0;

    var img1 = new Image();
    img1.src = "cat.jpg";
    img1.onload = function() {
        ctx1.drawImage(img1, 0, 0);
    }
    var img2 = new Image();
    img2.src = "bird.jpg";
    img2.onload = function() {
        ctx2.drawImage(img2, 0, 0);
    }


    for(var x = 0; x<c1.width; x++) {  // For each x value
        for(var y = 0; y<c1.height; y++) { // For each y value
            var data1 = ctx1.getImageData(x, y, 1, 1);
            var data2 = ctx2.getImageData(x, y, 1, 1);
            if (data1.data[0] == data2.data[0] && data1.data[1] == data2.data[1] && data1.data[2] == data2.data[2]) {
                match++;
            }
        }
    }
    var pixels = c1.width*c1.height;
    match = match/pixels*100;
    document.getElementById("match").innerHTML = match + "%";
}

【问题讨论】:

    标签: javascript html canvas getimagedata


    【解决方案1】:

    您无需等到图像加载并绘制完毕后才进行比较。试试这个:

    var img = new Image;
    img.onload = function(){
      ctx1.drawImage(img,0,0);
      var img = new Image;
      img.onload = function(){
        ctx2.drawImage(img,0,0);
        // diff them here
      };
      img.src = 'cat.jpg';
    };
    img.src = 'cat.jpg';
    

    如上所示,您应该始终set your src after your onload

    【讨论】:

    • 感谢您重复我对分配“src”和“onload”顺序的迷信。 :-) 也许这毕竟不是迷信!
    • 令人着迷,@Phrogz!这些年来我一直告诉人们这样做是正确的:-)
    • 你的意思是我应该把用于比较图像的代码放在你写的“diff them here”的地方吗?对不起,我不完全理解它:)
    • @iamarcel 是的 - 这个答案与我的基本相同,只是方式略有不同。如果你尝试这个,你最终也会遇到同样的安全错误问题:-)
    【解决方案2】:

    我怀疑问题在于您尝试将图像数据用于画布时可能还没有准备好。如果您将该代码推迟到 onload 处理程序,那将(可能)有所帮助:

    var img1 = new Image(), count = 2;
    img1.src = "cat.jpg";
    img1.onload = function() {
        ctx1.drawImage(img1, 0, 0);
        checkReadiness();
    }
    var img2 = new Image();
    img2.src = "bird.jpg";
    img2.onload = function() {
        ctx2.drawImage(img2, 0, 0);
        checkReadiness();
    }
    
    function checkReadiness() {
      if (--count !== 0) return;
    
      for(var x = 0; x<c1.width; x++) {  // For each x value
        for(var y = 0; y<c1.height; y++) { // For each y value
            var data1 = ctx1.getImageData(x, y, 1, 1);
            var data2 = ctx2.getImageData(x, y, 1, 1);
            if (data1.data[0] == data2.data[0] && data1.data[1] == data2.data[1] && data1.data[2] == data2.data[2]) {
                match++;
            }
        }
      }
      var pixels = c1.width*c1.height;
      match = match/pixels*100;
      document.getElementById("match").innerHTML = match + "%";
    }
    

    我所做的只是在您的代码周围添加一个函数包装器。该函数检查我添加的图像计数变量,只有当它为零时(即,只有在两个图像都加载后)才会起作用。

    (这可能是迷信,但我总是在设置“src”属性之前分配“onload”处理程序。我有这样的想法,也许只是在过去,浏览器可能无法如果图像已经在缓存中,则运行处理程序。)

    现在还有一件事:您可能应该只获取一次图像数据,然后遍历返回的数据。为每个像素调用“getImageData()”对于浏览器来说将是很多工作。

    【讨论】:

    • 现在脚本获取图像数据的第一行出现“安全错误”... Chrome 显示“SECURITY_ERR:DOM 异常 18”,Firefox 显示“错误:未捕获的异常: [异常...“安全错误”代码:“1000”nsresult:“0x805303e8(NS_ERROR_DOM_SECURITY_ERR)...]”
    • 您是从另一个域获取图像吗?如果是这样,那么这是一个安全错误 :-) 它被认为与试图弄乱加载了来自另一个域的内容的 &lt;iframe&gt; 相同。
    • 不,我正在从与 HTML 文件相同的文件夹中加载图像。 (顺便说一句,本地)
    • 啊,一些/大多数/所有现代浏览器将所有本地文件视为相互不信任。有些选项允许访问;例如,对于 Chrome,您可以使用标志“--allow-file-access-from-files”开始它(漂亮确定就是这样......)
    猜你喜欢
    • 2015-09-27
    • 2014-03-20
    • 2013-04-13
    • 2013-03-30
    • 2016-07-13
    • 2023-04-09
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多