/// <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;
                }
            }
        }
Esempio n. 2
0
        // 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;
                }
            }
        }