AForge.Imaging.Filters.AdaptiveSmoothing.ProcessFilter C# (CSharp) Method

ProcessFilter() protected method

Process the filter on the specified image.
protected ProcessFilter ( UnmanagedImage source, UnmanagedImage destination, Rectangle rect ) : void
source UnmanagedImage Source image data.
destination UnmanagedImage Destination image data.
rect System.Drawing.Rectangle Image rectangle for processing by the filter.
return void
        protected override unsafe void ProcessFilter( UnmanagedImage source, UnmanagedImage destination, Rectangle rect )
        {
            int pixelSize  = Image.GetPixelFormatSize( source.PixelFormat ) / 8;
            int pixelSize2 = pixelSize * 2;

            // processing start and stop X,Y positions
            int startX  = rect.Left;
            int startY  = rect.Top;
            int stopX   = startX + rect.Width;
            int stopY   = startY + rect.Height;

            int startXP2    = startX + 2;
            int startYP2    = startY + 2;
            int stopXM2     = stopX - 2;
            int stopYM2     = stopY - 2;

            int srcStride = source.Stride;
            int dstStride = destination.Stride;
            int srcOffset = srcStride - rect.Width * pixelSize;
            int dstOffset = dstStride - rect.Width * pixelSize;

            // gradient and weights
            double gx, gy, weight, weightTotal, total;
            // precalculated factor value
            double f = -8 * factor * factor;

            // do the job
            byte* src = (byte*) source.ImageData.ToPointer( ) + srcStride * 2;
            byte* dst = (byte*) destination.ImageData.ToPointer( ) + dstStride * 2;

            // allign pointers to the first pixel to process
            src += ( startY * srcStride + startX * pixelSize );
            dst += ( startY * dstStride + startX * pixelSize );

            for ( int y = startYP2; y < stopYM2; y++ )
            {
                src += pixelSize2;
                dst += pixelSize2;

                for ( int x = startXP2; x < stopXM2; x++ )
                {
                    for ( int i = 0; i < pixelSize; i++, src++, dst++ )
                    {
                        weightTotal = 0;
                        total = 0;

                        // original formulas for weight calculation:
                        // w(x, y) = exp( -1 * (Gx^2 + Gy^2) / (2 * factor^2) )
                        // Gx(x, y) = (I(x + 1, y) - I(x - 1, y)) / 2
                        // Gy(x, y) = (I(x, y + 1) - I(x, y - 1)) / 2
                        //
                        // here is a little bit optimized version

                        // x - 1, y - 1
                        gx = src[-srcStride] - src[-pixelSize2 - srcStride];
                        gy = src[-pixelSize] - src[-pixelSize - 2 * srcStride];
                        weight = System.Math.Exp( ( gx * gx + gy * gy ) / f );
                        total += weight * src[-pixelSize - srcStride];
                        weightTotal += weight;

                        // x, y - 1
                        gx = src[pixelSize - srcStride] - src[-pixelSize - srcStride];
                        gy = *src - src[-2 * srcStride];
                        weight = System.Math.Exp( ( gx * gx + gy * gy ) / f );
                        total += weight * src[-srcStride];
                        weightTotal += weight;

                        // x + 1, y - 1
                        gx = src[pixelSize2 - srcStride] - src[-srcStride];
                        gy = src[pixelSize] - src[pixelSize - 2 * srcStride];
                        weight = System.Math.Exp( ( gx * gx + gy * gy ) / f );
                        total += weight * src[pixelSize - srcStride];
                        weightTotal += weight;

                        // x - 1, y
                        gx = *src - src[-pixelSize2];
                        gy = src[-pixelSize + srcStride] - src[-pixelSize - srcStride];
                        weight = System.Math.Exp( ( gx * gx + gy * gy ) / f );
                        total += weight * src[-pixelSize];
                        weightTotal += weight;

                        // x, y
                        gx = src[pixelSize] - src[-pixelSize];
                        gy = src[srcStride] - src[-srcStride];
                        weight = System.Math.Exp( ( gx * gx + gy * gy ) / f );
                        total += weight * ( *src );
                        weightTotal += weight;

                        // x + 1, y
                        gx = src[pixelSize2] - *src;
                        gy = src[pixelSize + srcStride] - src[pixelSize - srcStride];
                        weight = System.Math.Exp( ( gx * gx + gy * gy ) / f );
                        total += weight * src[pixelSize];
                        weightTotal += weight;

                        // x - 1, y + 1
                        gx = src[srcStride] - src[-pixelSize2 + srcStride];
                        gy = src[-pixelSize + 2 * srcStride] - src[-pixelSize];
                        weight = System.Math.Exp( ( gx * gx + gy * gy ) / f );
                        total += weight * src[-pixelSize + srcStride];
                        weightTotal += weight;

                        // x, y + 1
                        gx = src[pixelSize + srcStride] - src[-pixelSize + srcStride];
                        gy = src[2 * srcStride] - *src;
                        weight = System.Math.Exp( ( gx * gx + gy * gy ) / f );
                        total += weight * src[srcStride];
                        weightTotal += weight;

                        // x + 1, y + 1
                        gx = src[pixelSize2 + srcStride] - src[srcStride];
                        gy = src[pixelSize + 2 * srcStride] - src[pixelSize];
                        weight = System.Math.Exp( ( gx * gx + gy * gy ) / f );
                        total += weight * src[pixelSize + srcStride];
                        weightTotal += weight;

                        // save destination value
                        *dst = ( weightTotal == 0.0 ) ? *src : (byte) System.Math.Min( total / weightTotal, 255.0 );
                    }
                }
                src += srcOffset + pixelSize2;
                dst += dstOffset + pixelSize2;
            }
        }
    }