Initial commit
This commit is contained in:
commit
9f7abe4761
1
.gitignore
vendored
Executable file
1
.gitignore
vendored
Executable file
@ -0,0 +1 @@
|
||||
/target
|
405
Cargo.lock
generated
Executable file
405
Cargo.lock
generated
Executable file
@ -0,0 +1,405 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "adler32"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "color_quant"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ae5588f6b3c3cb05239e90bd110f257254aecd01e4635400391aeae07497845"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-queue",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-channel"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "deflate"
|
||||
version = "0.7.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "707b6a7b384888a70c8d2e8650b3e60170dfc6a67bb4aa67b6dfca57af4bedb4"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
"byteorder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "471d90201b3b223f3451cd4ad53e34295f16a1df17b1edf3736d47761c3981af"
|
||||
dependencies = [
|
||||
"color_quant",
|
||||
"lzw",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.1.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "image"
|
||||
version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebdff791af04e30089bde8ad2a632b86af433b40c04db8d70ad4b21487db7a6a"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"gif",
|
||||
"jpeg-decoder",
|
||||
"lzw",
|
||||
"num-derive",
|
||||
"num-iter",
|
||||
"num-rational 0.1.42",
|
||||
"num-traits",
|
||||
"png",
|
||||
"scoped_threadpool",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inflate"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cdb29978cc5797bd8dcc8e5bf7de604891df2a8dc576973d71a281e916db2ff"
|
||||
dependencies = [
|
||||
"adler32",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jpeg-decoder"
|
||||
version = "0.1.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2"
|
||||
dependencies = [
|
||||
"rayon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.105"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013"
|
||||
|
||||
[[package]]
|
||||
name = "lzw"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
|
||||
|
||||
[[package]]
|
||||
name = "mandelbrot"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"crossbeam",
|
||||
"image",
|
||||
"num",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-complex",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-rational 0.4.0",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74e768dff5fb39a41b3bcd30bb25cf989706c90d028d1ad71971987aa309d535"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-complex"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26873667bbbb7c5182d4a37c1add32cdf09f841af72da53318fdb81543c15085"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-derive"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.1.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee314c74bd753fc86b4780aa9475da469155f3848473a261d2d18e35245a784e"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d41702bd167c2df5520b384281bc111a4b5efcf7fbc4c9c222c815b07e0a6a6a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-bigint",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "png"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f54b9600d584d3b8a739e1662a595fab051329eff43f20e7d8cc22872962145b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"deflate",
|
||||
"inflate",
|
||||
"num-iter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"crossbeam-deque",
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"num_cpus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped_threadpool"
|
||||
version = "0.1.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
11
Cargo.toml
Executable file
11
Cargo.toml
Executable file
@ -0,0 +1,11 @@
|
||||
[package]
|
||||
name = "mandelbrot"
|
||||
version = "0.1.0"
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
num = "*"
|
||||
image = "0.19"
|
||||
crossbeam = "*"
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# mandelbrot-rs
|
||||
|
||||
Implementation of mandelbrot renderer in rust, as described in [Programming Rust: Fast, Safe Systems Development](https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/)
|
BIN
mandel.png
Executable file
BIN
mandel.png
Executable file
Binary file not shown.
After ![]() (image error) Size: 19 MiB |
BIN
mandelbrot.png
Executable file
BIN
mandelbrot.png
Executable file
Binary file not shown.
After ![]() (image error) Size: 137 KiB |
165
src/main.rs
Executable file
165
src/main.rs
Executable file
@ -0,0 +1,165 @@
|
||||
use num::Complex;
|
||||
use std::str::FromStr;
|
||||
use image::ColorType;
|
||||
use image::png::PNGEncoder;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use crossbeam;
|
||||
|
||||
fn escape_time(c: Complex<f64>, limit: u32) -> Option<u32> {
|
||||
let mut z = Complex {re: 0.0, im: 0.0};
|
||||
for i in 0..limit {
|
||||
z = z * z + c;
|
||||
if z.norm_sqr() > 4.0 {
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
fn parse_pair<T: FromStr>(s: &str, separator: char) -> Option<(T,T)> {
|
||||
s.find(separator).and_then(|i| {
|
||||
match (T::from_str(&s[..i]), T::from_str(&s[i + 1..])) {
|
||||
(Ok(l), Ok(r)) => Some((l,r)),
|
||||
_ => None
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_pair() {
|
||||
assert_eq!(parse_pair::<i32>("", ','), None);
|
||||
assert_eq!(parse_pair::<i32>("10,", ','), None);
|
||||
assert_eq!(parse_pair::<i32>(",10", ','), None);
|
||||
assert_eq!(parse_pair::<i32>("10,20", ','), Some((10, 20)));
|
||||
assert_eq!(parse_pair::<i32>("10,20xy", ','), None);
|
||||
assert_eq!(parse_pair::<f64>("0.5x", 'x'), None);
|
||||
assert_eq!(parse_pair::<f64>("0.5x1.5", 'x'), Some((0.5, 1.5)));
|
||||
}
|
||||
|
||||
fn parse_complex(s: &str) -> Option<Complex<f64>> {
|
||||
parse_pair(s, ',').and_then(|(re, im)| Some(Complex {re, im}))
|
||||
// match parse_pair(s, ',') {
|
||||
// None => None
|
||||
// Some((re, im))
|
||||
// }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_complex() {
|
||||
assert_eq!(parse_complex("1.25,-0.0625"),
|
||||
Some(Complex { re: 1.25, im: -0.0625 }));
|
||||
assert_eq!(parse_complex(",-0.0625"), None);
|
||||
}
|
||||
|
||||
fn pixel_to_point(bounds: (usize, usize),
|
||||
pixel: (usize, usize),
|
||||
upper_left: Complex<f64>,
|
||||
lower_right: Complex<f64>) -> Complex<f64> {
|
||||
let (width, height) = (lower_right.re - upper_left.re,
|
||||
upper_left.im - lower_right.im);
|
||||
Complex {
|
||||
re: upper_left.re + pixel.0 as f64 * width / bounds.0 as f64,
|
||||
im: upper_left.im - pixel.1 as f64 * height / bounds.1 as f64
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pixel_to_point() {
|
||||
assert_eq!(pixel_to_point((100, 200), (25, 175),
|
||||
Complex { re: -1.0, im: 1.0 },
|
||||
Complex { re: 1.0, im: -1.0 }),
|
||||
Complex { re: -0.5, im: -0.75 });
|
||||
}
|
||||
|
||||
fn render(pixels: &mut [u8],
|
||||
bounds: (usize, usize),
|
||||
upper_left: Complex<f64>,
|
||||
lower_right: Complex<f64>) {
|
||||
|
||||
assert!(pixels.len() == bounds.0 * bounds.1);
|
||||
|
||||
for row in 0 .. bounds.1 {
|
||||
for column in 0 .. bounds.0 {
|
||||
let point = pixel_to_point(bounds, (column,row), upper_left, lower_right);
|
||||
pixels[row * bounds.0 + column] =
|
||||
match escape_time(point, 255) {
|
||||
None => 0,
|
||||
Some(count) => 255 - count as u8
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use std::io::Result;
|
||||
|
||||
fn write_image(filename: &str, pixels: &[u8], bounds: (usize, usize)) -> Result<()> {
|
||||
let output = File::create(filename)?;
|
||||
// let output = match File::create(filename) {
|
||||
// Ok(f) => { f },
|
||||
// Err(e) => { return Err(e); }
|
||||
// }
|
||||
|
||||
let encoder = PNGEncoder::new(output);
|
||||
|
||||
encoder.encode(&pixels, bounds.0 as u32, bounds.1 as u32, ColorType::Gray(8))?;
|
||||
// match encoder.encode(&pixels, bounds.0 as u32, bounds.1 as u32, ColorType::Gray(8)) {
|
||||
// Ok(_) => { () },
|
||||
// _ => { return Err(std::io::Error::new(std::io::ErrorKind::Other, "oh no!")); }
|
||||
// };
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn single_threaded_render(pixels: &mut [u8],
|
||||
bounds: (usize, usize),
|
||||
upper_left: Complex<f64>,
|
||||
lower_right: Complex<f64>) {
|
||||
render(pixels, bounds, upper_left, lower_right);
|
||||
}
|
||||
|
||||
fn multi_threaded_render(pixels: &mut [u8],
|
||||
bounds: (usize, usize),
|
||||
upper_left: Complex<f64>,
|
||||
lower_right: Complex<f64>) {
|
||||
let threads = 8;
|
||||
let rows_per_band = bounds.1 / threads + 1;
|
||||
|
||||
let bands: Vec<&mut [u8]> = pixels.chunks_mut(rows_per_band * bounds.0).collect();
|
||||
crossbeam::scope(|spawner| {
|
||||
for (i, band) in bands.into_iter().enumerate() {
|
||||
let top = rows_per_band * i;
|
||||
let height = band.len() / bounds.0;
|
||||
let band_bounds = (bounds.0, height);
|
||||
let band_upper_left = pixel_to_point(bounds, (0, top), upper_left, lower_right);
|
||||
let band_lower_right = pixel_to_point(bounds, (bounds.0, top + height), upper_left, lower_right);
|
||||
|
||||
spawner.spawn(move |_| {
|
||||
render(band, band_bounds, band_upper_left, band_lower_right);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
if args.len() != 5 {
|
||||
writeln!(std::io::stderr(), "Usage: mandelbrot FILE PIXELS UPPERLEFT LOWERRIGHT").unwrap();
|
||||
writeln!(std::io::stderr(), "Example: {} mandel.png 1000x750 -1.20,0.35 -1,0.20", args[0]).unwrap();
|
||||
std::process::exit(1);
|
||||
}
|
||||
|
||||
let bounds = parse_pair(&args[2], 'x').expect("error parsing image dimensions");
|
||||
let upper_left = parse_complex(&args[3]).expect("error parsing upper left corner point");
|
||||
let lower_right = parse_complex(&args[4]).expect("error parsing lower right corner point");
|
||||
|
||||
let mut pixels = vec![0; bounds.0 * bounds.1];
|
||||
|
||||
multi_threaded_render(&mut pixels, bounds, upper_left, lower_right);
|
||||
// single_threaded_render(&mut pixels, bounds, upper_left, lower_right);
|
||||
|
||||
write_image(&args[1], &pixels, bounds).expect("error writing PNG file");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user