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 dstOffset = dstStride - rect.Width * pixelSize;
// new pixel's position
int ox, oy;
// maximum value for random number generator
int max = radius * 2 + 1;
byte* src = (byte*)sourceData.ImageData.ToPointer();
byte* dst = (byte*)destinationData.ImageData.ToPointer();
byte* p;
// copy source to destination before
if (srcStride == dstStride)
{
Accord.SystemTools.CopyUnmanagedMemory(dst, src, srcStride * sourceData.Height);
}
else
{
int len = sourceData.Width * pixelSize;
for (int y = 0, heigh = sourceData.Height; y < heigh; y++)
{
Accord.SystemTools.CopyUnmanagedMemory(
dst + dstStride * y, src + srcStride * y, len);
}
}
// allign pointer to the first pixel to process
dst += (startY * dstStride + startX * pixelSize);
// Note:
// It is possible to speed-up this filter creating separate
// loops for RGB and grayscale images.
// for each line
for (int y = startY; y < stopY; y++)
{
// for each pixel
for (int x = startX; x < stopX; x++)
{
// generate radnom pixel's position
ox = x + rand.Next(max) - radius;
oy = y + rand.Next(max) - radius;
// check if the random pixel is inside our image
if ((ox >= startX) && (oy >= startY) && (ox < stopX) && (oy < stopY))
{
p = src + oy * srcStride + ox * pixelSize;
for (int i = 0; i < pixelSize; i++, dst++, p++)
{
*dst = *p;
}
}
else
{
dst += pixelSize;
}
}
dst += dstOffset;
}
}
}