21

HTML 5 キャンバスのピクセル操作を使用して動的な視覚効果を実行しようとしていますが、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 でプロファイリングすると、CanvasPixelArray が使用されていない次のコードよりも 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 の double と、CanvasPixelArray で使用される内部の符号なし 8 ビット整数との間の変換によるものです。

  1. この推測は正しいですか?
  2. CanvasPixelArray で値を設定するのにかかる時間を短縮する方法はありますか?
4

4 に答える 4

12

dataピクセル配列への参照をキャッシュしてみてください。速度低下は、 への追加のプロパティ アクセスが原因である可能性がありますimageData.data。詳細については、この記事を参照してください。

たとえば、これは現在持っているものよりも高速である必要があります。

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);
于 2010-06-02T18:11:24.300 に答える
4

ピクセルを操作したいので、これが役立つかどうかはわかりませんが、私にとっては、Firefox 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)
于 2010-11-26T03:28:55.400 に答える
1

ある種の「ブリッティング」を行っているように見えるので、drawImageまたは一度にputImageDataが役立つ可能性があります。大規模な「ブリッティング」操作を使用するのではなく、ピクセルを個別にコピーするために 25 万回ループすると、Javascript だけでなく、はるかに遅くなる傾向があります;-)。

于 2010-04-04T01:43:55.663 に答える
1

奇妙なことに、2 次元オブジェクト配列のループは、1 次元配列オフセット calcs とオブジェクトなしよりも高速です。それに応じてフォーマットし、それが役立つかどうかを確認します (私のテストでは、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

于 2015-09-17T16:19:05.123 に答える