123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- use std::fs::File;
- use std::io::BufReader;
- use std::io::Read;
- // ┏━┓┏━┓┏┓╻╺┳┓┏━┓┏┳┓ ┏┓╻╻ ╻┏┳┓┏┓ ┏━╸┏━┓ ┏━╸┏━╸┏┓╻┏━╸┏━┓┏━┓╺┳╸╻┏━┓┏┓╻
- // ┣┳┛┣━┫┃┗┫ ┃┃┃ ┃┃┃┃ ┃┗┫┃ ┃┃┃┃┣┻┓┣╸ ┣┳┛ ┃╺┓┣╸ ┃┗┫┣╸ ┣┳┛┣━┫ ┃ ┃┃ ┃┃┗┫
- // ╹┗╸╹ ╹╹ ╹╺┻┛┗━┛╹ ╹ ╹ ╹┗━┛╹ ╹┗━┛┗━╸╹┗╸ ┗━┛┗━╸╹ ╹┗━╸╹┗╸╹ ╹ ╹ ╹┗━┛╹ ╹
- pub struct RNG {
- random_device: BufReader<File>,
- }
- impl RNG {
- pub fn next_float(&mut self) -> f32 {
- let mut buf: [u8; 4] = [0, 0, 0, 0];
- self.random_device
- .read(&mut buf)
- .expect("Read from /dev/random failed");
- let val: f32 = u32::from_be_bytes(buf) as f32;
- val as f32 / u32::max_value() as f32
- }
- pub fn create() -> RNG {
- let f = File::open("/dev/urandom").expect("Did not find source of randomness");
- let reader: BufReader<File> = BufReader::new(f);
- return RNG {
- random_device: reader,
- };
- }
- }
- // ┏━╸┏━╸┏━┓┏┳┓┏━╸╺┳╸┏━┓╻ ╻
- // ┃╺┓┣╸ ┃ ┃┃┃┃┣╸ ┃ ┣┳┛┗┳┛
- // ┗━┛┗━╸┗━┛╹ ╹┗━╸ ╹ ╹┗╸ ╹
- #[derive(Copy, Clone)]
- pub struct Vec3 {
- x: f32,
- y: f32,
- z: f32,
- }
- // ╻┏┳┓┏━┓┏━╸┏━╸ ╻┏━┓
- // ┃┃┃┃┣━┫┃╺┓┣╸ ┃┃ ┃
- // ╹╹ ╹╹ ╹┗━┛┗━╸ ╹┗━┛
- use std::convert::From;
- use std::io::BufWriter;
- use std::io::Write;
- use std::path::Path;
- pub struct Image {
- width: u16,
- height: u16,
- data: Vec<Vec3>,
- }
- impl Image {
- fn get_pixel(&self, x: usize, y: usize) -> &Vec3 {
- &self.data[y * self.width as usize + x]
- }
- fn mod_pixel(&mut self, x: usize, y: usize) -> &mut Vec3 {
- &mut self.data[y * self.width as usize + x]
- }
- 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,
- }
- }
- }
- 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(())
- }
- fn save_bmp(p: &Path, i: &Image) -> 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, i.width as u32)?;
- write_int(&mut w, i.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..i.height).rev() {
- for x in 0..i.width {
- write_vec3(&mut w, i.get_pixel(x.into(), y.into()))?;
- }
- }
- Ok(())
- }
- fn main() {
- let mut rng = RNG::create();
- println!("{}", rng.next_float());
- let path = Path::new("skymap.bmp");
- let image = load_bmp(&path);
- println!(
- "Image length: {}, {}x{}",
- image.data.len(),
- image.width,
- image.height
- );
- let pix = image.get_pixel(0, 0);
- println!("RGB Val: ({}, {}, {})", pix.x, pix.y, pix.z);
- // Create a new pixel from scratch
- let mut rand_bitmap = Image::new(1024, 1024);
- for x in 0..1024 {
- for y in 0..1024 {
- let mut p = rand_bitmap.mod_pixel(x, y);
- p.x = rng.next_float() * 255.0;
- p.y = rng.next_float() * 255.0;
- p.z = rng.next_float() * 255.0;
- }
- }
- let outpath = Path::new("random.bmp");
- save_bmp(&outpath, &rand_bitmap).expect("Could not save bitmap :(");
- }
|