#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PixelFormat {
Rgba8,
Rgb8,
Gray8,
GrayAlpha8,
}
impl PixelFormat {
pub fn bpp(self) -> usize {
match self {
PixelFormat::Rgba8 => 4,
PixelFormat::Rgb8 => 3,
PixelFormat::Gray8 => 1,
PixelFormat::GrayAlpha8 => 2,
}
}
pub fn channels(self) -> usize {
self.bpp()
}
pub fn stride(self, width: usize) -> usize {
width * self.bpp()
}
pub fn buffer_size(self, width: usize, height: usize) -> usize {
self.stride(width) * height
}
pub fn from_content_type(content_type: &str) -> Option<Self> {
match content_type {
"image/raw-rgba" => Some(PixelFormat::Rgba8),
"image/raw-rgb" => Some(PixelFormat::Rgb8),
"image/raw-gray" => Some(PixelFormat::Gray8),
"image/raw-gray-alpha" => Some(PixelFormat::GrayAlpha8),
_ => None,
}
}
pub fn content_type(self) -> &'static str {
match self {
PixelFormat::Rgba8 => "image/raw-rgba",
PixelFormat::Rgb8 => "image/raw-rgb",
PixelFormat::Gray8 => "image/raw-gray",
PixelFormat::GrayAlpha8 => "image/raw-gray-alpha",
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_bpp() {
assert_eq!(PixelFormat::Rgba8.bpp(), 4);
assert_eq!(PixelFormat::Rgb8.bpp(), 3);
assert_eq!(PixelFormat::Gray8.bpp(), 1);
assert_eq!(PixelFormat::GrayAlpha8.bpp(), 2);
}
#[test]
fn test_stride() {
assert_eq!(PixelFormat::Rgba8.stride(256), 1024);
assert_eq!(PixelFormat::Gray8.stride(100), 100);
}
#[test]
fn test_buffer_size() {
assert_eq!(PixelFormat::Rgba8.buffer_size(256, 256), 262144);
}
#[test]
fn test_content_type_roundtrip() {
for fmt in [
PixelFormat::Rgba8,
PixelFormat::Rgb8,
PixelFormat::Gray8,
PixelFormat::GrayAlpha8,
] {
let ct = fmt.content_type();
assert_eq!(PixelFormat::from_content_type(ct), Some(fmt));
}
}
}