Change BitDepth to u8 representation with TryFrom
This commit is contained in:
parent
873f0fefbe
commit
4e0cbbe973
8 changed files with 34 additions and 63 deletions
|
|
@ -1,6 +1,8 @@
|
|||
use rgb::{RGB16, RGBA8};
|
||||
use std::fmt;
|
||||
|
||||
use crate::PngError;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
/// The color type used to represent this image
|
||||
pub enum ColorType {
|
||||
|
|
@ -67,64 +69,40 @@ impl ColorType {
|
|||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
|
||||
/// The number of bits to be used per channel per pixel
|
||||
pub enum BitDepth {
|
||||
/// One bit per channel per pixel
|
||||
One,
|
||||
One = 1,
|
||||
/// Two bits per channel per pixel
|
||||
Two,
|
||||
Two = 2,
|
||||
/// Four bits per channel per pixel
|
||||
Four,
|
||||
Four = 4,
|
||||
/// Eight bits per channel per pixel
|
||||
Eight,
|
||||
Eight = 8,
|
||||
/// Sixteen bits per channel per pixel
|
||||
Sixteen,
|
||||
Sixteen = 16,
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for BitDepth {
|
||||
type Error = PngError;
|
||||
|
||||
fn try_from(value: u8) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
1 => Ok(Self::One),
|
||||
2 => Ok(Self::Two),
|
||||
4 => Ok(Self::Four),
|
||||
8 => Ok(Self::Eight),
|
||||
16 => Ok(Self::Sixteen),
|
||||
_ => Err(PngError::new("Unexpected bit depth")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for BitDepth {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
BitDepth::One => "1",
|
||||
BitDepth::Two => "2",
|
||||
BitDepth::Four => "4",
|
||||
BitDepth::Eight => "8",
|
||||
BitDepth::Sixteen => "16",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl BitDepth {
|
||||
/// Retrieve the number of bits per channel per pixel as a `u8`
|
||||
#[inline]
|
||||
pub fn as_u8(self) -> u8 {
|
||||
match self {
|
||||
BitDepth::One => 1,
|
||||
BitDepth::Two => 2,
|
||||
BitDepth::Four => 4,
|
||||
BitDepth::Eight => 8,
|
||||
BitDepth::Sixteen => 16,
|
||||
}
|
||||
}
|
||||
/// Parse a number of bits per channel per pixel into a `BitDepth`
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If depth is unsupported
|
||||
#[inline]
|
||||
pub fn from_u8(depth: u8) -> BitDepth {
|
||||
match depth {
|
||||
1 => BitDepth::One,
|
||||
2 => BitDepth::Two,
|
||||
4 => BitDepth::Four,
|
||||
8 => BitDepth::Eight,
|
||||
16 => BitDepth::Sixteen,
|
||||
_ => panic!("Unsupported bit depth"),
|
||||
}
|
||||
write!(f, "{}", *self as u8)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ impl IhdrData {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
pub fn bpp(&self) -> usize {
|
||||
(self.bit_depth.as_u8() * self.color_type.channels_per_pixel()) as usize
|
||||
self.bit_depth as usize * self.color_type.channels_per_pixel() as usize
|
||||
}
|
||||
|
||||
/// Byte length of IDAT that is correct for this IHDR
|
||||
|
|
@ -173,14 +173,7 @@ pub fn parse_ihdr_header(
|
|||
6 => ColorType::RGBA,
|
||||
_ => return Err(PngError::new("Unexpected color type in header")),
|
||||
},
|
||||
bit_depth: match byte_data[8] {
|
||||
1 => BitDepth::One,
|
||||
2 => BitDepth::Two,
|
||||
4 => BitDepth::Four,
|
||||
8 => BitDepth::Eight,
|
||||
16 => BitDepth::Sixteen,
|
||||
_ => return Err(PngError::new("Unexpected bit depth in header")),
|
||||
},
|
||||
bit_depth: byte_data[8].try_into()?,
|
||||
width: read_be_u32(&mut rdr).map_err(|_| PngError::TruncatedData)?,
|
||||
height: read_be_u32(&mut rdr).map_err(|_| PngError::TruncatedData)?,
|
||||
compression: byte_data[10],
|
||||
|
|
|
|||
|
|
@ -569,7 +569,7 @@ fn optimize_png(
|
|||
|
||||
if filters.is_empty() {
|
||||
// Pick a filter automatically
|
||||
if png.raw.ihdr.bit_depth.as_u8() >= 8 {
|
||||
if png.raw.ihdr.bit_depth as u8 >= 8 {
|
||||
// Bigrams is the best all-rounder when there's at least one byte per pixel
|
||||
filters.insert(RowFilter::Bigrams);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ impl PngData {
|
|||
ihdr_data
|
||||
.write_all(&self.raw.ihdr.height.to_be_bytes())
|
||||
.ok();
|
||||
ihdr_data.write_all(&[self.raw.ihdr.bit_depth.as_u8()]).ok();
|
||||
ihdr_data.write_all(&[self.raw.ihdr.bit_depth as u8]).ok();
|
||||
ihdr_data
|
||||
.write_all(&[self.raw.ihdr.color_type.png_header_code()])
|
||||
.ok();
|
||||
|
|
@ -165,7 +165,7 @@ impl PngData {
|
|||
match &self.raw.ihdr.color_type {
|
||||
ColorType::Indexed { palette } => {
|
||||
let mut palette_data = Vec::with_capacity(palette.len() * 3);
|
||||
let mut max_palette_size = 1 << (self.raw.ihdr.bit_depth.as_u8() as usize);
|
||||
let mut max_palette_size = 1 << (self.raw.ihdr.bit_depth as u8);
|
||||
// Ensure bKGD color doesn't get truncated from palette
|
||||
if let Some(&idx) = self.raw.aux_headers.get(b"bKGD").and_then(|b| b.first()) {
|
||||
max_palette_size = max_palette_size.max(idx as usize + 1);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ pub fn reduce_bit_depth(png: &PngImage, minimum_bits: usize) -> Option<PngImage>
|
|||
#[must_use]
|
||||
pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Option<PngImage> {
|
||||
assert!((1..8).contains(&minimum_bits));
|
||||
let bit_depth: usize = png.ihdr.bit_depth.as_u8() as usize;
|
||||
let bit_depth = png.ihdr.bit_depth as usize;
|
||||
if minimum_bits >= bit_depth || bit_depth > 8 {
|
||||
return None;
|
||||
}
|
||||
|
|
@ -154,7 +154,7 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> Op
|
|||
data: reduced,
|
||||
ihdr: IhdrData {
|
||||
color_type,
|
||||
bit_depth: BitDepth::from_u8(minimum_bits as u8),
|
||||
bit_depth: (minimum_bits as u8).try_into().unwrap(),
|
||||
..png.ihdr
|
||||
},
|
||||
aux_headers: png.aux_headers.clone(),
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ fn test_it_converts(
|
|||
assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_out);
|
||||
assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out);
|
||||
if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type {
|
||||
assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth.as_u8() as usize));
|
||||
assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth as u8));
|
||||
}
|
||||
|
||||
remove_file(output).ok();
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ fn test_it_converts(
|
|||
"optimized to wrong bit depth"
|
||||
);
|
||||
if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type {
|
||||
let mut max_palette_size = 1 << (png.raw.ihdr.bit_depth.as_u8() as usize);
|
||||
let mut max_palette_size = 1 << (png.raw.ihdr.bit_depth as u8);
|
||||
// Ensure bKGD color is valid
|
||||
if let Some(&idx) = png.raw.aux_headers.get(b"bKGD").and_then(|b| b.first()) {
|
||||
assert!(palette.len() > idx as usize);
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ fn test_it_converts(
|
|||
assert_eq!(png.raw.ihdr.color_type.png_header_code(), color_type_out);
|
||||
assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out);
|
||||
if let ColorType::Indexed { palette } = &png.raw.ihdr.color_type {
|
||||
assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth.as_u8() as usize));
|
||||
assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth as u8));
|
||||
}
|
||||
|
||||
remove_file(output).ok();
|
||||
|
|
|
|||
Loading…
Reference in a new issue