問題タブ [putimagedata]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
javascript - キャンバス ノイズ関数が常に赤くしか表示されないのはなぜですか?
私が見たコードペンに基づいて、キャンバスにノイズ効果を適用しようとしていますが、これはSO answerに非常に似ているようです。
ランダムに透明なピクセルの「スクリーン」を生成したいのですが、その代わりに完全に不透明な赤のフィールドを取得します。キャンバスまたは型付き配列のどちらかに精通している人が、私が間違っていることを示してくれることを願っています。
(今のところ) ノイズのアニメーション化は気にしないので、codepen コードを大幅にリファクタリングしました。
私が知る限り、起こっていることの核心は、ImageData
の生データ表現 (各ピクセルの赤、緑、青、およびアルファ値を連続して反映する一連の 8 ビット要素)をラップすることです。 32 ビット配列。これにより、各ピクセルを 1 つのタプルとして操作できます。ピクセルあたり 4 つの要素ではなく、ピクセルあたり 1 つの要素を持つ配列を取得します。
次に、その配列内の要素を反復処理し、ノイズ ロジックに基づいて各要素 (つまり、各ピクセル) に RGBA 値を書き込みます。ここでのノイズ ロジックは非常に単純です。各ピクセルが「ノイズ」ピクセルである確率は 50% までです。
ノイズ ピクセルには 32 ビット値 が割り当てられます0x00000088
。これは、(配列によって提供される 32 ビット チャンクのおかげで) rgba(0, 0, 0, 0.5)
、つまり黒、50% の不透明度に相当します。
ノイズのないピクセルには 32 ビット値 が割り当てられます0x00000000
。これは黒の不透明度 0%、つまり完全に透明です。
buffer32
興味深いことに、キャンバスには を書きません。代わりに、 のimageData
構築に使用されたを記述しているためUint32Array
、何らかの参照渡しによって imageData オブジェクトを変更していると思われます。これがなぜなのか正確にはわかりません。値と参照の受け渡しが JS で一般的にどのように機能するかは知っていますが (スカラーは値によって渡され、オブジェクトは参照によって渡されます)、型指定されていない配列の世界では、配列コンストラクターに渡される値が配列の長さを決定するだけです。それは明らかにここで起こっていることではありません。
前述のように、50% または 100% 透明な黒いピクセルのフィールドの代わりに、すべて赤のすべてのベタ ピクセルのフィールドを取得します。赤が表示されるとは思わないだけでなく、ランダムな色の割り当ての証拠はありません。すべてのピクセルが赤一色です。
2 つの 16 進数の値をいじってみると、これにより適切な種類の分布を持つ黒地に赤の散乱が生成されることがわかりました。
しかし、それはまだ真っ赤で、真っ黒です。基になるキャンバス データは、非表示にする必要があるピクセルを通して表示されません。
紛らわしいことに、赤か黒以外の色を取得できません。また、100% 不透明以外の透明度も得られません。切断を説明するために、ランダム要素を削除し、これらの 9 つの値のそれぞれをすべてのピクセルに書き込んで、何が起こるかを確認しました。
どうしたの?
編集: のMDN 記事にUint32Array
基づいて、 と不気味な突然変異を省いた後の同様の (悪い) 結果:ImageData.data
canvas - WebAssembly からキャンバスを更新するために 2 つの完全なコピーを避けるには?
JavaScript では、キャンバスのピクセルを直接操作して、単一のコピーで更新できます。
しかし、wasmTypedArray
では、wasm メモリを使用して独自のものを割り当てる必要があり、その後使用できますimageData.data.set(myTypedArray)
が、新しい型付き配列の内容全体をキャンバスの型付き配列にコピーするだけのように見えますputImageData
。 2回目。
を使用して単一のコピーのみでキャンバスを更新できるように、キャンバスの ImageData を新しい ImageData に再割り当てする方法はありますctx.putImageData()
か?
そうでない場合、wasm を使用して画像を操作する利点の多くは、非効率的な二重コピーと二重のメモリ内表現によって無駄になるように思われます。特に、大きな画像を操作したり、canvas を継続的に更新したりする場合に顕著です。