#[derive(Default)]
pub struct ImageData {
pub width: u32,
pub height: u32,
pub data: Vec<u8>,
}
impl ImageData {
pub(crate) fn copy(&self, inverted: bool) -> Option<Self> {
let mut dst = Self {
width: self.width,
height: self.height,
data: vec![0; self.data.len()],
};
if !inverted {
dst.data.copy_from_slice(&self.data);
} else {
for (dp, sp) in dst.data.iter_mut().zip(self.data.iter()) {
*dp = !(*sp);
}
}
Some(dst)
}
pub(crate) fn crop(&self, x: u32, y: u32, w: u32, h: u32) -> Option<Self> {
if w == 0 || h == 0 || x + w > self.width || y + h > self.height {
return None;
}
let mut data = vec![0u8; (w * h) as usize];
for row in 0..h {
let src_start = ((y + row) * self.width + x) as usize;
let dst_start = (row * w) as usize;
data[dst_start..dst_start + w as usize]
.copy_from_slice(&self.data[src_start..src_start + w as usize]);
}
Some(Self {
width: w,
height: h,
data,
})
}
pub(crate) fn upscale(&self, scale: u32) -> Option<Self> {
if scale < 2 || self.width == 0 || self.height == 0 {
return None;
}
let new_width = self.width.checked_mul(scale)?;
let new_height = self.height.checked_mul(scale)?;
let total_pixels = new_width.checked_mul(new_height)?;
let mut data = vec![0u8; total_pixels as usize];
let w = self.width as usize;
let h = self.height as usize;
let nw = new_width as usize;
for ny in 0..new_height as usize {
for nx in 0..nw {
let sy_f = (ny as f32 + 0.5) / scale as f32 - 0.5;
let sx_f = (nx as f32 + 0.5) / scale as f32 - 0.5;
let sy0 = sy_f.floor().max(0.0) as usize;
let sx0 = sx_f.floor().max(0.0) as usize;
let sy1 = (sy0 + 1).min(h - 1);
let sx1 = (sx0 + 1).min(w - 1);
let fy = (sy_f - sy0 as f32).clamp(0.0, 1.0);
let fx = (sx_f - sx0 as f32).clamp(0.0, 1.0);
let p00 = self.data[sy0 * w + sx0] as f32;
let p10 = self.data[sy0 * w + sx1] as f32;
let p01 = self.data[sy1 * w + sx0] as f32;
let p11 = self.data[sy1 * w + sx1] as f32;
let value = p00 * (1.0 - fx) * (1.0 - fy)
+ p10 * fx * (1.0 - fy)
+ p01 * (1.0 - fx) * fy
+ p11 * fx * fy;
data[ny * nw + nx] = value.round().clamp(0.0, 255.0) as u8;
}
}
Some(Self {
width: new_width,
height: new_height,
data,
})
}
}