#[derive(PartialEq, Debug, Clone)]
pub struct ColorBuffer {
pub width: usize,
pub height: usize,
pub pixels: Vec<f64>,
pub frames: usize,
pub file_path: Option<std::path::PathBuf>,
}
impl ColorBuffer {
pub fn new(width: usize, height: usize) -> Self {
Self {
width,
height,
pixels: vec![0.0; width * height * 4],
frames: 0,
file_path: None,
}
}
#[inline(always)]
pub fn at(&self, x: usize, y: usize) -> [f64; 4] {
let i = y * self.width * 4 + x * 4;
[
self.pixels[i],
self.pixels[i + 1],
self.pixels[i + 2],
self.pixels[i + 3],
]
}
pub fn set(&mut self, x: usize, y: usize, color: [f64; 4]) {
let i = y * self.width * 4 + x * 4;
self.pixels[i..i + 4].copy_from_slice(&color);
}
pub fn copy_from(&mut self, x: usize, y: usize, other: &ColorBuffer) {
for local_y in 0..other.height {
for local_x in 0..other.width {
let global_x = x + local_x;
let global_y = y + local_y;
if global_x >= self.width || global_y >= self.height {
continue;
}
let index = (global_y * self.width + global_x) * 4;
let local_index = (local_y * other.width + local_x) * 4;
self.pixels[index..index + 4]
.copy_from_slice(&other.pixels[local_index..local_index + 4]);
}
}
}
pub fn to_u8_vec_gamma(&self) -> Vec<u8> {
let source = &self.pixels[..];
let mut out: Vec<u8> = vec![0; self.width * self.height * 4];
let gamma_correction = 0.4545;
for y in 0..self.height {
for x in 0..self.width {
let d = x * 4 + y * self.width * 4;
let c = [
(source[d].powf(gamma_correction) * 255.0) as u8,
(source[d + 1].powf(gamma_correction) * 255.0) as u8,
(source[d + 2].powf(gamma_correction) * 255.0) as u8,
(source[d + 3] * 255.0) as u8,
];
out[d..d + 4].copy_from_slice(&c);
}
}
out
}
pub fn to_u8_vec(&self) -> Vec<u8> {
let source = &self.pixels[..];
let mut out: Vec<u8> = vec![0; self.width * self.height * 4];
for y in 0..self.height {
for x in 0..self.width {
let d = x * 4 + y * self.width * 4;
let c = [
(source[d] * 255.0) as u8,
(source[d + 1] * 255.0) as u8,
(source[d + 2] * 255.0) as u8,
(source[d + 3] * 255.0) as u8,
];
out[d..d + 4].copy_from_slice(&c);
}
}
out
}
pub fn save(&self, path: std::path::PathBuf) {
let mut image = image::ImageBuffer::new(self.width as u32, self.height as u32);
for y in 0..self.height {
for x in 0..self.width {
let i = y * self.width * 4 + x * 4;
let c = image::Rgb([
(self.pixels[i] * 255.0) as u8,
(self.pixels[i + 1] * 255.0) as u8,
(self.pixels[i + 2] * 255.0) as u8,
]);
image.put_pixel(x as u32, y as u32, c);
}
}
image.save(path).unwrap();
}
}