feat: successfully generate mandelbrot
This commit is contained in:
110
src/main.rs
Normal file
110
src/main.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user