Mandelbrot
Mandelbrot code sample
// Use the num crate to bring in complex numbers use num::Complex; use std::str::FromStr; use image::ColorType; use image::png::PNGEncoder; use std::fs::File; use std::env; fn complex_square_add_loop(c: Complex<f64>) { let mut z = Complex { re: 0.0, im: 0.0 }; loop { z = z * z + c; } } fn escape_time(c: Complex<f64>, limit: usize) -> Option<usize> { let mut z = Complex { re: 0.0, im: 0.0}; for i in 0..limit { if z.norm_sqr() > 4.0 { return Some(i); } z = z * z + c; } None } fn parse_pair<T: FromStr>(s: &str, separator: char) -> Option<(T, T)> { match s.find(separator) { None => None, Some(Index) => { match (T::from_str(&s[..index]), T::from_str(&s[index + 1..])) { (Ok(l), Ok(r)) => Some((l, r)), _ => None } } } } #[test] fn test_parse_pair() { assert_eq!(parse_pair::<i32>("", ','), None); } fn pixel_to_point(bounds: (usize, usize), pixel: (usize, usize), upper_left: Complex<f64>, lower_right: Complex<f64>) -> Complex<f64> { let (width, height) = (lower_right.re - upper_left.re, upper_left.im - lower_right.im); Complex { re: upper_left.re + pixel.0 as f64 * width / bounds.0 as f64, im: upper_left.im - pixel.1 as f64 * height / bounds.1 as f64 } } #[test] fn test_pixel_to_point() { assert_eq!(pixel_to_point((100, 200), (25, 175), Complex { re: -1.0, im: 1.0 }, Complex { re: 1.0, im: -1.0 }), Complex { re: -0.5, im: -0.75 }); } fn render(pixels: &mut[u8], bounds: (usize, usize), upper_left: Complex<f64>, lower_right: Complex<f64>) { assert!(pizels.len() == bounds.0 * bounds.1); for row in 0..bounds.1 { for column in 0..bounds.0 { let point = pixel_to_point(bounds, (column, row), upper_left, lower_right); pixels[row * bounds.0 + column] = match escape_time(point, 255) { None => 0, Some(count) => 255 - count as u8 }; } } } fn write_image(filename: &str, pixels: &[u8], bounds: (usize, usize)) -> Result<(), std::io::Error> { let output = File::create(filename)?; let encoder = PNGEncoder::new(output); encoder.encode(pixels, bounds.0 as u32, bounds.1 as u32, ColorType::Gray(8))?; Ok(()) } fn main() { let args: Vec<String> = env::args().collect(); if args.len() != 5 { eprintln!("Usage: {} FILE PIXELS UPPERLEFT LOWERRIGHT", args[0]); eprintln!("Example: {} mandel.png 1000X750 -1.20,0.35 -1,0.20", args[0]); std::process::exit(1); } let bounds = parse_pair(&args[2], 'x') .expect("error parsing image dimensions"); let upper_left = parse_complex(&args[3]) .expect("error parsing upper left corner point"); let lower_right = parse_complex(&args[4]) .expect("error parsing lower right corner"); let mut pixels = vec![0; bounds.0 * bounds.1]; render(&mut pixels, bounds, upper_left, lower_right); write_image(&args[1], &pixels, bounds) .expect("error writing PNG file"); }