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
2 changes: 1 addition & 1 deletion benches/imageops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub fn bench_imageops(c: &mut Criterion) {
});

c.bench_function("unsharpen", |b| {
b.iter(|| imageops::unsharpen(&src, 2.0, 0));
b.iter(|| imageops::unsharpen(&src, 2.0, 0.0));
});
}

Expand Down
26 changes: 16 additions & 10 deletions src/imageops/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1546,25 +1546,31 @@ fn gaussian_blur_indirect_impl<I: GenericImageView, const CN: usize>(

/// Performs an unsharpen mask on the supplied image.
///
/// # Arguments:
/// # Arguments
///
/// * `sigma` - is the amount to blur the image by.
/// * `threshold` - is the threshold for minimal brightness change that will be sharpened.
/// - `sigma` - The amount to blur the image by.
/// - `threshold` - The threshold between 0 and 1 that removes sharpening from
/// areas with little contrast.
///
/// # 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.
pub fn unsharpen<I, P, S>(image: &I, sigma: f32, threshold: i32) -> ImageBuffer<P, Vec<S>>
pub fn unsharpen<I, P, S>(image: &I, sigma: f32, threshold: f32) -> ImageBuffer<P, Vec<S>>
where
I: GenericImageView<Pixel = P>,
P: Pixel<Subpixel = S>,
S: Primitive,
{
let mut tmp = blur_advanced(image, GaussianBlurParameters::new_from_sigma(sigma));

let max = S::DEFAULT_MAX_VALUE;
let max: i32 = NumCast::from(max).unwrap();
let max: f32 = NumCast::from(S::DEFAULT_MAX_VALUE).unwrap();
let min: f32 = NumCast::from(S::DEFAULT_MIN_VALUE).unwrap();

let threshold = threshold * (max - min);

let (width, height) = image.dimensions();

for y in 0..height {
Expand All @@ -1573,13 +1579,13 @@ where
let b = tmp.get_pixel_mut(x, y);

let p = a.map2(b, |c, d| {
let ic: i32 = NumCast::from(c).unwrap();
let id: i32 = NumCast::from(d).unwrap();
let c_f: f32 = NumCast::from(c).unwrap();
let d_f: f32 = NumCast::from(d).unwrap();

let diff = ic - id;
let diff = c_f - d_f;

if diff.abs() > threshold {
let e = clamp(ic + diff, 0, max); // FIXME what does this do for f32? clamp 0-1 integers??
let e = clamp(c_f + diff, min, max);

NumCast::from(e).unwrap()
} else {
Expand Down
11 changes: 7 additions & 4 deletions src/images/dynimage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1019,8 +1019,11 @@ impl DynamicImage {
///
/// # Arguments
///
/// * `sigma` - value controls image flattening level.
/// * `threshold` - is a control of how much to sharpen.
/// - `sigma` - The amount to blur the image by.
/// - `threshold` - The threshold between 0 and 1 that removes sharpening from
/// areas with little contrast.
///
/// # 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
Expand All @@ -1029,7 +1032,7 @@ impl DynamicImage {
/// See [Digital unsharp masking](https://en.wikipedia.org/wiki/Unsharp_masking#Digital_unsharp_masking)
/// for more information
#[must_use]
pub fn unsharpen(&self, sigma: f32, threshold: i32) -> DynamicImage {
pub fn unsharpen(&self, sigma: f32, threshold: f32) -> DynamicImage {
dynamic_map!(*self, ref p => imageops::unsharpen(p, sigma, threshold))
}

Expand Down Expand Up @@ -2219,7 +2222,7 @@ mod test {
)
},
&|img| img.fast_blur(1.0),
&|img| img.unsharpen(1.0, 3),
&|img| img.unsharpen(1.0, 0.02),
&|img| img.filter3x3(&[0.0, -1.0, 0.0, -1.0, 5.0, -1.0, 0.0, -1.0, 0.0]),
&|img| img.adjust_contrast(0.5),
&|img| img.brighten(10),
Expand Down
Loading