summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs185
-rw-r--r--src/reader.rs56
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)
+ }
+}