summaryrefslogtreecommitdiff
path: root/src/bmp.rs
diff options
context:
space:
mode:
authorDylan <boss@tehbox.org>2026-06-21 15:01:28 +1200
committerDylan <boss@tehbox.org>2026-06-21 15:03:02 +1200
commita472b1cdaa8a1f72b96988009b3d4d9820e7128f (patch)
tree833959761c3c1f60c60425bdc7553162cacb3f2d /src/bmp.rs
parent14de6db28fb689cdb066c5b01a2885b6a6a35157 (diff)
downloadtehimage-rs-a472b1cdaa8a1f72b96988009b3d4d9820e7128f.tar.gz
tehimage-rs-a472b1cdaa8a1f72b96988009b3d4d9820e7128f.zip
feat: Added bitmap writing
Diffstat (limited to 'src/bmp.rs')
-rw-r--r--src/bmp.rs107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/bmp.rs b/src/bmp.rs
new file mode 100644
index 0000000..f6c0c7e
--- /dev/null
+++ b/src/bmp.rs
@@ -0,0 +1,107 @@
+use crate::{image::{ColorType, Image, ImageBase, PixelArr, RGB}, reader::FileReader, writer::FileWriter};
+
+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
+ {
+ bit_depth: bpp,
+ pixels: pixel_arr,
+ })
+ }
+ else
+ {
+ return Err("Header size not supported yet");
+ }
+
+
+ }
+
+ fn write_image(image: &ImageBase, writer: &mut FileWriter) -> () {
+ writer.write_array([0x42, 0x4d] as [u8; 2]);
+
+ let row_size = (((24) * image.pixels.width + 31)/32) * 4;
+ let file_size: u32 = 14 + 12 + row_size*image.pixels.height;
+ let offset: u32 = 26;
+ writer.write(file_size as u32);
+ writer.write_zeros(4);
+ writer.write(offset as u32);
+ writer.write(12 as u32); // Header size
+
+ writer.write(image.pixels.width as u16);
+ writer.write(image.pixels.height as u16);
+ writer.write(1 as u16); // Color planes
+ writer.write(24 as u16); // bpp
+
+ let skip: usize = (row_size - image.pixels.width * 3) as usize;
+ for y in (0..image.pixels.height).rev()
+ {
+ for x in 0..image.pixels.width
+ {
+ let pixel = image.pixels[(x as usize, y as usize)];
+ writer.write(pixel.b);
+ writer.write(pixel.g);
+ writer.write(pixel.r);
+ }
+ writer.write_zeros(skip);
+ }
+ writer.flush();
+ }
+}
+
+
+pub struct BMPImage
+{
+}