Accord.Imaging.Filters.TransformToPolar.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;

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

            // get position of center pixel
            double cx = (double) ( newWidth - 1 ) / 2;
            double cy = (double) ( newHeight - 1 ) / 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 = offsetAngle / 180 * Math.PI;
            if ( offsetAngleR < 0 )
            {
                offsetAngleR = Pi2 - offsetAngleR;
            }
            // add extra offset to make sure rotation starts from Y axis and Pi*2 to
            // make sure any negative angle will get positive
            offsetAngleR += PiHalf + Pi2;

            // 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;

            byte fillR = fillColor.R;
            byte fillB = fillColor.B;
            byte fillG = fillColor.G;
            byte fillA = fillColor.A;
            byte fillGrey = (byte) ( 0.2125 * fillR + 0.7154 * fillG + 0.0721 * fillB );

            for ( int y = 0; y < newHeight; y++ )
            {
                double dy = y - cy;
                double dydy = dy * dy;

                for ( int x = 0; x < newWidth; x++ )
                {
                    double dx = x - cx;
                    // distance from the center
                    double distance = Math.Sqrt( dx * dx + dydy );
                    // angle of the line connecting center and the current pixel
                    double angle = Math.Atan2( dy, dx );

                    // calculate minimum angle between X axis and the
                    // line connecting center and the current pixel
                    double oxAngle = ( angle > 0 ) ? angle : -angle;
                    if ( oxAngle > PiHalf )
                    {
                        oxAngle = Math.PI - oxAngle;
                    }

                    // calculate maximm distance from center for this angle - distance to image's edge
                    double maxDistance = ( oxAngle > diagonalAngle ) ? ( cy / Math.Sin( oxAngle ) ) : ( cx / Math.Cos( oxAngle ) );

                    // calculate maximum allowed distance within wich we need to map Y axis of the source image
                    double maxAllowedDistance = radius + maxDistance * circleDisform;

                    if ( distance < maxAllowedDistance + 1 )
                    {
                        // add angle offset and make sure it is in the [0, 2PI) range
                        angle += offsetAngleR;
                        angle = angle % Pi2;

                        // calculate pixel coordinates in the source image
                        double sy = ( distance / maxAllowedDistance ) * heightM1;

                        if ( sy > heightM1 )
                        {
                            sy = heightM1;
                        }

                        if ( !mapFromTop )
                        {
                            sy = heightM1 - sy;
                        }

                        double sx = ( angle / Pi2 ) * widthM1;

                        if ( mapBackwards )
                        {
                            sx = widthM1 - sx;
                        }

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

                        sy1 = (int) sy;
                        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 ) ) );
                        }
                    }
                    else
                    {
                        // fill unprocessed pixel with default color
                        if ( pixelSize == 1 )
                        {
                            *dst = fillGrey;
                        }
                        else
                        {
                            dst[RGB.R] = fillR;
                            dst[RGB.G] = fillG;
                            dst[RGB.B] = fillB;

                            if ( pixelSize > 3 )
                            {
                                dst[RGB.A] = fillA;
                            }
                        }

                        dst += pixelSize;
                    }
                }
                dst += dstOffset;
            }
        }
    }