Faster bit depth check
This commit is contained in:
parent
f7337084ad
commit
de61b7abf9
1 changed files with 28 additions and 17 deletions
|
|
@ -78,28 +78,39 @@ pub fn reduce_bit_depth(png: &PngImage) -> Option<PngImage> {
|
||||||
pub fn reduce_bit_depth_8_or_less(png: &PngImage) -> Option<PngImage> {
|
pub fn reduce_bit_depth_8_or_less(png: &PngImage) -> Option<PngImage> {
|
||||||
let mut reduced = BitVec::with_capacity(png.data.len() * 8);
|
let mut reduced = BitVec::with_capacity(png.data.len() * 8);
|
||||||
let bit_depth: usize = png.ihdr.bit_depth.as_u8() as usize;
|
let bit_depth: usize = png.ihdr.bit_depth.as_u8() as usize;
|
||||||
let mut allowed_bits = 1;
|
let mut minimum_bits = 1;
|
||||||
|
if minimum_bits >= bit_depth {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
for line in png.scan_lines() {
|
for line in png.scan_lines() {
|
||||||
let bit_vec = BitVec::from_bytes(&line.data);
|
|
||||||
if png.ihdr.color_type == ColorType::Indexed {
|
if png.ihdr.color_type == ColorType::Indexed {
|
||||||
for (i, bit) in bit_vec.iter().enumerate() {
|
let line_max = line.data.iter().map(|&byte| match png.ihdr.bit_depth {
|
||||||
let bit_index = bit_depth - (i % bit_depth);
|
BitDepth::Two => (byte & 0x3).max((byte >> 2) & 0x3).max((byte >> 4) & 0x3).max(byte >> 6),
|
||||||
if bit && bit_index > allowed_bits {
|
BitDepth::Four => (byte & 0xF).max(byte >> 4),
|
||||||
allowed_bits = bit_index.next_power_of_two();
|
_ => byte,
|
||||||
if allowed_bits == bit_depth {
|
}).max().unwrap_or(0);
|
||||||
// Not reducable
|
let required_bits = match line_max {
|
||||||
return None;
|
x if x > 0x0F => 8,
|
||||||
}
|
x if x > 0x03 => 4,
|
||||||
|
x if x > 0x01 => 2,
|
||||||
|
_ => 1,
|
||||||
|
};
|
||||||
|
if required_bits > minimum_bits {
|
||||||
|
minimum_bits = required_bits;
|
||||||
|
if minimum_bits >= bit_depth {
|
||||||
|
// Not reducable
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
let bit_vec = BitVec::from_bytes(&line.data);
|
||||||
for byte in bit_vec.to_bytes() {
|
for byte in bit_vec.to_bytes() {
|
||||||
while allowed_bits < bit_depth {
|
while minimum_bits < bit_depth {
|
||||||
let permutations: &[u8] = if allowed_bits == 1 {
|
let permutations: &[u8] = if minimum_bits == 1 {
|
||||||
&ONE_BIT_PERMUTATIONS
|
&ONE_BIT_PERMUTATIONS
|
||||||
} else if allowed_bits == 2 {
|
} else if minimum_bits == 2 {
|
||||||
&TWO_BIT_PERMUTATIONS
|
&TWO_BIT_PERMUTATIONS
|
||||||
} else if allowed_bits == 4 {
|
} else if minimum_bits == 4 {
|
||||||
&FOUR_BIT_PERMUTATIONS
|
&FOUR_BIT_PERMUTATIONS
|
||||||
} else {
|
} else {
|
||||||
return None;
|
return None;
|
||||||
|
|
@ -107,7 +118,7 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage) -> Option<PngImage> {
|
||||||
if permutations.iter().any(|perm| *perm == byte) {
|
if permutations.iter().any(|perm| *perm == byte) {
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
allowed_bits <<= 1;
|
minimum_bits <<= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -119,7 +130,7 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage) -> Option<PngImage> {
|
||||||
let bit_vec = BitVec::from_bytes(&line.data);
|
let bit_vec = BitVec::from_bytes(&line.data);
|
||||||
for (i, bit) in bit_vec.iter().enumerate() {
|
for (i, bit) in bit_vec.iter().enumerate() {
|
||||||
let bit_index = bit_depth - (i % bit_depth);
|
let bit_index = bit_depth - (i % bit_depth);
|
||||||
if bit_index <= allowed_bits {
|
if bit_index <= minimum_bits {
|
||||||
reduced.push(bit);
|
reduced.push(bit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -132,7 +143,7 @@ pub fn reduce_bit_depth_8_or_less(png: &PngImage) -> Option<PngImage> {
|
||||||
Some(PngImage {
|
Some(PngImage {
|
||||||
data: reduced.to_bytes(),
|
data: reduced.to_bytes(),
|
||||||
ihdr: IhdrData {
|
ihdr: IhdrData {
|
||||||
bit_depth: BitDepth::from_u8(allowed_bits as u8),
|
bit_depth: BitDepth::from_u8(minimum_bits as u8),
|
||||||
..png.ihdr
|
..png.ihdr
|
||||||
},
|
},
|
||||||
aux_headers: png.aux_headers.clone(),
|
aux_headers: png.aux_headers.clone(),
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue