55 lines
1.2 KiB
Rust
55 lines
1.2 KiB
Rust
use std::io::{Result, Write};
|
|
|
|
/// A 24-bit pixel represented by a red, green, and blue value.
|
|
#[derive(Clone, Copy, Default, Debug)]
|
|
pub struct Color {
|
|
pub red: u8,
|
|
pub green: u8,
|
|
pub blue: u8,
|
|
}
|
|
|
|
impl Color {
|
|
pub fn new(r: u8, g: u8, b: u8) -> Self {
|
|
Color {
|
|
red: r,
|
|
green: g,
|
|
blue: b,
|
|
}
|
|
}
|
|
|
|
pub fn from_01_float(r: f64, g: f64, b: f64) -> Self {
|
|
Color::new((r * 256.0) as u8, (g * 256.0) as u8, (b * 256.0) as u8)
|
|
}
|
|
}
|
|
|
|
/// A representation of an image
|
|
pub struct Image {
|
|
/// Width in pixels
|
|
pub(crate) width: usize,
|
|
|
|
/// Height in pixels
|
|
pub(crate) height: usize,
|
|
|
|
/// Pixel data in row-major form.
|
|
pub(crate) data: Vec<Color>,
|
|
}
|
|
|
|
impl Image {
|
|
/// Write the image in PPM format to a file.
|
|
pub fn write(&self, mut w: impl Write) -> Result<()> {
|
|
// Header
|
|
let header = format!("P3 {} {} 255\n", self.width, self.height);
|
|
w.write_all(header.as_bytes())?;
|
|
|
|
// Pixel data
|
|
assert_eq!(self.data.len(), self.width * self.height);
|
|
|
|
for pixel in self.data.iter() {
|
|
let Color { red, green, blue } = pixel;
|
|
let pixel = format!("{red} {green} {blue}\n");
|
|
w.write_all(pixel.as_bytes())?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|