From 8f0add0e286e180123ac2d6b8143cabdccee2f06 Mon Sep 17 00:00:00 2001 From: Clemens-Dautermann Date: Mon, 22 Mar 2021 11:22:26 +0100 Subject: [PATCH] Implemented sequence rendering --- Cargo.lock | 108 ++++++++++++++---- Cargo.toml | 3 +- colortest.png => pictures/colortest.png | Bin .../mandelbrot_4k.png | Bin subset.png => pictures/subset.png | Bin test.png => pictures/test.png | Bin src/main.rs | 104 ++++++++++++----- 7 files changed, 163 insertions(+), 52 deletions(-) rename colortest.png => pictures/colortest.png (100%) rename mandelbrot_4k.png => pictures/mandelbrot_4k.png (100%) rename subset.png => pictures/subset.png (100%) rename test.png => pictures/test.png (100%) diff --git a/Cargo.lock b/Cargo.lock index 16889e7..ef39b4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -50,6 +50,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "console" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "regex", + "terminal_size", + "unicode-width", + "winapi", +] + [[package]] name = "crc32fast" version = "1.2.1" @@ -121,15 +136,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] -name = "getrandom" -version = "0.2.2" +name = "encode_unicode" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "gif" @@ -169,6 +179,18 @@ dependencies = [ "tiff", ] +[[package]] +name = "indicatif" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7baab56125e25686df467fe470785512329883aab42696d661247aca2a2896e4" +dependencies = [ + "console", + "lazy_static", + "number_prefix", + "regex", +] + [[package]] name = "jpeg-decoder" version = "0.1.22" @@ -195,8 +217,8 @@ name = "mandelbrot" version = "0.1.0" dependencies = [ "image", + "indicatif", "num-complex", - "uuid", ] [[package]] @@ -287,6 +309,12 @@ dependencies = [ "libc", ] +[[package]] +name = "number_prefix" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a" + [[package]] name = "png" version = "0.16.8" @@ -324,6 +352,21 @@ dependencies = [ "num_cpus", ] +[[package]] +name = "regex" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" + [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -336,6 +379,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "terminal_size" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "tiff" version = "0.6.1" @@ -348,22 +401,35 @@ dependencies = [ ] [[package]] -name = "uuid" -version = "0.8.2" +name = "unicode-width" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -dependencies = [ - "getrandom", -] - -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" [[package]] name = "weezl" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 1afb804..b3271ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,4 +9,5 @@ edition = "2018" [dependencies] image = "0.23.14" num-complex = "0.4.0" -uuid = { version = "0.8", features = ["v4"] } \ No newline at end of file +# uuid = { version = "0.8", features = ["v4"] } +indicatif = "0.15.0" \ No newline at end of file diff --git a/colortest.png b/pictures/colortest.png similarity index 100% rename from colortest.png rename to pictures/colortest.png diff --git a/mandelbrot_4k.png b/pictures/mandelbrot_4k.png similarity index 100% rename from mandelbrot_4k.png rename to pictures/mandelbrot_4k.png diff --git a/subset.png b/pictures/subset.png similarity index 100% rename from subset.png rename to pictures/subset.png diff --git a/test.png b/pictures/test.png similarity index 100% rename from test.png rename to pictures/test.png diff --git a/src/main.rs b/src/main.rs index 2b1686b..41435c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,10 +4,9 @@ extern crate num_complex; use image::{RgbImage, ImageBuffer, Rgb}; use std::fmt::Error; use num_complex::Complex; -use uuid::Uuid; -use std::ops::Add; +use indicatif::ProgressBar; -const THRESHHOLD: f64 = 200.0; +const THRESHHOLD: f64 = 200_i32.pow(2) as f64; fn calculate_color(number: Complex, iterations: u32) -> Result, Error> { let mut z: Complex = Complex::new(0.0, 0.0); @@ -18,7 +17,7 @@ fn calculate_color(number: Complex, iterations: u32) -> Result, Err if cycle.contains(&z) { return Ok(Rgb::from([0, 0, 0])); } - if z.norm() > THRESHHOLD { + if z.norm_sqr() > THRESHHOLD { return Ok(map_num_to_color(i, iterations)); } @@ -32,21 +31,28 @@ fn map_num_to_color(i: u32, maximum: u32) -> Rgb { let frac: f32 = (i as f32 / maximum as f32) * 255.0 * 3.0; let r: u8; - if frac / 3.0 >= 255.0 { - r = 255 - } else { r = (frac as i32 % 255) as u8 } - let g: u8; - if frac / 3.0 >= 255.0 * 2.0 { - g = 255 - } else { g = (frac as i32 % 255) as u8 } - let b: u8; - if frac / 3.0 >= 255.0 * 3.0 { - b = 255 - } else { b = (frac as i32 % 255) as u8 } - Rgb::from([r, g, b]) + if frac < 255.0 { + r = frac.ceil() as u8; + g = 0; + b = 0; + } else if frac >= 255.0 && frac < 255.0 * 2.0 { + r = 255; + g = (frac as i32 % 255) as u8; + b = 0; + } else if frac >= 255.0 * 2.0 && frac < 255.0 * 3.0 { + r = 255; + g = 255; + b = (frac as i32 % 255) as u8; + } else { + r = 255; + g = 255; + b = 255; + } + + Rgb::from([b, g, r]) } fn generate_mandelbrot(width: u32, @@ -59,8 +65,10 @@ fn generate_mandelbrot(width: u32, let section_width: f64 = (upper_left.re - lower_right.re).abs(); let section_height: f64 = (upper_left.im - lower_right.im).abs(); + let bar = ProgressBar::new(width as u64); + for x in 0..width { - println!("Col: {}", x); + bar.inc(1); for y in 0..height { let x_offset: f64 = (x as f64 / width as f64) * section_width; let y_offset: f64 = (y as f64 / width as f64) * section_height; @@ -68,25 +76,61 @@ fn generate_mandelbrot(width: u32, let color = calculate_color( Complex::new(upper_left.re + x_offset, upper_left.im + y_offset), iterations).unwrap(); - out_image.put_pixel(x, y, color); } } - + bar.finish_with_message("Rendered frame."); Ok(out_image) } +fn render_around_point(image_size: u32, + iterations: u32, + window_size: f64, + pivot_point: Complex) -> Result { + let upper_left: Complex = Complex::new(pivot_point.re - window_size / 2.0, + pivot_point.im - window_size / 2.0); + + let lower_right: Complex = Complex::new(pivot_point.re + window_size / 2.0, + pivot_point.im + window_size / 2.0); + + generate_mandelbrot(image_size, + image_size, + iterations, + upper_left, + lower_right) +} + +fn render_sequence(num_frames: u32, + image_size: u32, + iterations: u32, + initial_size: f64, + zoom_point: Complex, + scale_factor: f32, + path: String) { + let mut scale = initial_size; + + for frame in 0..num_frames { + let fractal: RgbImage = render_around_point(image_size, + iterations, + scale, + zoom_point) + .unwrap(); + + scale *= (1.0 - scale_factor) as f64; + + let filename: String = path.clone() + "frame_" + &*frame.to_string() + ".png"; + fractal.save(filename).unwrap(); + println!("Rendered frame {}", frame); + } +} fn main() { - let fractal: RgbImage = generate_mandelbrot(4096, - 4096, - 100, - Complex::new(-0.7, -0.7), - Complex::new(-0.4, -0.4)) - .unwrap(); - - let filename: String = String::from("mandelbrot_") - .add(&Uuid::new_v4().to_string()) + ".png"; - - fractal.save(filename).unwrap(); + render_sequence(10, + 500, + 200, + 1.0, + Complex::new(-0.5, -0.5), + 1.0 / 10.0, + "./out/".parse().unwrap(), + ) }