protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect )
{
int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8;
if ( ( channel == RGB.A ) && ( pixelSize != 4 ) && ( pixelSize != 8 ) )
{
throw new InvalidImagePropertiesException( "Can not replace alpha channel of none ARGB image." );
}
int width = image.Width;
int height = image.Height;
int startX = rect.Left;
int startY = rect.Top;
int stopX = startX + rect.Width;
int stopY = startY + rect.Height;
int offset = image.Stride - rect.Width * pixelSize;
BitmapData chData = null;
// pointer to channel's data
byte* ch;
// channel's image stride
int chStride = 0;
PixelFormat chFormat = PixelFormat.Format16bppGrayScale;
// check channel's image type
if ( channelImage != null )
{
// check channel's image dimension
if ( ( width != channelImage.Width ) || ( height != channelImage.Height ) )
throw new InvalidImagePropertiesException( "Channel image size does not match source image size." );
// lock channel image
chData = channelImage.LockBits(
new Rectangle( 0, 0, width, height ),
ImageLockMode.ReadOnly, channelImage.PixelFormat );
ch = (byte*) chData.Scan0.ToPointer( );
chStride = chData.Stride;
chFormat = chData.PixelFormat;
}
else
{
// check channel's image dimension
if ( ( width != unmanagedChannelImage.Width ) || ( height != unmanagedChannelImage.Height ) )
throw new InvalidImagePropertiesException( "Channel image size does not match source image size." );
ch = (byte*) unmanagedChannelImage.ImageData;
chStride = unmanagedChannelImage.Stride;
chFormat = unmanagedChannelImage.PixelFormat;
}
if ( pixelSize <= 4 )
{
// check channel image's format
if ( chFormat != PixelFormat.Format8bppIndexed )
throw new InvalidImagePropertiesException( "Channel image's format does not correspond to format of the source image." );
int offsetCh = chData.Stride - rect.Width;
// do the job
byte* dst = (byte*) image.ImageData.ToPointer( );
// allign pointers to the first pixel to process
dst += ( startY * image.Stride + startX * pixelSize );
ch += ( startY * chStride + startX );
// for each line
for ( int y = startY; y < stopY; y++ )
{
// for each pixel
for ( int x = startX; x < stopX; x++, dst += pixelSize, ch++ )
{
dst[channel] = *ch;
}
dst += offset;
ch += offsetCh;
}
}
else
{
// check channel image's format
if ( chFormat != PixelFormat.Format16bppGrayScale )
throw new InvalidImagePropertiesException( "Channel image's format does not correspond to format of the source image." );
int stride = image.Stride;
// do the job
byte* baseDst = (byte*) image.ImageData.ToPointer( );
// allign pointers for X coordinate
baseDst += startX * pixelSize;
ch += startX * 2;
pixelSize /= 2;
// for each line
for ( int y = startY; y < stopY; y++ )
{
ushort* dst = (ushort*) ( baseDst + y * stride );
ushort* chPtr = (ushort*) ( ch + y * chStride );
// for each pixel
for ( int x = startX; x < stopX; x++, dst += pixelSize, chPtr++ )
{
dst[channel] = *chPtr;
}
}
}
if ( chData != null )
{
// unlock
channelImage.UnlockBits( chData );
}
}
}