@@ -8,9 +8,10 @@ use std::fs::File;
8
8
use std:: slice;
9
9
use std:: collections:: HashMap ;
10
10
use std:: cmp:: { min, max} ;
11
+ use std:: f32:: consts:: TAU ;
11
12
12
13
use exr:: prelude:: simple_image;
13
- use half :: f16 ;
14
+ use color_space :: { Rgb , Hsv } ;
14
15
15
16
pub enum DataType {
16
17
NONE ,
@@ -27,10 +28,9 @@ pub struct DataExport {
27
28
pub rgb : Vec < u8 > ,
28
29
pub palette : Vec < ( u8 , u8 , u8 ) > ,
29
30
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 > ,
34
34
pub display_glitches : bool ,
35
35
pub iteration_division : f32 ,
36
36
pub iteration_offset : f32 ,
@@ -42,8 +42,7 @@ pub struct DataExport {
42
42
impl DataExport {
43
43
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 {
44
44
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 ( ) ;
47
46
let mut distance_x = Vec :: new ( ) ;
48
47
let mut distance_y = Vec :: new ( ) ;
49
48
@@ -54,23 +53,23 @@ impl DataExport {
54
53
} ,
55
54
DataType :: GUI => {
56
55
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] ;
60
59
}
61
60
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] ;
65
64
} ,
66
65
DataType :: KFB => {
67
- smooth_f32 = vec ! [ 0.0f32 ; image_width * image_height] ;
66
+ smooth = vec ! [ 0.0f32 ; image_width * image_height] ;
68
67
} ,
69
68
DataType :: BOTH => {
70
69
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] ;
74
73
}
75
74
}
76
75
@@ -80,8 +79,7 @@ impl DataExport {
80
79
rgb,
81
80
palette,
82
81
iterations : vec ! [ 0u32 ; image_width * image_height] ,
83
- smooth_f16,
84
- smooth_f32,
82
+ smooth,
85
83
distance_x,
86
84
distance_y,
87
85
display_glitches,
@@ -156,7 +154,7 @@ impl DataExport {
156
154
let z_norm = ( reference. reference_data [ pixel. iteration - reference. start_iteration ] . z_fixed + pixel. delta_current . mantissa ) . norm_sqr ( ) as f32 ;
157
155
let smooth = 1.0 - ( z_norm. ln ( ) / escape_radius_ln) . log2 ( ) ;
158
156
159
- self . smooth_f32 [ k] = smooth;
157
+ self . smooth [ k] = smooth;
160
158
161
159
if self . analytic_derivative {
162
160
let temp1 = reference. reference_data [ pixel. iteration - reference. start_iteration ] . z_extended + pixel. delta_current ;
@@ -185,8 +183,8 @@ impl DataExport {
185
183
186
184
let output = num / ComplexFixed :: new ( den_1, den_2) ;
187
185
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 ;
190
188
} ;
191
189
192
190
self . colour_index ( k)
@@ -206,7 +204,7 @@ impl DataExport {
206
204
} ;
207
205
208
206
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 ( ) ;
210
208
211
209
if self . analytic_derivative && pixel. iteration < self . maximum_iteration {
212
210
let temp1 = reference. reference_data [ pixel. iteration - reference. start_iteration ] . z_extended + pixel. delta_current ;
@@ -235,8 +233,8 @@ impl DataExport {
235
233
236
234
let output = num / ComplexFixed :: new ( den_1, den_2) ;
237
235
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 ;
240
238
}
241
239
}
242
240
} ,
@@ -253,7 +251,7 @@ impl DataExport {
253
251
} ;
254
252
255
253
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 ( ) ;
257
255
}
258
256
} ,
259
257
DataType :: BOTH => {
@@ -276,7 +274,7 @@ impl DataExport {
276
274
let z_norm = ( reference. reference_data [ pixel. iteration - reference. start_iteration ] . z_fixed + pixel. delta_current . mantissa ) . norm_sqr ( ) as f32 ;
277
275
let smooth = 1.0 - ( z_norm. ln ( ) / escape_radius_ln) . log2 ( ) ;
278
276
279
- self . smooth_f16 [ k] = f16 :: from_f32 ( smooth) ;
277
+ self . smooth [ k] = smooth;
280
278
281
279
if self . analytic_derivative {
282
280
let temp1 = reference. reference_data [ pixel. iteration - reference. start_iteration ] . z_extended + pixel. delta_current ;
@@ -305,8 +303,8 @@ impl DataExport {
305
303
306
304
let output = num / ComplexFixed :: new ( den_1, den_2) ;
307
305
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 ;
310
308
} ;
311
309
312
310
self . colour_index ( k)
@@ -367,11 +365,11 @@ impl DataExport {
367
365
368
366
pub fn save_raw ( & mut self , filename : & str , approximation_order : usize , zoom : & str ) {
369
367
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 ( ) ) ) ;
371
369
372
370
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 ( ) ) ) ;
375
373
376
374
smallvec:: smallvec![ iterations, smooth, distance_x, distance_y]
377
375
} else {
@@ -430,7 +428,7 @@ impl DataExport {
430
428
} ) . unwrap ( ) ;
431
429
432
430
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 )
434
432
} ) . unwrap ( ) ;
435
433
436
434
}
@@ -444,26 +442,26 @@ impl DataExport {
444
442
DataType :: GUI => {
445
443
self . rgb = vec ! [ 0u8 ; self . image_width * self . image_height * 3 ] ;
446
444
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] ;
450
448
}
451
449
DataType :: RAW => {
452
450
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] ;
456
454
} ,
457
455
DataType :: KFB => {
458
456
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] ;
460
458
} ,
461
459
DataType :: BOTH => {
462
460
self . rgb = vec ! [ 0u8 ; self . image_width * self . image_height * 3 ] ;
463
461
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] ;
467
465
}
468
466
}
469
467
}
@@ -493,11 +491,11 @@ impl DataExport {
493
491
let k_right = pixel. image_y * self . image_width + min ( self . image_width - 2 , pixel. image_x ) + 1 ;
494
492
495
493
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 ;
497
495
498
496
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 ;
501
499
}
502
500
503
501
self . colour_index ( k) ;
@@ -514,15 +512,32 @@ impl DataExport {
514
512
self . rgb [ 3 * i + 1 ] = 0u8 ;
515
513
self . rgb [ 3 * i + 2 ] = 0u8 ;
516
514
} 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] ) ;
518
519
519
- let out = ( 255.0 * output. tanh ( ) ) as u8 ;
520
+ let mut hue = angle / TAU ;
521
+ hue -= hue. floor ( ) ;
520
522
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;
524
539
} 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 ;
526
541
527
542
let temp2 = temp. floor ( ) as usize % self . palette . len ( ) ;
528
543
let temp3 = ( temp as usize + 1 ) % self . palette . len ( ) ;
0 commit comments