Skip to content
Open
Changes from 2 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
23 changes: 11 additions & 12 deletions src/imageops/resize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
//! Everything that references pic-scale-safe crate is contained to this file
//! so that it could easily be made an optional dependency in the future.

use std::ops::{AddAssign, BitXor};
use std::ops::{BitOrAssign, BitXor};

use crate::{imageops::FilterType, DynamicImage, ImageBuffer, Pixel};
use num_traits::Zero;
use pic_scale_safe::ResamplingFunction;

pub(crate) fn resize_impl(
Expand Down Expand Up @@ -158,26 +159,25 @@ fn has_constant_alpha_integer<P, Container>(img: &ImageBuffer<P, Container>) ->
where
P: Pixel,
Container: std::ops::Deref<Target = [P::Subpixel]>,
P::Subpixel:
Copy + PartialEq + BitXor<P::Subpixel, Output = P::Subpixel> + AddAssign + Into<u64>,
P::Subpixel: Copy + PartialEq + BitXor<P::Subpixel, Output = P::Subpixel> + BitOrAssign,
{
let first_pixel_alpha = *match img.pixels().first() {
Some(pixel) => pixel.channels().last().unwrap(), // there doesn't seem to be a better way to retrieve the alpha channel
None => return true, // empty input image
let first_pixel_alpha = match img.pixels().first() {
Some(pixel) => pixel.alpha(),
None => return true, // empty input image
};
// A naive, slower implementation that branches on every pixel:
//
// img.pixels().map(|pixel| pixel.channels().last().unwrap()).all(|alpha| alpha == first_pixel_alpha);
// img.pixels().iter().all(|pixel| pixel.alpha() == first_pixel_alpha);
//
// Instead of doing that we scan every row first with cheap arithmetic instructions
// and only compare the sum of divergences on every row, which should be 0
let mut sum_of_diffs: u64 = 0;
let mut diff_acc = <P::Subpixel as Zero>::zero();
for row in img.rows() {
row.iter().for_each(|pixel| {
let alpha = pixel.alpha();
sum_of_diffs += alpha.bitxor(first_pixel_alpha).into();
diff_acc |= alpha.bitxor(first_pixel_alpha);
});
if sum_of_diffs != 0 {
if !diff_acc.is_zero() {
return false;
}
}
Expand All @@ -193,8 +193,7 @@ fn has_constant_alpha_f32(img: &ImageBuffer<crate::Rgba<f32>, Vec<f32>>) -> bool
};
img.pixels()
.iter()
.map(|pixel| pixel.channels().last().unwrap())
.all(|alpha| *alpha == first_pixel_alpha)
.all(|pixel| pixel.alpha() == first_pixel_alpha)
}

#[cfg(test)]
Expand Down
Loading