Skip to content

Commit 7b32fd8

Browse files
committed
made distance estimation more colourful
1 parent acb0d7c commit 7b32fd8

File tree

4 files changed

+80
-52
lines changed

4 files changed

+80
-52
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ clap = "^3.0.0-beta.1"
1616
config = "^0.9"
1717
half = "^1.6.0"
1818
atomic-counter = "^1.0.1"
19+
color_space = "^0.5.3"
1920

2021
[dependencies.rug]
2122
version = "1.10"

locations/dragon_detail.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
real = "-0.749999987350877481864108888020013802837969258626230419972587823828734338471228477079750588709551510361714463695461745528645748607681279674273355384334270208362211787387351792878073779449767292692440"
2+
imag = "0.001000038688236832013124581230049849132759425863378894883003211011278068229551274712347955044740933397589760194545872789087012331273586364914484522575986336846199522726507205442204060303594956029930"
3+
zoom = "9.099999999999616E191"
4+
iterations = 5000000
5+
rotate = 0

src/util/data_export.rs

Lines changed: 67 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@ use std::fs::File;
88
use std::slice;
99
use std::collections::HashMap;
1010
use std::cmp::{min, max};
11+
use std::f32::consts::TAU;
1112

1213
use exr::prelude::simple_image;
13-
use half::f16;
14+
use color_space::{Rgb, Hsv};
1415

