AForge.Imaging.Filters.RotateBilinear.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 )
        {
            // get source image size
            int     width      = sourceData.Width;
            int     height     = sourceData.Height;
            double  oldXradius = (double) ( width  - 1 ) / 2;
            double  oldYradius = (double) ( height - 1 ) / 2;

            // get destination image size
            int     newWidth   = destinationData.Width;
            int     newHeight  = destinationData.Height;
            double  newXradius = (double) ( newWidth  - 1 ) / 2;
            double  newYradius = (double) ( newHeight - 1 ) / 2;

            // angle's sine and cosine
            double angleRad = -angle * Math.PI / 180;
			double angleCos = Math.Cos( angleRad );
			double angleSin = Math.Sin( angleRad );

            int srcStride = sourceData.Stride;
            int dstOffset = destinationData.Stride -
                ( ( destinationData.PixelFormat == PixelFormat.Format8bppIndexed ) ? newWidth : newWidth * 3 );

            // fill values
            byte fillR = fillColor.R;
            byte fillG = fillColor.G;
            byte fillB = fillColor.B;

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

            // destination pixel's coordinate relative to image center
            double cx, cy;
            // coordinates of source points
            double  ox, oy, tx, ty, dx1, dy1, dx2, dy2;
            int     ox1, oy1, ox2, oy2;
            // width and height decreased by 1
            int ymax = height - 1;
            int xmax = width - 1;
            // temporary pointers
            byte* p1, p2, p3, p4;

            // check pixel format
            if ( destinationData.PixelFormat == PixelFormat.Format8bppIndexed )
            {
                // grayscale
                cy = -newYradius;
                for ( int y = 0; y < newHeight; y++ )
                {
                    // do some pre-calculations of source points' coordinates
                    // (calculate the part which depends on y-loop, but does not
                    // depend on x-loop)
                    tx = angleSin * cy + oldXradius;
                    ty = angleCos * cy + oldYradius;

                    cx = -newXradius;
                    for ( int x = 0; x < newWidth; x++, dst++ )
                    {
                        // coordinates of source point
                        ox = tx + angleCos * cx;
                        oy = ty - angleSin * cx;

                        // top-left coordinate
                        ox1 = (int) ox;
                        oy1 = (int) oy;

                        // validate source pixel's coordinates
                        if ( ( ox1 < 0 ) || ( oy1 < 0 ) || ( ox1 >= width ) || ( oy1 >= height ) )
                        {
                            // fill destination image with filler
                            *dst = fillG;
                        }
                        else
                        {
                            // bottom-right coordinate
                            ox2 = ( ox1 == xmax ) ? ox1 : ox1 + 1;
                            oy2 = ( oy1 == ymax ) ? oy1 : oy1 + 1;

                            if ( ( dx1 = ox - (double) ox1 ) < 0 )
                                dx1 = 0;
                            dx2 = 1.0 - dx1;

                            if ( ( dy1 = oy - (double) oy1 ) < 0 )
                                dy1 = 0;
                            dy2 = 1.0 - dy1;

                            p1 = src + oy1 * srcStride;
                            p2 = src + oy2 * srcStride;

                            // interpolate using 4 points
                            *dst = (byte) (
                                dy2 * ( dx2 * p1[ox1] + dx1 * p1[ox2] ) +
                                dy1 * ( dx2 * p2[ox1] + dx1 * p2[ox2] ) );
                        }
                        cx++;
                    }
                    cy++;
                    dst += dstOffset;
                }
            }
            else
            {
                // RGB
                cy = -newYradius;
                for ( int y = 0; y < newHeight; y++ )
                {
                    // do some pre-calculations of source points' coordinates
                    // (calculate the part which depends on y-loop, but does not
                    // depend on x-loop)
                    tx = angleSin * cy + oldXradius;
                    ty = angleCos * cy + oldYradius;

                    cx = -newXradius;
                    for ( int x = 0; x < newWidth; x++, dst += 3 )
                    {
                        // coordinates of source point
                        ox = tx + angleCos * cx;
                        oy = ty - angleSin * cx;

                        // top-left coordinate
                        ox1 = (int) ox;
                        oy1 = (int) oy;

                        // validate source pixel's coordinates
                        if ( ( ox1 < 0 ) || ( oy1 < 0 ) || ( ox1 >= width ) || ( oy1 >= height ) )
                        {
                            // fill destination image with filler
                            dst[RGB.R] = fillR;
                            dst[RGB.G] = fillG;
                            dst[RGB.B] = fillB;
                        }
                        else
                        {
                            // bottom-right coordinate
                            ox2 = ( ox1 == xmax ) ? ox1 : ox1 + 1;
                            oy2 = ( oy1 == ymax ) ? oy1 : oy1 + 1;

                            if ( ( dx1 = ox - (float) ox1 ) < 0 )
                                dx1 = 0;
                            dx2 = 1.0f - dx1;

                            if ( ( dy1 = oy - (float) oy1 ) < 0 )
                                dy1 = 0;
                            dy2 = 1.0f - dy1;

                            // get four points
                            p1 = p2 = src + oy1 * srcStride;
                            p1 += ox1 * 3;
                            p2 += ox2 * 3;

                            p3 = p4 = src + oy2 * srcStride;
                            p3 += ox1 * 3;
                            p4 += ox2 * 3;

                            // interpolate using 4 points

                            // red
                            dst[RGB.R] = (byte) (
                                dy2 * ( dx2 * p1[RGB.R] + dx1 * p2[RGB.R] ) +
                                dy1 * ( dx2 * p3[RGB.R] + dx1 * p4[RGB.R] ) );

                            // green
                            dst[RGB.G] = (byte) (
                                dy2 * ( dx2 * p1[RGB.G] + dx1 * p2[RGB.G] ) +
                                dy1 * ( dx2 * p3[RGB.G] + dx1 * p4[RGB.G] ) );

                            // blue
                            dst[RGB.B] = (byte) (
                                dy2 * ( dx2 * p1[RGB.B] + dx1 * p2[RGB.B] ) +
                                dy1 * ( dx2 * p3[RGB.B] + dx1 * p4[RGB.B] ) );
                        }
                        cx++;
                    }
                    cy++;
                    dst += dstOffset;
                }
            }
        }
    }