【发布时间】:2014-08-15 17:00:04
【问题描述】:
我从 BitmapSource (RenderTargetBitmap) 中提取了位图,其中带有蓝色圆圈。 RenderTargetBitmap 是使用 PixelFormats.Pbgra32 创建的。
PixelFormats Pbgra32 将每个颜色通道预乘以 alpha 值。因此,当我尝试将位图转换为光标时,我得到的不透明图像比应有的要少。
我找到了here 问题的解决方案,它将位图克隆到Format24bppRgb 并手动设置 R、B、G 和 alpha 值。然而,解决方案工作得非常好,但对于克隆的位图,我看到视觉周围有黑色边框。
我可以去掉克隆位图中的黑色边框吗? (我怀疑是 SafeCopy 方法内部的东西)
链接中使用的方法是:
private static void SafeCopy(BitmapData srcData, BitmapData dstData, byte alphaLevel)
{
for (int y = 0; y < srcData.Height; y++)
for (int x = 0; x < srcData.Width; x++)
{
byte b = Marshal.ReadByte(srcData.Scan0, y * srcData.Stride + x * 3);
byte g = Marshal.ReadByte(srcData.Scan0, y * srcData.Stride + x * 3 + 1);
byte r = Marshal.ReadByte(srcData.Scan0, y * srcData.Stride + x * 3 + 2);
Marshal.WriteByte(dstData.Scan0, y * dstData.Stride + x * 4, b);
Marshal.WriteByte(dstData.Scan0, y * dstData.Stride + x * 4 + 1, g);
Marshal.WriteByte(dstData.Scan0, y * dstData.Stride + x * 4 + 2, r);
Marshal.WriteByte(dstData.Scan0, y * dstData.Stride + x * 4 + 3, alphaLevel);
}
}
private static Cursor CreateCustomCursorInternal(Bitmap bitmap, double opacity)
{
Bitmap cursorBitmap = null;
IconInfo iconInfo = new IconInfo();
Rectangle rectangle = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
try
{
byte alphaLevel = System.Convert.ToByte(byte.MaxValue * opacity);
// Here, the pre-multiplied alpha channel is specified
cursorBitmap = new Bitmap(bitmap.Width, bitmap.Height,
PixelFormat.Format32bppPArgb);
// Assuming the source bitmap can be locked in a 24 bits per pixel format
BitmapData bitmapData = bitmap.LockBits(rectangle, ImageLockMode.ReadOnly,
PixelFormat.Format24bppRgb);
BitmapData cursorBitmapData = cursorBitmap.LockBits(rectangle,
ImageLockMode.WriteOnly, cursorBitmap.PixelFormat);
// Use SafeCopy() to set the bitmap contents
SafeCopy(bitmapData, cursorBitmapData, alphaLevel);
cursorBitmap.UnlockBits(cursorBitmapData);
bitmap.UnlockBits(bitmapData);
.......
}
原始位图:
克隆位图:
【问题讨论】:
-
通过转换为 24bpp RGB,您移除了 Alpha 通道,即移除了透明背景。那么您希望背景颜色是什么?
-
没有
cursorBitmap(克隆位图)仍然是Format32bppPArgb。只是我将源位图锁定在 24bpp 以避免预乘位,然后从源位图的 SafeCopy 方法中手动设置 cursorBitmap 上的 R、G、B 和 alpha 值。因此,克隆的位图仍然具有 alpha 值。 -
当然,但是您(错误地)将相同的 alpha 值应用于所有像素。但是对于完全透明的背景像素,它必须是
0。您可以简单地通过将每个像素 R、G 和 B 值乘以255d/(double)A来恢复预乘,而不是转换为 RGB。 -
你想对所有像素应用不透明度,当然。但是透明背景的像素(圆圈外)在原始图像中的 alpha 值(即不透明度)为
0。你不会想要改变它。他们应该保持这个价值。但是通过转换为 24bpp RGB,您可以有效地删除所有 alpha 值,这会留下黑色背景像素或背景像素所具有的任何(不可见)颜色。同样,转换为 24bpp 是错误的。它有效地消除了背景的透明度,这不是您想要的。 -
或者更简单,转换为
Format32bppArgb而不是Format24bppRgb,然后应用您的全局alpha值。这可能已经解决了所有问题。