protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect)
{
// get pixel size
int pixelSize = (image.PixelFormat == PixelFormat.Format24bppRgb) ? 3 : 4;
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;
RGB rgb = new RGB();
YCbCr ycbcr = new YCbCr();
bool updated;
// do the job
byte* ptr = (byte*)image.ImageData.ToPointer();
// allign pointer to the first pixel to process
ptr += (startY * image.Stride + startX * pixelSize);
// for each row
for (int y = startY; y < stopY; y++)
{
// for each pixel
for (int x = startX; x < stopX; x++, ptr += pixelSize)
{
updated = false;
rgb.Red = ptr[RGB.R];
rgb.Green = ptr[RGB.G];
rgb.Blue = ptr[RGB.B];
// convert to YCbCr
Accord.Imaging.YCbCr.FromRGB(rgb, ycbcr);
// check YCbCr values
if (
(ycbcr.Y >= yRange.Min) && (ycbcr.Y <= yRange.Max) &&
(ycbcr.Cb >= cbRange.Min) && (ycbcr.Cb <= cbRange.Max) &&
(ycbcr.Cr >= crRange.Min) && (ycbcr.Cr <= crRange.Max)
)
{
if (!fillOutsideRange)
{
if (updateY) ycbcr.Y = fillY;
if (updateCb) ycbcr.Cb = fillCb;
if (updateCr) ycbcr.Cr = fillCr;
updated = true;
}
}
else
{
if (fillOutsideRange)
{
if (updateY) ycbcr.Y = fillY;
if (updateCb) ycbcr.Cb = fillCb;
if (updateCr) ycbcr.Cr = fillCr;
updated = true;
}
}
if (updated)
{
// convert back to RGB
Accord.Imaging.YCbCr.ToRGB(ycbcr, rgb);
ptr[RGB.R] = rgb.Red;
ptr[RGB.G] = rgb.Green;
ptr[RGB.B] = rgb.Blue;
}
}
ptr += offset;
}
}
}