Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions benches/blur.rs
Original file line number Diff line number Diff line change
@@ -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) {
Expand All @@ -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));
});
}

Expand Down
3 changes: 1 addition & 2 deletions examples/fast_blur/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use image::imageops::GaussianBlurParameters;
use image::ImageReader;

fn main() {
Expand All @@ -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();
Expand Down
16 changes: 11 additions & 5 deletions src/imageops/fast_blur.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<P: Pixel>(
input_buffer: &ImageBuffer<P, Vec<P::Subpixel>>,
Expand Down
4 changes: 1 addition & 3 deletions src/imageops/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
45 changes: 34 additions & 11 deletions src/imageops/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<I: GenericImageView>(
image: &I,
radius: f32,
sigma: f32,
) -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::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.
Expand All @@ -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<I: GenericImageView>(
image: &I,
parameters: GaussianBlurParameters,
Expand Down Expand Up @@ -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<I, P, S>(image: &I, sigma: f32, threshold: i32) -> ImageBuffer<P, Vec<S>>
where
I: GenericImageView<Pixel = P>,
P: Pixel<Subpixel = S> + '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();
Expand Down
48 changes: 34 additions & 14 deletions src/images/dynimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
///
Expand All @@ -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.
Expand All @@ -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))
Expand Down
Loading