午後わてんのブログ

ベランダ菜園とWindows用アプリ作成(WPFとC#)

WPF、PixelFormatsのBgra32とPbgra32の違いは何?

7年前の疑問をAIに聞いて、返ってきた答えがわかりやすかったのでコピペ

非常に良いところに気づきましたね!画像処理をプログラムで行う際、この「P」があるかないかで計算結果(特に透明な部分の見た目)が大きく変わります。

結論から言うと、Pbgra32 の「P」は「Premultiplied(乗算済み)」の頭文字です。


1. 決定的な違い:アルファ値の扱い

Bgra32 (非乗算済み)

RGB(色)と A(透明度)が完全に独立して保存されています。

  • データ構造: [B,G,R,A]
  • 特徴: 私たちが直感的に理解しやすい形式です。例えば「不透明度50%の真っ赤」なら、RGBはそのまま (0, 0, 255)、Aは 128 となります。

Pbgra32 (乗算済みアルファ)

RGBの値に、あらかじめアルファ値を掛け算した状態で保存されています。

  • データ構造: [B * A, G * A, R * A, A](実際には A/255 を掛けた値)
  • 特徴: WPFレンダリングエンジン(内部処理)で標準的に使われる形式です。

2. なぜ Pbgra32 が存在するのか?(メリット)

「計算が二度手間じゃないか」と思うかもしれませんが、実は描画速度が圧倒的に速くなるからです。

画面上で画像を重ね合わせる(アルファブレンディング)とき、数学的には以下の計算を行います。

表示色 = (前景色 * 前景Alpha) + (背景色 * (1 - 前景Alpha))

  • Bgra32の場合: 描画のたびに「色 × Alpha」の掛け算をする必要があります。
  • Pbgra32の場合: すでに「色 × Alpha」が計算済みなので、そのまま足し算するだけで済みます。

WPFはこの効率化のために、内部的には Pbgra32 で画像を扱おうとします。


3. 画像処理アプリを作る際の注意点

画像処理のアルゴリズムを書くときは、基本的には Bgra32 を使うことを強くおすすめします。

[!WARNING] Pbgra32 で加工するときの罠 Pbgra32 のデータを直接ポインタでいじって「明るさ」などを変えると、計算が狂います。 例えば、半透明なピクセルに対して単純に値を加算すると、「Alpha値(透明度)よりもRGBの値の方が大きくなる」という、物理的にあり得ない色データが生成され、表示がバグる(色が白飛びしたり、変な枠線が出たりする)原因になります。


まとめ:どっちを使えばいい?

  • 今回のようなピクセル操作(明るさ変更など): Bgra32 を使いましょう。計算が直感的でミスが起きません。
  • とにかく描画パフォーマンスを極限まで上げたい: Pbgra32 を使いますが、ピクセル計算時に毎回 Alpha を考慮した複雑な処理が必要です。

先ほどのコードで PixelFormats.Bgra32 を指定したのは、計算をシンプルに保つための正解の選択だったわけです。

次は、この「Alpha(透明度)」も考慮して、画像を薄く(半透明に)する処理を書いてみますか?それとも、RGBのチャンネルを入れ替える(赤と青を逆にするなど)遊びをやってみますか?


コピペした感想

使ったAIはグーグルのこれ、普通の無料の

Google Gemini
Google Gemini
gemini.google.com

左下のコピーボタン
で、コピペなんだけど、左下にある回答をコピーボタンから一応コピーはできるけど、一部がコピーされないくて、数式の掛け算表記の"×"とか、"["が入っている行が空白になってしまうので、そこだけは手動でする必要があった。それ以外は強調表示とかも再現されている

7年前ってのは
半透明画像とWPFのPixelFormats.Pbgra32は相性が良くないかも - 午後わてんのブログ
https://gogowaten.hatenablog.com/entry/15904871
これね
当時は検索したけど、たいてい「Pbgra32のほうがパフォーマンスが良くなる」とかしか書いてなくて理解できなかった。
何のパフォーマンスなのか、描画なのか、画像処理なのか、アプリ全体なのか。そもそも、なぜパフォーマンスが良くなるのかとかね、見つけられなかった
結果、今まではBgra32を使っていて、それ自体は正解だったんだけど、Pbgra32よりパフォーマンスは劣るんだよなあとか思って気分が良くなかった

んで、今回はAIで画像処理についてコードを書いてもらったりしている中で、思い出して聞いてみたら、納得できる答えが返ってきて、しかもBgra32を気分よく使えるようになって、ブログに保存しておこうってなったわけ
スッキリした