I have bitmap extracted from BitmapSource (RenderTargetBitmap) with blue circle in it. RenderTargetBitmap is created with PixelFormats.Pbgra32.
PixelFormats Pbgra32
pre-multiplies each color channel with alpha value. So, when I try to convert bitmap to cursor I was getting less opaque image than is should have.
I found solution to the problem here which clone the bitmap to Format24bppRgb
and manually set R,B,G and alpha values. However, solutions works perfectly fine but for cloned bitmap I see black border around visual.
Can I get rid of that black border in cloned bitmap? (I suspect it's something inside SafeCopy method)
Methods used from the link are:
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);
.......
}
Original bitmap:
Cloned bitmap: