added canvas sizes
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
use color::Color;
|
||||
|
||||
struct Canvas {
|
||||
pub struct Canvas {
|
||||
width: usize,
|
||||
height: usize,
|
||||
pixels: Vec<Vec<Color>>,
|
||||
}
|
||||
|
||||
impl Canvas {
|
||||
fn new(width: usize, height: usize) -> Canvas {
|
||||
pub fn new(width: usize, height: usize) -> Canvas {
|
||||
Canvas {
|
||||
width,
|
||||
height,
|
||||
@@ -16,6 +16,58 @@ impl Canvas {
|
||||
}
|
||||
}
|
||||
|
||||
impl Canvas {
|
||||
pub fn write_pixel(&mut self, x: usize, y: usize, color: Color) {
|
||||
self.pixels[y][x] = color;
|
||||
}
|
||||
|
||||
pub fn pixel(&self, x: usize, y: usize) -> Color {
|
||||
self.pixels[y][x]
|
||||
}
|
||||
|
||||
fn header(&self) -> String {
|
||||
let mut ppm = String::new();
|
||||
ppm.push_str("P3\n");
|
||||
ppm.push_str(self.width.to_string().as_str());
|
||||
ppm.push(' ');
|
||||
ppm.push_str(self.height.to_string().as_str());
|
||||
ppm.push('\n');
|
||||
ppm.push_str("255");
|
||||
ppm.push('\n');
|
||||
ppm
|
||||
}
|
||||
|
||||
pub fn to_ppm(&self) -> String {
|
||||
let mut ppm = self.header();
|
||||
for row in &self.pixels {
|
||||
let mut ppm_row = String::new();
|
||||
for pixel in row {
|
||||
let pixel_str = pixel.ppm_str();
|
||||
if pixel_str.len() + ppm_row.len() > 70 {
|
||||
let components: Vec<&str> = pixel_str.split(" ").collect();
|
||||
for component in components {
|
||||
if ppm_row.len() + component.len() > 70 {
|
||||
ppm_row.pop();
|
||||
ppm.push_str(&ppm_row);
|
||||
ppm.push_str("\n");
|
||||
ppm_row = String::new();
|
||||
}
|
||||
ppm_row.push_str(component);
|
||||
ppm_row.push_str(" ");
|
||||
}
|
||||
} else {
|
||||
ppm_row.push_str(&pixel_str);
|
||||
ppm_row.push_str(" ");
|
||||
}
|
||||
}
|
||||
ppm_row.pop();
|
||||
ppm.push_str(&ppm_row);
|
||||
ppm.push('\n');
|
||||
}
|
||||
ppm
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -33,4 +85,73 @@ mod tests {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn write_pixels_to_canvas() {
|
||||
let mut c = Canvas::new(10, 20);
|
||||
let red = Color::new(1.0, 0.0, 0.0);
|
||||
c.write_pixel(2, 3, red);
|
||||
assert_eq!(red, c.pixel(2, 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constructing_ppm_header() {
|
||||
let c = Canvas::new(5, 3);
|
||||
let ppm = c.to_ppm();
|
||||
|
||||
let expected = "P3
|
||||
5 3
|
||||
255";
|
||||
|
||||
let header = ppm.split("\n").take(3).collect::<Vec<&str>>().join("\n");
|
||||
|
||||
assert_eq!(expected, header);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn constructing_the_ppm_pixel_data() {
|
||||
let mut c = Canvas::new(5, 3);
|
||||
let c1 = Color::new(1.5, 0.0, 0.0);
|
||||
let c2 = Color::new(0.0, 0.5, 0.0);
|
||||
let c3 = Color::new(-0.5, 0.0, 1.0);
|
||||
|
||||
c.write_pixel(0, 0, c1);
|
||||
c.write_pixel(2, 1, c2);
|
||||
c.write_pixel(4, 2, c3);
|
||||
|
||||
let ppm = c.to_ppm();
|
||||
|
||||
|
||||
let line_4 = "255 0 0 0 0 0 0 0 0 0 0 0 0 0 0";
|
||||
let line_5 = "0 0 0 0 0 0 0 127 0 0 0 0 0 0 0";
|
||||
let line_6 = "0 0 0 0 0 0 0 0 0 0 0 0 0 0 255";
|
||||
|
||||
let v : Vec<&str> = ppm.split("\n").collect();
|
||||
|
||||
print!("{}", ppm);
|
||||
|
||||
assert_eq!(line_4, *v.get(3).expect("must exist"));
|
||||
assert_eq!(line_5, *v.get(4).expect("must exist"));
|
||||
assert_eq!(line_6, *v.get(5).expect("must exist"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_split_long_lines() {
|
||||
let mut c = Canvas::new(10, 2);
|
||||
for row in &mut c.pixels {
|
||||
for pix in row {
|
||||
*pix = Color::new(1.0, 0.8, 0.6);
|
||||
}
|
||||
}
|
||||
|
||||
let line4_7 = r#"255 204 153 255 204 153 255 204 153 255 204 153 255 204 153 255 204
|
||||
153 255 204 153 255 204 153 255 204 153 255 204 153
|
||||
255 204 153 255 204 153 255 204 153 255 204 153 255 204 153 255 204
|
||||
153 255 204 153 255 204 153 255 204 153 255 204 153
|
||||
"#;
|
||||
|
||||
let ppm = c.to_ppm();
|
||||
let four_to_seven = ppm.split("\n").skip(3).collect::<Vec<&str>>().join("\n");
|
||||
assert_eq!(line4_7, four_to_seven);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,27 @@ impl Color {
|
||||
blue,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn red(&self) -> f32 {
|
||||
self.red
|
||||
}
|
||||
|
||||
pub fn green(&self) -> f32 {
|
||||
self.green
|
||||
}
|
||||
|
||||
pub fn blue(&self) -> f32 {
|
||||
self.blue
|
||||
}
|
||||
|
||||
pub fn ppm_str(&self) -> String {
|
||||
// need to scale 0 - 1 -> 0 - 255
|
||||
let r = (self.red * 255.0) as u8;
|
||||
let g = (self.green * 255.0) as u8;
|
||||
let b = (self.blue * 255.0) as u8;
|
||||
|
||||
format!("{} {} {}", r, g, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Color {
|
||||
|
||||
Reference in New Issue
Block a user