【问题标题】:Fastest way to iterate pixels in a canvas and copy some of them in another one在画布中迭代像素并将其中一些复制到另一个中的最快方法
【发布时间】:2012-12-17 15:34:40
【问题描述】:

我正在进行 2D/3D 图形项目,但遇到了性能问题。

我的算法需要两张图像:一张图片和相对灰度深度图。 我还有一组 10 个画布(“图层”)最初是空白的。注意:所有图像的尺寸相同。

我需要检查深度图的每个像素 X;Y,并根据其颜色值访问 10 个画布之一并在其上绘制原始图像的 X;Y 像素。

生成的算法类似于:

for (var y = 0; y < totalHeight; ++y) {
   for (var x = 0; x < totalWidth; ++x) {
     var index = (y * totalWidth + x) * 4; // index of the current pixel
     // parse depth level using luminosity method
     var depthLevel = Math.round(
         0.21 * depthData[index] + 
         0.71 * depthData[index + 1] + 
         0.07 * depthData[index + 2]
     );

     // get the proper layer to modify
     var layerIndex = Math.floor((layersCount / 256) * depthLevel);
     var layerContext = layers[layerIndex].getContext("2d");
     var layerData = layerContext.getImageData(0, 0, totalWidth, totalHeight);

     layerData.data[index] = originalData[index];
     layerData.data[index + 1] = originalData[index + 1];
     layerData.data[index + 2] = originalData[index + 2];
     layerData.data[index + 3] = originalData[index + 3];

     layerContext.putImageData(layerData, 0, 0);
}

在 200x200 的图像上完成这样的循环大约需要 3 分钟!我很确定缓慢是由最后一个函数 putImageData 引起的。有没有更快的方法以我需要的方式绘制像素?谢谢

【问题讨论】:

    标签: javascript html canvas putimagedata


    【解决方案1】:

    不要在循环的每次迭代中设置图像数据。这是一个繁重的操作,您正在执行它40.000 (200*200) 次。
    这应该会为您节省一些处理能力:

    var contexts = [];
    var data = [];
    // Save your contexts and data to 2 arrays.
    for (var i = 0; i < layers.length; i++) {
        contexts[i] = layers[i].getContext("2d");
        data[i] = contexts[i].getImageData(0, 0, totalWidth, totalHeight);
    }
    
    for (var y = 0; y < totalHeight; ++y) {
        for (var x = 0; x < totalWidth; ++x) {
            var index = (y * totalWidth + x) * 4; // index of the current pixel
            // parse depth level using luminosity method
            var depthLevel = Math.round(
                0.21 * depthData[index]
              + 0.71 * depthData[index + 1]
              + 0.07 * depthData[index + 2]);
    
            // get the proper layer to modify
            var layerIndex = Math.floor((layersCount / 256) * depthLevel);
    
            data[layerIndex].data[index] = originalData[index];
            data[layerIndex].data[index + 1] = originalData[index + 1];
            data[layerIndex].data[index + 2] = originalData[index + 2];
            data[layerIndex].data[index + 3] = originalData[index + 3];
        }
    }
    
    // Apply your new data to the contexts.
    for (var i = 0; i < layers.length; i++) { 
        contexts[i].putImageData(data[i]);
    }
    

    我还没有测试过,但这应该能让你对如何做有一些了解。

    【讨论】:

    • 有适合您的“救世主”徽章吗? :) 非常感谢,现在它的速度很快
    • 哈哈,没问题:D徽章与否,接受的答案就足够了^_^
    猜你喜欢
    • 2015-09-06
    • 1970-01-01
    • 2018-06-09
    • 2018-01-03
    • 2011-11-17
    • 2016-03-03
    • 2013-01-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多