1516
pub enum DataType {
1617
NONE,
@@ -27,10 +28,9 @@ pub struct DataExport {
2728
pub rgb: Vec<u8>,
2829
pub palette: Vec<(u8, u8, u8)>,
2930
pub iterations: Vec<u32>,
30-
pub smooth_f16: Vec<f16>,
31-
pub smooth_f32: Vec<f32>,
32-
pub distance_x: Vec<f16>,
33-
pub distance_y: Vec<f16>,
31+
pub smooth: Vec<f32>,
32+
pub distance_x: Vec<f32>,
33+
pub distance_y: Vec<f32>,
3434
pub display_glitches: bool,
3535
pub iteration_division: f32,
3636
pub iteration_offset: f32,
@@ -42,8 +42,7 @@ pub struct DataExport {
4242
impl DataExport {
4343
pub fn new(image_width: usize, image_height: usize, display_glitches: bool, data_type: DataType, palette: Vec<(u8, u8, u8)>, iteration_division: f32, iteration_offset: f32, analytic_derivative: bool) -> Self {
4444
let mut rgb = Vec::new();
45-
let mut smooth_f16 = Vec::new();
46-
let mut smooth_f32 = Vec::new();
45+
let mut smooth = Vec::new();
4746
let mut distance_x = Vec::new();
4847
let mut distance_y = Vec::new();
4948

@@ -54,23 +53,23 @@ impl DataExport {
5453
},
5554
DataType::GUI => {
5655
rgb = vec![0u8; image_width * image_height * 3];
57-
smooth_f32 = vec![0.0f32; image_width * image_height];
58-
distance_x = vec![f16::ZERO; image_width * image_height];
59-
distance_y = vec![f16::ZERO; image_width * image_height];
56+
smooth = vec![0.0f32; image_width * image_height];
57+
distance_x = vec![0.0f32; image_width * image_height];
58+
distance_y = vec![0.0f32; image_width * image_height];
6059
}
6160
DataType::RAW => {
62-
smooth_f16 = vec![f16::ZERO; image_width * image_height];
63-
distance_x = vec![f16::ZERO; image_width * image_height];
64-
distance_y = vec![f16::ZERO; image_width * image_height];
61+
smooth = vec![0.0f32; image_width * image_height];
62+
distance_x = vec![0.0f32; image_width * image_height];
63+
distance_y = vec![0.0f32; image_width * image_height];
6564
},
6665
DataType::KFB => {
67-
smooth_f32 = vec![0.0f32; image_width * image_height];
66+
smooth = vec![0.0f32; image_width * image_height];
6867
},
6968
DataType::BOTH => {
7069
rgb = vec![0u8; image_width * image_height * 3];
71-
smooth_f16 = vec![f16::ZERO; image_width * image_height];
72-
distance_x = vec![f16::ZERO; image_width * image_height];
73-
distance_y = vec![f16::ZERO; image_width * image_height];
70+
smooth = vec![0.0f32; image_width * image_height];
71+
distance_x = vec![0.0f32; image_width * image_height];
72+
distance_y = vec![0.0f32; image_width * image_height];
7473
}
7574
}
7675

@@ -80,8 +79,7 @@ impl DataExport {
8079
rgb,
8180
palette,
8281
iterations: vec![0u32; image_width * image_height],
83-
smooth_f16,
84-
smooth_f32,
82+
smooth,
8583
distance_x,
8684
distance_y,
8785
display_glitches,
@@ -156,7 +154,7 @@ impl DataExport {
156154
let z_norm = (reference.reference_data[pixel.iteration - reference.start_iteration].z_fixed + pixel.delta_current.mantissa).norm_sqr() as f32;
157155
let smooth = 1.0 - (z_norm.ln() / escape_radius_ln).log2();
158156

159-
self.smooth_f32[k] = smooth;
157+
self.smooth[k] = smooth;
160158

161159
if self.analytic_derivative {
162160
let temp1 = reference.reference_data[pixel.iteration - reference.start_iteration].z_extended + pixel.delta_current;
@@ -185,8 +183,8 @@ impl DataExport {
185183

186184
let output = num / ComplexFixed::new(den_1, den_2);
187185

188-
self.distance_x[k] = f16::from_f64(output.re);
189-
self.distance_y[k] = f16::from_f64(output.im);
186+
self.distance_x[k] = output.re as f32;
187+
self.distance_y[k] = output.im as f32;
190188
};
191189

192190
self.colour_index(k)
@@ -206,7 +204,7 @@ impl DataExport {
206204
};
207205

208206
let z_norm = (reference.reference_data[pixel.iteration - reference.start_iteration].z_fixed + pixel.delta_current.mantissa).norm_sqr() as f32;
209-
self.smooth_f16[k] = f16::from_f32(1.0 - (z_norm.ln() / escape_radius_ln).log2());
207+
self.smooth[k] = 1.0 - (z_norm.ln() / escape_radius_ln).log2();
210208

211209
if self.analytic_derivative && pixel.iteration < self.maximum_iteration {
212210
let temp1 = reference.reference_data[pixel.iteration - reference.start_iteration].z_extended + pixel.delta_current;
@@ -235,8 +233,8 @@ impl DataExport {
235233

236234
let output = num / ComplexFixed::new(den_1, den_2);
237235

238-
self.distance_x[k] = f16::from_f64(output.re);
239-
self.distance_y[k] = f16::from_f64(output.im);
236+
self.distance_x[k] = output.re as f32;
237+
self.distance_y[k] = output.im as f32;
240238
}
241239
}
242240
},
@@ -253,7 +251,7 @@ impl DataExport {
253251
};
254252

255253
let z_norm = (reference.reference_data[pixel.iteration - reference.start_iteration].z_fixed + pixel.delta_current.mantissa).norm_sqr() as f32;
256-
self.smooth_f32[k] = 1.0 - (z_norm.ln() / escape_radius_ln).log2();
254+
self.smooth[k] = 1.0 - (z_norm.ln() / escape_radius_ln).log2();
257255
}
258256
},
259257
DataType::BOTH => {
@@ -276,7 +274,7 @@ impl DataExport {
276274
let z_norm = (reference.reference_data[pixel.iteration - reference.start_iteration].z_fixed + pixel.delta_current.mantissa).norm_sqr() as f32;
277275
let smooth = 1.0 - (z_norm.ln() / escape_radius_ln).log2();
278276

279-
self.smooth_f16[k] = f16::from_f32(smooth);
277+
self.smooth[k] = smooth;
280278

281279
if self.analytic_derivative {
282280
let temp1 = reference.reference_data[pixel.iteration - reference.start_iteration].z_extended + pixel.delta_current;
@@ -305,8 +303,8 @@ impl DataExport {
305303

306304
let output = num / ComplexFixed::new(den_1, den_2);
307305

308-
self.distance_x[k] = f16::from_f64(output.re);
309-
self.distance_y[k] = f16::from_f64(output.im);
306+
self.distance_x[k] = output.re as f32;
307+
self.distance_y[k] = output.im as f32;
310308
};
311309

312310
self.colour_index(k)
@@ -367,11 +365,11 @@ impl DataExport {
367365

368366
pub fn save_raw(&mut self, filename: &str, approximation_order: usize, zoom: &str) {
369367
let iterations = simple_image::Channel::non_color_data(simple_image::Text::from("N").unwrap(), simple_image::Samples::U32(self.iterations.clone()));
370-
let smooth = simple_image::Channel::non_color_data(simple_image::Text::from("NF").unwrap(), simple_image::Samples::F16(self.smooth_f16.clone()));
368+
let smooth = simple_image::Channel::non_color_data(simple_image::Text::from("NF").unwrap(), simple_image::Samples::F32(self.smooth.clone()));
371369

372370
let channels = if self.analytic_derivative {
373-
let distance_x = simple_image::Channel::non_color_data(simple_image::Text::from("DEX").unwrap(), simple_image::Samples::F16(self.distance_x.clone()));
374-
let distance_y = simple_image::Channel::non_color_data(simple_image::Text::from("DEY").unwrap(), simple_image::Samples::F16(self.distance_y.clone()));
371+
let distance_x = simple_image::Channel::non_color_data(simple_image::Text::from("DEX").unwrap(), simple_image::Samples::F32(self.distance_x.clone()));
372+
let distance_y = simple_image::Channel::non_color_data(simple_image::Text::from("DEY").unwrap(), simple_image::Samples::F32(self.distance_y.clone()));
375373

376374
smallvec::smallvec![iterations, smooth, distance_x, distance_y]
377375
} else {
@@ -430,7 +428,7 @@ impl DataExport {
430428
}).unwrap();
431429

432430
file.write_all(unsafe {
433-
slice::from_raw_parts(self.smooth_f32.as_ptr() as *const u8, self.iterations.len() * 4)
431+
slice::from_raw_parts(self.smooth.as_ptr() as *const u8, self.iterations.len() * 4)
434432
}).unwrap();
435433

436434
}
@@ -444,26 +442,26 @@ impl DataExport {
444442
DataType::GUI => {
445443
self.rgb = vec![0u8; self.image_width * self.image_height * 3];
446444
self.iterations = vec![0xFFFFFFFF; self.image_width * self.image_height];
447-
self.smooth_f32 = vec![0.0f32; self.image_width * self.image_height];
448-
self.distance_x = vec![f16::ZERO; self.image_width * self.image_height];
449-
self.distance_y = vec![f16::ZERO; self.image_width * self.image_height];
445+
self.smooth = vec![0.0f32; self.image_width * self.image_height];
446+
self.distance_x = vec![0.0f32; self.image_width * self.image_height];
447+
self.distance_y = vec![0.0f32; self.image_width * self.image_height];
450448
}
451449
DataType::RAW => {
452450
self.iterations = vec![0xFFFFFFFF; self.image_width * self.image_height];
453-
self.smooth_f16 = vec![f16::ZERO; self.image_width * self.image_height];
454-
self.distance_x = vec![f16::ZERO; self.image_width * self.image_height];
455-
self.distance_y = vec![f16::ZERO; self.image_width * self.image_height];
451+
self.smooth = vec![0.0f32; self.image_width * self.image_height];
452+
self.distance_x = vec![0.0f32; self.image_width * self.image_height];
453+
self.distance_y = vec![0.0f32; self.image_width * self.image_height];
456454
},
457455
DataType::KFB => {
458456
self.iterations = vec![0xFFFFFFFF; self.image_width * self.image_height];
459-
self.smooth_f32 = vec![0.0f32; self.image_width * self.image_height];
457+
self.smooth = vec![0.0f32; self.image_width * self.image_height];
460458
},
461459
DataType::BOTH => {
462460
self.rgb = vec![0u8; self.image_width * self.image_height * 3];
463461
self.iterations = vec![0xFFFFFFFF; self.image_width * self.image_height];
464-
self.smooth_f16 = vec![f16::ZERO; self.image_width * self.image_height];
465-
self.distance_x = vec![f16::ZERO; self.image_width * self.image_height];
466-
self.distance_y = vec![f16::ZERO; self.image_width * self.image_height];
462+
self.smooth = vec![0.0f32; self.image_width * self.image_height];
463+
self.distance_x = vec![0.0f32; self.image_width * self.image_height];
464+
self.distance_y = vec![0.0f32; self.image_width * self.image_height];
467465
}
468466
}
469467
}
@@ -493,11 +491,11 @@ impl DataExport {
493491
let k_right = pixel.image_y * self.image_width + min(self.image_width - 2, pixel.image_x) + 1;
494492

495493
self.iterations[k] = (self.iterations[k_up] + self.iterations[k_down] + self.iterations[k_left] + self.iterations[k_right]) / 4;
496-
self.smooth_f32[k] = (self.smooth_f32[k_up] + self.smooth_f32[k_down] + self.smooth_f32[k_left] + self.smooth_f32[k_right]) / 4.0;
494+
self.smooth[k] = (self.smooth[k_up] + self.smooth[k_down] + self.smooth[k_left] + self.smooth[k_right]) / 4.0;
497495

498496
if self.analytic_derivative {
499-
self.distance_x[k] = f16::from_f32((f32::from(self.distance_x[k_up]) + f32::from(self.distance_x[k_down]) + f32::from(self.distance_x[k_left]) + f32::from(self.distance_x[k_right])) / 4.0);
500-
self.distance_y[k] = f16::from_f32((f32::from(self.distance_y[k_up]) + f32::from(self.distance_y[k_down]) + f32::from(self.distance_y[k_left]) + f32::from(self.distance_y[k_right])) / 4.0);
497+
self.distance_x[k] = (self.distance_x[k_up] + self.distance_x[k_down] + self.distance_x[k_left] + self.distance_x[k_right]) / 4.0;
498+
self.distance_y[k] = (self.distance_y[k_up] + self.distance_y[k_down] + self.distance_y[k_left] + self.distance_y[k_right]) / 4.0;
501499
}
502500

503501
self.colour_index(k);
@@ -514,15 +512,32 @@ impl DataExport {
514512
self.rgb[3 * i + 1] = 0u8;
515513
self.rgb[3 * i + 2] = 0u8;
516514
} else if self.analytic_derivative {
517-
let output = ((f32::from(self.distance_x[i])).powi(2) + (f32::from(self.distance_y[i])).powi(2)).sqrt();
515+
let length = (self.distance_x[i].powi(2) + self.distance_y[i].powi(2)).sqrt();
516+
517+
// colouring algorithm based on 'rainbow_fringe' by claude
518+
let angle = self.distance_y[i].atan2(self.distance_x[i]);
518519

519-
let out = (255.0 * output.tanh()) as u8;
520+
let mut hue = angle / TAU;
521+
hue -= hue.floor();
520522

521-
self.rgb[3 * i] = out as u8;
522-
self.rgb[3 * i + 1] = out as u8;
523-
self.rgb[3 * i + 2] = out as u8;
523+
let saturation = (1.0 / (1.0 + length)).max(0.0).min(1.0);
524+
let value = length.max(0.0).min(1.0);
525+
526+
let hsv = Hsv::new(hue as f64 * 360.0, saturation as f64, value as f64);
527+
let rgb = Rgb::from(hsv);
528+
529+
self.rgb[3 * i] = rgb.r as u8;
530+
self.rgb[3 * i + 1] = rgb.g as u8;
531+
self.rgb[3 * i + 2] = rgb.b as u8;
532+
533+
// default colouring algorithm
534+
// let out = (255.0 * length) as u8;
535+
536+
// self.rgb[3 * i] = out as u8;
537+
// self.rgb[3 * i + 1] = out as u8;
538+
// self.rgb[3 * i + 2] = out as u8;
524539
} else {
525-
let temp = ((self.iterations[i] as f32 + self.smooth_f32[i]) / self.iteration_division) + self.iteration_offset;
540+
let temp = ((self.iterations[i] as f32 + self.smooth[i]) / self.iteration_division) + self.iteration_offset;
526541

527542
let temp2 = temp.floor() as usize % self.palette.len();
528543
let temp3 = (temp as usize + 1) % self.palette.len();

0 commit comments

Comments
 (0)