diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/benoit/benoit/application.rs | 7 | ||||
-rw-r--r-- | source/benoit/benoit/application/colour.rs | 54 | ||||
-rw-r--r-- | source/benoit/benoit/application/draw.rs | 61 | ||||
-rw-r--r-- | source/benoit/benoit/application/dump.rs | 49 | ||||
-rw-r--r-- | source/benoit/benoit/application/initialise.rs | 2 | ||||
-rw-r--r-- | source/benoit/benoit/application/poll_events.rs | 3 | ||||
-rw-r--r-- | source/benoit/benoit/application/render.rs | 89 | ||||
-rw-r--r-- | source/benoit/benoit/application/run.rs | 6 |
8 files changed, 195 insertions, 76 deletions
diff --git a/source/benoit/benoit/application.rs b/source/benoit/benoit/application.rs index a203d4c..335d754 100644 --- a/source/benoit/benoit/application.rs +++ b/source/benoit/benoit/application.rs @@ -26,10 +26,13 @@ extern crate sdl2; use sdl2::{Sdl, VideoSubsystem}; use sdl2::render::WindowCanvas; +pub mod colour; +pub mod draw; +pub mod dump; pub mod initialise; pub mod poll_events; -pub mod render; pub mod render_row; +pub mod render; pub mod run; pub struct Application { @@ -48,5 +51,5 @@ pub struct Application { zoom: f64, maximum_iteration_count: u32, - do_render: bool, + do_draw: bool, } diff --git a/source/benoit/benoit/application/colour.rs b/source/benoit/benoit/application/colour.rs new file mode 100644 index 0000000..f0b1f19 --- /dev/null +++ b/source/benoit/benoit/application/colour.rs @@ -0,0 +1,54 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::benoit::application::Application; + +impl Application { + pub fn colour(&mut self, buffer: &mut [u8], data: &[u32]) { + let canvas_size = self.canvas_height * self.canvas_width; + + for pixel in 0x0..canvas_size { + let iteration_count = data[pixel as usize]; + + let factor = { + let factor = iteration_count as f32 / 64.0 % 1.0; + + (if factor >= 1.0 / 2.0 { + 1.0 - factor + } else { + factor + }) * 2.0 + }; + + let colour: u8 = if iteration_count != self.maximum_iteration_count { + (factor * 255.0).round() as u8 + } else { + 0x0 + }; + + buffer[pixel as usize * 0x3] = colour; + buffer[pixel as usize * 0x3 + 0x1] = colour; + buffer[pixel as usize * 0x3 + 0x2] = colour; + } + } +} diff --git a/source/benoit/benoit/application/draw.rs b/source/benoit/benoit/application/draw.rs new file mode 100644 index 0000000..29e0faf --- /dev/null +++ b/source/benoit/benoit/application/draw.rs @@ -0,0 +1,61 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::benoit::application::Application; + +extern crate sdl2; + +use sdl2::pixels::Color; +use sdl2::rect::Rect; + +impl Application { + pub fn draw(&mut self) { + let canvas_size = self.canvas_height * self.canvas_width; + + let mut data: Vec::<u32> = vec![0x0; canvas_size as usize]; + self.render(&mut data[..]); + + let mut image: Vec::<u8> = vec![0x0; canvas_size as usize * 0x3]; + self.colour(&mut image[..], &data[..]); + + for pixel in 0x0..canvas_size { + let y = pixel as u32 / self.canvas_width; + let x = pixel as u32 - y * self.canvas_width; + + let value = image[pixel as usize * 0x3]; + + let colour = Color::RGB(value, value, value); + self.canvas.set_draw_color(colour); + + let rectangle = Rect::new( + (x * self.scale) as i32, + (y * self.scale) as i32, + self.scale, + self.scale + ); + self.canvas.fill_rects(&[rectangle]).unwrap(); + } + + self.canvas.present(); + } +} diff --git a/source/benoit/benoit/application/dump.rs b/source/benoit/benoit/application/dump.rs new file mode 100644 index 0000000..25ec520 --- /dev/null +++ b/source/benoit/benoit/application/dump.rs @@ -0,0 +1,49 @@ +/* + Copyright 2021, 2023 Gabriel Bjørnager Jensen. + + This file is part of Benoit. + + Benoit is free software: you can redistribute it + and/or modify it under the terms of the GNU + Affero General Public License as published by + the Free Software Foundation, either version 3 + of the License, or (at your option) any later + version. + + Benoit is distributed in the hope that it will + be useful, but WITHOUT ANY WARRANTY; without + even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU + Affero General Public License along with Benoit. + If not, see <https://www.gnu.org/licenses/>. +*/ + +use crate::benoit::application::Application; + +extern crate webp; + +use std::fs::write; +use webp::Encoder; + +impl Application { + pub fn dump_image(&mut self) { + let canvas_size = self.canvas_height * self.canvas_width; + + let mut data: Vec::<u32> = vec![0x0; canvas_size as usize]; + self.render(&mut data[..]); + + let mut image: Vec::<u8> = vec![0x0; canvas_size as usize * 0x3]; + self.colour(&mut image[..], &data[..]); + + let encoder = Encoder::from_rgb(&image[..], self.canvas_width, self.canvas_height); + + let data = encoder.encode_lossless(); + + let file_path = "./image.webp"; + + write(file_path, &*data); + } +} diff --git a/source/benoit/benoit/application/initialise.rs b/source/benoit/benoit/application/initialise.rs index dafaf0e..28245b2 100644 --- a/source/benoit/benoit/application/initialise.rs +++ b/source/benoit/benoit/application/initialise.rs @@ -52,7 +52,7 @@ impl Application { zoom: 1.0, maximum_iteration_count: 0x100, - do_render: true, + do_draw: true, }; } } diff --git a/source/benoit/benoit/application/poll_events.rs b/source/benoit/benoit/application/poll_events.rs index a83678d..42e9c55 100644 --- a/source/benoit/benoit/application/poll_events.rs +++ b/source/benoit/benoit/application/poll_events.rs @@ -45,6 +45,7 @@ impl Application { match scancode { Scancode::Escape => return true, + Scancode::X => self.dump_image(), _ => {}, } @@ -74,7 +75,7 @@ impl Application { _ => self.maximum_iteration_count, }; - self.do_render = match scancode { + self.do_draw = match scancode { Scancode::A => true, Scancode::D => true, Scancode::E => true, diff --git a/source/benoit/benoit/application/render.rs b/source/benoit/benoit/application/render.rs index ec6c582..becf95b 100644 --- a/source/benoit/benoit/application/render.rs +++ b/source/benoit/benoit/application/render.rs @@ -23,106 +23,57 @@ use crate::benoit::application::Application; -extern crate sdl2; - -use sdl2::pixels::Color; -use sdl2::rect::Rect; use std::slice; use std::thread::{JoinHandle, spawn}; use std::time::Instant; use std::ptr::addr_of_mut; impl Application { - pub fn render(&mut self) { + pub fn render(&mut self, buffer: &mut [u32]) { eprintln!("rendering: {}{:+}i ({}x) @ ({})", self.position_x, self.position_y, self.zoom, self.maximum_iteration_count); - let canvas_size = self.canvas_height * self.canvas_width; - - let mut data = vec![0x0; canvas_size as usize]; - let mut threads = Vec::<JoinHandle<()>>::with_capacity(self.thread_count as usize); let time_start = Instant::now(); 'render_loop: { + let get_slice = |buffer: &mut [u32], y: u32, canvas_width: u32| -> &mut [u32] { + let slice_start = y as usize * canvas_width as usize; + let slice = unsafe { slice::from_raw_parts_mut(addr_of_mut!(buffer[slice_start]), canvas_width as usize) }; + + return slice; + }; + + let canvas_width = self.canvas_width; + let canvas_height = self.canvas_height; + let position_x = self.position_x; + let position_y = self.position_y; + let zoom = self.zoom; + let maximum_iteration_count = self.maximum_iteration_count; + let mut y: u32 = 0x0; for _thread in 0x0..self.thread_count { if y == self.canvas_height { break 'render_loop; } - let slice_start = y as usize * self.canvas_width as usize; - let data_slice = unsafe { slice::from_raw_parts_mut(addr_of_mut!(data[slice_start]), self.canvas_width as usize) }; - - let canvas_width = self.canvas_width; - let canvas_height = self.canvas_height; - let position_x = self.position_x; - let position_y = self.position_y; - let zoom = self.zoom; - let maximum_iteration_count = self.maximum_iteration_count; + let buffer_slice = get_slice(buffer, y, self.canvas_width); - threads.push(spawn(move || { Application::render_row(data_slice, y, canvas_width, canvas_height, position_x, position_y, zoom, maximum_iteration_count) })); + threads.push(spawn(move || { Application::render_row(buffer_slice, y, canvas_width, canvas_height, position_x, position_y, zoom, maximum_iteration_count) })); y += 0x1; } for y in 0x0..self.canvas_height { - threads.remove(0x0).join(); + threads.remove(0x0).join().unwrap(); - let slice_start = y as usize * self.canvas_width as usize; - let data_slice = unsafe { slice::from_raw_parts_mut(addr_of_mut!(data[slice_start]), self.canvas_width as usize) }; + let buffer_slice = get_slice(buffer, y, self.canvas_width); - let canvas_width = self.canvas_width; - let canvas_height = self.canvas_height; - let position_x = self.position_x; - let position_y = self.position_y; - let zoom = self.zoom; - let maximum_iteration_count = self.maximum_iteration_count; - - threads.push(spawn(move || { Application::render_row(data_slice, y, canvas_width, canvas_height, position_x, position_y, zoom, maximum_iteration_count) })); + threads.push(spawn(move || { Application::render_row(buffer_slice, y, canvas_width, canvas_height, position_x, position_y, zoom, maximum_iteration_count) })); } } let duration = time_start.elapsed(); - for thread in threads { - thread.join().unwrap(); - } - - for pixel in 0x0..canvas_size { - let y = pixel as u32 / self.canvas_width; - let x = pixel as u32 - y * self.canvas_width; - - let iteration_count = data[pixel as usize]; - - let factor = { - let factor = iteration_count as f32 / 64.0 % 1.0; - - (if factor >= 1.0 / 2.0 { - 1.0 - factor - } else { - factor - }) * 2.0 - }; - - let value: u8 = if iteration_count != self.maximum_iteration_count { - (factor * 255.0).round() as u8 - } else { - 0x0 - }; - let colour = Color::RGB(value, value, value); - self.canvas.set_draw_color(colour); - - let rectangle = Rect::new( - (x * self.scale) as i32, - (y * self.scale) as i32, - self.scale, - self.scale - ); - self.canvas.fill_rects(&[rectangle]).unwrap(); - } - - self.canvas.present(); - eprintln!("done ({}ms)", duration.as_millis()); } } diff --git a/source/benoit/benoit/application/run.rs b/source/benoit/benoit/application/run.rs index a0f9c27..393918a 100644 --- a/source/benoit/benoit/application/run.rs +++ b/source/benoit/benoit/application/run.rs @@ -32,10 +32,10 @@ impl Application { loop { if self.poll_events(&mut event_pump) { break } - if self.do_render { - self.render(); + if self.do_draw { + self.draw(); - self.do_render = false; + self.do_draw = false; } } } |