binary_image 0.8.1

A library for handling binary images
Documentation
#![allow(clippy::suspicious_arithmetic_impl)]
use derive_more::{
    derive::{BitAnd, BitOr, BitXor, Shl, ShlAssign, Shr, ShrAssign},
    AsMut, AsRef, BitAndAssign, BitOrAssign, BitXorAssign, Deref, DerefMut, Display, From, Into,
    Not,
};
use num_traits::{One, Zero};

#[repr(transparent)]
#[derive(
    Clone,
    Copy,
    Debug,
    Display,
    Default,
    PartialEq,
    Eq,
    PartialOrd,
    Ord,
    Hash,
    Deref,
    DerefMut,
    AsMut,
    AsRef,
    Not,
    BitOrAssign,
    BitAndAssign,
    BitXorAssign,
    ShlAssign,
    ShrAssign,
    BitOr,
    BitAnd,
    BitXor,
    Shl,
    Shr,
    Into,
    From,
)]
pub struct Bit(pub bool);

impl std::ops::AddAssign for Bit {
    fn add_assign(&mut self, rhs: Self) {
        *self = *self + rhs;
    }
}

impl std::ops::SubAssign for Bit {
    fn sub_assign(&mut self, rhs: Self) {
        *self = *self - rhs;
    }
}

impl std::ops::MulAssign for Bit {
    fn mul_assign(&mut self, rhs: Self) {
        *self = *self * rhs;
    }
}

impl std::ops::DivAssign for Bit {
    fn div_assign(&mut self, rhs: Self) {
        *self = *self / rhs;
    }
}

impl std::ops::Add for Bit {
    type Output = Self;
    fn add(mut self, rhs: Self) -> Self::Output {
        self.0 |= *rhs;
        self
    }
}

impl std::ops::Sub for Bit {
    type Output = Self;
    fn sub(mut self, rhs: Self) -> Self::Output {
        self.0 ^= *rhs;
        self
    }
}

impl std::ops::Mul for Bit {
    type Output = Self;
    fn mul(mut self, rhs: Self) -> Self::Output {
        self.0 &= *rhs;
        self
    }
}

impl std::ops::Div for Bit {
    type Output = Self;
    fn div(mut self, rhs: Self) -> Self::Output {
        debug_assert!(*rhs, "Cannot divide by zero");
        self.0 &= *rhs;
        self
    }
}

impl std::ops::Rem for Bit {
    type Output = Self;
    fn rem(self, rhs: Self) -> Self::Output {
        debug_assert!(*rhs, "Cannot divide by zero");
        Self(false)
    }
}

impl Zero for Bit {
    fn is_zero(&self) -> bool {
        !**self
    }
    fn set_zero(&mut self) {
        self.0 = false;
    }
    fn zero() -> Self {
        Self(false)
    }
}

impl One for Bit {
    fn is_one(&self) -> bool {
        **self
    }
    fn set_one(&mut self) {
        self.0 = true;
    }
    fn one() -> Self {
        Self(true)
    }
}

impl num_traits::Num for Bit {
    type FromStrRadixErr = ();
    fn from_str_radix(str: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
        if str.chars().all(|ch| ch.is_digit(radix)) {
            Ok(Self(str.chars().all(|ch| !matches!(ch, '0'))))
        } else {
            Err(())
        }
    }
}

impl num_traits::NumCast for Bit {
    fn from<T: num_traits::ToPrimitive>(n: T) -> Option<Self> {
        n.to_usize()
            .map(|n| Self(n != 0))
            .or_else(|| n.to_isize().map(|n| Self(n != 0)))
    }
}

impl num_traits::ToPrimitive for Bit {
    #[allow(clippy::cast_possible_wrap)]
    fn to_i64(&self) -> Option<i64> {
        Some(self.0.into())
    }

    fn to_u64(&self) -> Option<u64> {
        Some(self.0.into())
    }
}

impl num_traits::Bounded for Bit {
    fn min_value() -> Self {
        Self(false)
    }
    fn max_value() -> Self {
        Self(true)
    }
}

impl image::Primitive for Bit {
    const DEFAULT_MAX_VALUE: Self = Self(true);
    const DEFAULT_MIN_VALUE: Self = Self(false);
}

