ドラッグ アンド ドロップ操作で部分的に透明な画像を使用したい。これですべての設定が完了し、正常に動作しますが、実際の透明度への変換には奇妙な副作用があります。何らかの理由で、ピクセルが黒い背景に対してブレンドされているように見えます。
次の図は、問題を説明しています。
図 a) は元のビットマップです。
図 b) は、アルファ ブレンディングが実行された後に生成されるものです。明らかに、これは意図した 50% アルファ フィルターよりもかなり暗いです。
図 c) は目的の効果、画像 a) は 50% の透明度 (描画プログラムでコンポジションに追加) です。
透明な画像を生成するために使用するコードは次のとおりです。
Bitmap bmpNew = new Bitmap(bmpOriginal.Width, bmpOriginal.Height);
Graphics g = Graphics.FromImage(bmpNew);
// Making the bitmap 50% transparent:
float[][] ptsArray ={
new float[] {1, 0, 0, 0, 0}, // Red
new float[] {0, 1, 0, 0, 0}, // Green
new float[] {0, 0, 1, 0, 0}, // Blue
new float[] {0, 0, 0, 0.5f, 0}, // Alpha
new float[] {0, 0, 0, 0, 1} // Brightness
};
ColorMatrix clrMatrix = new ColorMatrix(ptsArray);
ImageAttributes imgAttributes = new ImageAttributes();
imgAttributes.SetColorMatrix(clrMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
g.DrawImage(bmpOriginal, new Rectangle(0, 0, bmpOriginal.Width, bmpOriginal.Height), 0, 0, bmpOriginal.Width, bmpOriginal.Height, GraphicsUnit.Pixel, imgAttributes);
Cursors.Default.Draw(g, new Rectangle(bmpOriginal.Width / 2 - 8, bmpOriginal.Height / 2 - 8, 32, 32));
g.Dispose();
imgAttributes.Dispose();
return bmpNew;
アルファブレンディングが機能しない理由を知っている人はいますか?
アップデート I:
明確にするために、描画されたサーフェスの上でアルファブレンディングを行っている場合、コードは機能します。問題は、既存の画像から完全に半透明の画像を作成し、これをドラッグ アンド ドロップ操作中に動的カーソルとして使用することです。上記をスキップして、色 88ffffff の塗りつぶされた長方形のみをペイントしても、濃い灰色が得られます。アイコンで何か怪しいことが起こっています。
更新 II:
いろいろと調べて、これが Cursor の作成と関係があると信じているので、そのコードも以下に含めます。CreateIconIndirect 呼び出しの直前にビットマップを GetPixel サンプリングすると、4 つの色の値はそのままのように見えます。したがって、犯人は IconInfo 構造の hbmColor または hbmMask メンバーである可能性があると感じています。
IconInfo 構造は次のとおりです。
public struct IconInfo { // http://msdn.microsoft.com/en-us/library/ms648052(VS.85).aspx
public bool fIcon; // Icon or cursor. True = Icon, False = Cursor
public int xHotspot;
public int yHotspot;
public IntPtr hbmMask; // Specifies the icon bitmask bitmap. If this structure defines a black and white icon,
// this bitmask is formatted so that the upper half is the icon AND bitmask and the lower
// half is the icon XOR bitmask. Under this condition, the height should be an even multiple of two.
// If this structure defines a color icon, this mask only defines the AND bitmask of the icon.
public IntPtr hbmColor; // Handle to the icon color bitmap. This member can be optional if this structure defines a black
// and white icon. The AND bitmask of hbmMask is applied with the SRCAND flag to the destination;
// subsequently, the color bitmap is applied (using XOR) to the destination by using the SRCINVERT flag.
}
そして、実際に Cursor を作成するコードは次のとおりです。
public static Cursor CreateCursor(Bitmap bmp, int xHotSpot, int yHotSpot) {
IconInfo iconInfo = new IconInfo();
GetIconInfo(bmp.GetHicon(), ref iconInfo);
iconInfo.hbmColor = (IntPtr)0;
iconInfo.hbmMask = bmp.GetHbitmap();
iconInfo.xHotspot = xHotSpot;
iconInfo.yHotspot = yHotSpot;
iconInfo.fIcon = false;
return new Cursor(CreateIconIndirect(ref iconInfo));
}
2 つの外部関数は次のように定義されます。
[DllImport("user32.dll", EntryPoint = "CreateIconIndirect")]
public static extern IntPtr CreateIconIndirect(ref IconInfo icon);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetIconInfo(IntPtr hIcon, ref IconInfo pIconInfo);