use crate::Size;
use std::mem;
pub fn from_rgba(
rgba: Vec<u8>,
width: u32,
height: u32,
) -> Result<Icon, Error> {
const PIXEL_SIZE: usize = mem::size_of::<u8>() * 4;
if !rgba.len().is_multiple_of(PIXEL_SIZE) {
return Err(Error::ByteCountNotDivisibleBy4 {
byte_count: rgba.len(),
});
}
let pixel_count = rgba.len() / PIXEL_SIZE;
if pixel_count != (width * height) as usize {
return Err(Error::DimensionsVsPixelCount {
width,
height,
width_x_height: (width * height) as usize,
pixel_count,
});
}
Ok(Icon {
rgba,
size: Size::new(width, height),
})
}
#[derive(Clone)]
pub struct Icon {
rgba: Vec<u8>,
size: Size<u32>,
}
impl Icon {
pub fn into_raw(self) -> (Vec<u8>, Size<u32>) {
(self.rgba, self.size)
}
}
impl std::fmt::Debug for Icon {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Icon")
.field("rgba", &format!("{} pixels", self.rgba.len() / 4))
.field("size", &self.size)
.finish()
}
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error(
"The provided RGBA data (with length {byte_count}) isn't divisible \
by 4. Therefore, it cannot be safely interpreted as 32bpp RGBA pixels"
)]
ByteCountNotDivisibleBy4 {
byte_count: usize,
},
#[error(
"The number of RGBA pixels ({pixel_count}) does not match the \
provided dimensions ({width}x{height})."
)]
DimensionsVsPixelCount {
width: u32,
height: u32,
width_x_height: usize,
pixel_count: usize,
},
}