Windows PhoneやWindowsストアアプリの開発で超便利なWriteableBitmapExですが、Blitメソッドを使ったときにハマったので、メモとして書いておきます。
まずは不透明度が100%の画像を2枚用意します。
これらの画像を以下のコードを使って画像合成します。
WriteableBitmapExはWriteableBitmapの拡張メソッド集ですので、1ピクセルx1ピクセルの画像をダミーで生成して、FromContentメソッドで画像を読み込みます。それをBlitメソッドで合成しています。
protected override async void OnNavigatedTo(NavigationEventArgs e) { var dummy = new WriteableBitmap(1, 1); var image1 = await dummy.FromContent(new Uri("ms-appx:///Assets/image1.png")); var image2 = await dummy.FromContent(new Uri("ms-appx:///Assets/image2.png")); image1.Blit(new Rect(0, 0, image1.PixelWidth, image1.PixelHeight), image2, new Rect(0, 0, image2.PixelWidth, image2.PixelHeight)); blendedImage.Source = image1; }
Imageコントロールに読み込ませて2つ重ねたのと、WriteableBitmapExで合成したものを比較してみましょう。
結果は下図の通りです。左がImageコントロールを重ねたもの、右がBlitメソッドで合成したものです。意図通り……というか同じ結果ですね。
さて次に、不透明度50%の画像を2枚用意します。透けています。
これらの画像を合成した結果、下図の通りとなりました。Imageコントロールを重ねたものと、Blitメソッドで合成したものを比較してみましょう。
アルファブレンドの扱いの違いで不透明度100%画像の合成と50%画像の合成とでは、結果が違ってくることが分かりました。
追記(2013/7/4 14:41)
アルファブレンドの計算方法を変更してみた。色合いは近くなったが完全ではない。合成対象ではないはずの中央右側の緑色が薄くなってしまっています。
計算量が多いのは後でなんとかするとして、現状の計算方法を以下の通りです。
var As = (double)sa / 255; var Ad = (double)da / 255; var 係数 = (1 - As) * Ad; var Ar = As + 係数; var r2 = (sr * As) + (dr * 係数) / Ar; var g2 = (sg * As) + (dg * 係数) / Ar; var b2 = (sb * As) + (db * 係数) / Ar; destPixel = (int)(Ar * 255) << 24 | (int)r2 << 16 | (int)g2 << 8 | (int)b2;