Skip to content

Commit 7d73aee

Browse files
committed
added in configurable palette
1 parent 13d3746 commit 7d73aee

File tree

3 files changed

+108
-96
lines changed

3 files changed

+108
-96
lines changed

src/renderer.rs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::util::{data_export::*, ComplexFixed, ComplexArbitrary, PixelData, complex_extended::ComplexExtended, float_extended::FloatExtended, string_to_extended, extended_to_string_short, extended_to_string_long, get_approximation_terms, get_delta_top_left};
1+
use crate::util::{data_export::*, ComplexFixed, ComplexArbitrary, PixelData, complex_extended::ComplexExtended, float_extended::FloatExtended, string_to_extended, extended_to_string_short, extended_to_string_long, get_approximation_terms, get_delta_top_left, generate_default_palette};
22
use crate::math::{SeriesApproximation, Perturbation, Reference};
33

44
use std::time::Instant;
@@ -47,6 +47,7 @@ impl FractalRenderer {
4747
let experimental = settings.get_bool("experimental").unwrap_or(false);
4848
let probe_sampling = settings.get_int("probe_sampling").unwrap_or(3) as usize;
4949
let remove_centre = settings.get_bool("remove_centre").unwrap_or(true);
50+
let iteration_division = settings.get_float("iteration_division").unwrap_or(0.1) as f32;
5051
let data_type = match settings.get_str("export").unwrap_or(String::from("COLOUR")).to_ascii_uppercase().as_ref() {
5152
"RAW" | "EXR" => DataType::RAW,
5253
"COLOUR" | "COLOR" | "PNG" => DataType::COLOUR,
@@ -55,6 +56,24 @@ impl FractalRenderer {
5556
_ => DataType::COLOUR
5657
};
5758

59+
let palette = match data_type {
60+
DataType::RAW => {
61+
Vec::new()
62+
},
63+
DataType::KFB | DataType::COLOUR | DataType::BOTH => {
64+
if let Ok(colour_values) = settings.get_array("palette") {
65+
colour_values.chunks_exact(3).map(|value| {
66+
// We assume the palette is in BGR rather than RGB
67+
(value[2].clone().into_int().unwrap() as u8,
68+
value[1].clone().into_int().unwrap() as u8,
69+
value[0].clone().into_int().unwrap() as u8)
70+
}).collect::<Vec<(u8, u8, u8)>>()
71+
} else {
72+
generate_default_palette()
73+
}
74+
}
75+
};
76+
5877
let mut zoom = string_to_extended(&initial_zoom);
5978
let delta_pixel = (-2.0 * (4.0 / image_height as f64 - 2.0) / zoom) / image_height as f64;
6079
let radius = delta_pixel * image_width as f64;
@@ -88,7 +107,7 @@ impl FractalRenderer {
88107
auto_adjust_iterations,
89108
maximum_iteration,
90109
glitch_tolerance,
91-
data_export: DataExport::new(image_width, image_height, display_glitches, data_type),
110+
data_export: DataExport::new(image_width, image_height, display_glitches, data_type, palette, iteration_division),
92111
start_render_time: Instant::now(),
93112
remaining_frames,
94113
frame_offset,

src/util/data_export.rs

Lines changed: 39 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,19 @@ pub struct DataExport {
2525
pub smooth_f16: Vec<f16>,
2626
pub smooth_f32: Vec<f32>,
2727
pub display_glitches: bool,
28+
iteration_division: f32,
2829
data_type: DataType,
2930
}
3031

3132
impl DataExport {
32-
pub fn new(image_width: usize, image_height: usize, display_glitches: bool, data_type: DataType) -> Self {
33+
pub fn new(image_width: usize, image_height: usize, display_glitches: bool, data_type: DataType, palette: Vec<(u8, u8, u8)>, iteration_division: f32) -> Self {
3334
let mut rgb = Vec::new();
34-
let mut palette = Vec::new();
3535
let mut smooth_f16 = Vec::new();
3636
let mut smooth_f32 = Vec::new();
3737

3838
match data_type {
3939
DataType::COLOUR => {
4040
rgb = vec![0u8; image_width * image_height * 3];
41-
palette = DataExport::generate_default_palette();
4241
},
4342
DataType::RAW => {
4443
smooth_f16 = vec![f16::ZERO; image_width * image_height];
@@ -48,7 +47,6 @@ impl DataExport {
4847
},
4948
DataType::BOTH => {
5049
rgb = vec![0u8; image_width * image_height * 3];
51-
palette = DataExport::generate_default_palette();
5250
smooth_f16 = vec![f16::ZERO; image_width * image_height];
5351
}
5452
}
@@ -62,6 +60,7 @@ impl DataExport {
6260
smooth_f16,
6361
smooth_f32,
6462
display_glitches,
63+
iteration_division,
6564
data_type
6665
}
6766
}
@@ -74,35 +73,33 @@ impl DataExport {
7473
for pixel in pixel_data {
7574
let k = (pixel.image_y * self.image_width + pixel.image_x) * 3;
7675

77-
if pixel.glitched {
78-
if self.display_glitches {
79-
self.rgb[k] = 255;
80-
self.rgb[k + 1] = 0;
81-
self.rgb[k + 2] = 0;
82-
} else {
83-
// Pixel is glitched so the smooth won't do much
84-
85-
let colour = self.palette[10 * pixel.iteration % 1024];
86-
self.rgb[k] = colour.0;
87-
self.rgb[k + 1] = colour.1;
88-
self.rgb[k + 2] = colour.2;
89-
}
76+
if pixel.glitched && self.display_glitches {
77+
self.rgb[k] = 255;
78+
self.rgb[k + 1] = 0;
79+
self.rgb[k + 2] = 0;
9080
} else if pixel.iteration >= maximum_iteration {
9181
self.rgb[k] = 0;
9282
self.rgb[k + 1] = 0;
9383
self.rgb[k + 2] = 0;
9484
} else {
9585
let z_norm = (reference.reference_data[pixel.iteration - reference.start_iteration].z_fixed + pixel.delta_current.mantissa).norm_sqr() as f32;
96-
9786
let smooth = 1.0 - (z_norm.ln() / escape_radius_ln).log2();
9887

99-
let colour = self.palette[(10.0 * (pixel.iteration as f32 + smooth)) as usize % 1024];
100-
self.rgb[k] = colour.0;
101-
self.rgb[k + 1] = colour.1;
102-
self.rgb[k + 2] = colour.2;
88+
let temp = (pixel.iteration as f32 + smooth) / self.iteration_division;
89+
90+
let temp2 = temp.floor() as usize % self.palette.len();
91+
let temp3 = (temp as usize + 1) % self.palette.len();
92+
let temp4 = temp.fract();
93+
94+
let colour1 = self.palette[temp2];
95+
let colour2 = self.palette[temp3];
96+
97+
self.rgb[k] = (colour1.0 as f32 + temp4 * (colour2.0 as f32 - colour1.0 as f32)) as u8;
98+
self.rgb[k + 1] = (colour1.1 as f32 + temp4 * (colour2.1 as f32 - colour1.1 as f32)) as u8;
99+
self.rgb[k + 2] = (colour1.2 as f32 + temp4 * (colour2.2 as f32 - colour1.2 as f32)) as u8;
103100
};
104101

105-
self.iterations[k / 3] = pixel.iteration as u32;
102+
// self.iterations[k / 3] = pixel.iteration as u32;
106103
}
107104
},
108105
DataType::RAW => {
@@ -141,33 +138,32 @@ impl DataExport {
141138
for pixel in pixel_data {
142139
let k = (pixel.image_y * self.image_width + pixel.image_x) * 3;
143140

144-
if pixel.glitched {
145-
if self.display_glitches {
146-
self.rgb[k] = 255;
147-
self.rgb[k + 1] = 0;
148-
self.rgb[k + 2] = 0;
149-
self.iterations[k / 3] = 0x00000000
150-
} else {
151-
let colour = self.palette[10 * pixel.iteration % 1024];
152-
self.rgb[k] = colour.0;
153-
self.rgb[k + 1] = colour.1;
154-
self.rgb[k + 2] = colour.2;
155-
self.iterations[k / 3] = 0x00000000
156-
}
141+
if pixel.glitched && self.display_glitches {
142+
self.rgb[k] = 255;
143+
self.rgb[k + 1] = 0;
144+
self.rgb[k + 2] = 0;
145+
self.iterations[k / 3] = 0x00000000;
157146
} else if pixel.iteration >= maximum_iteration {
158147
self.rgb[k] = 0;
159148
self.rgb[k + 1] = 0;
160149
self.rgb[k + 2] = 0;
161150
self.iterations[k / 3] = 0xFFFFFFFF;
162151
} else {
163152
let z_norm = (reference.reference_data[pixel.iteration - reference.start_iteration].z_fixed + pixel.delta_current.mantissa).norm_sqr() as f32;
164-
165153
let smooth = 1.0 - (z_norm.ln() / escape_radius_ln).log2();
166154

167-
let colour = self.palette[(10.0 * (pixel.iteration as f32 + smooth)) as usize % 1024];
168-
self.rgb[k] = colour.0;
169-
self.rgb[k + 1] = colour.1;
170-
self.rgb[k + 2] = colour.2;
155+
let temp = (pixel.iteration as f32 + smooth) / self.iteration_division;
156+
157+
let temp2 = temp.floor() as usize % self.palette.len();
158+
let temp3 = (temp as usize + 1) % self.palette.len();
159+
let temp4 = temp.fract();
160+
161+
let colour1 = self.palette[temp2];
162+
let colour2 = self.palette[temp3];
163+
164+
self.rgb[k] = (colour1.0 as f32 + temp4 * (colour2.0 as f32 - colour1.0 as f32)) as u8;
165+
self.rgb[k + 1] = (colour1.1 as f32 + temp4 * (colour2.1 as f32 - colour1.1 as f32)) as u8;
166+
self.rgb[k + 2] = (colour1.2 as f32 + temp4 * (colour2.2 as f32 - colour1.2 as f32)) as u8;
171167
self.iterations[k / 3] = pixel.iteration as u32;
172168
self.smooth_f16[k / 3] = f16::from_f32(smooth)
173169
};
@@ -232,11 +228,8 @@ impl DataExport {
232228

233229
let test1 = [self.image_width as u32, self.image_height as u32];
234230

235-
// Colours in colourmap
236-
let test5 = DataExport::generate_default_palette();
237-
238231
// iteration division??
239-
let test3 = [1u32, test5.len() as u32];
232+
let test3 = [1u32, self.palette.len() as u32];
240233

241234
// Maxmimum iteration
242235
let test6 = [maximum_iteration as u32];
@@ -254,7 +247,7 @@ impl DataExport {
254247
}).unwrap();
255248

256249
file.write_all(unsafe {
257-
slice::from_raw_parts(test5.as_ptr() as *const u8, 3 * test5.len())
250+
slice::from_raw_parts(self.palette.as_ptr() as *const u8, 3 * self.palette.len())
258251
}).unwrap();
259252

260253
file.write_all(unsafe {
@@ -267,54 +260,6 @@ impl DataExport {
267260

268261
}
269262

270-
fn generate_default_palette() -> Vec<(u8, u8, u8)> {
271-
let mut colours = Vec::with_capacity(1024);
272-
273-
for i in 0..1024 {
274-
let value = i as f32 / 1024.0;
275-
276-
let red;
277-
let green;
278-
let blue;
279-
280-
if value < 0.16 {
281-
let factor = (value - 0.0) / (0.16 - 0.0);
282-
283-
red = 0.0 + factor * (32.0 - 0.0);
284-
green = 7.0 + factor * (107.0 - 7.0);
285-
blue = 100.0 + factor * (203.0 - 100.0);
286-
} else if value < 0.42 {
287-
let factor = (value - 0.16) / (0.42 - 0.16);
288-
289-
red = 32.0 + factor * (237.0 - 32.0);
290-
green = 107.0 + factor * (255.0 - 107.0);
291-
blue = 203.0 + factor * (255.0 - 203.0);
292-
} else if value < 0.6425 {
293-
let factor = (value - 0.42) / (0.6425 - 0.42);
294-
295-
red = 237.0 + factor * (255.0 - 237.0);
296-
green = 255.0 + factor * (170.0 - 255.0);
297-
blue = 255.0 + factor * (0.0 - 255.0);
298-
} else if value < 0.8575 {
299-
let factor = (value - 0.6425) / (0.8575 - 0.6425);
300-
301-
red = 255.0 + factor * (0.0 - 255.0);
302-
green = 170.0 + factor * (2.0 - 170.0);
303-
blue = 0.0;
304-
} else {
305-
let factor = (value - 0.8575) / (1.0 - 0.8575);
306-
307-
red = 0.0;
308-
green = 2.0 + factor * (7.0 - 2.0);
309-
blue = 0.0 + factor * (100.0 - 0.0);
310-
}
311-
312-
colours.push((red as u8, green as u8, blue as u8))
313-
}
314-
315-
colours
316-
}
317-
318263
pub fn clear_buffers(&mut self) {
319264
match self.data_type {
320265
DataType::COLOUR => {

src/util/mod.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,54 @@ pub fn get_approximation_terms(approximation_order: usize, image_width: usize, i
102102
}
103103
}
104104

105+
pub fn generate_default_palette() -> Vec<(u8, u8, u8)> {
106+
let mut colours = Vec::with_capacity(1024);
107+
108+
for i in 0..1024 {
109+
let value = i as f32 / 1024.0;
110+
111+
let red;
112+
let green;
113+
let blue;
114+
115+
if value < 0.16 {
116+
let factor = (value - 0.0) / (0.16 - 0.0);
117+
118+
red = 0.0 + factor * (32.0 - 0.0);
119+
green = 7.0 + factor * (107.0 - 7.0);
120+
blue = 100.0 + factor * (203.0 - 100.0);
121+
} else if value < 0.42 {
122+
let factor = (value - 0.16) / (0.42 - 0.16);
123+
124+
red = 32.0 + factor * (237.0 - 32.0);
125+
green = 107.0 + factor * (255.0 - 107.0);
126+
blue = 203.0 + factor * (255.0 - 203.0);
127+
} else if value < 0.6425 {
128+
let factor = (value - 0.42) / (0.6425 - 0.42);
129+
130+
red = 237.0 + factor * (255.0 - 237.0);
131+
green = 255.0 + factor * (170.0 - 255.0);
132+
blue = 255.0 + factor * (0.0 - 255.0);
133+
} else if value < 0.8575 {
134+
let factor = (value - 0.6425) / (0.8575 - 0.6425);
135+
136+
red = 255.0 + factor * (0.0 - 255.0);
137+
green = 170.0 + factor * (2.0 - 170.0);
138+
blue = 0.0;
139+
} else {
140+
let factor = (value - 0.8575) / (1.0 - 0.8575);
141+
142+
red = 0.0;
143+
green = 2.0 + factor * (7.0 - 2.0);
144+
blue = 0.0 + factor * (100.0 - 0.0);
145+
}
146+
147+
colours.push((red as u8, green as u8, blue as u8))
148+
}
149+
150+
colours
151+
}
152+
105153
#[derive(Clone)]
106154
pub struct PixelData {
107155
pub image_x: usize,

0 commit comments

Comments
 (0)