summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md7
-rw-r--r--Cargo.toml5
-rw-r--r--source/benoit/benoit/application.rs7
-rw-r--r--source/benoit/benoit/application/colour.rs54
-rw-r--r--source/benoit/benoit/application/draw.rs61
-rw-r--r--source/benoit/benoit/application/dump.rs49
-rw-r--r--source/benoit/benoit/application/initialise.rs2
-rw-r--r--source/benoit/benoit/application/poll_events.rs3
-rw-r--r--source/benoit/benoit/application/render.rs89
-rw-r--r--source/benoit/benoit/application/run.rs6
10 files changed, 205 insertions, 78 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 400b288..829e080 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,10 @@
+# 16
+
+* Clean up code
+* Support rendering to files
+* Depend on webp
+* Modulise code
+
# 15
* Render using multiple threads
diff --git a/Cargo.toml b/Cargo.toml
index 286bf07..4690167 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "benoit"
-version = "0.14.0"
+version = "0.18.0"
authors = ["Gabriel Bjørnager Jensen"]
edition = "2021"
description = "Mandelbrot renderer."
@@ -15,4 +15,5 @@ path = "source/benoit/main.rs"
lto = true
[dependencies]
-sdl2 = "0.35.2"
+sdl2 = "0.35.2"
+webp = "0.2.5"
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;
}
}
}