迭代画布中像素的最快方法,并将其中一些复制到另一个画布中 [英] Fastest way to iterate pixels in a canvas and copy some of them in another one

查看:137
本文介绍了迭代画布中像素的最快方法,并将其中一些复制到另一个画布中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm into a 2D/3D graphic project and I'm facing a performance problem.

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

My algorithm takes two images: a picture and the relative grayscale depth map. I have also an array of 10 canvases ("layers") initally blank. A note: all the images have the same dimension.

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

I need to check every pixel X;Y of the depth map and, depending on its color value, access one of the 10 canvases and draw the X;Y pixel of the original image on it.

结果算法如下:

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引起的。是否有更快的方式以我需要的方式绘制像素?谢谢

A loop like that takes around 3 minutes to complete on a 200x200 image! I'm pretty sure that the slowness is caused by the last function, putImageData. Is there a faster way to draw pixels in the way I need? Thank you

推荐答案

不要在循环的每次迭代中设置图像数据。这是一个繁重的操作,你正在执行它 40.000 (200 * 200) 时间。

这可以为您节省一些处理能力:

Don't set your image data in every iteration of the loop. That's a heavy operation, and you're executing it 40.000 (200*200) times.
This should save you a bit of processing power:

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]);
}

我还没有测试过,但是这应该给你一点点如何做到这一点的想法。

I haven't tested it, but this should give you a bit of an idea of how to do it.

这篇关于迭代画布中像素的最快方法,并将其中一些复制到另一个画布中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