代码之家  ›  专栏  ›  技术社区  ›  Nixuz

为什么设置HTML5的canvaspixelaray值会慢得离谱,我如何才能更快?

  •  21
  • Nixuz  · 技术社区  · 15 年前

    我正在尝试使用HTML5画布的像素操作来进行一些动态视觉效果,但是我遇到了一个问题,即在CanvaSpixelArray中设置像素的速度非常慢。

    例如,如果我有如下代码:

    imageData = ctx.getImageData(0, 0, 500, 500);
    
    for (var i = 0; i < imageData.length; i += 4){
        imageData.data[i] = buffer[i];
        imageData.data[i + 1] = buffer[i + 1];
        imageData.data[i + 2] = buffer[i + 2];
    }
    
    ctx.putImageData(imageData, 0, 0);
    

    使用chrome进行分析显示,它比不使用canvaspixelaray的以下代码慢44%。

    tempArray = new Array(500 * 500 * 4);
    imageData = ctx.getImageData(0, 0, 500, 500);
    
    for (var i = 0; i < imageData.length; i += 4){
        tempArray[i] = buffer[i];
        tempArray[i + 1] = buffer[i + 1];
        tempArray[i + 2] = buffer[i + 2];
    }
    
    ctx.putImageData(imageData, 0, 0);
    

    我的猜测是,这种速度减慢的原因是由于JavaScript双精度数和CanvaSpixelaray使用的内部无符号8bit整数之间的转换。

    1. 这个猜测是正确的吗?
    2. 是否有必要减少在CanvaSpixelaray中设置值所花费的时间?
    4 回复  |  直到 9 年前
        1
  •  12
  •   jimr    15 年前

    尝试缓存对 data 像素阵列。你的经济放缓可能归因于 imageData.data . 见 this article 更多解释。

    例如,这应该比你现在拥有的更快。

    var imageData = ctx.getImageData(0, 0, 500, 500),
        data = imageData.data,
        len = data.length;
    
    for (var i = 0; i < len; i += 4){
     data[i] = buffer[i];
     data[i + 1] = buffer[i + 1];
     data[i + 2] = buffer[i + 2];
    }
    
    ctx.putImageData(imageData, 0, 0);
    
        2
  •  4
  •   Corey Trager    14 年前

    我不知道这是否对你有帮助,因为你想操纵像素,但对我来说,在火狐3.6.8中,仅仅调用putimagedata非常非常慢,而不需要任何像素操作。在我的例子中,我只想恢复用getImageData保存的图像的早期版本。太慢了。

    相反,我使用todataurl/drawimage让它工作得很好。对我来说,它的工作速度足够快,我可以在处理mousemove事件时调用它:

    要保存:

    savedImage = new Image()  
    savedImage.src = canvas.toDataURL("image/png")
    

    要还原的:

    ctx = canvas.getContext('2d')  
    ctx.drawImage(savedImage,0,0)
    
        3
  •  1
  •   Alex Martelli    15 年前

    看起来你在做某种“飞碟”,所以也许 drawImage 或者一次全部 putImageData 会有帮助的。循环25万次以单独复制像素,而不是使用大量的“blitting”操作,往往要慢得多——而不仅仅是在javascript中;-)。

        4
  •  1
  •   Anthony Caudill    9 年前

    奇怪的是,通过二维对象数组的循环比一维数组偏移计算快,而且没有对象。相应地格式化,看看是否有帮助(在我的测试中,速度快了20倍)。

    (注意:这个脚本可能会使您的浏览器崩溃!如果你跑步,坐几分钟,让它做它该做的事) http://jsfiddle.net/hc52jx04/16/

    function arrangeImageData (target) {
    
    var imageCapture = target.context.getImageData(0, 0, target.width, target.height);
    var imageData = {
        data: []
    };
    imageData.data[0] = [];
    var x = 0;
    var y = 0;
    var imageLimit = imageCapture.data.length;
    
    for (var index = 0; index < imageLimit; index += 4) {
    
        if (x == target.width) {
            y++;
            imageData.data[y] = [];
            x = 0;
        }
    
        imageData.data[y][x] = {
            red: imageCapture.data[index],
            green: imageCapture.data[index + 1],
            blue: imageCapture.data[index + 2],
            alpha: imageCapture.data[index + 3]
        };
        x++;
    }
    return imageData;
    
    }
    
    
    function codifyImageData (target, data) {
    
    var imageData = data.data;
    
    var index = 0;
    var codedImage = target.context.createImageData(target.width, target.height);
    
    for (var y = 0; y < target.height; y++) {
    
        for (var x = 0; x < target.width; x++) {
    
            codedImage.data[index] = imageData[y][x].red;
            index++;
            codedImage.data[index] = imageData[y][x].green;
            index++;
            codedImage.data[index] = imageData[y][x].blue;
            index++;
            codedImage.data[index] = imageData[y][x].alpha;
            index++;
        }
    
    }
    
    return codedImage;
    
    }
    

    更多信息: http://discourse.wicg.io/t/why-a-straight-array-for-canvas-getimagedata/1020/6