protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
{
// get source and destination images size
int srcWidth = sourceData.Width;
int srcHeight = sourceData.Height;
int dstWidth = destinationData.Width;
int dstHeight = destinationData.Height;
int pixelSize = Image.GetPixelFormatSize(sourceData.PixelFormat) / 8;
int srcStride = sourceData.Stride;
int dstStride = destinationData.Stride;
int offset = dstStride - dstWidth * pixelSize;
// calculate tranformation matrix
List<IntPoint> dstRect = new List<IntPoint>();
dstRect.Add(new IntPoint(0, 0));
dstRect.Add(new IntPoint(dstWidth - 1, 0));
dstRect.Add(new IntPoint(dstWidth - 1, dstHeight - 1));
dstRect.Add(new IntPoint(0, dstHeight - 1));
// calculate tranformation matrix
double[,] matrix = QuadTransformationCalcs.MapQuadToQuad(dstRect, sourceQuadrilateral);
// do the job
byte* ptr = (byte*)destinationData.ImageData.ToPointer();
byte* baseSrc = (byte*)sourceData.ImageData.ToPointer();
if (!useInterpolation)
{
byte* p;
// for each row
for (int y = 0; y < dstHeight; y++)
{
// for each pixel
for (int x = 0; x < dstWidth; 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
{
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 = 0; y < dstHeight; y++)
{
// for each pixel
for (int x = 0; x < dstWidth; 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
{
ptr += pixelSize;
}
}
ptr += offset;
}
}
}
}