private unsafe void ProcessFilter( UnmanagedImage dstImage, UnmanagedImage srcImage )
{
// get source and destination images size
int srcWidth = srcImage.Width;
int srcHeight = srcImage.Height;
int dstWidth = dstImage.Width;
int dstHeight = dstImage.Height;
int pixelSize = Image.GetPixelFormatSize( srcImage.PixelFormat ) / 8;
int srcStride = srcImage.Stride;
int dstStride = dstImage.Stride;
// get bounding rectangle of the quadrilateral
IntPoint minXY, maxXY;
PointsCloud.GetBoundingRectangle( destinationQuadrilateral, out minXY, out maxXY );
// make sure the rectangle is inside of destination image
if ( ( maxXY.X < 0 ) || ( maxXY.Y < 0 ) || ( minXY.X >= dstWidth ) || ( minXY.Y >= dstHeight ) )
return; // nothing to do, since quadrilateral is completely outside
// correct rectangle if required
if ( minXY.X < 0 )
minXY.X = 0;
if ( minXY.Y < 0 )
minXY.Y = 0;
if ( maxXY.X >= dstWidth )
maxXY.X = dstWidth - 1;
if ( maxXY.Y >= dstHeight )
maxXY.Y = dstHeight - 1;
int startX = minXY.X;
int startY = minXY.Y;
int stopX = maxXY.X + 1;
int stopY = maxXY.Y + 1;
int offset = dstStride - ( stopX - startX ) * pixelSize;
// calculate tranformation matrix
List<IntPoint> srcRect = new List<IntPoint>( );
srcRect.Add( new IntPoint( 0, 0 ) );
srcRect.Add( new IntPoint( srcWidth - 1, 0 ) );
srcRect.Add( new IntPoint( srcWidth - 1, srcHeight - 1 ) );
srcRect.Add( new IntPoint( 0, srcHeight - 1 ) );
double[,] matrix = QuadTransformationCalcs.MapQuadToQuad( destinationQuadrilateral, srcRect );
// do the job
byte* ptr = (byte*) dstImage.ImageData.ToPointer( );
byte* baseSrc = (byte*) srcImage.ImageData.ToPointer( );
// allign pointer to the first pixel to process
ptr += ( startY * dstStride + startX * pixelSize );
if ( !useInterpolation )
{
byte* p;
// for each row
for ( int y = startY; y < stopY; y++ )
{
// for each pixel
for ( int x = startX; x < stopX; x++ )
{
double factor = matrix[2, 0] * x + matrix[2, 1] * y + matrix[2, 2];
double srcX = ( matrix[0, 0] * x + matrix[0, 1] * y + matrix[0, 2] ) / factor;
double srcY = ( matrix[1, 0] * x + matrix[1, 1] * y + matrix[1, 2] ) / factor;
if ( ( srcX >= 0 ) && ( srcY >= 0 ) && ( srcX < srcWidth ) && ( srcY < srcHeight ) )
{
// get pointer to the pixel in the source image
p = baseSrc + (int) srcY * srcStride + (int) srcX * pixelSize;
// copy pixel's values
for ( int i = 0; i < pixelSize; i++, ptr++, p++ )
{
*ptr = *p;
}
}
else
{
// skip the pixel
ptr += pixelSize;
}
}
ptr += offset;
}
}
else
{
int srcWidthM1 = srcWidth - 1;
int srcHeightM1 = srcHeight - 1;
// coordinates of source points
double dx1, dy1, dx2, dy2;
int sx1, sy1, sx2, sy2;
// temporary pointers
byte* p1, p2, p3, p4;
// for each row
for ( int y = startY; y < stopY; y++ )
{
// for each pixel
for ( int x = startX; x < stopX; x++ )
{
double factor = matrix[2, 0] * x + matrix[2, 1] * y + matrix[2, 2];
double srcX = ( matrix[0, 0] * x + matrix[0, 1] * y + matrix[0, 2] ) / factor;
double srcY = ( matrix[1, 0] * x + matrix[1, 1] * y + matrix[1, 2] ) / factor;
if ( ( srcX >= 0 ) && ( srcY >= 0 ) && ( srcX < srcWidth ) && ( srcY < srcHeight ) )
{
sx1 = (int) srcX;
sx2 = ( sx1 == srcWidthM1 ) ? sx1 : sx1 + 1;
dx1 = srcX - sx1;
dx2 = 1.0 - dx1;
sy1 = (int) srcY;
sy2 = ( sy1 == srcHeightM1 ) ? sy1 : sy1 + 1;
dy1 = srcY - sy1;
dy2 = 1.0 - dy1;
// get four points
p1 = p2 = baseSrc + sy1 * srcStride;
p1 += sx1 * pixelSize;
p2 += sx2 * pixelSize;
p3 = p4 = baseSrc + sy2 * srcStride;
p3 += sx1 * pixelSize;
p4 += sx2 * pixelSize;
// interpolate using 4 points
for ( int i = 0; i < pixelSize; i++, ptr++, p1++, p2++, p3++, p4++ )
{
*ptr = (byte) (
dy2 * ( dx2 * ( *p1 ) + dx1 * ( *p2 ) ) +
dy1 * ( dx2 * ( *p3 ) + dx1 * ( *p4 ) ) );
}
}
else
{
// skip the pixel
ptr += pixelSize;
}
}
ptr += offset;
}
}
}
}