Determine min depth by palette length

This commit is contained in:
Andrew 2023-05-18 16:54:25 +12:00
parent 27d9e34ff9
commit 4a1cd2db3e

View file

@ -36,37 +36,22 @@ pub fn reduced_bit_depth_8_or_less(png: &PngImage, mut minimum_bits: usize) -> O
// Calculate the current number of pixels per byte // Calculate the current number of pixels per byte
let ppb = 8 / bit_depth; let ppb = 8 / bit_depth;
if let ColorType::Indexed { .. } = png.ihdr.color_type { if let ColorType::Indexed { palette } = &png.ihdr.color_type {
for line in png.scan_lines(false) { // We can easily determine minimum depth by the palette size
let line_max = line let required_bits = match palette.len() {
.data 0..=2 => 1,
.iter() 3..=4 => 2,
.map(|&byte| match png.ihdr.bit_depth { 5..=16 => 4,
BitDepth::Two => (byte & 0x3) _ => 8,
.max((byte >> 2) & 0x3)
.max((byte >> 4) & 0x3)
.max(byte >> 6),
BitDepth::Four => (byte & 0xF).max(byte >> 4),
_ => byte,
})
.max()
.unwrap_or(0);
let required_bits = match line_max {
x if x > 0x0F => 8,
x if x > 0x03 => 4,
x if x > 0x01 => 2,
_ => 1,
}; };
if required_bits > minimum_bits { if required_bits >= bit_depth {
minimum_bits = required_bits;
if minimum_bits >= bit_depth {
// Not reducable // Not reducable
return None; return None;
} } else if required_bits > minimum_bits {
} minimum_bits = required_bits;
} }
} else { } else {
// Checking for grayscale depth reduction is quite different than for indexed // Finding minimum depth for grayscale is much more complicated
let mut mask = (1 << minimum_bits) - 1; let mut mask = (1 << minimum_bits) - 1;
let mut divisions = 1..(bit_depth / minimum_bits); let mut divisions = 1..(bit_depth / minimum_bits);
for &b in &png.data { for &b in &png.data {