protected ProcessFilter ( UnmanagedImage sourceData, UnmanagedImage destinationData ) : void | ||
sourceData | UnmanagedImage | Source image data. |
destinationData | UnmanagedImage | Destination image data. |
return | void |
protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
{
int width = sourceData.Width;
int height = sourceData.Height;
int size = radius * 2;
int pixelSize = System.Drawing.Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;
int srcStride = sourceData.Stride;
int dstStride = destinationData.Stride;
int srcOffset = srcStride - width * pixelSize;
int dstOffset = dstStride - width * pixelSize;
byte* src = (byte*)sourceData.ImageData.ToPointer();
byte* dst = (byte*)destinationData.ImageData.ToPointer();
// do the processing job
if (destinationData.PixelFormat == PixelFormat.Format8bppIndexed)
{
// for each line
for (int y = 0; y < height; y++)
{
// for each pixel
for (int x = 0; x < width; x++, src++, dst++)
{
long sum = 0;
int count = 0;
for (int i = 0; i < radius; i++)
{
int ir = i - radius;
int t = y + ir;
if (t < 0)
continue;
if (t >= height)
break;
for (int j = 0; j < size; j++)
{
int jr = j - radius;
t = x + jr;
if (t < 0)
continue;
if (t >= width)
continue;
sum += src[ir * srcStride + jr];
count++;
}
}
double mean = sum / (double)count;
double variance = 0;
for (int i = 0; i < radius; i++)
{
int ir = i - radius;
int t = y + ir;
if (t < 0)
continue;
if (t >= height)
break;
for (int j = 0; j < size; j++)
{
int jr = j - radius;
t = x + jr;
if (t < 0)
continue;
if (t >= width)
continue;
byte val = src[ir * srcStride + jr];
variance += (val - mean) * (val - mean);
}
}
variance /= count - 1;
*dst = (byte)((variance > 255) ? 255 : ((variance < 0) ? 0 : variance));
}
src += srcOffset;
dst += dstOffset;
}
}
else
{
// for each line
for (int y = 0; y < height; y++)
{
// for each pixel
for (int x = 0; x < width; x++, src += pixelSize, dst += pixelSize)
{
long sumR = 0;
long sumG = 0;
long sumB = 0;
int count = 0;
for (int i = 0; i < size; i++)
{
int ir = i - radius;
int t = y + ir;
if (t < 0)
continue;
if (t >= height)
break;
for (int j = 0; j < size; j++)
{
int jr = j - radius;
t = x + jr;
if (t < 0)
continue;
if (t >= width)
continue;
byte* p = &src[ir * srcStride + jr * pixelSize];
count++;
sumR += p[RGB.R];
sumG += p[RGB.G];
sumB += p[RGB.B];
}
}
double meanR = sumR / (double)count;
double meanG = sumG / (double)count;
double meanB = sumB / (double)count;
double varR = 0;
double varG = 0;
double varB = 0;
for (int i = 0; i < size; i++)
{
int ir = i - radius;
int t = y + ir;
if (t < 0)
continue;
if (t >= height)
break;
// for each kernel column
for (int j = 0; j < size; j++)
{
int jr = j - radius;
t = x + jr;
if (t < 0)
continue;
if (t >= width)
continue;
byte* p = &src[ir * srcStride + jr * pixelSize];
count++;
varR += (p[RGB.R] - meanR) * (p[RGB.R] - meanR);
varG += (p[RGB.G] - meanG) * (p[RGB.G] - meanG);
varB += (p[RGB.B] - meanB) * (p[RGB.B] - meanB);
}
}
varR /= count - 1;
varG /= count - 1;
varB /= count - 1;
dst[RGB.R] = (byte)((varR > 255) ? 255 : ((varR < 0) ? 0 : varR));
dst[RGB.G] = (byte)((varG > 255) ? 255 : ((varG < 0) ? 0 : varG));
dst[RGB.B] = (byte)((varB > 255) ? 255 : ((varB < 0) ? 0 : varB));
// take care of alpha channel
if (pixelSize == 4)
dst[RGB.A] = src[RGB.A];
}
src += srcOffset;
dst += dstOffset;
}
}
}
}