use crate::error::{ErrorKind, ImageError, ImageType};
pub struct Png(Vec<u8>, u32, u32);
impl Png {
pub fn new(width: u32, height: u32) -> Self {
let mut data = vec![];
for _i in 0..width * height {
data.push(0);
data.push(0);
data.push(0);
data.push(0);
}
Self {
0: data,
1: width,
2: height,
}
}
pub fn clear(&mut self, color: (u8, u8, u8, u8)) {
let mut data = vec![];
for _ in 0..self.1 * self.2 {
data.push(color.0);
data.push(color.1);
data.push(color.2);
data.push(color.3);
}
self.0 = data;
}
pub fn line(
&mut self,
from: (u32, u32),
to: (u32, u32),
thickness: u32,
color: (u8, u8, u8, u8),
) -> Result<(), ImageError> {
if from.1 == to.1 {
self.fill_rectangle(from.0, from.1, from.0 + to.0 + 1, thickness, color)?;
} else if from.0 == to.0 {
self.fill_rectangle(from.0, from.1, thickness, from.1 + to.1 + 1, color)?;
} else if from.0 < to.0 {
let shift = to.0 - from.0;
let mut shift_x_count = 0;
let mut shift_y_count = 0;
let height = (from.1 + to.1) / shift;
for _ in 0..shift {
self.fill_rectangle(
from.0 + shift_x_count,
from.1 + shift_y_count,
thickness,
height,
color,
)?;
shift_x_count += thickness;
shift_y_count += height;
}
let actual_height = height * shift;
if actual_height < from.1 + to.1 {
self.fill_rectangle(
from.0 + shift_x_count - 1,
from.1 + shift_y_count,
thickness,
from.1 + to.1 - actual_height,
color,
)?;
}
} else if to.0 < from.0 {
}
Ok(())
}
pub fn point(&mut self, x: u32, y: u32, color: (u8, u8, u8, u8)) -> Result<(), ImageError> {
let (r, g, b, a) = color;
let index = ((x + y * self.1) * 4) as usize;
self.0[index] = r;
self.0[index + 1] = g;
self.0[index + 2] = b;
self.0[index + 3] = a;
Ok(())
}
pub fn fill_rectangle(
&mut self,
x: u32,
y: u32,
width: u32,
height: u32,
color: (u8, u8, u8, u8),
) -> Result<(), ImageError> {
let x_start = x;
let x_end = x + width;
let y_start = y;
let y_end = y + height;
for x in 0..self.1 {
for y in 0..self.2 {
if x >= x_start && x <= x_end {
if y >= y_start && y <= y_end {
self.point(x, y, color)?;
}
}
}
}
Ok(())
}
pub fn draw_rectangle(
&mut self,
x: u32,
y: u32,
width: u32,
height: u32,
thickness: u32,
color: (u8, u8, u8, u8),
) -> Result<(), ImageError> {
let thickness = if thickness != 0 {
thickness - 1
} else {
return Err(ImageError::new_simple(ErrorKind::InvalidValue(
ImageType::Png,
)));
};
self.fill_rectangle(x, y, width, thickness, color)?;
self.fill_rectangle(x, y, thickness, height, color)?;
self.fill_rectangle(x, height + y - thickness, width, thickness, color)?;
self.fill_rectangle(width + x - thickness, y, thickness, height, color)?;
Ok(())
}
pub fn as_slice(&self) -> &[u8] {
self.0.as_slice()
}
}