1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
extern crate lodepng;
extern crate rgb;

use crate::color::*;
use rgb::*;

/// Uncompressed bitmap image, typically loaded from PNG files.
pub struct Image {
	pub buffer: Vec<u8>,
	pub width: usize,
	pub height: usize,
}

impl Image {

	pub fn default() -> Image {
		let mut img = Image {
			buffer: Vec::new(),
			width: 1,
			height: 1,
		};

		// Blank pixel (RGBA 4 Bytes)
		img.buffer.push(0);
		img.buffer.push(0);
		img.buffer.push(0);
		img.buffer.push(0);
		img
	}

	pub fn new_with_size(width: usize, height: usize) -> Image {
		Image {
			buffer: vec![0; width * height * 4],
			width,
			height,
		}
	}

	/// Create a new image and load from disk. Only supports PNG files.
	pub fn new(path_to: &str) -> Image {
		match lodepng::decode32_file(path_to) {
			Ok(image) => {
				//println!("Image: {}, Res: {} x {}, Size: {}B", path_to, image.width, image.height, image.buffer.len());
				let buffer_new: Vec<u8> =  image.buffer.as_bytes().to_vec();

				return Image {
					buffer: buffer_new,
					width: image.width,
					height: image.height,
				}
			},
			Err(reason) => {
				println!("ASERROR - IMAGE: Could not load | {}", reason);
				return Image::default();
			}
		};
	}

	/// Change a pixel color in the image.
	pub fn pset(&mut self, x: i32, y: i32, color: Color) {
		if self.buffer.len() > 0 {
			let idx: usize = ((y * (self.width as i32) + x) * 4) as usize;
        
			let out_left: bool = x < 0;
			let out_right: bool = x > (self.width) as i32 - 1;
			let out_top: bool = y < 0;
			let out_bottom: bool = y > (self.height) as i32 - 1;
			let out_of_range: bool = idx > (self.width * self.height * 4) - 1;

			if out_of_range || out_left || out_right || out_top || out_bottom  { return; }

			self.buffer[idx + 0] = color.r;  // R
			self.buffer[idx + 1] = color.g;  // G
			self.buffer[idx + 2] = color.b;  // B
			self.buffer[idx + 3] = color.a;  // A
			
		} else {
			println!("ASERROR - IMAGE: Buffer is not initialized. Did you remember to use load()?");
		}
	}

	/// Get a pixel color from the image.
	pub fn pget(&self, x: i32, y: i32) -> Color {
		if self.buffer.len() > 0 {
			let idx: usize = ((y * (self.width as i32) + x) as usize) * 4;

			let out_left: bool = x < 0;
			let out_right: bool = x > (self.width) as i32 - 1;
			let out_top: bool = y < 0;
			let out_bottom: bool = y > (self.height) as i32 - 1;
			let out_of_range: bool = idx > (self.width * self.height * 4) - 1;

			if out_of_range || out_left || out_right || out_top || out_bottom  { return Color::clear(); }

			return Color::new(
				self.buffer[idx + 0],
				self.buffer[idx + 1],
				self.buffer[idx + 2],
				self.buffer[idx + 3]
			);
		} else {
			println!("ASERROR - IMAGE: Buffer is not initialized. Did you remember to use load()?");
			Color::black()
		}
	}
}