public unsafe Bitmap Apply( UnmanagedImage sourceImage )
{
if ( ( sourceImage.PixelFormat != PixelFormat.Format24bppRgb ) &&
( sourceImage.PixelFormat != PixelFormat.Format32bppRgb ) &&
( sourceImage.PixelFormat != PixelFormat.Format32bppArgb ) &&
( sourceImage.PixelFormat != PixelFormat.Format32bppPArgb ) )
{
throw new UnsupportedImageFormatException( "Unsupported pixel format of the source image." );
}
cache.Clear( );
// get image size
int width = sourceImage.Width;
int height = sourceImage.Height;
int stride = sourceImage.Stride;
int pixelSize = Bitmap.GetPixelFormatSize( sourceImage.PixelFormat ) / 8;
int offset = stride - width * pixelSize;
// create destination image
Bitmap destImage = new Bitmap( width, height, ( colorTable.Length > 16 ) ?
PixelFormat.Format8bppIndexed : PixelFormat.Format4bppIndexed );
// and init its palette
ColorPalette cp = destImage.Palette;
for ( int i = 0, n = colorTable.Length; i < n; i++ )
{
cp.Entries[i] = colorTable[i];
}
destImage.Palette = cp;
// lock destination image
BitmapData destData = destImage.LockBits( new Rectangle( 0, 0, width, height ),
ImageLockMode.ReadWrite, destImage.PixelFormat );
// pixel values
int r, g, b, toAdd;
int rows = matrix.GetLength( 0 );
int cols = matrix.GetLength( 1 );
// do the job
byte* ptr = (byte*) sourceImage.ImageData.ToPointer( );
byte* dstBase = (byte*) destData.Scan0.ToPointer( );
byte colorIndex;
bool is8bpp = ( colorTable.Length > 16 );
// for each line
for ( int y = 0; y < height; y++ )
{
byte* dst = dstBase + y * destData.Stride;
// for each pixels
for ( int x = 0; x < width; x++, ptr += pixelSize )
{
toAdd = matrix[( y % rows ), ( x % cols )];
r = ptr[RGB.R] + toAdd;
g = ptr[RGB.G] + toAdd;
b = ptr[RGB.B] + toAdd;
if ( r > 255 )
r = 255;
if ( g > 255 )
g = 255;
if ( b > 255 )
b = 255;
// get color from palette, which is the closest to current pixel's value
Color closestColor = GetClosestColor( r, g, b, out colorIndex );
// write color index as pixel's value to destination image
if ( is8bpp )
{
*dst = colorIndex;
dst++;
}
else
{
if ( x % 2 == 0 )
{
*dst |= (byte) ( colorIndex << 4 );
}
else
{
*dst |= ( colorIndex );
dst++;
}
}
}
}
destImage.UnlockBits( destData );
return destImage;
}