protected unsafe override void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
{
// check image format
if ((sourceData.PixelFormat != PixelFormat.Format8bppIndexed) &&
(sourceData.PixelFormat != PixelFormat.Format24bppRgb))
throw new UnsupportedImageFormatException("Unsupported image format.");
if (sourceData.PixelFormat != PixelFormat.Format8bppIndexed)
{
sourceData = Grayscale.CommonAlgorithms.BT709.Apply(sourceData);
}
if (recompute)
{
recompute = false;
kernel = Gabor.Kernel2D(size: size,
lambda: lambda,
theta: theta,
psi: psi,
sigma: sigma,
gamma: gamma,
normalized: true,
function: GaborKernelKind.Imaginary);
}
int kernelHeight = kernel.GetLength(0);
int kernelWidth = kernel.GetLength(1);
int centerX = kernelHeight / 2;
int centerY = kernelWidth / 2;
int width = sourceData.Width;
int height = sourceData.Height;
int srcStride = sourceData.Stride;
int srcOffset = srcStride - width;
byte* src = (byte*)sourceData.ImageData.ToPointer();
int[,] response = new int[height, width];
int max = int.MinValue;
int min = int.MaxValue;
// for each image row
for (int y = 0; y < height; y++)
{
// for each pixel in the row
for (int x = 0; x < width; x++, src++)
{
double sum = 0;
// for each kernel row
for (int i = 0; i < kernelHeight; i++)
{
int ir = i - centerY;
int t = y + ir;
// skip row
if (t < 0)
continue;
// break
if (t >= height)
break;
int col = ir * srcStride;
// for each kernel value in the row
for (int j = 0; j < kernelWidth; j++)
{
int jr = j - centerX;
t = x + jr;
// skip column
if (t < 0)
continue;
if (t < width)
{
double k = kernel[i, j];
sum += k * src[col + jr];
}
}
int v = response[y, x] = (int)sum;
if (v > max) max = v;
if (v < min) min = v;
}
}
src += srcOffset;
}
byte* dst = (byte*)destinationData.ImageData.ToPointer();
int pixelSize = System.Drawing.Image.GetPixelFormatSize(destinationData.PixelFormat) / 8;
int dstStride = destinationData.Stride;
int dstOffset = dstStride - width * pixelSize;
if (destinationData.PixelFormat == PixelFormat.Format8bppIndexed)
{
// for each image row
for (int y = 0; y < height; y++)
{
// for each pixel in the row
for (int x = 0; x < width; x++, dst++)
{
*dst = (byte)((255 * (response[y, x] - min)) / (max - min));
}
dst += dstOffset;
}
}
else
{
// for each image row
for (int y = 0; y < height; y++)
{
// for each pixel in the row
for (int x = 0; x < width; x++, dst += pixelSize)
{
int v = response[y, x];
if (v > 0)
{
dst[RGB.R] = (byte)((255 * v) / max);
}
else // (v <= 0)
{
dst[RGB.B] = (byte)((255 * v) / min);
}
}
dst += dstOffset;
}
}
}