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
/// Information describing the binary data of an image.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ImageInfo {
	/// The width of the image in pixels.
	pub width: usize,

	/// The height of the image in pixels.
	pub height: usize,

	/// The row stride of the image data in bytes.
	///
	/// The data is assumed to be stored row-major.
	/// The stride is the byte offset between two rows in the data.
	pub row_stride: usize,

	/// The pixel format of the image data.
	pub pixel_format: PixelFormat,
}

/// Supported pixel formats.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum PixelFormat {
	/// Interlaced 8-bit RGB data.
	Rgb8,

	/// Interlaced 8-bit RGBA data.
	Rgba8,

	/// Interlaced 8-bit BGR data.
	Bgr8,

	/// Interlaced 8-bit BGRA data.
	Bgra8,

	/// 8-bit monochrome data.
	Mono8,
}

impl ImageInfo {
	/// Create a new info struct with the given format, width and height.
	///
	/// The row stride is automatically calculated based on the image width and pixel format.
	/// If you wish to use a different row stride, construct the struct directly.
	pub fn new(pixel_format: PixelFormat, width: usize, height: usize) -> Self {
		let row_stride = usize::from(pixel_format.bytes_per_pixel()) * width;
		Self { pixel_format, width, height, row_stride}
	}

	/// Create a new 8-bit RGB info struct with the given width and height.
	pub fn rgb8(width: usize, height: usize) -> Self {
		Self::new(PixelFormat::Rgb8, width, height)
	}

	/// Create a new 8-bit RGBA info struct with the given width and height.
	pub fn rgba8(width: usize, height: usize) -> Self {
		Self::new(PixelFormat::Rgba8, width, height)
	}

	/// Create a new 8-bit BGR info struct with the given width and height.
	pub fn bgr8(width: usize, height: usize) -> Self {
		Self::new(PixelFormat::Bgr8, width, height)
	}

	/// Create a new 8-bit BGRA info struct with the given width and height.
	pub fn bgra8(width: usize, height: usize) -> Self {
		Self::new(PixelFormat::Bgra8, width, height)
	}

	/// Create a new 8-bit monochrome info struct with the given width and height.
	pub fn mono8(width: usize, height: usize) -> Self {
		Self::new(PixelFormat::Mono8, width, height)
	}
}

impl PixelFormat {
	/// Get the number of channels.
	pub fn channels(self) -> u8 {
		match self {
			PixelFormat::Bgr8  => 3,
			PixelFormat::Bgra8 => 4,
			PixelFormat::Rgb8  => 3,
			PixelFormat::Rgba8 => 4,
			PixelFormat::Mono8 => 1,
		}
	}

	/// Get the bytes per channel.
	const fn byte_depth(self) -> u8 {
		1
	}

	/// Get the bytes per pixel.
	pub fn bytes_per_pixel(self) -> u8 {
		self.byte_depth() * self.channels()
	}
}