private Bitmap ToBitmap(bool xor, bool transparent)
{
CursorImage ci;
CursorInfoHeader cih;
int ncolors;
Bitmap bmp;
BitmapData bits;
ColorPalette pal;
int biHeight;
int bytesPerLine;
if (cursor_data == null)
return new Bitmap(32, 32);
ci = cursor_data[this.id];
cih = ci.cursorHeader;
biHeight = cih.biHeight / 2;
if (!xor) {
// The AND mask is 1bit - very straightforward
bmp = new Bitmap(cih.biWidth, biHeight, PixelFormat.Format1bppIndexed);
pal = bmp.Palette;
pal.Entries[0] = Color.FromArgb(0, 0, 0);
pal.Entries[1] = Color.FromArgb(unchecked((int)0xffffffffff));
bits = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
for (int y = 0; y < biHeight; y++) {
Marshal.Copy(ci.cursorAND, bits.Stride * y, (IntPtr)(bits.Scan0.ToInt64() + bits.Stride * (biHeight - 1 - y)), bits.Stride);
}
bmp.UnlockBits(bits);
} else {
ncolors = (int)cih.biClrUsed;
if (ncolors == 0) {
if (cih.biBitCount < 24) {
ncolors = (int)(1 << cih.biBitCount);
}
}
switch(cih.biBitCount) {
case 1: { // Monochrome
bmp = new Bitmap (cih.biWidth, biHeight, PixelFormat.Format1bppIndexed);
break;
}
case 4: { // 4bpp
bmp = new Bitmap (cih.biWidth, biHeight, PixelFormat.Format4bppIndexed);
break;
}
case 8: { // 8bpp
bmp = new Bitmap (cih.biWidth, biHeight, PixelFormat.Format8bppIndexed);
break;
}
case 24:
case 32: { // 32bpp
bmp = new Bitmap (cih.biWidth, biHeight, PixelFormat.Format32bppArgb);
break;
}
default:
throw new Exception("Unexpected number of bits:" + cih.biBitCount.ToString());
}
if (cih.biBitCount < 24) {
pal = bmp.Palette; // Managed palette
for (int i = 0; i < ci.cursorColors.Length; i++)
pal.Entries[i] = Color.FromArgb((int)ci.cursorColors[i] | unchecked((int)0xff000000));
bmp.Palette = pal;
}
bytesPerLine = (int)((((cih.biWidth * cih.biBitCount) + 31) & ~31) >> 3);
bits = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
for (int y = 0; y < biHeight; y++)
Marshal.Copy(ci.cursorXOR, bytesPerLine * y, (IntPtr)(bits.Scan0.ToInt64() + bits.Stride * (biHeight - 1 - y)), bytesPerLine);
bmp.UnlockBits(bits);
}
if (transparent) {
bmp = new Bitmap(bmp); // This makes a 32bpp image out of an indexed one
// Apply the mask to make properly transparent
for (int y = 0; y < biHeight; y++) {
for (int x = 0; x < cih.biWidth / 8; x++) {
for (int bit = 7; bit >= 0; bit--) {
if (((ci.cursorAND[y * cih.biWidth / 8 +x] >> bit) & 1) != 0)
bmp.SetPixel(x*8 + 7-bit, biHeight - y - 1, Color.Transparent);
}
}
}
}
return bmp;
}
#endregion // Private Methods