1use crate::sample::SampleType;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
7#[non_exhaustive]
8pub enum PixelLayout {
9 Rgb,
11 Rgba,
13 Gray,
15}
16
17impl PixelLayout {
18 #[must_use]
20 pub const fn channels(self) -> usize {
21 match self {
22 Self::Rgb => 3,
23 Self::Rgba => 4,
24 Self::Gray => 1,
25 }
26 }
27}
28
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31#[non_exhaustive]
32pub enum PixelFormat {
33 Rgb8,
35 Rgba8,
37 Gray8,
39 Rgb16,
41 Rgba16,
43 Gray16,
45 RgbI16,
47 RgbaI16,
49 GrayI16,
51}
52
53impl PixelFormat {
54 #[must_use]
56 pub const fn layout(self) -> PixelLayout {
57 match self {
58 Self::Rgb8 | Self::Rgb16 | Self::RgbI16 => PixelLayout::Rgb,
59 Self::Rgba8 | Self::Rgba16 | Self::RgbaI16 => PixelLayout::Rgba,
60 Self::Gray8 | Self::Gray16 | Self::GrayI16 => PixelLayout::Gray,
61 }
62 }
63
64 #[must_use]
66 pub const fn sample(self) -> SampleType {
67 match self {
68 Self::Rgb8 | Self::Rgba8 | Self::Gray8 => SampleType::U8,
69 Self::Rgb16 | Self::Rgba16 | Self::Gray16 => SampleType::U16,
70 Self::RgbI16 | Self::RgbaI16 | Self::GrayI16 => SampleType::I16,
71 }
72 }
73
74 #[must_use]
76 pub const fn channels(self) -> usize {
77 self.layout().channels()
78 }
79
80 #[must_use]
82 pub const fn bytes_per_sample(self) -> usize {
83 match self.sample() {
84 SampleType::U8 => 1,
85 SampleType::U16 | SampleType::I16 => 2,
86 }
87 }
88
89 #[must_use]
91 pub const fn bytes_per_pixel(self) -> usize {
92 self.channels() * self.bytes_per_sample()
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::{PixelFormat, PixelLayout};
99 use crate::SampleType;
100
101 #[test]
102 fn signed_sixteen_bit_formats_preserve_layout_and_size() {
103 for (format, layout, channels) in [
104 (PixelFormat::RgbI16, PixelLayout::Rgb, 3),
105 (PixelFormat::RgbaI16, PixelLayout::Rgba, 4),
106 (PixelFormat::GrayI16, PixelLayout::Gray, 1),
107 ] {
108 assert_eq!(format.layout(), layout);
109 assert_eq!(format.sample(), SampleType::I16);
110 assert_eq!(format.channels(), channels);
111 assert_eq!(format.bytes_per_sample(), 2);
112 assert_eq!(format.bytes_per_pixel(), channels * 2);
113 }
114 }
115}