我制作了一个jsFiddle,用于演示JavaScript中的像素操作。它在Chrome中运行得非常好。然后我开始在Firefox上测试它。
它不起作用,它引发了一个错误:
IndexSizeError: Index or size is negative or greater than the allowed amount
这让我很困惑。但是等等,还有更多。
当我再次点击Run
时,代码突然有效。我不知道这是什么巫术,或者只是一些奇怪的Firefox bug。
您可以在此处查看问题:http://jsfiddle.net/DerekL/RdK7H/
当您在jsFiddle中时,单击选择文件并选择一个PNG文件。你应该看到代码不起作用。然后单击“运行”。再做同样的事情,它突然起作用。
Firefox中的一些功能也存在一些问题,这也让我感到沮丧,但这并不是这个问题的一部分。
如果你需要知道,我使用的是Firefox 26.0。
答案 0 :(得分:1)
这是因为您的图像尚未完成加载,因此返回图像的默认宽度和高度(均为0)。由于您无法使用0作为getImageData()
的宽度和高度,因此会出现错误。
当我再次单击“运行”时,代码突然运行。我不知道是什么 巫术就是这个,或者它只是一些奇怪的Firefox bug。
这是因为图像现在位于缓存中,并且在您尝试读取其宽度和高度之前,浏览器恰好能够提供它(不,错误在您的代码中:-) )。
使用busy循环和超时值处理图像加载是乞求失败。
确保向图像添加onload
处理程序(这可能需要您稍微重构代码以支持回调(或承诺),并且返回值将无效,原因与错误):
getRGBArray: function(uri, callback){ /// add parameter for callback here
var image = new Image();
image.onload = imageLoaded; /// add an onload handler here
image.src = uri;
function imageLoaded() {
//var t = Date.now();
//while(Date.now() - t < 3000 && !image.width);
var width = this.width, /// replace image with this to be sure you
height = this.height, /// ..are dealing with the correct image in
canvas = $("<canvas>").attr({ /// ..case you load several ones..
width: width,
height: height
}).appendTo("body"),
ctx = canvas[0].getContext("2d");
ctx.drawImage(this, 0, 0);
var imgData = ctx.getImageData(0, 0, width, height).data;
...
callback(imgData); /// example of callback
}
...
}
可选择分开图像加载,这样您就可以调用此功能,而不必依赖图像是否已加载。
<强>更新强>
如前所述,您可以将图像加载与主代码分开。例如 - 不是在getRGBArray()
函数中加载图像,而是将其预先加载到代码中的其他位置并将图像作为参数传递(回调无法避免,但您可以在加载后保持原始代码同步点):
function loadImage(url, callback) {
var image = new Image();
image.onload = function() {
callback(this);
}
image.src = uri;
}
然后像这样调用它:
loadImage(url, readyToGo);
function readyToGo(image) {
var pixels = getRGBArray(image);
...
}
原始函数中的一个小修改,使其使用传递的图像而不是url:
getRGBArray: function(image){
var width = image.width,
height = image.height,
canvas = $("<canvas>").attr({
width: width,
height: height
}).appendTo("body"),
ctx = canvas[0].getContext("2d");
ctx.drawImage(image, 0, 0);
var imgData = ctx.getImageData(0, 0, width, height).data;
...
return opt;
}
...
}
希望这有帮助!