#![forbid(unsafe_code)]
use num_traits::AsPrimitive;
use std::ops::{AddAssign, BitXor};
#[allow(dead_code)]
pub(crate) fn has_non_constant_cap_alpha_rgba8(store: &[u8], width: usize, stride: usize) -> bool {
has_non_constant_cap_alpha::<u8, u32, 3, 4>(store, width, stride)
}
#[allow(dead_code)]
pub(crate) fn has_non_constant_cap_alpha_gray_alpha8(
store: &[u8],
width: usize,
stride: usize,
) -> bool {
has_non_constant_cap_alpha::<u8, u32, 1, 2>(store, width, stride)
}
#[allow(dead_code)]
pub(crate) fn has_non_constant_cap_alpha_rgba16(
store: &[u16],
width: usize,
stride: usize,
) -> bool {
has_non_constant_cap_alpha::<u16, u64, 3, 4>(store, width, stride)
}
#[allow(dead_code)]
pub(crate) fn has_non_constant_cap_alpha_gray_alpha16(
store: &[u16],
width: usize,
stride: usize,
) -> bool {
has_non_constant_cap_alpha::<u16, u64, 1, 2>(store, width, stride)
}
pub(crate) fn has_non_constant_cap_alpha_rgba_f32(
store: &[f32],
width: usize,
stride: usize,
) -> bool {
has_non_constant_cap_alpha_f32_impl::<3, 4>(store, width, stride)
}
pub(crate) fn has_non_constant_cap_alpha_gray_alpha_f32(
store: &[f32],
width: usize,
stride: usize,
) -> bool {
has_non_constant_cap_alpha_f32_impl::<1, 2>(store, width, stride)
}
pub(crate) fn has_non_constant_cap_alpha<
V: Copy + PartialEq + BitXor<V, Output = V> + 'static + AsPrimitive<J> + 'static,
J: Copy + AddAssign + Default + 'static + Eq + Ord,
const ALPHA_CHANNEL_INDEX: usize,
const CN: usize,
>(
store: &[V],
width: usize,
stride: usize,
) -> bool
where
i32: AsPrimitive<V>,
u32: AsPrimitive<V> + AsPrimitive<J>,
{
assert!(ALPHA_CHANNEL_INDEX < CN);
assert!(CN <= 4);
if store.is_empty() {
return false;
}
let first = store[ALPHA_CHANNEL_INDEX];
let mut row_sums: J = 0u32.as_();
for row in store.chunks(stride) {
let row = &row[..width * CN];
for color in row.as_chunks::<CN>().0.iter() {
row_sums += color[ALPHA_CHANNEL_INDEX].bitxor(first).as_();
}
if row_sums != 0.as_() {
return true;
}
}
let zeros = 0.as_();
row_sums.ne(&zeros)
}
fn has_non_constant_cap_alpha_f32_impl<const ALPHA_CHANNEL_INDEX: usize, const CN: usize>(
store: &[f32],
width: usize,
stride: usize,
) -> bool {
assert!(ALPHA_CHANNEL_INDEX < CN);
assert!(CN <= 4);
if store.is_empty() {
return false;
}
let first = store[ALPHA_CHANNEL_INDEX].to_bits();
let mut row_sums: u64 = 0u64;
for row in store.chunks(stride) {
let row = &row[..width * CN];
for color in row.as_chunks::<CN>().0.iter() {
row_sums += color[ALPHA_CHANNEL_INDEX].to_bits().bitxor(first) as u64;
}
if row_sums != 0 {
return true;
}
}
let zeros = 0;
row_sums.ne(&zeros)
}