canvas: enable saving to PNG.
This commit is contained in:
parent
536b6bed1f
commit
7786aa99a1
@ -1,12 +1,26 @@
|
|||||||
|
use std::fs::File;
|
||||||
|
use std::io::BufWriter;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use png;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
use crate::tuples::{color, Color};
|
use crate::tuples::{color, Color};
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum CanvasError {
|
||||||
|
#[error("faile to write canvas")]
|
||||||
|
IOError(#[from] std::io::Error),
|
||||||
|
#[error("faile to encode canvas to png")]
|
||||||
|
EncodingError(#[from] png::EncodingError),
|
||||||
|
}
|
||||||
pub struct Canvas {
|
pub struct Canvas {
|
||||||
pub height: usize,
|
pub height: usize,
|
||||||
pub width: usize,
|
pub width: usize,
|
||||||
pub pixels: Vec<Color>,
|
pub pixels: Vec<Color>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn canvas(width: usize, height: usize) -> Canvas {
|
pub fn canvas(width: usize, height: usize) -> Canvas {
|
||||||
let pixels = vec![color(0., 0., 0.); width * height];
|
let pixels = vec![color(0., 0., 0.); width * height];
|
||||||
Canvas {
|
Canvas {
|
||||||
width,
|
width,
|
||||||
@ -17,11 +31,44 @@ fn canvas(width: usize, height: usize) -> Canvas {
|
|||||||
|
|
||||||
impl Canvas {
|
impl Canvas {
|
||||||
pub fn set(&mut self, x: usize, y: usize, c: Color) {
|
pub fn set(&mut self, x: usize, y: usize, c: Color) {
|
||||||
|
if x > self.width {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if y > self.height {
|
||||||
|
return;
|
||||||
|
}
|
||||||
self.pixels[x + y * self.width] = c;
|
self.pixels[x + y * self.width] = c;
|
||||||
}
|
}
|
||||||
pub fn get(&mut self, x: usize, y: usize) -> Color {
|
pub fn get(&mut self, x: usize, y: usize) -> Color {
|
||||||
self.pixels[x + y * self.width]
|
self.pixels[x + y * self.width]
|
||||||
}
|
}
|
||||||
|
pub fn write_to_file<P>(&self, path: P) -> Result<(), CanvasError>
|
||||||
|
where
|
||||||
|
P: AsRef<Path>,
|
||||||
|
{
|
||||||
|
let path = Path::new(path.as_ref());
|
||||||
|
let file = File::create(path)?;
|
||||||
|
let ref mut w = BufWriter::new(file);
|
||||||
|
|
||||||
|
let mut encoder = png::Encoder::new(w, self.width as u32, self.height as u32);
|
||||||
|
encoder.set_color(png::ColorType::RGB);
|
||||||
|
encoder.set_depth(png::BitDepth::Eight);
|
||||||
|
let mut writer = encoder.write_header()?;
|
||||||
|
|
||||||
|
let data: Vec<u8> = self
|
||||||
|
.pixels
|
||||||
|
.iter()
|
||||||
|
.flat_map(|p| {
|
||||||
|
vec![
|
||||||
|
(p.red.clamp(0., 1.) * 255.) as u8,
|
||||||
|
(p.green.clamp(0., 1.) * 255.) as u8,
|
||||||
|
(p.blue.clamp(0., 1.) * 255.) as u8,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
writer.write_image_data(&data)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user