Accord.Imaging.Filters.TransformFromPolar.ProcessFilter C# (CSharp) Method

ProcessFilter() protected method

Process the filter on the specified image.
protected ProcessFilter ( UnmanagedImage sourceData, UnmanagedImage destinationData ) : void
sourceData UnmanagedImage Source image data.
destinationData UnmanagedImage Destination image data.
return void
        protected override unsafe void ProcessFilter(UnmanagedImage sourceData, UnmanagedImage destinationData)
        {
            int pixelSize = Bitmap.GetPixelFormatSize(destinationData.PixelFormat) / 8;

            // get source image size
            int width = sourceData.Width;
            int height = sourceData.Height;
            int widthM1 = width - 1;
            int heightM1 = height - 1;

            // get destination image size
            int newWidth = destinationData.Width;
            int newHeight = destinationData.Height;
            int newHeightM1 = newHeight - 1;

            // invert circle depth
            double circleDisform = 1 - circleDepth;

            // get position of center pixel
            double cx = (double)widthM1 / 2;
            double cy = (double)heightM1 / 2;
            double radius = (cx < cy) ? cx : cy;
            radius -= radius * circleDisform;

            // angle of the diagonal
            double diagonalAngle = Math.Atan2(cy, cx);

            // offset angle in radians
            double offsetAngleR = ((mapBackwards) ? offsetAngle : -offsetAngle) / 180 * Math.PI + PiHalf;

            // do the job
            byte* baseSrc = (byte*)sourceData.ImageData.ToPointer();
            byte* dst = (byte*)destinationData.ImageData.ToPointer();

            int srcStride = sourceData.Stride;
            int dstOffset = destinationData.Stride - newWidth * pixelSize;

            // coordinates of source points
            int sx1, sy1, sx2, sy2;
            double dx1, dy1, dx2, dy2;

            // temporary pointers
            byte* p1, p2, p3, p4;

            // precalculate Sin/Cos values and distances from center to edge in the source image
            double[] angleCos = new double[newWidth];
            double[] angleSin = new double[newWidth];
            double[] maxDistance = new double[newWidth];

            for (int x = 0; x < newWidth; x++)
            {
                double angle = -Pi2 * x / newWidth + offsetAngleR;

                angleCos[x] = Math.Cos(angle);
                angleSin[x] = Math.Sin(angle);

                // calculate minimum angle between X axis and the
                // line with the above calculated angle
                double oxAngle = ((angle > 0) ? angle : -angle) % Math.PI;
                if (oxAngle > PiHalf)
                {
                    oxAngle = Math.PI - oxAngle;
                }

                // calculate maximum distance from center for this angle - distance to image's edge
                maxDistance[x] = circleDisform * ((oxAngle > diagonalAngle) ? (cy / Math.Sin(oxAngle)) : (cx / Math.Cos(oxAngle)));
            }

            for (int y = 0; y < newHeight; y++)
            {
                double yPart = (double)y / newHeightM1;

                if (!mapFromTop)
                {
                    yPart = 1 - yPart;
                }

                for (int x = 0; x < newWidth; x++)
                {
                    // calculate maximum allowed distance within wich we need to map Y axis of the destination image
                    double maxAllowedDistance = radius + maxDistance[x];

                    // source pixel's distance from the center of the source image
                    double distance = yPart * maxAllowedDistance;

                    // calculate pixel coordinates in the source image
                    double sx = cx + distance * ((mapBackwards) ? -angleCos[x] : angleCos[x]);
                    double sy = cy - distance * angleSin[x];

                    sx1 = (int)sx;
                    sy1 = (int)sy;

                    sx2 = (sx1 == widthM1) ? sx1 : sx1 + 1;
                    dx1 = sx - sx1;
                    dx2 = 1.0 - dx1;

                    sy2 = (sy1 == heightM1) ? sy1 : sy1 + 1;
                    dy1 = sy - 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++, dst++, p1++, p2++, p3++, p4++)
                    {
                        *dst = (byte)(
                            dy2 * (dx2 * (*p1) + dx1 * (*p2)) +
                            dy1 * (dx2 * (*p3) + dx1 * (*p4)));
                    }
                }
                dst += dstOffset;
            }
        }
    }