summaryrefslogtreecommitdiff
path: root/src/image.rs
blob: 365596ba235a17547c5a19d1291e382d547a0d8f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
use std::io::Write;

use crate::vec3::Color;

pub struct Image {
    width: usize,
    height: usize,
    data: Vec<Color>,
}

impl Image {
    pub fn new(width: usize, height: usize) -> Image {
        let data = vec![
            Color {
                x: 0.0,
                y: 0.0,
                z: 0.0
            };
            width * height
        ];
        Image {
            width,
            height,
            data,
        }
    }

    pub fn set(&mut self, x: usize, y: usize, color: &Color) -> Result<(), ()> {
        *self.data.get_mut(y * self.width + x).ok_or(())? = color.clone();
        Ok(())
    }

    pub fn get(&self, x: usize, y: usize) -> Option<&Color> {
        self.data.get(y * self.width + x)
    }

    pub fn write(&self, output: &mut impl Write) {
        output.write_fmt(format_args!("P3\n{} {}\n255\n", self.width, self.height)).unwrap();
        for y in (0..self.height).rev() {
            for x in 0..self.width {
                let pixel = self.get(x, y).unwrap();
                let mut r = pixel.x;
                let mut g = pixel.y;
                let mut b = pixel.z;

                // Divide by the number of samples and perform gamma correction for gamma 2
                r = r.sqrt();
                g = g.sqrt();
                b = b.sqrt();

                output
                    .write_fmt(format_args!(
                        "{} {} {}\n",
                        (256.0 * r.clamp(0.0, 0.999)) as u32,
                        (256.0 * g.clamp(0.0, 0.999)) as u32,
                        (256.0 * b.clamp(0.0, 0.999)) as u32,
                    ))
                    .unwrap();
            }
        }
    }
}