Initial commit
This commit is contained in:
commit
dd639174f0
9 changed files with 652 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
/target
|
||||
*.png
|
||||
416
Cargo.lock
generated
Normal file
416
Cargo.lock
generated
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
"anstyle-query",
|
||||
"anstyle-wincon",
|
||||
"colorchoice",
|
||||
"is_terminal_polyfill",
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
|
||||
dependencies = [
|
||||
"utf8parse",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-query"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
|
||||
dependencies = [
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-wincon"
|
||||
version = "3.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.16.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder-lite"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
|
||||
|
||||
[[package]]
|
||||
name = "colorchoice"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
|
||||
[[package]]
|
||||
name = "fdeflate"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645"
|
||||
dependencies = [
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.25.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"byteorder-lite",
|
||||
"num-traits",
|
||||
"png",
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is_terminal_polyfill"
|
||||
version = "1.70.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||
|
||||
[[package]]
|
||||
name = "mandelbrot"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"image",
|
||||
"num-complex",
|
||||
"num-traits",
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.17.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crc32fast",
|
||||
"fdeflate",
|
||||
"flate2",
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.72"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[package]
|
||||
name = "mandelbrot"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.11", features = ["derive"] }
|
||||
image = { version = "0.25.2", default-features = false, features = [
|
||||
"rayon",
|
||||
"png",
|
||||
] }
|
||||
num-complex = "0.4.6"
|
||||
num-traits = "0.2.19"
|
||||
rayon = "1.10.0"
|
||||
42
src/cli.rs
Normal file
42
src/cli.rs
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
use clap::Parser;
|
||||
use std::{path::PathBuf, str::FromStr};
|
||||
|
||||
/// Map MIDI signals to commands
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct Cli {
|
||||
/// Center point of the image
|
||||
#[arg(long, short, default_value = "0:0")]
|
||||
pub center: String,
|
||||
|
||||
/// Scale of the set on the X axis
|
||||
#[arg(long, short, default_value_t = 4.0)]
|
||||
pub scale: f64,
|
||||
|
||||
/// Max number of iterations
|
||||
#[arg(long, short, default_value_t = 200)]
|
||||
pub nmax: u32,
|
||||
|
||||
/// Image resolution
|
||||
#[arg(long, short, default_value = "1000:1000")]
|
||||
pub resolution: String,
|
||||
|
||||
/// Output filepath
|
||||
#[arg(long, short, default_value = "output.png")]
|
||||
pub output: PathBuf,
|
||||
|
||||
/// Use double precision
|
||||
#[clap(long, action)]
|
||||
pub f64: bool,
|
||||
}
|
||||
|
||||
pub fn parse_two_nums<T>(input: &str) -> Result<(T, T), Box<dyn std::error::Error>>
|
||||
where
|
||||
T: FromStr,
|
||||
<T as FromStr>::Err: std::error::Error + 'static,
|
||||
{
|
||||
let col = input.find(":").unwrap();
|
||||
let v1 = input[0..col].parse::<T>()?;
|
||||
let v2 = input[col + 1..].parse::<T>()?;
|
||||
Ok((v1, v2))
|
||||
}
|
||||
50
src/color.rs
Normal file
50
src/color.rs
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
use image::Rgb;
|
||||
|
||||
pub type Color = Rgb<u8>;
|
||||
|
||||
const COLOR_CYCLE: u32 = 120;
|
||||
|
||||
const N1: f32 = 1.0 * (COLOR_CYCLE as f32) / 6.0;
|
||||
const N2: f32 = 2.0 * (COLOR_CYCLE as f32) / 6.0;
|
||||
const N3: f32 = 3.0 * (COLOR_CYCLE as f32) / 6.0;
|
||||
const N4: f32 = 4.0 * (COLOR_CYCLE as f32) / 6.0;
|
||||
const N5: f32 = 5.0 * (COLOR_CYCLE as f32) / 6.0;
|
||||
const N6: f32 = 6.0 * (COLOR_CYCLE as f32) / 6.0;
|
||||
|
||||
// const WHITE: Color = Rgb([u8::MAX, u8::MAX, u8::MAX]);
|
||||
const BLACK: Color = Rgb([0, 0, 0]);
|
||||
const RED: Color = Rgb([u8::MAX, 0, 0]);
|
||||
const YELLOW: Color = Rgb([u8::MAX, u8::MAX, 0]);
|
||||
const GREEN: Color = Rgb([0, u8::MAX, 0]);
|
||||
const CYAN: Color = Rgb([0, u8::MAX, u8::MAX]);
|
||||
const BLUE: Color = Rgb([0, 0, u8::MAX]);
|
||||
const PURPLE: Color = Rgb([u8::MAX, 0, u8::MAX]);
|
||||
|
||||
fn gradient_fct(c1: Color, c2: Color, res: &mut Color, cross: f32) {
|
||||
res.0[0] = (c1.0[0] as f32 * (1.0 - cross) + c2.0[0] as f32 * cross) as u8;
|
||||
res.0[1] = (c1.0[1] as f32 * (1.0 - cross) + c2.0[1] as f32 * cross) as u8;
|
||||
res.0[2] = (c1.0[2] as f32 * (1.0 - cross) + c2.0[2] as f32 * cross) as u8;
|
||||
}
|
||||
|
||||
pub fn pixel_color_fct(n: u32, res: &mut Color) {
|
||||
if n == 0 {
|
||||
*res = BLACK;
|
||||
} else {
|
||||
let n: f32 = (n % COLOR_CYCLE) as f32;
|
||||
if n < N1 {
|
||||
gradient_fct(BLUE, CYAN, res, n / N1);
|
||||
} else if n < N2 {
|
||||
gradient_fct(CYAN, GREEN, res, (n - N1) / (N2 - N1));
|
||||
} else if n < N3 {
|
||||
gradient_fct(GREEN, YELLOW, res, (n - N2) / (N3 - N2));
|
||||
} else if n < N4 {
|
||||
gradient_fct(YELLOW, RED, res, (n - N3) / (N4 - N3));
|
||||
} else if n < N5 {
|
||||
gradient_fct(RED, PURPLE, res, (n - N4) / (N5 - N4));
|
||||
} else if n < N6 {
|
||||
gradient_fct(PURPLE, BLUE, res, (n - N5) / (N6 - N5));
|
||||
} else {
|
||||
*res = BLACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/compute.rs
Normal file
18
src/compute.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
use num_complex::Complex;
|
||||
|
||||
pub fn mandelbrot_n<T>(c: Complex<T>, nmax: u32) -> u32
|
||||
where
|
||||
T: num_traits::Float + num_traits::FromPrimitive + 'static,
|
||||
{
|
||||
let mut ci = c;
|
||||
let mut i = 1;
|
||||
let limit: T = T::from(4.0).unwrap();
|
||||
while i <= nmax {
|
||||
if ci.re * ci.re + ci.im * ci.im > limit {
|
||||
return i;
|
||||
}
|
||||
ci = ci * ci + c;
|
||||
i += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
48
src/main.rs
Normal file
48
src/main.rs
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
pub mod cli;
|
||||
pub mod color;
|
||||
pub mod compute;
|
||||
pub mod viewport;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use image::{ImageBuffer, Rgb};
|
||||
use num_traits::{Float, FromPrimitive};
|
||||
use viewport::Viewport;
|
||||
|
||||
use rayon::prelude::*;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
fn main() {
|
||||
let args = cli::Cli::parse();
|
||||
|
||||
let nmax = args.nmax;
|
||||
let imgbuf = if args.f64 {
|
||||
let viewport: Viewport<f64> = Viewport::from(&args);
|
||||
compute(&viewport, nmax)
|
||||
} else {
|
||||
let viewport: Viewport<f32> = Viewport::from(&args);
|
||||
compute(&viewport, nmax)
|
||||
};
|
||||
|
||||
imgbuf.save(args.output).unwrap();
|
||||
}
|
||||
|
||||
fn compute<T>(viewport: &Viewport<T>, nmax: u32) -> ImageBuffer<Rgb<u8>, Vec<u8>>
|
||||
where
|
||||
T: Float + FromStr + FromPrimitive + Sync + 'static,
|
||||
<T as FromStr>::Err: std::error::Error + 'static,
|
||||
{
|
||||
let mut imgbuf = ImageBuffer::new(viewport.x(), viewport.y());
|
||||
|
||||
// Iterate over the coordinates and pixels of the image
|
||||
imgbuf
|
||||
.par_enumerate_pixels_mut()
|
||||
.map(|(x, y, pixel)| {
|
||||
let c = viewport.pixel_to_complex(x, y);
|
||||
let n = compute::mandelbrot_n(c, nmax);
|
||||
color::pixel_color_fct(n, pixel);
|
||||
})
|
||||
.count();
|
||||
imgbuf
|
||||
}
|
||||
0
src/type.rs
Normal file
0
src/type.rs
Normal file
62
src/viewport.rs
Normal file
62
src/viewport.rs
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
use std::str::FromStr;
|
||||
|
||||
use num_complex::Complex;
|
||||
use num_traits::Float;
|
||||
|
||||
use crate::cli::{parse_two_nums, Cli};
|
||||
|
||||
pub struct Viewport<T: Float> {
|
||||
x: u32,
|
||||
y: u32,
|
||||
center: Complex<T>,
|
||||
scale: T,
|
||||
scaler: T,
|
||||
}
|
||||
|
||||
impl<T: Float> Viewport<T> {
|
||||
pub fn new(x: u32, y: u32, center: Complex<T>, scale: T) -> Self {
|
||||
Self {
|
||||
x,
|
||||
y,
|
||||
center,
|
||||
scale,
|
||||
scaler: scale / T::from(x).unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn x(&self) -> u32 {
|
||||
self.x
|
||||
}
|
||||
pub fn y(&self) -> u32 {
|
||||
self.y
|
||||
}
|
||||
pub fn center(&self) -> Complex<T> {
|
||||
self.center
|
||||
}
|
||||
pub fn scale(&self) -> T {
|
||||
self.scale
|
||||
}
|
||||
pub fn scaler(&self) -> T {
|
||||
self.scaler
|
||||
}
|
||||
|
||||
pub fn pixel_to_complex(&self, x: u32, y: u32) -> Complex<T> {
|
||||
let cx = T::from(x as i32 - self.x as i32 / 2).unwrap() * self.scaler;
|
||||
let cy = T::from(y as i32 - self.y as i32 / 2).unwrap() * self.scaler;
|
||||
Complex::new(cx, cy) + self.center
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<&Cli> for Viewport<T>
|
||||
where
|
||||
T: Float + FromStr,
|
||||
<T as FromStr>::Err: std::error::Error + 'static,
|
||||
{
|
||||
fn from(args: &Cli) -> Self {
|
||||
let (imgx, imgy): (u32, u32) = parse_two_nums(&args.resolution).unwrap();
|
||||
let scale: T = T::from(args.scale).unwrap();
|
||||
let (center_x, center_y): (T, T) = parse_two_nums(&args.center).unwrap();
|
||||
let center = Complex::new(center_x, center_y);
|
||||
Self::new(imgx, imgy, center, scale)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue