diff --git a/benches/blur.rs b/benches/blur.rs index 25668fac0d..ee80d2f8f4 100644 --- a/benches/blur.rs +++ b/benches/blur.rs @@ -1,5 +1,5 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use image::imageops::{blur_advanced, fast_blur, GaussianBlurParameters}; +use image::imageops::{blur, fast_blur}; use image::{DynamicImage, ImageBuffer, Rgb, RgbImage}; pub fn bench_fast_blur(c: &mut Criterion) { @@ -19,27 +19,27 @@ pub fn bench_fast_blur(c: &mut Criterion) { }); c.bench_function("gaussian blur: sigma 3.0", |b| { - b.iter(|| blur_advanced(&src, GaussianBlurParameters::new_from_sigma(3.0))); + b.iter(|| blur(&src, 3.0)); }); c.bench_function("gaussian blur: sigma 7.0", |b| { - b.iter(|| blur_advanced(&src, GaussianBlurParameters::new_from_sigma(7.0))); + b.iter(|| blur(&src, 7.0)); }); c.bench_function("gaussian blur: sigma 50.0", |b| { - b.iter(|| blur_advanced(&src, GaussianBlurParameters::new_from_sigma(50.0))); + b.iter(|| blur(&src, 50.0)); }); c.bench_function("gaussian blur (dynamic image): sigma 3.0", |b| { - b.iter(|| dynamic.blur_advanced(GaussianBlurParameters::new_from_sigma(3.0))); + b.iter(|| dynamic.blur(3.0)); }); c.bench_function("gaussian blur (dynamic image): sigma 7.0", |b| { - b.iter(|| dynamic.blur_advanced(GaussianBlurParameters::new_from_sigma(7.0))); + b.iter(|| dynamic.blur(7.0)); }); c.bench_function("gaussian blur (dynamic image): sigma 50.0", |b| { - b.iter(|| dynamic.blur_advanced(GaussianBlurParameters::new_from_sigma(50.0))); + b.iter(|| dynamic.blur(50.0)); }); } diff --git a/examples/fast_blur/main.rs b/examples/fast_blur/main.rs index 4523934e9a..40b92960ae 100644 --- a/examples/fast_blur/main.rs +++ b/examples/fast_blur/main.rs @@ -1,4 +1,3 @@ -use image::imageops::GaussianBlurParameters; use image::ImageReader; fn main() { @@ -8,7 +7,7 @@ fn main() { ); let img = ImageReader::open(path).unwrap().decode().unwrap(); - let img2 = img.blur_advanced(GaussianBlurParameters::new_from_sigma(10.0)); + let img2 = img.blur(10.0); img2.save("examples/fast_blur/mandril_color_blurred.tif") .unwrap(); diff --git a/src/imageops/fast_blur.rs b/src/imageops/fast_blur.rs index a1b9978a92..5ddc344349 100644 --- a/src/imageops/fast_blur.rs +++ b/src/imageops/fast_blur.rs @@ -3,20 +3,26 @@ use num_traits::Bounded; use crate::imageops::filter_1d::{SafeAdd, SafeMul}; use crate::{ImageBuffer, Pixel, Primitive}; -/// Approximation of Gaussian blur. +/// A fast approximation of Gaussian blur. /// /// # Arguments /// -/// * `image_buffer` - source image. -/// * `sigma` - value controls image flattening level. +/// * `sigma` - Radius of the blur. Defines the standard deviation of the +/// Gaussian function to approximate. Larger values create more blur. +/// +/// # Notes /// /// This method assumes alpha pre-multiplication for images that contain non-constant alpha. /// /// This method typically assumes that the input is scene-linear light. /// If it is not, color distortion may occur. /// -/// Source: Kovesi, P.: Fast Almost-Gaussian Filtering The Australian Pattern -/// Recognition Society Conference: DICTA 2010. December 2010. Sydney. +/// # See also +/// +/// - [`blur()`](crate::imageops::blur()) - more accurate Gaussian blur implementation, but slower. +// +// Source: Kovesi, P.: Fast Almost-Gaussian Filtering The Australian Pattern +// Recognition Society Conference: DICTA 2010. December 2010. Sydney. #[must_use] pub fn fast_blur( input_buffer: &ImageBuffer>, diff --git a/src/imageops/mod.rs b/src/imageops/mod.rs index 5e37d1d605..340d2c2284 100644 --- a/src/imageops/mod.rs +++ b/src/imageops/mod.rs @@ -534,9 +534,7 @@ mod tests { "/tests/images/tiff/testsuite/rgb-3c-16b.tiff" ); let image = crate::open(path).unwrap(); - let image_blurred_gauss = image - .blur_advanced(GaussianBlurParameters::new_from_sigma(50.0)) - .to_rgb8(); + let image_blurred_gauss = image.blur(50.0).to_rgb8(); let image_blurred_gauss_samples = image_blurred_gauss.as_flat_samples(); let image_blurred_gauss_bytes = image_blurred_gauss_samples.as_slice(); let image_blurred_fast = image.fast_blur(50.0).to_rgb8(); diff --git a/src/imageops/sample.rs b/src/imageops/sample.rs index 5997c3d543..af7acbcba6 100644 --- a/src/imageops/sample.rs +++ b/src/imageops/sample.rs @@ -995,23 +995,32 @@ where /// /// # Arguments /// -/// * `radius` - Blurring window radius. These parameter controls directly the window size. -/// We choose visually optimal sigma for the given radius. To control sigma -/// directly use [DynamicImage::blur_advanced] instead. +/// * `sigma` - Radius of the blur. Defines the standard deviation of the +/// Gaussian function. Larger values create more blur. +/// +/// # Notes /// -/// Use [`crate::imageops::fast_blur()`] for a faster but less -/// accurate version. /// This method assumes alpha pre-multiplication for images that contain non-constant alpha. +/// /// This method typically assumes that the input is scene-linear light. /// If it is not, color distortion may occur. +/// +/// # Panics +/// +/// Panics if `sigma` is negative, NaN, or infinity. +/// +/// # See also +/// +/// - [`blur_advanced()`] for a more flexible version of this function. +/// - [`fast_blur`](crate::imageops::fast_blur()) for a faster but less accurate Gaussian blur. pub fn blur( image: &I, - radius: f32, + sigma: f32, ) -> ImageBuffer::Subpixel>> where I::Pixel: 'static, { - gaussian_blur_indirect(image, GaussianBlurParameters::new_from_radius(radius)) + gaussian_blur_indirect(image, GaussianBlurParameters::new_from_sigma(sigma)) } /// Performs a Gaussian blur on the supplied image. @@ -1020,9 +1029,16 @@ where /// /// - `parameters` - see [GaussianBlurParameters] for more info. /// +/// # Notes +/// /// This method assumes alpha pre-multiplication for images that contain non-constant alpha. +/// /// This method typically assumes that the input is scene-linear light. /// If it is not, color distortion may occur. +/// +/// # See also +/// +/// - [`blur()`] for a simpler version of this function. pub fn blur_advanced( image: &I, parameters: GaussianBlurParameters, @@ -1560,24 +1576,31 @@ where out } -/// Performs an unsharpen mask on the supplied image. +/// Performs an [unsharpen mask](https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking) +/// on the supplied image. /// /// # Arguments: /// -/// * `sigma` - is the amount to blur the image by. +/// * `sigma` - Radius of the blur. Defines the standard deviation of the +/// Gaussian function used to create the unsharp mask. Larger values +/// create a blurrier mask and thus a sharpening effect for a larger area. /// * `threshold` - is the threshold for minimal brightness change that will be sharpened. /// +/// # Notes +/// /// This method typically assumes that the input is scene-linear light. /// If it is not, color distortion may occur. /// -/// See [Digital unsharp masking](https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking) for more information. +/// # Panics +/// +/// Panics if `sigma` is negative, NaN, or infinity. pub fn unsharpen(image: &I, sigma: f32, threshold: i32) -> ImageBuffer> where I: GenericImageView, P: Pixel + 'static, S: Primitive + 'static, { - let mut tmp = blur_advanced(image, GaussianBlurParameters::new_from_sigma(sigma)); + let mut tmp = blur(image, sigma); let max = S::DEFAULT_MAX_VALUE; let max: i32 = NumCast::from(max).unwrap(); diff --git a/src/images/dynimage.rs b/src/images/dynimage.rs index 82ba790b05..1b901256bc 100644 --- a/src/images/dynimage.rs +++ b/src/images/dynimage.rs @@ -964,22 +964,30 @@ impl DynamicImage { /// /// # Arguments /// - /// * `radius` - Blurring window radius. These parameter controls directly the window size. - /// We choose visually optimal sigma for the given radius. To control sigma - /// directly use [DynamicImage::blur_advanced] instead. + /// * `sigma` - Radius of the blur. Defines the standard deviation of the + /// Gaussian function. Larger values create more blur. /// - /// Use [DynamicImage::fast_blur()] for a faster but less - /// accurate version. + /// # Notes /// /// This method assumes alpha pre-multiplication for images that contain non-constant alpha. + /// /// This method typically assumes that the input is scene-linear light. /// If it is not, color distortion may occur. /// /// This method operates on pixel channel values directly without taking into account color /// space data. + /// + /// # Panics + /// + /// Panics if `sigma` is negative, NaN, or infinity. + /// + /// # See also + /// + /// - [DynamicImage::blur_advanced()] for more control over the blur parameters. + /// - [DynamicImage::fast_blur()] for a faster but less accurate version. #[must_use] - pub fn blur(&self, radius: f32) -> DynamicImage { - gaussian_blur_dyn_image(self, GaussianBlurParameters::new_from_radius(radius)) + pub fn blur(&self, sigma: f32) -> DynamicImage { + gaussian_blur_dyn_image(self, GaussianBlurParameters::new_from_sigma(sigma)) } /// Performs a Gaussian blur on this image. @@ -988,7 +996,10 @@ impl DynamicImage { /// /// * `parameters` - see [GaussianBlurParameters] for more info /// + /// # Notes + /// /// This method assumes alpha pre-multiplication for images that contain non-constant alpha. + /// /// This method typically assumes that the input is scene-linear light. /// If it is not, color distortion may occur. /// @@ -1003,7 +1014,10 @@ impl DynamicImage { /// /// # Arguments /// - /// * `sigma` - value controls image flattening level. + /// * `sigma` - Radius of the blur. Defines the standard deviation of the + /// Gaussian function to approximate. Larger values create more blur. + /// + /// # Notes /// /// This method typically assumes that the input is scene-linear light. /// If it is not, color distortion may occur. @@ -1015,19 +1029,25 @@ impl DynamicImage { dynamic_map!(*self, ref p => imageops::fast_blur(p, sigma)) } - /// Performs an unsharpen mask on this image. + /// Performs an [unsharpen mask](https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking) on this image. /// /// # Arguments /// - /// * `sigma` - value controls image flattening level. + /// * `sigma` - Radius of the blur. Defines the standard deviation of the + /// Gaussian function used to create the unsharp mask. Larger values + /// create a blurrier mask and thus a sharpening effect for a larger area. /// * `threshold` - is a control of how much to sharpen. /// + /// # Notes + /// /// This method typically assumes that the input is scene-linear light. If it is not, color - /// distortion may occur. It operates on pixel channel values directly without taking into - /// account color space data. + /// distortion may occur. + /// + /// It operates on pixel channel values directly without taking into account color space data. + /// + /// # Panics /// - /// See [Digital unsharp masking](https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking) - /// for more information + /// Panics if `sigma` is negative, NaN, or infinity. #[must_use] pub fn unsharpen(&self, sigma: f32, threshold: i32) -> DynamicImage { dynamic_map!(*self, ref p => imageops::unsharpen(p, sigma, threshold))