protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect)
{
if ((channelImage == null) && (unmanagedChannelImage == null))
throw new InvalidOperationException("Channel image was not specified.");
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 = chStride - 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);
}
}
}