public static Bitmap Convert16bppTo8bpp(this Bitmap bimap)
{
Bitmap newImage = null;
int layers = 0;
// get image size
int width = bimap.Width;
int height = bimap.Height;
// create new image depending on source image format
switch (bimap.PixelFormat)
{
case PixelFormat.Format16bppGrayScale:
// create new grayscale image
newImage = CreateGrayscaleImage(width, height);
layers = 1;
break;
case PixelFormat.Format48bppRgb:
// create new color 24 bpp image
newImage = new Bitmap(width, height, PixelFormat.Format24bppRgb);
layers = 3;
break;
case PixelFormat.Format64bppArgb:
// create new color 32 bpp image
newImage = new Bitmap(width, height, PixelFormat.Format32bppArgb);
layers = 4;
break;
case PixelFormat.Format64bppPArgb:
// create new color 32 bpp image
newImage = new Bitmap(width, height, PixelFormat.Format32bppPArgb);
layers = 4;
break;
default:
throw new UnsupportedImageFormatException("Invalid pixel format of the source image.");
}
// lock both images
BitmapData sourceData = bimap.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadOnly, bimap.PixelFormat);
BitmapData newData = newImage.LockBits(new Rectangle(0, 0, width, height),
ImageLockMode.ReadWrite, newImage.PixelFormat);
unsafe
{
// base pointers
byte* sourceBasePtr = (byte*)sourceData.Scan0.ToPointer();
byte* newBasePtr = (byte*)newData.Scan0.ToPointer();
// image strides
int sourceStride = sourceData.Stride;
int newStride = newData.Stride;
for (int y = 0; y < height; y++)
{
ushort* sourcePtr = (ushort*)(sourceBasePtr + y * sourceStride);
byte* newPtr = (byte*)(newBasePtr + y * newStride);
for (int x = 0, lineSize = width * layers; x < lineSize; x++, sourcePtr++, newPtr++)
{
*newPtr = (byte)(*sourcePtr >> 8);
}
}
}
// unlock both image
bimap.UnlockBits(sourceData);
newImage.UnlockBits(newData);
return newImage;
}