added canvas sizes
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
use color::Color;
|
use color::Color;
|
||||||
|
|
||||||
struct Canvas {
|
pub struct Canvas {
|
||||||
width: usize,
|
width: usize,
|
||||||
height: usize,
|
height: usize,
|
||||||
pixels: Vec<Vec<Color>>,
|
pixels: Vec<Vec<Color>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Canvas {
|
impl Canvas {
|
||||||
fn new(width: usize, height: usize) -> Canvas {
|
pub fn new(width: usize, height: usize) -> Canvas {
|
||||||
Canvas {
|
Canvas {
|
||||||
width,
|
width,
|
||||||
height,
|
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)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
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,
|
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 {
|
impl PartialEq for Color {
|
||||||
|
|||||||
Reference in New Issue
Block a user