/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="sourceData">Source image data.</param> /// <param name="destinationData">Destination image data.</param> /// 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; } } }
// Process both images transforming source image into quadrilateral in destination image 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; } } }