/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="image">Source image data.</param> /// protected override unsafe void ProcessFilter(UnmanagedImage image) { UnmanagedImage bgImage = null; BitmapData bgLockedData = null; // get image size int width = image.Width; int height = image.Height; int offset = image.Stride - ((image.PixelFormat == PixelFormat.Format8bppIndexed) ? width : width * 3); // check if we have provided background if ((backgroundImage == null) && (unmanagedBackgroundImage == null)) { // resize image to 1/3 of its original size to make bluring faster ResizeBicubic resizeFilter = new ResizeBicubic((int)width / 3, (int)height / 3); UnmanagedImage tempImage = resizeFilter.Apply(image); // create background image from the input image blurring it with Gaussian 5 times GaussianBlur blur = new GaussianBlur(5, 21); blur.ApplyInPlace(tempImage); blur.ApplyInPlace(tempImage); blur.ApplyInPlace(tempImage); blur.ApplyInPlace(tempImage); blur.ApplyInPlace(tempImage); // resize the blurred image back to original size resizeFilter.NewWidth = width; resizeFilter.NewHeight = height; bgImage = resizeFilter.Apply(tempImage); tempImage.Dispose( ); } else { if (backgroundImage != null) { // check background image if ((width != backgroundImage.Width) || (height != backgroundImage.Height) || (image.PixelFormat != backgroundImage.PixelFormat)) { throw new InvalidImagePropertiesException("Source image and background images must have the same size and pixel format"); } // lock background image bgLockedData = backgroundImage.LockBits( new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, backgroundImage.PixelFormat); bgImage = new UnmanagedImage(bgLockedData); } else { bgImage = unmanagedBackgroundImage; } } // get background image's statistics (mean value is used as correction factor) ImageStatistics bgStatistics = new ImageStatistics(bgImage); byte *src = (byte *)image.ImageData.ToPointer( ); byte *bg = (byte *)bgImage.ImageData.ToPointer( ); // do the job if (image.PixelFormat == PixelFormat.Format8bppIndexed) { // grayscale image double mean = bgStatistics.Gray.Mean; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++, src++, bg++) { if (*bg != 0) { *src = (byte)Math.Min(mean * *src / *bg, 255); } } src += offset; bg += offset; } } else { // color image double meanR = bgStatistics.Red.Mean; double meanG = bgStatistics.Green.Mean; double meanB = bgStatistics.Blue.Mean; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++, src += 3, bg += 3) { // red if (bg[RGB.R] != 0) { src[RGB.R] = (byte)Math.Min(meanR * src[RGB.R] / bg[RGB.R], 255); } // green if (bg[RGB.G] != 0) { src[RGB.G] = (byte)Math.Min(meanG * src[RGB.G] / bg[RGB.G], 255); } // blue if (bg[RGB.B] != 0) { src[RGB.B] = (byte)Math.Min(meanB * src[RGB.B] / bg[RGB.B], 255); } } src += offset; bg += offset; } } if (backgroundImage != null) { backgroundImage.UnlockBits(bgLockedData); } // dispose background image if it was not set manually if ((backgroundImage == null) && (unmanagedBackgroundImage == null)) { bgImage.Dispose( ); } }
/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="image">Source image data.</param> /// protected override unsafe void ProcessFilter( UnmanagedImage image ) { UnmanagedImage bgImage = null; BitmapData bgLockedData = null; // get image size int width = image.Width; int height = image.Height; int offset = image.Stride - ( ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ? width : width * 3 ); // check if we have provided background if ( ( backgroundImage == null ) && ( unmanagedBackgroundImage == null ) ) { // resize image to 1/3 of its original size to make bluring faster ResizeBicubic resizeFilter = new ResizeBicubic( (int) width / 3, (int) height / 3 ); UnmanagedImage tempImage = resizeFilter.Apply( image ); // create background image from the input image blurring it with Gaussian 5 times GaussianBlur blur = new GaussianBlur( 5, 21 ); blur.ApplyInPlace( tempImage ); blur.ApplyInPlace( tempImage ); blur.ApplyInPlace( tempImage ); blur.ApplyInPlace( tempImage ); blur.ApplyInPlace( tempImage ); // resize the blurred image back to original size resizeFilter.NewWidth = width; resizeFilter.NewHeight = height; bgImage = resizeFilter.Apply( tempImage ); tempImage.Dispose( ); } else { if ( backgroundImage != null ) { // check background image if ( ( width != backgroundImage.Width ) || ( height != backgroundImage.Height ) || ( image.PixelFormat != backgroundImage.PixelFormat ) ) { throw new InvalidImagePropertiesException( "Source image and background images must have the same size and pixel format" ); } // lock background image bgLockedData = backgroundImage.LockBits( new Rectangle( 0, 0, width, height ), ImageLockMode.ReadOnly, backgroundImage.PixelFormat ); bgImage = new UnmanagedImage( bgLockedData ); } else { bgImage = unmanagedBackgroundImage; } } // get background image's statistics (mean value is used as correction factor) ImageStatistics bgStatistics = new ImageStatistics( bgImage ); byte* src = (byte*) image.ImageData.ToPointer( ); byte* bg = (byte*) bgImage.ImageData.ToPointer( ); // do the job if ( image.PixelFormat == PixelFormat.Format8bppIndexed ) { // grayscale image double mean = bgStatistics.Gray.Mean; for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++, src++, bg++ ) { if ( *bg != 0 ) { *src = (byte) Math.Min( mean * *src / *bg, 255 ); } } src += offset; bg += offset; } } else { // color image double meanR = bgStatistics.Red.Mean; double meanG = bgStatistics.Green.Mean; double meanB = bgStatistics.Blue.Mean; for ( int y = 0; y < height; y++ ) { for ( int x = 0; x < width; x++, src += 3, bg += 3 ) { // red if ( bg[RGB.R] != 0 ) { src[RGB.R] = (byte) Math.Min( meanR * src[RGB.R] / bg[RGB.R], 255 ); } // green if ( bg[RGB.G] != 0 ) { src[RGB.G] = (byte) Math.Min( meanG * src[RGB.G] / bg[RGB.G], 255 ); } // blue if ( bg[RGB.B] != 0 ) { src[RGB.B] = (byte) Math.Min( meanB * src[RGB.B] / bg[RGB.B], 255 ); } } src += offset; bg += offset; } } if ( backgroundImage != null ) { backgroundImage.UnlockBits( bgLockedData ); } // dispose background image if it was not set manually if ( ( backgroundImage == null ) && ( unmanagedBackgroundImage == null ) ) { bgImage.Dispose( ); } }