From ac320b0513ec67b6c933569c3b11820641c6b198 Mon Sep 17 00:00:00 2001 From: Isabelle L Date: Tue, 16 Jun 2020 13:17:58 -0500 Subject: [PATCH] image rendering --- .gitignore | 1 + Cargo.toml | 1 + img.png | Bin 0 -> 105 bytes src/color.rs | 12 +++++++++++- src/img.rs | 34 ++++++++++++++++++++++++++++++++++ src/lib.rs | 39 +++++++++++++++++++++++++++++++-------- src/prelude.rs | 3 +++ 7 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 img.png create mode 100644 src/img.rs diff --git a/.gitignore b/.gitignore index 96ef6c0..726ce46 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target Cargo.lock +/src/main.rs \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 7281073..99f5d19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,4 @@ edition = "2018" [dependencies] minifb = {git = "https://github.com/emoon/rust_minifb" } thiserror = "1.0.19" +image = "0.23.5" diff --git a/img.png b/img.png new file mode 100644 index 0000000000000000000000000000000000000000..1aecb444d0c65f8808d13ebdaa3f25425969566b GIT binary patch literal 105 zcmeAS@N?(olHy`uVBq!ia0vp^tRT$61|)m))t&+=#^NA%Cx&(BWL^R}%APKcAsjQ4 zzr=5PY|ku}@JBwRPxHsu|J;v4HnFf+F6uU9V2F|D`S12KzZ|HX!PC{xWt~$(696T` B9s2+P literal 0 HcmV?d00001 diff --git a/src/color.rs b/src/color.rs index e2be827..7c358bc 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,4 +1,4 @@ -// a 32 bit rgb +/// an 8 bit rgb with built in conversion to u32 #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Color { pub r: u8, @@ -7,10 +7,20 @@ pub struct Color { } impl Color { + /// create a new color pub fn new(r: u8, g: u8, b: u8) -> Color { Color { r, g, b } } + /// return a color from a given u32 + pub fn from_u32(color: u32) -> Color { + let b = (color & 0xff) as u8; + let g = ((color >> 8) & 0xff) as u8; + let r = ((color >> 16) & 0xff) as u8; + Color { r, g, b } + } + + /// return color as a u32 structured 0bxxxx_rrrr_gggg_bbbb pub fn as_u32(&self) -> u32 { let (r, g, b) = (self.r as u32, self.g as u32, self.b as u32); (r << 16) | (g << 8) | b diff --git a/src/img.rs b/src/img.rs new file mode 100644 index 0000000..85e2fb0 --- /dev/null +++ b/src/img.rs @@ -0,0 +1,34 @@ +use crate::{Color, Result}; +use std::path::PathBuf; + +/// an image +pub struct Image { + width: usize, + height: usize, + data: Vec, +} + +impl Image { + /// load an image from a file + pub fn load(path: PathBuf) -> Result { + let (width, height) = image::image_dimensions(&path)?; + let (width, height) = (width as usize, height as usize); + let data: Vec = image::open(path)? + .into_rgb() + .pixels() + .map(|pixel| Color::new(pixel[0], pixel[1], pixel[2])) + .collect(); + + Ok(Image { width, height, data }) + } +} + +impl crate::Renderable for Image { + fn dimensions(&self) -> (usize, usize) { + (self.width, self.height) + } + + fn data(&self) -> &Vec { + &self.data + } +} diff --git a/src/lib.rs b/src/lib.rs index 72cd7b5..86abefc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,24 +1,36 @@ #![allow(dead_code)] // modules -pub mod color; +mod color; +mod img; pub mod prelude; // namespacing -use color::Color; +pub use color::Color; +pub use img::Image; pub use minifb::{Key, MouseButton}; use minifb::{Window, WindowOptions}; -// error type +/// error type #[derive(Debug, thiserror::Error)] pub enum Error { #[error(transparent)] MiniFb(#[from] minifb::Error), + #[error(transparent)] + Image(#[from] image::ImageError), } -// result type +/// result type pub type Result = std::result::Result; +/// renderable trait +pub trait Renderable { + /// return the dimensions of the structure + fn dimensions(&self) -> (usize, usize); + /// return a slice of row major data to be rendered + fn data(&self) -> &Vec; +} + // pixel buffer for internal use struct PixelBuffer { data: Vec, @@ -102,15 +114,26 @@ impl Context { /// !! this method can panic if the given buffer dimensions don't match the buffer length pub fn insert_slice(&mut self, x: usize, y: usize, w: usize, h: usize, slice: &[Color]) { assert!(w * h == slice.len()); + let (ox, oy) = (x, y); - for i in x..(x + w) { - for j in y..(y + h) { - let color = slice[w * (i - x) + (j - y)]; - self.insert_pixel(i, j, color); + for x in 0..w { + for y in 0..h { + self.insert_pixel(x + ox, y + oy, slice[y * w + x]) } } } + /// render a structure that impl's the renderable trait + pub fn render(&mut self, x: usize, y: usize, renderable: &T) + where + T: Renderable, + { + let (w, h) = renderable.dimensions(); + let slice = renderable.data(); + + self.insert_slice(x, y, w, h, &slice); + } + /// get mouse position pub fn get_mouse_pos(&self) -> Option<(f32, f32)> { self.window.get_mouse_pos(minifb::MouseMode::Discard) diff --git a/src/prelude.rs b/src/prelude.rs index 1d84fe1..e1b5da6 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,3 +1,6 @@ +//! namespacing for lazy people pub use crate::color::Color; +pub use crate::img::Image; pub use crate::Context; pub use crate::Result; +pub use minifb::{Key, MouseButton};