diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.rs | 185 | ||||
| -rw-r--r-- | src/reader.rs | 56 |
2 files changed, 241 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..c348e77 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,185 @@ +// #![allow(dead_code)] + +use crate::reader::FileReader; +use std::{fs::File, io::BufReader, ops::{self}}; + +mod reader; + +// #[derive(Debug)] +// struct RGB<T: Add<Output = T> + Copy> +// { +// r: T, +// g: T, +// b: T +// } + +trait ColorDepth: Clone +{ + const DEFAULT: Self; +} +impl ColorDepth for u8 { + const DEFAULT: Self = 0; +} +impl ColorDepth for u16 { + const DEFAULT: Self = 0; +} +impl ColorDepth for u32 { + const DEFAULT: Self = 0; +} + +#[derive(Debug, Clone)] +struct RGBA<T: ColorDepth> +{ + r: T, + g: T, + b: T, + a: T +} +#[derive(Debug, Clone)] +struct RGB<T: ColorDepth> +{ + r: T, + g: T, + b: T, +} + +trait ColorType: Clone +{ + const DEFAULT: Self; +} +impl<T: ColorDepth> ColorType for RGBA<T> +{ + const DEFAULT: Self = Self { r: T::DEFAULT, g: T::DEFAULT, b: T::DEFAULT, a: T::DEFAULT }; +} +impl<T: ColorDepth> ColorType for RGB<T> +{ + const DEFAULT: Self = Self { r: T::DEFAULT, g: T::DEFAULT, b: T::DEFAULT}; +} + +#[derive(Debug)] +struct PixelArr<T: ColorType> +{ + width: u32, + height: u32, + raw: Vec<T> +} +impl<T: ColorType> PixelArr<T> { + fn new(width: u32, height: u32) -> Self { + let raw = vec![T::DEFAULT;(width*height) as usize]; + Self { width, height, raw } + } +} +impl<T: ColorType> ops::Index<(usize, usize)> for PixelArr<T> +{ + type Output = T; + + fn index(&self, index: (usize, usize)) -> &Self::Output { + let (x, y) = index; + &self.raw[x + y*(self.width as usize)] + } +} +impl<T: ColorType> ops::IndexMut<(usize, usize)> for PixelArr<T> +{ + fn index_mut(&mut self, index: (usize, usize)) -> &mut T { + let (x, y) = index; + &mut self.raw[x + y*(self.width as usize)] + } +} + +#[derive(Debug)] +struct ImageBase +{ + width: u32, + height: u32, + bit_depth: u8, + pixels: PixelArr<RGB<u8>> +} + +struct BMPImage +{ +} + + +trait Image +{ + fn read_image(reader: &mut FileReader) -> Result<ImageBase, &'static str>; +} + +impl Image for BMPImage +{ + fn read_image(reader: &mut FileReader) -> Result<ImageBase, &'static str> + { + let magic: [u8; 2] = reader.read_array(); + if magic != [0x42, 0x4d] + { + return Err("Not a bitmap!"); + } + + let _file_size: u32 = reader.read(); + reader.skip(4); + let _offset: u32 = reader.read(); + + let header_size: u32 = reader.read(); + + // println!("File header: {file_size} {offset} {header_size}"); + + if header_size == 40 + { + + let width: u32 = reader.read(); + let height: u32 = reader.read(); + let _color_planes: u16 = reader.read(); + let bpp = reader.read::<2, u16>() as u8; + let compression_method: u32 = reader.read(); + let _image_size: u32 = reader.read(); + let _horr_res: u32 = reader.read(); + let _vert_res: u32 = reader.read(); + let _color_count: u32 = reader.read(); + let _impotant_color_count: u32 = reader.read(); + + if + bpp != 24 + || compression_method != 0 + { + return Err("bpp or compresssion method not supported") + } + + let row_size = (((bpp as u32) * width + 31)/32) * 4; + let skip: usize = (row_size - width * 3) as usize; + let mut pixel_arr = PixelArr::new(width, height); + for y in (0..height).rev() + { + for x in 0..width + { + let mut pixel = RGB::DEFAULT; + pixel.b = reader.read(); + pixel.g = reader.read(); + pixel.r = reader.read(); + pixel_arr[(x as usize, y as usize)] = pixel; + } + reader.skip(skip); + } + + return Ok(ImageBase + { + width, + height, + bit_depth: bpp, + pixels: pixel_arr, + }) + } + else + { + return Err("Header size not supported yet"); + } + + + } +} + +fn main() { + let file = File::open("smiley.bmp").expect("File does not exist"); + let mut reader = FileReader::new(BufReader::new(file)); + let _bmp = BMPImage::read_image(&mut reader).expect("Bitmap had error"); + // println!("{bmp:?}"); +} diff --git a/src/reader.rs b/src/reader.rs new file mode 100644 index 0000000..affd2da --- /dev/null +++ b/src/reader.rs @@ -0,0 +1,56 @@ +use std::{fs::File, io::{BufReader, Read}}; + +pub struct FileReader<const BUFF_SIZE: usize = 1024> +{ + buf_reader: BufReader<File> +} + +impl<const BUFF_SIZE: usize> FileReader<BUFF_SIZE> { + pub fn new(buf_reader: BufReader<File>) -> Self + { + Self + { + buf_reader + } + } + + pub fn skip(&mut self, c: usize) + { + self.buf_reader.seek_relative(c as i64).expect("Cannot seek!"); + } + pub fn read_array<const N: usize, T: FromBytes<N> + Sized, const C: usize>(&mut self) -> [T; C] + { + std::array::from_fn(|_| self.read()) + } + + pub fn read<const N: usize, T: FromBytes<N> + Sized>(&mut self) -> T + { + let mut data = [0u8; N]; + self.buf_reader.read_exact(&mut data).expect("Bad read"); + T::from_le_bytes(&data) + } +} + +pub trait FromBytes<const N: usize>: Sized +{ + fn from_le_bytes(buffer: &[u8; N]) -> Self; +} + +impl FromBytes<4> for u32 +{ + fn from_le_bytes(buffer: &[u8; 4]) -> Self { + u32::from_le_bytes(*buffer) + } +} +impl FromBytes<2> for u16 +{ + fn from_le_bytes(buffer: &[u8; 2]) -> Self { + u16::from_le_bytes(*buffer) + } +} +impl FromBytes<1> for u8 +{ + fn from_le_bytes(buffer: &[u8; 1]) -> Self { + u8::from_le_bytes(*buffer) + } +} |
