Implemented sequence rendering
108
Cargo.lock
generated
|
|
@ -50,6 +50,21 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
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]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.2.1"
|
version = "1.2.1"
|
||||||
|
|
@ -121,15 +136,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "encode_unicode"
|
||||||
version = "0.2.2"
|
version = "0.3.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"wasi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gif"
|
name = "gif"
|
||||||
|
|
@ -169,6 +179,18 @@ dependencies = [
|
||||||
"tiff",
|
"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]]
|
[[package]]
|
||||||
name = "jpeg-decoder"
|
name = "jpeg-decoder"
|
||||||
version = "0.1.22"
|
version = "0.1.22"
|
||||||
|
|
@ -195,8 +217,8 @@ name = "mandelbrot"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"image",
|
"image",
|
||||||
|
"indicatif",
|
||||||
"num-complex",
|
"num-complex",
|
||||||
"uuid",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -287,6 +309,12 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "number_prefix"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17b02fc0ff9a9e4b35b3342880f48e896ebf69f2967921fe8646bf5b7125956a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.16.8"
|
version = "0.16.8"
|
||||||
|
|
@ -324,6 +352,21 @@ dependencies = [
|
||||||
"num_cpus",
|
"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]]
|
[[package]]
|
||||||
name = "scoped_threadpool"
|
name = "scoped_threadpool"
|
||||||
version = "0.1.9"
|
version = "0.1.9"
|
||||||
|
|
@ -336,6 +379,16 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
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]]
|
[[package]]
|
||||||
name = "tiff"
|
name = "tiff"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
|
|
@ -348,22 +401,35 @@ dependencies = [
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "unicode-width"
|
||||||
version = "0.8.2"
|
version = "0.1.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7"
|
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
|
||||||
dependencies = [
|
|
||||||
"getrandom",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "wasi"
|
|
||||||
version = "0.10.2+wasi-snapshot-preview1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "weezl"
|
name = "weezl"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a32b378380f4e9869b22f0b5177c68a5519f03b3454fde0b291455ddbae266c"
|
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"
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,5 @@ edition = "2018"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
image = "0.23.14"
|
image = "0.23.14"
|
||||||
num-complex = "0.4.0"
|
num-complex = "0.4.0"
|
||||||
uuid = { version = "0.8", features = ["v4"] }
|
# uuid = { version = "0.8", features = ["v4"] }
|
||||||
|
indicatif = "0.15.0"
|
||||||
|
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 119 KiB |
|
Before Width: | Height: | Size: 3.6 MiB After Width: | Height: | Size: 3.6 MiB |
|
Before Width: | Height: | Size: 333 KiB After Width: | Height: | Size: 333 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
98
src/main.rs
|
|
@ -4,10 +4,9 @@ extern crate num_complex;
|
||||||
use image::{RgbImage, ImageBuffer, Rgb};
|
use image::{RgbImage, ImageBuffer, Rgb};
|
||||||
use std::fmt::Error;
|
use std::fmt::Error;
|
||||||
use num_complex::Complex;
|
use num_complex::Complex;
|
||||||
use uuid::Uuid;
|
use indicatif::ProgressBar;
|
||||||
use std::ops::Add;
|
|
||||||
|
|
||||||
const THRESHHOLD: f64 = 200.0;
|
const THRESHHOLD: f64 = 200_i32.pow(2) as f64;
|
||||||
|
|
||||||
fn calculate_color(number: Complex<f64>, iterations: u32) -> Result<Rgb<u8>, Error> {
|
fn calculate_color(number: Complex<f64>, iterations: u32) -> Result<Rgb<u8>, Error> {
|
||||||
let mut z: Complex<f64> = Complex::new(0.0, 0.0);
|
let mut z: Complex<f64> = Complex::new(0.0, 0.0);
|
||||||
|
|
@ -18,7 +17,7 @@ fn calculate_color(number: Complex<f64>, iterations: u32) -> Result<Rgb<u8>, Err
|
||||||
|
|
||||||
if cycle.contains(&z) { return Ok(Rgb::from([0, 0, 0])); }
|
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));
|
return Ok(map_num_to_color(i, iterations));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -32,21 +31,28 @@ fn map_num_to_color(i: u32, maximum: u32) -> Rgb<u8> {
|
||||||
let frac: f32 = (i as f32 / maximum as f32) * 255.0 * 3.0;
|
let frac: f32 = (i as f32 / maximum as f32) * 255.0 * 3.0;
|
||||||
|
|
||||||
let r: u8;
|
let r: u8;
|
||||||
if frac / 3.0 >= 255.0 {
|
|
||||||
r = 255
|
|
||||||
} else { r = (frac as i32 % 255) as u8 }
|
|
||||||
|
|
||||||
let g: 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;
|
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,
|
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_width: f64 = (upper_left.re - lower_right.re).abs();
|
||||||
let section_height: f64 = (upper_left.im - lower_right.im).abs();
|
let section_height: f64 = (upper_left.im - lower_right.im).abs();
|
||||||
|
|
||||||
|
let bar = ProgressBar::new(width as u64);
|
||||||
|
|
||||||
for x in 0..width {
|
for x in 0..width {
|
||||||
println!("Col: {}", x);
|
bar.inc(1);
|
||||||
for y in 0..height {
|
for y in 0..height {
|
||||||
let x_offset: f64 = (x as f64 / width as f64) * section_width;
|
let x_offset: f64 = (x as f64 / width as f64) * section_width;
|
||||||
let y_offset: f64 = (y as f64 / width as f64) * section_height;
|
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(
|
let color = calculate_color(
|
||||||
Complex::new(upper_left.re + x_offset, upper_left.im + y_offset),
|
Complex::new(upper_left.re + x_offset, upper_left.im + y_offset),
|
||||||
iterations).unwrap();
|
iterations).unwrap();
|
||||||
|
|
||||||
out_image.put_pixel(x, y, color);
|
out_image.put_pixel(x, y, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bar.finish_with_message("Rendered frame.");
|
||||||
Ok(out_image)
|
Ok(out_image)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_around_point(image_size: u32,
|
||||||
|
iterations: u32,
|
||||||
|
window_size: f64,
|
||||||
|
pivot_point: Complex<f64>) -> Result<RgbImage, Error> {
|
||||||
|
let upper_left: Complex<f64> = Complex::new(pivot_point.re - window_size / 2.0,
|
||||||
|
pivot_point.im - window_size / 2.0);
|
||||||
|
|
||||||
fn main() {
|
let lower_right: Complex<f64> = Complex::new(pivot_point.re + window_size / 2.0,
|
||||||
let fractal: RgbImage = generate_mandelbrot(4096,
|
pivot_point.im + window_size / 2.0);
|
||||||
4096,
|
|
||||||
100,
|
generate_mandelbrot(image_size,
|
||||||
Complex::new(-0.7, -0.7),
|
image_size,
|
||||||
Complex::new(-0.4, -0.4))
|
iterations,
|
||||||
|
upper_left,
|
||||||
|
lower_right)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_sequence(num_frames: u32,
|
||||||
|
image_size: u32,
|
||||||
|
iterations: u32,
|
||||||
|
initial_size: f64,
|
||||||
|
zoom_point: Complex<f64>,
|
||||||
|
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();
|
.unwrap();
|
||||||
|
|
||||||
let filename: String = String::from("mandelbrot_")
|
scale *= (1.0 - scale_factor) as f64;
|
||||||
.add(&Uuid::new_v4().to_string()) + ".png";
|
|
||||||
|
|
||||||
|
let filename: String = path.clone() + "frame_" + &*frame.to_string() + ".png";
|
||||||
fractal.save(filename).unwrap();
|
fractal.save(filename).unwrap();
|
||||||
|
println!("Rendered frame {}", frame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
render_sequence(10,
|
||||||
|
500,
|
||||||
|
200,
|
||||||
|
1.0,
|
||||||
|
Complex::new(-0.5, -0.5),
|
||||||
|
1.0 / 10.0,
|
||||||
|
"./out/".parse().unwrap(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||