impl image::Pixel for Bit {
    type Subpixel = Self;
    const CHANNEL_COUNT: u8 = 1;
    const COLOR_MODEL: &'static str = "BLACKANDWHITE";
    fn channels(&self) -> &[Self] {
        unimplemented!()
    }
    fn channels_mut(&mut self) -> &mut [Self] {
        unimplemented!()
    }
    fn from_slice(slice: &[Self]) -> &Self {
        assert_eq!(slice.len(), 1);
        unsafe { &*slice.as_ptr().cast() }
    }
    fn from_slice_mut(slice: &mut [Self]) -> &mut Self {
        assert_eq!(slice.len(), 1);
        unsafe { &mut *slice.as_mut_ptr().cast() }
    }
    fn to_rgb(&self) -> image::Rgb<Bit> {
        image::Rgb([if **self { One::one() } else { Zero::zero() }; 3])
    }
    fn to_rgba(&self) -> image::Rgba<Bit> {
        image::Rgba([if **self { One::one() } else { Zero::zero() }; 4])
    }
    fn to_luma(&self) -> image::Luma<Self> {
        image::Luma([if **self { One::one() } else { Zero::zero() }])
    }
    fn to_luma_alpha(&self) -> image::LumaA<Self> {
        image::LumaA([if **self { One::one() } else { Zero::zero() }; 2])
    }
    fn map<F>(&self, mut f: F) -> Self
    where
        F: FnMut(Self) -> Self,
    {
        Self(*f(*self))
    }
    fn map_with_alpha<F, G>(&self, mut f: F, _: G) -> Self
    where
        F: FnMut(Self) -> Self,
        G: FnMut(Self) -> Self,
    {
        Self(*f(*self))
    }
    fn apply<F>(&mut self, mut f: F)
    where
        F: FnMut(Self) -> Self,
    {
        self.0 = *f(*self);
    }
    fn apply_with_alpha<F, G>(&mut self, f: F, _: G)
    where
        F: FnMut(Self) -> Self,
        G: FnMut(Self) -> Self,
    {
        self.apply(f);
    }
    fn map2<F>(&self, other: &Self, mut f: F) -> Self
    where
        F: FnMut(Self, Self) -> Self,
    {
        Self(*f(*self, *other))
    }
    fn apply2<F>(&mut self, other: &Self, mut f: F)
    where
        F: FnMut(Self, Self) -> Self,
    {
        self.0 = *f(*self, *other);
    }
    fn invert(&mut self) {
        self.0 = !self.0;
    }
    fn blend(&mut self, other: &Self) {
        *self -= *other;
    }
    fn channels4(&self) -> (Self, Self, Self, Self) {
        (*self, *self, *self, *self)
    }
    fn map_without_alpha<F>(&self, mut f: F) -> Self
    where
        F: FnMut(Self) -> Self,
    {
        Self(*f(*self))
    }
    fn apply_without_alpha<F>(&mut self, f: F)
    where
        F: FnMut(Self) -> Self,
    {
        self.apply(f);
    }
    fn from_channels(a: Self, b: Self, c: Self, d: Self) -> Self {
        Self(*(a | b | c | d))
    }
}

impl<T: image::Primitive> From<image::Rgb<T>> for Bit {
    fn from(pixel: image::Rgb<T>) -> Self {
        Self(!pixel.0.iter().all(Zero::is_zero))
    }
}
impl<T: image::Primitive> From<image::Luma<T>> for Bit {
    fn from(pixel: image::Luma<T>) -> Self {
        Self(!pixel.0[0].is_zero())
    }
}
impl<T: image::Primitive> From<image::Rgba<T>> for Bit {
    fn from(pixel: image::Rgba<T>) -> Self {
        Self(!pixel.0[3].is_zero())
    }
}
impl<T: image::Primitive> From<image::LumaA<T>> for Bit {
    fn from(pixel: image::LumaA<T>) -> Self {
        Self(!pixel.0[1].is_zero())
    }
}

impl<T: image::Primitive> From<&image::Rgb<T>> for Bit {
    fn from(pixel: &image::Rgb<T>) -> Self {
        Self(!pixel.0.iter().all(Zero::is_zero))
    }
}
impl<T: image::Primitive> From<&image::Luma<T>> for Bit {
    fn from(pixel: &image::Luma<T>) -> Self {
        Self(!pixel.0[0].is_zero())
    }
}
impl<T: image::Primitive> From<&image::Rgba<T>> for Bit {
    fn from(pixel: &image::Rgba<T>) -> Self {
        Self(!pixel.0[3].is_zero())
    }
}
impl<T: image::Primitive> From<&image::LumaA<T>> for Bit {
    fn from(pixel: &image::LumaA<T>) -> Self {
        Self(!pixel.0[1].is_zero())
    }
}