Skip to content

Commit dc1b992

Browse files
committed
added working central part deletion
1 parent 9f07fa5 commit dc1b992

File tree

5 files changed

+106
-126
lines changed

5 files changed

+106
-126
lines changed

default.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
image_width = 1920
22
image_height = 1080
3-
frames = 9999
3+
frames = 100
44
export = "colour"
55
rotate = 0
66
glitch_tolerance = 0.000001
7-
approximation_order = "32"
7+
zoom_scale = 2.0

segments.txt

Lines changed: 0 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,2 @@
1-
file 'segment_00000078.mp4'
2-
file 'segment_00000077.mp4'
3-
file 'segment_00000076.mp4'
4-
file 'segment_00000075.mp4'
5-
file 'segment_00000074.mp4'
6-
file 'segment_00000073.mp4'
7-
file 'segment_00000072.mp4'
8-
file 'segment_00000071.mp4'
9-
file 'segment_00000070.mp4'
10-
file 'segment_00000069.mp4'
11-
file 'segment_00000068.mp4'
12-
file 'segment_00000067.mp4'
13-
file 'segment_00000066.mp4'
14-
file 'segment_00000065.mp4'
15-
file 'segment_00000064.mp4'
16-
file 'segment_00000063.mp4'
17-
file 'segment_00000062.mp4'
18-
file 'segment_00000061.mp4'
19-
file 'segment_00000060.mp4'
20-
file 'segment_00000059.mp4'
21-
file 'segment_00000058.mp4'
22-
file 'segment_00000057.mp4'
23-
file 'segment_00000056.mp4'
24-
file 'segment_00000055.mp4'
25-
file 'segment_00000054.mp4'
26-
file 'segment_00000053.mp4'
27-
file 'segment_00000052.mp4'
28-
file 'segment_00000051.mp4'
29-
file 'segment_00000050.mp4'
30-
file 'segment_00000049.mp4'
31-
file 'segment_00000048.mp4'
32-
file 'segment_00000047.mp4'
33-
file 'segment_00000046.mp4'
34-
file 'segment_00000045.mp4'
35-
file 'segment_00000044.mp4'
36-
file 'segment_00000043.mp4'
37-
file 'segment_00000042.mp4'
38-
file 'segment_00000041.mp4'
39-
file 'segment_00000040.mp4'
40-
file 'segment_00000039.mp4'
41-
file 'segment_00000038.mp4'
42-
file 'segment_00000037.mp4'
43-
file 'segment_00000036.mp4'
44-
file 'segment_00000035.mp4'
45-
file 'segment_00000034.mp4'
46-
file 'segment_00000033.mp4'
47-
file 'segment_00000032.mp4'
48-
file 'segment_00000031.mp4'
49-
file 'segment_00000030.mp4'
50-
file 'segment_00000029.mp4'
51-
file 'segment_00000028.mp4'
52-
file 'segment_00000027.mp4'
53-
file 'segment_00000026.mp4'
54-
file 'segment_00000025.mp4'
55-
file 'segment_00000024.mp4'
56-
file 'segment_00000023.mp4'
57-
file 'segment_00000022.mp4'
58-
file 'segment_00000021.mp4'
59-
file 'segment_00000020.mp4'
60-
file 'segment_00000019.mp4'
61-
file 'segment_00000018.mp4'
62-
file 'segment_00000017.mp4'
63-
file 'segment_00000016.mp4'
64-
file 'segment_00000015.mp4'
65-
file 'segment_00000014.mp4'
66-
file 'segment_00000013.mp4'
67-
file 'segment_00000012.mp4'
68-
file 'segment_00000011.mp4'
69-
file 'segment_00000010.mp4'
70-
file 'segment_00000009.mp4'
71-
file 'segment_00000008.mp4'
72-
file 'segment_00000007.mp4'
73-
file 'segment_00000006.mp4'
74-
file 'segment_00000005.mp4'
75-
file 'segment_00000004.mp4'
76-
file 'segment_00000003.mp4'
77-
file 'segment_00000002.mp4'
781
file 'segment_00000001.mp4'
792
file 'segment_00000000.mp4'

