高パフォーマンスなクライアントサイド画像処理

ブラウザでの画像処理は、今や標準的な要件となっています。フォトエディタ、アセットツールキット、あるいはアクセシビリティフィルターなどを構築する場合、UIのレスポンスを維持するために低レイテンシが求められます。

単純なタスクとして「色の反転」があります。これはRGB値をその負の値に反転させることを意味します。4K画像に対して標準的な手法を用いると、ハードウェアのボトルネックに直面します。

問題点:単純な反復処理

ほとんどの開発者は getImageData() メソッドを使用します。これは Uint8ClampedArray を返します。この配列は、ピクセルを赤 (Red)、緑 (Green)、青 (Blue)、アルファ (Alpha) の各チャンネル (RGBA) として保存します。

標準的なループは以下のようになります:

これは小さな画像には有効ですが、4Kアセットでは失敗します。4K画像には800万ピクセル以上が含まれています。標準的なループでは3,300万回以上の個別の書き込みが発生します。これによりメインスレッドがブロックされ、ブラウザのカクつきやフレームドロップの原因となります。

解決策:32ビットバッファ操作

ピクセルを4つの個別のチャンネルとして扱うのをやめましょう。代わりに、データバッファの上に Uint32Array を重ね合わせます。

32ビットビューを使用することで、R、G、B、Aを単一の整数としてグループ化できます。これにより、ループの回数は3,300万回ではなく、わずか820万回になります。4回ではなく、ピクセルごとに1回の操作で処理できるようになります。

ビット演算 XOR による高速な色反転

アルファ値に触れずに色を反転させるには、ビット演算の XOR 演算子 (^) を使用します。マスクとして 0x00FFFFFF を使用してください。

仕組み:

結果:

プロのヒント:Web Worker を使用する 高解像度のファイルを大量に処理する場合、32ビット操作であってもUIが遅くなる可能性があります。ロジックを Web Worker に移動しましょう。バッファを渡すには Transferable Objects を使用します。これによりデータのコピーを回避し、メインスレッドを自由に保つことができます。

重いループの使用はやめましょう。32ビットワードとビットフラグを活用して、軽量で高速な画像パイプラインを構築してください。

出典: https://dev.to/sharjeel360/high-performance-client-side-image-processing-optimizing-canvas-color-inversion-with-uint32array-1bgg