123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- // ╻┏┳┓┏━┓┏━╸┏━╸ ╻┏━┓
- // ┃┃┃┃┣━┫┃╺┓┣╸ ┃┃ ┃
- // ╹╹ ╹╹ ╹┗━┛┗━╸ ╹┗━┛
- use std::fs::File;
- use std::io::BufReader;
- use std::io::Read;
- use std::convert::From;
- use std::io::BufWriter;
- use std::io::Write;
- use std::path::Path;
- use crate::geometry::Vec3;
- pub struct Image {
- width: u16,
- height: u16,
- data: Vec<Vec3>,
- }
- impl Image {
- pub fn get_pixel(&self, x: usize, y: usize) -> &Vec3 {
- &self.data[y * self.width as usize + x]
- }
- pub fn mod_pixel(&mut self, x: usize, y: usize) -> &mut Vec3 {
- &mut self.data[y * self.width as usize + x]
- }
- pub fn new(width: u16, height: u16) -> Image {
- let mut data: Vec<Vec3> = Vec::new();
- data.resize(
- usize::from(width) * usize::from(height),
- Vec3 {
- x: 0.0,
- y: 0.0,
- z: 0.0,
- },
- );
- Image {
- width: width,
- height: height,
- data: data,
- }
- }
- pub fn save_bmp(self: &Image, p: &Path) -> std::io::Result<()> {
- let f: File = File::create(p)?;
- let mut w = BufWriter::new(f);
- // File header
- w.write_all(&['B' as u8, 'M' as u8])?;
- write_int(&mut w, 0)?; // size, left blank for now
- write_int(&mut w, 0)?; // reserved bytes
- write_int(&mut w, 54)?; // offset
- // Bitmap info header
- write_int(&mut w, 40)?; // header size in bytes
- write_int(&mut w, self.width as u32)?;
- write_int(&mut w, self.height as u32)?;
- write_int16(&mut w, 1)?; // number of color planes
- write_int16(&mut w, 24)?; // bits per pixel
- write_int(&mut w, 0)?; // no compression
- write_int(&mut w, 0)?; // image size
- write_int(&mut w, 1000)?; // horizontal resolution in pixels per metre
- write_int(&mut w, 1000)?; // vertical resolution
- write_int(&mut w, 0)?; // number of colors
- write_int(&mut w, 0)?; // number of important colors
- // Pixel data
- for y in (0..self.height).rev() {
- for x in 0..self.width {
- write_vec3(&mut w, self.get_pixel(x.into(), y.into()))?;
- }
- }
- Ok(())
- }
- }
- fn read_int(v: &[u8]) -> u32 {
- let mut result = 0;
- for i in 0..3 {
- result |= (v[i] as u32) << (i * 8);
- }
- result
- }
- fn read_int16(v: &[u8]) -> u16 {
- v[1] as u16 >> 8 | v[0] as u16
- }
- fn read_vec3(v: &[u8]) -> Vec3 {
- Vec3 {
- x: v[2] as f32,
- y: v[1] as f32,
- z: v[0] as f32,
- }
- }
- fn round_row_size(width: u32) -> u32 {
- ((24 * width + 31) / 32) * 4
- }
- pub fn load_bmp(path: &Path) -> Image {
- // See https://en.wikipedia.org/wiki/BMP_file_format for more information.
- // BMP is little-endian (least-significant bytes first)
- // Some limitations here:
- // - we only support bottom-up bitmaps
- // - without compression
- // - and a depth of 24 bits per pixel
- let mut buf = Vec::new();
- let mut f = BufReader::new(File::open(path).expect("Could not find image file"));
- f.read_to_end(&mut buf).expect("Could not read image file");
- assert!(
- buf[0] == 'B' as u8 && buf[1] == 'M' as u8,
- "File is not a bitmap file"
- );
- let width = read_int(&buf[18..22]);
- let height = read_int(&buf[22..26]);
- let compression = read_int(&buf[30..34]);
- assert!(compression == 0, "Only uncompressed BMPs are supported");
- let depth = read_int16(&buf[28..30]);
- assert!(depth == 24, "Only 24 bits per pixel are supported");
- let offset = read_int(&buf[10..14]);
- let row_size = round_row_size(width);
- let mut image_data = Vec::new();
- for row in 0..height {
- for col in 0..width {
- let y = height - row - 1;
- let x = 3 * col;
- let idx = (offset + y * row_size + x) as usize;
- let pixel = read_vec3(&buf[idx..(idx + 3)]);
- image_data.push(pixel);
- }
- }
- assert!(image_data.len() == (width * height) as usize);
- Image {
- width: width as u16,
- height: height as u16,
- data: image_data,
- }
- }
- fn write_int(f: &mut dyn Write, v: u32) -> std::io::Result<()> {
- let bytes = [v as u8, (v >> 8) as u8, (v >> 16) as u8, (v >> 24) as u8];
- f.write_all(&bytes)?;
- Ok(())
- }
- fn write_int16(f: &mut dyn Write, v: u16) -> std::io::Result<()> {
- let bytes = [v as u8, (v >> 8) as u8];
- f.write_all(&bytes)?;
- Ok(())
- }
- fn write_vec3(f: &mut dyn Write, v: &Vec3) -> std::io::Result<()> {
- let bytes = [v.z as u8, v.y as u8, v.x as u8];
- f.write_all(&bytes)?;
- Ok(())
- }
|