private unsafe void ProcessWithoutChecks( UnmanagedImage source, UnmanagedImage destination, Rectangle rect )
{
int startX = rect.Left;
int startY = rect.Top;
int stopX = rect.Right;
int stopY = rect.Bottom;
int pixelSize = System.Drawing.Image.GetPixelFormatSize( source.PixelFormat ) / 8;
int kernelHalf = kernelSize / 2;
int bytesInKernelRow = kernelSize * pixelSize;
int srcStride = source.Stride;
int dstStride = destination.Stride;
int srcOffset = srcStride - rect.Width * pixelSize;
int dstOffset = dstStride - rect.Width * pixelSize;
// offset of the first kernel's pixel
int srcKernelFistPixelOffset = kernelHalf * ( srcStride + pixelSize );
// offset to move to the next kernel's pixel after processing one kernel's row
int srcKernelOffset = srcStride - bytesInKernelRow;
int tx, ty;
byte* src = (byte*) source.ImageData.ToPointer( );
byte* dst = (byte*) destination.ImageData.ToPointer( );
// allign pointers to the first pixel to process
src += startY * srcStride + startX * pixelSize;
dst += startY * dstStride + startX * pixelSize;
if ( pixelSize > 1 )
{
byte srcR, srcG, srcB;
byte srcR0, srcG0, srcB0;
byte* srcPixel;
double sCoefR, sCoefG, sCoefB, sMembR, sMembG, sMembB, coefR, coefG, coefB;
for ( int y = startY; y < stopY; y++ )
{
for ( int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize )
{
// lower right corner - to start processing from that point
srcPixel = src + srcKernelFistPixelOffset;
sCoefR = 0;
sCoefG = 0;
sCoefB = 0;
sMembR = 0;
sMembG = 0;
sMembB = 0;
srcR0 = src[RGB.R];
srcG0 = src[RGB.G];
srcB0 = src[RGB.B];
// move from lower right to upper left corner
ty = kernelSize;
while ( ty != 0 )
{
ty--;
tx = kernelSize;
while ( tx != 0 )
{
tx--;
srcR = srcPixel[RGB.R];
srcG = srcPixel[RGB.G];
srcB = srcPixel[RGB.B];
coefR = spatialFunc[tx, ty] * colorFunc[srcR, srcR0];
coefG = spatialFunc[tx, ty] * colorFunc[srcG, srcG0];
coefB = spatialFunc[tx, ty] * colorFunc[srcB, srcB0];
sCoefR += coefR;
sCoefG += coefG;
sCoefB += coefB;
sMembR += coefR * srcR;
sMembG += coefG * srcG;
sMembB += coefB * srcB;
srcPixel -= pixelSize;
}
srcPixel -= srcKernelOffset;
}
dst[RGB.R] = (byte) ( sMembR / sCoefR );
dst[RGB.G] = (byte) ( sMembG / sCoefG );
dst[RGB.B] = (byte) ( sMembB / sCoefB );
}
src += srcOffset;
dst += dstOffset;
}
}
else
{
// 8bpp grayscale images
byte srcC;
byte srcC0;
byte* srcPixel;
double sCoefC, sMembC, coefC;
for ( int y = startY; y < stopY; y++ )
{
for ( int x = startX; x < stopX; x++, src++, dst++ )
{
// lower right corner - to start processing from that point
srcPixel = src + srcKernelFistPixelOffset;
sCoefC = 0;
sMembC = 0;
srcC0 = *src;
// move from lower right to upper left corner
ty = kernelSize;
while ( ty != 0 )
{
ty--;
tx = kernelSize;
while ( tx != 0 )
{
tx--;
srcC = *( srcPixel );
coefC = spatialFunc[tx, ty] * colorFunc[srcC, srcC0];
sCoefC += coefC;
sMembC += coefC * srcC;
srcPixel -= pixelSize;
}
srcPixel -= srcKernelOffset;
}
*dst = (byte) ( sMembC / sCoefC );
}
src += srcOffset;
dst += dstOffset;
}
}
}