feat: successfully generate mandelbrot

This commit is contained in:
2020-11-24 19:47:31 -06:00
commit d370a8fd5f
4 changed files with 475 additions and 0 deletions

110
src/main.rs Normal file
View File

@@ -0,0 +1,110 @@
use image::{ImageBuffer, Rgb, RgbImage};
use num_complex::Complex;
use rayon::prelude::*;
const IMG_WIDTH: usize = 1920;
const IMG_HEIGHT: usize = 1080;
const MAX_ITERATIONS: u16 = 1000;
fn main() {
let mut img: RgbImage = ImageBuffer::new(IMG_WIDTH as u32, IMG_HEIGHT as u32);
escape_time(&mut img);
img.save("test.png").unwrap();
}
fn escape_time(img: &mut ImageBuffer<Rgb<u8>, Vec<u8>>) {
let mut mandelbrot: Vec<u16> = vec![0; IMG_HEIGHT * IMG_WIDTH];
mandelbrot
.par_iter_mut()
.enumerate()
.for_each(|(i, value)| {
let px = i % IMG_WIDTH;
let py = i / IMG_WIDTH;
let c = coords_to_complex(px, py);
*value = calc_num_iterations(c);
});
for (px, py, pixel) in img.enumerate_pixels_mut() {
let i = px as usize + IMG_WIDTH * py as usize;
let num_iterations = mandelbrot[i];
match find_colour(num_iterations) {
Colour::White => *pixel = Rgb([0x00, 0x00, 0x00]),
Colour::Black => *pixel = Rgb([0xFF, 0xFF, 0xFF]),
Colour::Gray => *pixel = Rgb([0xAA, 0xAA, 0xAA]),
}
}
}
enum Colour {
White,
Black,
Gray,
}
fn find_colour(iteration: u16) -> Colour {
match iteration {
MAX_ITERATIONS => Colour::Black,
other => match other % 2 {
0 => Colour::White,
1 => Colour::Gray,
_ => unreachable!(),
},
}
}
fn calc_num_iterations(c: Complex<f64>) -> u16 {
let mut z: Complex<f64> = Complex::new(0.0, 0.0);
let mut num_iterations: u16 = 0;
for i in 0..MAX_ITERATIONS {
if z.norm_sqr() > 4.0 {
num_iterations = i;
break;
}
z = (z * z) + c;
}
num_iterations
}
fn coords_to_complex(px: usize, py: usize) -> Complex<f64> {
Complex::new(scale_width(px), scale_height(py))
}
fn scale_width(px: usize) -> f64 {
const X_MIN: f64 = -2.5;
const X_MAX: f64 = 1.0;
X_MIN + ((X_MAX - X_MIN) * (px as f64 - 0.0)) / (IMG_WIDTH as f64 - 0.0)
}
fn scale_height(py: usize) -> f64 {
const Y_MIN: f64 = -1.0;
const Y_MAX: f64 = 1.0;
Y_MIN + ((Y_MAX - Y_MIN) * (py as f64 - 0.0)) / (IMG_HEIGHT as f64 - 0.0)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn scale_width_bounds() {
assert_eq!(scale_width(0), -2.5f64);
assert_eq!(scale_width(IMG_WIDTH), 1f64);
}
#[test]
fn scale_height_bounds() {
assert_eq!(scale_height(0), -1f64);
assert_eq!(scale_height(IMG_HEIGHT), 1f64);
}
}