protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData, Rectangle rect)
{
int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;
// processing start and stop X,Y positions
int startX = rect.Left;
int startY = rect.Top;
int stopX = startX + rect.Width;
int stopY = startY + rect.Height;
int srcStride = sourceData.Stride;
int dstStride = destinationData.Stride;
int srcOffset = srcStride - rect.Width * pixelSize;
int dstOffset = dstStride - rect.Width * pixelSize;
// loop and array indexes
int i, j, t;
// kernel's radius
int radius = size >> 1;
// pixel value (min and max)
byte minR, maxR, minG, maxG, minB, maxB, v;
byte* src = (byte*)sourceData.ImageData.ToPointer();
byte* dst = (byte*)destinationData.ImageData.ToPointer();
byte* p;
// allign pointers to the first pixel to process
src += (startY * srcStride + startX * pixelSize);
dst += (startY * dstStride + startX * pixelSize);
if (destinationData.PixelFormat == PixelFormat.Format8bppIndexed)
{
// Grayscale image
// for each line
for (int y = startY; y < stopY; y++)
{
// for each pixel
for (int x = startX; x < stopX; x++, src++, dst++)
{
minG = 255;
maxG = 0;
// for each kernel row
for (i = -radius; i <= radius; i++)
{
t = y + i;
// skip row
if (t < startY)
continue;
// break
if (t >= stopY)
break;
// for each kernel column
for (j = -radius; j <= radius; j++)
{
t = x + j;
// skip column
if (t < startX)
continue;
if ((i != j) && (t < stopX))
{
// find MIN and MAX values
v = src[i * srcStride + j];
if (v < minG)
minG = v;
if (v > maxG)
maxG = v;
}
}
}
// set destination pixel
v = *src;
*dst = (v > maxG) ? maxG : ((v < minG) ? minG : v);
}
src += srcOffset;
dst += dstOffset;
}
}
else
{
// RGB image
// for each line
for (int y = startY; y < stopY; y++)
{
// for each pixel
for (int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize)
{
minR = minG = minB = 255;
maxR = maxG = maxB = 0;
// for each kernel row
for (i = -radius; i <= radius; i++)
{
t = y + i;
// skip row
if (t < startY)
continue;
// break
if (t >= stopY)
break;
// for each kernel column
for (j = -radius; j <= radius; j++)
{
t = x + j;
// skip column
if (t < startX)
continue;
if ((i != j) && (t < stopX))
{
p = &src[i * srcStride + j * pixelSize];
// find MIN and MAX values
// red
v = p[RGB.R];
if (v < minR)
minR = v;
if (v > maxR)
maxR = v;
// green
v = p[RGB.G];
if (v < minG)
minG = v;
if (v > maxG)
maxG = v;
// blue
v = p[RGB.B];
if (v < minB)
minB = v;
if (v > maxB)
maxB = v;
}
}
}
// set destination pixel
// red
v = src[RGB.R];
dst[RGB.R] = (v > maxR) ? maxR : ((v < minR) ? minR : v);
// green
v = src[RGB.G];
dst[RGB.G] = (v > maxG) ? maxG : ((v < minG) ? minG : v);
// blue
v = src[RGB.B];
dst[RGB.B] = (v > maxB) ? maxB : ((v < minB) ? minB : v);
}
src += srcOffset;
dst += dstOffset;
}
}
}
}