6

2D/3D グラフィック プロジェクトに参加していますが、パフォーマンスの問題に直面しています。

私のアルゴリズムは、写真と相対グレースケール深度マップの 2 つの画像を取ります。また、最初は空白の 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 が原因であることは間違いありません。必要な方法でピクセルを描画するより高速な方法はありますか? ありがとうございました

4

1 に答える 1

13

ループの反復ごとに画像データを設定しないでください。それは重い操作であり、あなたはそれを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]);
}

私はそれをテストしていませんが、これはあなたにそれを行う方法の少しのアイデアを与えるはずです.

于 2012-12-17T15:44:21.233 に答える