public static Bitmap Convert16bppTo8bpp( 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
int sourceBasePtr = (int) sourceData.Scan0.ToPointer( );
int newBasePtr = (int) 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;
}