protected override unsafe void ProcessFilter( UnmanagedImage image, Rectangle rect )
{
int pixelSize = Image.GetPixelFormatSize( image.PixelFormat ) / 8;
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;
// 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, PixelFormat.Format8bppIndexed );
ch = (byte*) chData.Scan0.ToPointer( );
chStride = chData.Stride;
}
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;
}
int offsetCh = chStride - rect.Width;
RGB rgb = new RGB( );
YCbCr ycbcr = new YCbCr( );
// do the job
byte* dst = (byte*) image.ImageData.ToPointer( );
// allign pointer 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++ )
{
rgb.Red = dst[RGB.R];
rgb.Green = dst[RGB.G];
rgb.Blue = dst[RGB.B];
// convert to YCbCr
AForge.Imaging.YCbCr.FromRGB( rgb, ycbcr );
switch ( channel )
{
case YCbCr.YIndex:
ycbcr.Y = (float) *ch / 255;
break;
case YCbCr.CbIndex:
ycbcr.Cb = (float) *ch / 255 - 0.5f;
break;
case YCbCr.CrIndex:
ycbcr.Cr = (float) *ch / 255 - 0.5f;
break;
}
// convert back to RGB
AForge.Imaging.YCbCr.ToRGB( ycbcr, rgb );
dst[RGB.R] = rgb.Red;
dst[RGB.G] = rgb.Green;
dst[RGB.B] = rgb.Blue;
}
dst += offset;
ch += offsetCh;
}
if ( chData != null )
{
// unlock
channelImage.UnlockBits( chData );
}
}
}