AForge.Imaging.Filters.BilateralSmoothing.ProcessWithEdgeChecks C# (CSharp) Method

ProcessWithEdgeChecks() private method

private ProcessWithEdgeChecks ( UnmanagedImage source, UnmanagedImage destination, Rectangle rect ) : void
source UnmanagedImage
destination UnmanagedImage
rect System.Drawing.Rectangle
return void
        private unsafe void ProcessWithEdgeChecks( UnmanagedImage source, UnmanagedImage destination, Rectangle rect )
        {
            int width  = source.Width;
            int height = source.Height;

            int startX = rect.Left;
            int startY = rect.Top;
            int stopX  = rect.Right;
            int stopY  = rect.Bottom;

            int pixelSize = System.Drawing.Image.GetPixelFormatSize( source.PixelFormat ) / 8;
            int kernelHalf = kernelSize / 2;
            int bytesInKernelRow = kernelSize * pixelSize;

            int srcStride = source.Stride;
            int dstStride = destination.Stride;

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

            // offset of the first kernel's pixel
            int srcKernelFistPixelOffset = kernelHalf * ( srcStride + pixelSize );
            // offset to move to the next kernel's pixel after processing one kernel's row
            int srcKernelOffset = srcStride - bytesInKernelRow;

            int rx, ry;
            int tx, ty;

            byte* src = (byte*) source.ImageData.ToPointer( );
            byte* dst = (byte*) destination.ImageData.ToPointer( );

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

            if ( pixelSize > 1 )
            {
                // color images
                byte srcR, srcG, srcB;
                byte srcR0, srcG0, srcB0;
                byte* srcPixel;

                double sCoefR, sCoefG, sCoefB, sMembR, sMembG, sMembB, coefR, coefG, coefB;

                for ( int y = startY; y < stopY; y++ )
                {
                    for ( int x = startX; x < stopX; x++, src += pixelSize, dst += pixelSize )
                    {
                        // lower right corner - to start processing from that point
                        srcPixel = src + srcKernelFistPixelOffset;

                        sCoefR = 0;
                        sCoefG = 0;
                        sCoefB = 0;
                        sMembR = 0;
                        sMembG = 0;
                        sMembB = 0;

                        srcR0 = src[RGB.R];
                        srcG0 = src[RGB.G];
                        srcB0 = src[RGB.B];

                        // move from lower right to upper left corner
                        ty = kernelSize;
                        while ( ty != 0 )
                        {
                            ty--;
                            ry = ty - kernelHalf;

                            if ( ( ry + y >= height ) || ( ry + y < 0 ) ) // bounds check
                            {
                                srcPixel -= srcStride;
                                continue;
                            }

                            tx = kernelSize;
                            while ( tx != 0 )
                            {
                                tx--;
                                rx = tx - kernelHalf;

                                if ( ( rx + x >= width ) || ( rx + x < 0 ) ) // bounds check
                                {
                                    srcPixel -= pixelSize;
                                    continue;
                                }

                                srcR = srcPixel[RGB.R];
                                srcG = srcPixel[RGB.G];
                                srcB = srcPixel[RGB.B];

                                coefR = spatialFunc[tx, ty] * colorFunc[srcR, srcR0];
                                coefG = spatialFunc[tx, ty] * colorFunc[srcG, srcG0];
                                coefB = spatialFunc[tx, ty] * colorFunc[srcB, srcB0];

                                sCoefR += coefR;
                                sCoefG += coefG;
                                sCoefB += coefB;

                                sMembR += coefR * srcR;
                                sMembG += coefG * srcG;
                                sMembB += coefB * srcB;

                                srcPixel -= pixelSize;
                            }

                            srcPixel -= srcKernelOffset;
                        }

                        dst[RGB.R] = (byte) ( sMembR / sCoefR );
                        dst[RGB.G] = (byte) ( sMembG / sCoefG );
                        dst[RGB.B] = (byte) ( sMembB / sCoefB );
                    }

                    src += srcOffset;
                    dst += dstOffset;
                }
            }
            else
            {
                // 8bpp grayscale images
                byte srcC;
                byte srcC0;
                byte* srcPixel;
                double sCoefC, sMembC, coefC;

                for ( int y = startY; y < stopY; y++ )
                {
                    for ( int x = startX; x < stopX; x++, src++, dst++ )
                    {
                        // lower right corner - to start processing from that point
                        srcPixel = src + srcKernelFistPixelOffset;

                        sCoefC = 0;
                        sMembC = 0;

                        srcC0 = *src;

                        // move from lower right to upper left corner
                        ty = kernelSize;
                        while ( ty != 0 )
                        {
                            ty--;
                            ry = (int) ( ty - kernelHalf );

                            if ( ( ry + y >= height ) || ( ry + y < 0 ) ) // bounds check
                            {
                                srcPixel -= srcStride;
                                continue;
                            }

                            tx = kernelSize;
                            while ( tx != 0 )
                            {
                                tx--;
                                rx = (int) ( tx - kernelHalf );

                                if ( ( rx + x >= source.Width ) || ( rx + x < 0 ) ) // bounds check
                                {
                                    srcPixel -= pixelSize;
                                    continue;
                                }

                                srcC = *( srcPixel );
                                coefC = spatialFunc[tx, ty] * colorFunc[srcC, srcC0];

                                sCoefC += coefC;
                                sMembC += coefC * srcC;

                                srcPixel -= pixelSize;
                            }

                            srcPixel -= srcKernelOffset;
                        }

                        *dst = (byte) ( sMembC / sCoefC );
                    }
                    src += srcOffset;
                    dst += dstOffset;
                }
            }
        }
    }