organicomplex 0.7.0

Interactive complex-valued cellular automaton on 2D and 3D grids in search of that stuff - emergence, open-endedness, organicity etc.
// use image::Pixel;

// use crate::base::BASE_DIR;

use super::System;

#[derive(Clone)]
pub struct Image{
    width: i32,
    height: i32,
    buffer: Vec<u8>
}

impl Image {
    pub fn make(width: i32, height: i32, buffer: Vec<u8>) -> Self {
        Self{width, height, buffer}
    }
/*
	pub fn load(base_filepath: impl ToString) -> Result<Self, String> {
		let base_filepath = base_filepath.to_string();

		match image::open(format!("{}/{}", BASE_DIR, base_filepath)) {
			Ok(img_buf) => {
				let img_buf = img_buf.into_rgba8();

				let width: i32 = img_buf.dimensions().0 as i32;
				let height: i32 = img_buf.dimensions().1 as i32;
				let mut buffer: Vec<u8> = vec![0; ((width as usize) * (height as usize)) << 2];

				let mut offs: usize = 0;
				for y in 0..height {
					for x in 0..width {
						let pixel = img_buf.get_pixel(x as u32, y as u32).to_rgba();
					
						buffer[offs + 3] = pixel[3]; // alpha
						buffer[offs + 2] = pixel[0]; // red
						buffer[offs + 1] = pixel[1]; // green
						buffer[offs] = pixel[2]; // blue

						offs += 4;
					}
				}

				Ok(Self{width, height, buffer})
			},
			Err(e) => Err(e.to_string())
		}
	}
*/
    pub fn width(&self) -> i32 {
        self.width
    }

    pub fn height(&self) -> i32 {
        self.height
    }

}

impl System {
	pub fn draw_image(&mut self, img: &Image, x: i32, y: i32) {
		let (width, height, scr_width, scr_height) = (img.width, img.height, self.width, self.height);
		if (x < scr_width) && (x + width > 0) && (y < scr_height) && (y + height > 0) { // intersects with screen
			// Corners of intersection in image's RF
			let (u0, v0) = (0i32.max(-x), 0i32.max(-y));
			let (u1, v1) = (width.min(scr_width - x), height.min(scr_height - y));

			let (y0, y1) = ((y + v0) as usize, (y + v1) as usize);

			let i2v_diff = v0 - (y0 as i32);

			let img_buf = &img.buffer;

			let row_offs_0 = ((x + u0) << 2) as usize;

			// Split into non-overlapping chunks (rows)
			let mut scr_rows: Vec<(usize, &mut [u8])> = self.buffer.chunks_mut((scr_width << 2) as usize)
				.enumerate()
				.collect();
			let scr_sub_rows = &mut scr_rows[y0..y1]; // rows intersecting with image
			// Parallelize by rayon iterator? slow if small images...
			// scr_sub_rows.into_par_iter().for_each(|(i, vb_row)| {
			scr_sub_rows.into_iter().for_each(|(i, vb_row)| {
				let v = (*i as i32) + i2v_diff;
				let mut img_offs = ((v * width + u0) << 2) as usize;
				let mut row_offs = row_offs_0;
				for _u in u0..u1 {
					let a = img_buf[img_offs + 3] as i32;
					let na = 0x100 - a;
					for i in 0..3 { // Compiler should unroll this...
						vb_row[row_offs + i] = (((img_buf[img_offs + i] as i32) * a + (vb_row[row_offs + i] as i32) * na) >> 8) as u8;
					}
					img_offs += 4;
					row_offs += 4;
				}
			});
		}
	}

}