src/renderer.rs

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,15 @@ impl FractalRenderer {
7878
}
7979
}
8080

81-
pub fn render_frame(&mut self, index: usize, filename: String) {
82-
print!("{:<6}", index);
81+
pub fn render_frame(&mut self, frame_index: usize, filename: String) {
82+
print!("{:<6}", frame_index);
8383
print!("| {:<15}", extended_to_string(self.zoom));
8484
std::io::stdout().flush().unwrap();
8585
let frame_time = Instant::now();
8686
let approximation_time = Instant::now();
8787

8888
// If we are on the first frame we need to run the central reference calculation
89-
if index == 0 {
89+
if frame_index == 0 {
9090
self.center_reference.run();
9191
self.series_approximation.maximum_iteration = self.center_reference.current_iteration;
9292
self.series_approximation.generate_approximation(&self.center_reference);
@@ -111,29 +111,45 @@ impl FractalRenderer {
111111

112112
let packing_time = Instant::now();
113113

114+
if frame_index == 1 {
115+
// This will remove the central pixels
116+
self.data_export.clear_buffers();
117+
}
118+
119+
// This could be optimised
114120
let mut pixel_data = (0..(self.image_width * self.image_height)).into_par_iter()
115-
.map(|index| {
121+
.filter_map(|index| {
116122
let i = index % self.image_width;
117123
let j = index / self.image_width;
118-
// This could be changed to account for rotation, and jittering if needed
119-
let element = ComplexFixed::new(
120-
i as f64 * delta_pixel * cos_rotate - j as f64 * delta_pixel * sin_rotate + delta_top_left.re,
121-
i as f64 * delta_pixel * sin_rotate + j as f64 * delta_pixel * cos_rotate + delta_top_left.im
122-
);
123-
124-
let point_delta = ComplexExtended::new(element, -self.zoom.exponent);
125-
let new_delta = self.series_approximation.evaluate(point_delta, None);
126-
127-
PixelData {
128-
image_x: i,
129-
image_y: j,
130-
iteration: self.series_approximation.valid_iteration,
131-
delta_centre: point_delta,
132-
delta_reference: point_delta,
133-
delta_current: new_delta,
134-
derivative_current: ComplexFixed::new(1.0, 0.0),
135-
glitched: false,
136-
escaped: false
124+
125+
// Add one to avoid rescaling artifacts
126+
let val1 = (self.image_width as f64 * (0.5 - 0.5 / self.zoom_scale_factor)).ceil() as usize;
127+
let val2 = (self.image_height as f64 * (0.5 - 0.5 / self.zoom_scale_factor)).ceil() as usize;
128+
129+
// Check if the pixel has already been covered in an earlier keyframe
130+
if frame_index >= 1 && i > val1 && i < self.image_width - val1 && j > val2 && j < self.image_height - val2 {
131+
None
132+
} else {
133+
// This could be changed to account for jittering if needed
134+
let element = ComplexFixed::new(
135+
i as f64 * delta_pixel * cos_rotate - j as f64 * delta_pixel * sin_rotate + delta_top_left.re,
136+
i as f64 * delta_pixel * sin_rotate + j as f64 * delta_pixel * cos_rotate + delta_top_left.im
137+
);
138+
139+
let point_delta = ComplexExtended::new(element, -self.zoom.exponent);
140+
let new_delta = self.series_approximation.evaluate(point_delta, None);
141+
142+
Some(PixelData {
143+
image_x: i,
144+
image_y: j,
145+
iteration: self.series_approximation.valid_iteration,
146+
delta_centre: point_delta,
147+
delta_reference: point_delta,
148+
delta_current: new_delta,
149+
derivative_current: ComplexFixed::new(1.0, 0.0),
150+
glitched: false,
151+
escaped: false
152+
})
137153
}
138154
}).collect::<Vec<PixelData>>();
139155

src/util/data_export.rs

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ pub enum DataType {
1717
pub struct DataExport {
1818
image_width: usize,
1919
image_height: usize,
20-
rgb: Vec<u8>,
20+
pub rgb: Vec<u8>,
2121
palette: Vec<(u8, u8, u8)>,
22-
iterations: Vec<u32>,
23-
smooth: Vec<f32>,
22+
pub iterations: Vec<u32>,
23+
pub smooth: Vec<f32>,
2424
pub display_glitches: bool,
2525
data_type: DataType,
2626
}
@@ -68,6 +68,8 @@ impl DataExport {
6868
}
6969

7070
pub fn export_pixels(&mut self, pixel_data: &[PixelData], maximum_iteration: usize, reference: &Reference) {
71+
let escape_radius_ln = 1e16f32.ln();
72+
7173
match self.data_type {
7274
DataType::COLOUR => {
7375
for pixel in pixel_data {
@@ -79,6 +81,8 @@ impl DataExport {
7981
self.rgb[k + 1] = 0;
8082
self.rgb[k + 2] = 0;
8183
} else {
84+
// Pixel is glitched so the smooth won't do much
85+
8286
let colour = self.palette[10 * pixel.iteration % 1024];
8387
self.rgb[k] = colour.0;
8488
self.rgb[k + 1] = colour.1;
@@ -89,16 +93,18 @@ impl DataExport {
8993
self.rgb[k + 1] = 0;
9094
self.rgb[k + 2] = 0;
9195
} else {
92-
let colour = self.palette[10 * pixel.iteration % 1024];
96+
let z_norm = (reference.reference_data[pixel.iteration - reference.start_iteration].z_fixed + pixel.delta_current.mantissa).norm_sqr() as f32;
97+
98+
let smooth = 1.0 - (z_norm.ln() / escape_radius_ln).log2();
99+
100+
let colour = self.palette[(10.0 * (pixel.iteration as f32 + smooth)) as usize % 1024];
93101
self.rgb[k] = colour.0;
94102
self.rgb[k + 1] = colour.1;
95103
self.rgb[k + 2] = colour.2;
96104
};
97105
}
98106
},
99107
DataType::RAW => {
100-
let escape_radius_ln = 1e16f32.ln();
101-
102108
for pixel in pixel_data {
103109
let k = pixel.image_y * self.image_width + pixel.image_x;
104110

@@ -115,8 +121,6 @@ impl DataExport {
115121
}
116122
},
117123
DataType::KFB => {
118-
let escape_radius_ln = 1e16f32.ln();
119-
120124
for pixel in pixel_data {
121125
let k = pixel.image_x * self.image_height + pixel.image_y;
122126

@@ -133,8 +137,6 @@ impl DataExport {
133137
}
134138
},
135139
DataType::BOTH => {
136-
let escape_radius_ln = 1e16f32.ln();
137-
138140
for pixel in pixel_data {
139141
let k = (pixel.image_y * self.image_width + pixel.image_x) * 3;
140142

@@ -157,15 +159,17 @@ impl DataExport {
157159
self.rgb[k + 2] = 0;
158160
self.iterations[k / 3] = 0xFFFFFFFF;
159161
} else {
160-
let colour = self.palette[10 * pixel.iteration % 1024];
162+
let z_norm = (reference.reference_data[pixel.iteration - reference.start_iteration].z_fixed + pixel.delta_current.mantissa).norm_sqr() as f32;
163+
164+
let smooth = 1.0 - (z_norm.ln() / escape_radius_ln).log2();
165+
166+
let colour = self.palette[(10.0 * (pixel.iteration as f32 + smooth)) as usize % 1024];
161167
self.rgb[k] = colour.0;
162168
self.rgb[k + 1] = colour.1;
163169
self.rgb[k + 2] = colour.2;
164170
self.iterations[k / 3] = pixel.iteration as u32;
171+
self.smooth[k / 3] = smooth
165172
};
166-
167-
let z_norm = (reference.reference_data[pixel.iteration - reference.start_iteration].z_fixed + pixel.delta_current.mantissa).norm_sqr() as f32;
168-
self.smooth[k / 3] = 1.0 - (z_norm.ln() / escape_radius_ln).log2();
169173
}
170174
}
171175
}
@@ -190,7 +194,12 @@ impl DataExport {
190194
}
191195

192196
fn save_colour(&mut self, filename: &str) {
193-
image::save_buffer(filename.to_owned() + ".png", &self.rgb, self.image_width as u32, self.image_height as u32, image::ColorType::Rgb8).unwrap();
197+
image::save_buffer(
198+
filename.to_owned() + ".png",
199+
&self.rgb,
200+
self.image_width as u32,
201+
self.image_height as u32,
202+
image::ColorType::Rgb8).unwrap();
194203
}
195204

196205
fn save_raw(&mut self, filename: &str) {
@@ -295,4 +304,21 @@ impl DataExport {
295304

296305
colours
297306
}
307+
308+
pub fn clear_buffers(&mut self) {
309+
match self.data_type {
310+
DataType::COLOUR => {
311+
self.rgb = vec![0u8; self.image_width * self.image_height * 3];
312+
}
313+
DataType::RAW | DataType::KFB => {
314+
self.iterations = vec![0u32; self.image_width * self.image_height];
315+
self.smooth = vec![0.0f32; self.image_width * self.image_height];
316+
}
317+
DataType::BOTH => {
318+
self.rgb = vec![0u8; self.image_width * self.image_height * 3];
319+
self.iterations = vec![0u32; self.image_width * self.image_height];
320+
self.smooth = vec![0.0f32; self.image_width * self.image_height];
321+
}
322+
}
323+
}
298324
}

test2.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,17 @@
22
import numpy as np
33
import time
44
import os
5+
import math
56

67
from PIL import Image
78

8-
frames_between_keyframes = 60
9-
maximum_keyframe_number = 783
10-
zoom_scale = 2
9+
frames_between_keyframes = 8
10+
maximum_keyframe_number = 99
11+
zoom_scale = 1.1
12+
13+
# log1.1 of 2 is 7.27
14+
# 60 / that is 8.25, so lets take 8 frames per keyframe
15+
1116

1217
# Arguments for ffmpeg
1318
kargs = {
@@ -31,8 +36,12 @@
3136
previous_keyframe = Image.open(f"output/output_00000000.png")
3237

3338
(width, height) = (previous_keyframe.width, previous_keyframe.height)
34-
(scaled_width, scaled_height) = (zoom_scale * width, zoom_scale * height)
35-
placement_box = (scaled_width//4, scaled_height//4, scaled_width//4 * 3, scaled_height//4 * 3)
39+
(scaled_width, scaled_height) = (int(zoom_scale * width), int(zoom_scale * height))
40+
41+
val1 = (scaled_width - width) // 2
42+
val2 = (scaled_height - height) // 2
43+
44+
placement_box = (val1, val2, val1 + width, val2 + height)
3645

3746
for i in range(0, maximum_keyframe_number):
3847
# Creates 10 second segments
@@ -47,15 +56,21 @@
4756

4857
next_keyframe = Image.open(f"output/output_{i + 1:08}.png")
4958

50-
scaled_keyframe = next_keyframe.resize((scaled_width, scaled_height), resample=Image.LANCZOS)
59+
scaled_keyframe = next_keyframe.resize((scaled_width, scaled_height), resample=Image.NEAREST)
5160

5261
scaled_keyframe.paste(previous_keyframe, placement_box)
5362

63+
current_scale = zoom_scale
64+
factor = 10**(math.log10(zoom_scale) / frames_between_keyframes)
65+
5466
for j in range(0, frames_between_keyframes):
55-
zoom = zoom_scale**(1.0 - j / frames_between_keyframes)
67+
# zoom = 1.0 + (2**(1.0 - j / frames_between_keyframes) - 1.0) * (zoom_scale - 1.0)
68+
# zoom = zoom_scale**(1.0 - j / frames_between_keyframes)
69+
# zoom = zoom_scale**((1.0 - j / frames_between_keyframes))
70+
current_scale /= factor
5671

57-
temp1 = (1.0 - 1.0 / zoom) * width
58-
temp2 = (1.0 - 1.0 / zoom) * height
72+
temp1 = (1.0 - 1.0 / current_scale) * (scaled_width // 2)
73+
temp2 = (1.0 - 1.0 / current_scale) * (scaled_height // 2)
5974
temp3 = scaled_width - temp1
6075
temp4 = scaled_height - temp2
6176

0 commit comments

Comments
 (0)