0

このコードを検討してください:

var deSaturated = deSaturate(greyscaleCtx.getImageData(0, 0, canvasWidth, canvasHeight));

imageData は getImageData キャンバス関数から取得されます。

function deSaturate (imageData) {
                var theData = imageData.data;

                var dataLength = theData.length;
                var i = dataLength-1;
                var lightLevel;
                // Iterate through each pixel, desaturating it
                while ( i >= 0) {
                    // To find the desaturated value, average the brightness of the red, green, and blue values

                    theData[i] = theData[i+1] = theData[i+2] = (theData[i] + theData[i + 1] + theData[i + 2]) / 3;

                    // Fully opaque
                    theData[i+3] = 255;
                    // returning an average intensity of all pixels.  Used for calibrating sensitivity based on room light level.
                    lightLevel += theData[i]; //combining the light level in the samefunction
                    i -= 4;

                }

                imageData.data = theData; //bring back theData into imageData.data - do I really need this?


                var r = [lightLevel/dataLength,imageData]
                return r;
            }

このコードの作成と最適化中に、js が "theData" 変数などをどのように扱っているかがよくわからないことがわかりました。imageData.data を参照する簡単な方法で作業しています。この場合、最終的に次のコードは必要ありません。

imageData.data = theData

しかし、その後、パフォーマンスの低下 (大量の DOM I/O) を支払うことになりますか?

またはtheData = imageData.data、元の配列 (Uint8ClampedArray として表される) を実際にコピーしてから、変更されたデータを に再割り当てする必要がありimageData.dataます。

これは基本的な JavaScript だと思いますが、MDN やその他の開発者リソースで矛盾したコード例を見つけたので、これを正しく理解したいと思います。

助けてくれてありがとう!

4

2 に答える 2

1

javascriptでは、arrayまたはのいずれかobjectを割り当てると、その配列またはオブジェクトへの参照が割り当てられます。データのコピーは作成されません。コピーは、新しい配列を物理的に作成してデータをコピーするか、それを実行するように設計された関数を呼び出す場合にのみ作成されます。

したがって、imageData.dataがの場合array、に割り当てるとtheData、同じデータを参照するためのショートカットになります。データの新しいコピーは作成されません。したがって、が指すデータを変更した後、データのコピーは1つだけであり、両方とポイントがすでに同じデータのコピーを指しているため、データtheDataを割り当てる必要はありません。imageData.datatheDataimageData.data

したがって、あなたの質問に直接答える場合、この行は不要です。

imageData.data = theData;
于 2012-10-27T16:08:17.300 に答える
1

簡単なテストを実行しました:

    var idata = ctx.getImageData(0,0,300,300);
    var data = idata.data;
    for(var i=0;i<data.length;i++){
        data[i]=0;
    }

    ctx.putImageData(idata,0,0);

そして、期待どおりに画面の一部を適切に空白にします。ただし、putImageData がなければ何も起こりません。そのため、別の変数に格納されているかどうかに関係なく、データ オブジェクトを変更すると、その imageData オブジェクトに反映されますただし、これは putImageData が呼び出されるまでキャンバスには影響しません。

したがって、はい、その最終的な割り当てを削除すると、必要に応じて機能します。

ただし、それが Uint8ClampedArray であるという有効な仮定ではないことを警告します。はい、それがChromeの処理方法です(最後に確認しました)。実際、公式仕様で使用されているものです。ただし、一部のブラウザーには Uint8ClampedArray の概念がありませんが、現在は非推奨の CanvasPixelArray を使用してキャンバスをサポートしています。

したがって、得られることが保証されているのは、配列のようなインターフェースを持つものだけです。新しい Uint8ClampedArray を作成して画像データの興味深い機能をキャッシュしようとしたとき、これを難しい方法で学ばなければなりませんでしたが、一部のブラウザーでは失敗しました。

参照: https://developer.mozilla.org/en-US/docs/DOM/CanvasPixelArray

于 2012-10-27T16:29:28.603 に答える