show_image/
image_info.rs

1/// Information describing the binary data of an image.
2#[derive(Debug, Clone, Copy, Eq, PartialEq)]
3pub struct ImageInfo {
4	/// The pixel format of the image data.
5	pub pixel_format: PixelFormat,
6
7	/// The size of the image in pixels
8	pub size: glam::UVec2,
9
10	/// The stride of the image data in bytes for both X and Y.
11	pub stride: glam::UVec2,
12}
13
14/// Supported pixel formats.
15#[derive(Copy, Clone, Debug, Eq, PartialEq)]
16pub enum PixelFormat {
17	/// 8-bit monochrome data.
18	Mono8,
19
20	/// 8-bit monochrome data with alpha.
21	MonoAlpha8(Alpha),
22
23	/// Interlaced 8-bit BGR data.
24	Bgr8,
25
26	/// Interlaced 8-bit BGRA data.
27	Bgra8(Alpha),
28
29	/// Interlaced 8-bit RGB data.
30	Rgb8,
31
32	/// Interlaced 8-bit RGBA data.
33	Rgba8(Alpha),
34}
35
36/// Possible alpha representations.
37///
38/// See also: <https://en.wikipedia.org/wiki/Alpha_compositing#Straight_versus_premultiplied>
39#[derive(Copy, Clone, Debug, Eq, PartialEq)]
40pub enum Alpha {
41	/// The alpha channel is encoded only in the alpha component of the pixel.
42	Unpremultiplied,
43
44	/// The alpha channel is also premultiplied into the other components of the pixel.
45	Premultiplied,
46}
47
48impl ImageInfo {
49	/// Create a new info struct with the given format, width and height.
50	///
51	/// The row stride is automatically calculated based on the image width and pixel format.
52	/// If you wish to use a different row stride, construct the struct directly.
53	pub fn new(pixel_format: PixelFormat, width: u32, height: u32) -> Self {
54		let stride_x = u32::from(pixel_format.bytes_per_pixel());
55		let stride_y = stride_x * width;
56		Self {
57			pixel_format,
58			size: glam::UVec2::new(width, height),
59			stride: glam::UVec2::new(stride_x, stride_y),
60		}
61	}
62
63	/// Create a new info struct for an 8-bit monochrome image with the given width and height.
64	pub fn mono8(width: u32, height: u32) -> Self {
65		Self::new(PixelFormat::Mono8, width, height)
66	}
67
68	/// Create a new info struct for an 8-bit monochrome image with with alpha channel and the given width and height.
69	pub fn mono_alpha8(width: u32, height: u32) -> Self {
70		Self::new(PixelFormat::MonoAlpha8(Alpha::Unpremultiplied), width, height)
71	}
72
73	/// Create a new info struct for an 8-bit monochrome image with premultiplied alpha channel and the given width and height.
74	pub fn mono_alpha8_premultiplied(width: u32, height: u32) -> Self {
75		Self::new(PixelFormat::MonoAlpha8(Alpha::Premultiplied), width, height)
76	}
77
78	/// Create a new info struct for an 8-bit BGR image with the given width and height.
79	pub fn bgr8(width: u32, height: u32) -> Self {
80		Self::new(PixelFormat::Bgr8, width, height)
81	}
82
83	/// Create a new info struct for an 8-bit BGRA image with the given width and height.
84	pub fn bgra8(width: u32, height: u32) -> Self {
85		Self::new(PixelFormat::Bgra8(Alpha::Unpremultiplied), width, height)
86	}
87
88	/// Create a new info struct for an 8-bit BGRA image with premultiplied alpha channel and the given width and height.
89	pub fn bgra8_premultiplied(width: u32, height: u32) -> Self {
90		Self::new(PixelFormat::Bgra8(Alpha::Premultiplied), width, height)
91	}
92
93	/// Create a new info struct for an 8-bit RGB image with the given width and height.
94	pub fn rgb8(width: u32, height: u32) -> Self {
95		Self::new(PixelFormat::Rgb8, width, height)
96	}
97
98	/// Create a new info struct for an 8-bit RGBA image with the given width and height.
99	pub fn rgba8(width: u32, height: u32) -> Self {
100		Self::new(PixelFormat::Rgba8(Alpha::Unpremultiplied), width, height)
101	}
102
103	/// Create a new info struct for an 8-bit RGBA image with premultiplied alpha channel and the given width and height.
104	pub fn rgba8_premultiplied(width: u32, height: u32) -> Self {
105		Self::new(PixelFormat::Rgba8(Alpha::Premultiplied), width, height)
106	}
107
108	/// Get the image size in bytes.
109	pub fn byte_size(self) -> u64 {
110		if self.stride.y >= self.stride.x {
111			u64::from(self.stride.y) * u64::from(self.size.y)
112		} else {
113			u64::from(self.stride.x) * u64::from(self.size.x)
114		}
115	}
116}
117
118impl PixelFormat {
119	/// Get the number of channels.
120	pub fn channels(self) -> u8 {
121		match self {
122			PixelFormat::Mono8 => 1,
123			PixelFormat::MonoAlpha8(_) => 1,
124			PixelFormat::Bgr8 => 3,
125			PixelFormat::Bgra8(_) => 4,
126			PixelFormat::Rgb8 => 3,
127			PixelFormat::Rgba8(_) => 4,
128		}
129	}
130
131	/// Get the bytes per channel.
132	const fn byte_depth(self) -> u8 {
133		1
134	}
135
136	/// Get the bytes per pixel.
137	pub fn bytes_per_pixel(self) -> u8 {
138		self.byte_depth() * self.channels()
139	}
140
141	/// Get the alpha representation of the pixel format.
142	///
143	/// Returns [`None`], if the pixel format has no alpha channel.
144	pub fn alpha(self) -> Option<Alpha> {
145		match self {
146			PixelFormat::Mono8 => None,
147			PixelFormat::MonoAlpha8(a) => Some(a),
148			PixelFormat::Bgr8 => None,
149			PixelFormat::Bgra8(a) => Some(a),
150			PixelFormat::Rgb8 => None,
151			PixelFormat::Rgba8(a) => Some(a),
152		}
153	}
154}