1use cgmath::{vec2, Vector2, Vector3};
2use crate::ImageData;
3use simple_canvas::*;
4use std::sync::{Arc, Mutex};
5use std::thread;
6use std::collections::VecDeque;
7
8pub fn main_image(
14 canvas: &mut Canvas<Vector3<u8>>,
15 pixel_func: impl Fn(&ImageData, &Vector2<u32>) -> Vector3<u8> + Send + 'static + Copy
16) {
17 let image_data = ImageData {
18 resolution: vec2(canvas.width, canvas.height),
19 aspect_ratio: canvas.width as f64 / canvas.height as f64,
20 size: (canvas.width * canvas.height)
21 };
22 for row in 0..canvas.height {
23 for col in 0..canvas.width {
24 *canvas.get_mut(row, col).expect("Index out of bounds") =
25 pixel_func(&image_data, &vec2(row as u32, col as u32));
26 }
27 }
28}
29
30pub fn main_image_mt(
37 canvas: &mut Canvas<Vector3<u8>>,
38 pixel_func: impl Fn(&ImageData, &Vector2<u32>) -> Vector3<u8> + Send + 'static + Copy,
39 thread_count: usize
40) {
41 if thread_count > (canvas.width * canvas.height) {
43 panic!("Cannot have more thread than pixels");
44 }
45
46 let image_data = Arc::new(
48 ImageData {
49 resolution: vec2(canvas.width, canvas.height),
50 aspect_ratio: canvas.width as f64 / canvas.height as f64,
51 size: (canvas.width * canvas.height)
52 }
53 );
54
55 let slice_size = image_data.size / thread_count;
58
59 let slice_diff = image_data.size - (slice_size * thread_count);
62
63 let mut slices: VecDeque<Vec<Vector3<u8>>> = VecDeque::new();
65
66 for i in 0..thread_count {
68 let mut curr_size = slice_size;
69 if i == thread_count - 1 {
70 curr_size += slice_diff;
71 }
72 let mut slice: Vec<Vector3<u8>> = Vec::with_capacity(curr_size as usize);
73 for j in (i * slice_size as usize)..(i * slice_size as usize + curr_size as usize) {
74 slice.push(*canvas.data.get(j).unwrap());
75 }
76 slices.push_front(slice);
77 }
78
79
80 let mut threads: Vec<thread::JoinHandle<_>> = Vec::new();
82
83 let mut result_vec: Vec<Vec<Vector3<u8>>> = Vec::with_capacity(thread_count);
85
86 let placeholder_vec: Vec<Vector3<u8>> = Vec::new();
88
89 (0..thread_count).for_each(|_| result_vec.push(placeholder_vec.clone()));
91
92 let result_vec = Arc::new(Mutex::new(result_vec));
94
95 let offset = Arc::new(slice_size as usize);
97
98 for i in 0..thread_count {
100
101 let image_data = Arc::clone(&image_data);
103 let offset = Arc::clone(&offset);
107 let mut slice = slices.pop_back().unwrap();
108 let result_vec = Arc::clone(&result_vec);
109
110 threads.push(thread::spawn(move || {
112
113 let mut curr_offset = *offset;
117
118 if i == thread_count - 1 {
120 curr_offset += slice_diff;
121 }
122
123 let mut curr_row;
126 let mut curr_col;
127 for index in ((i * *offset)..(i * *offset + curr_offset)).enumerate() {
128 curr_row = (index.1) / image_data.resolution.x;
130 curr_col = (index.1) - curr_row * image_data.resolution.x;
131
132 let pixel = pixel_func(&image_data, &vec2(curr_row as u32, curr_col as u32));
134 *slice.get_mut(index.0).unwrap() = pixel;
135 }
136
137 let mut result_vec = result_vec.lock().unwrap();
140 *result_vec.get_mut(i).unwrap() = slice;
141 }));
142 };
143
144 for thread in threads {
146 thread.join().expect("Could not join thread.");
147 }
148
149 let mut data_vec: Vec<Vector3<u8>> = Vec::with_capacity(image_data.size);
151
152 for slice in result_vec.lock().unwrap().iter() {
154 for pixel in slice {
155 data_vec.push(*pixel);
156 }
157 }
158
159 canvas.data = data_vec;
161}