Fix incorrect detection of images that can reduce bit depth
Closes #140
This commit is contained in:
parent
903f962f29
commit
87e738dda2
3 changed files with 62 additions and 11 deletions
|
|
@ -2,23 +2,62 @@ use bit_vec::BitVec;
|
||||||
use colors::{BitDepth, ColorType};
|
use colors::{BitDepth, ColorType};
|
||||||
use png::PngData;
|
use png::PngData;
|
||||||
|
|
||||||
|
const ONE_BIT_PERMUTATIONS: [u8; 2] = [0b0000_0000, 0b1111_1111];
|
||||||
|
const TWO_BIT_PERMUTATIONS: [u8; 5] = [
|
||||||
|
0b0000_0000,
|
||||||
|
0b0000_1111,
|
||||||
|
0b0011_1100,
|
||||||
|
0b1111_0000,
|
||||||
|
0b1111_1111,
|
||||||
|
];
|
||||||
|
const FOUR_BIT_PERMUTATIONS: [u8; 11] = [
|
||||||
|
0b0000_0000,
|
||||||
|
0b0000_0011,
|
||||||
|
0b0000_1100,
|
||||||
|
0b0011_0000,
|
||||||
|
0b1100_0000,
|
||||||
|
0b0000_1111,
|
||||||
|
0b0011_1100,
|
||||||
|
0b1111_0000,
|
||||||
|
0b0011_1111,
|
||||||
|
0b1111_1100,
|
||||||
|
0b1111_1111,
|
||||||
|
];
|
||||||
|
|
||||||
pub fn reduce_bit_depth_8_or_less(png: &mut PngData) -> bool {
|
pub fn reduce_bit_depth_8_or_less(png: &mut PngData) -> bool {
|
||||||
let mut reduced = BitVec::with_capacity(png.raw_data.len() * 8);
|
let mut reduced = BitVec::with_capacity(png.raw_data.len() * 8);
|
||||||
let bit_depth: usize = png.ihdr_data.bit_depth.as_u8() as usize;
|
let bit_depth: usize = png.ihdr_data.bit_depth.as_u8() as usize;
|
||||||
let mut allowed_bits = 1;
|
let mut allowed_bits = 1;
|
||||||
for line in png.scan_lines() {
|
for line in png.scan_lines() {
|
||||||
let bit_vec = BitVec::from_bytes(&line.data);
|
let bit_vec = BitVec::from_bytes(&line.data);
|
||||||
for (i, bit) in bit_vec.iter().enumerate() {
|
if png.ihdr_data.color_type == ColorType::Indexed {
|
||||||
let bit_index = if png.ihdr_data.color_type == ColorType::Indexed {
|
for (i, bit) in bit_vec.iter().enumerate() {
|
||||||
bit_depth - (i % bit_depth)
|
let bit_index = bit_depth - (i % bit_depth);
|
||||||
} else {
|
if bit && bit_index > allowed_bits {
|
||||||
i % bit_depth
|
allowed_bits = bit_index.next_power_of_two();
|
||||||
};
|
if allowed_bits == bit_depth {
|
||||||
if bit && bit_index > allowed_bits {
|
// Not reducable
|
||||||
allowed_bits = bit_index.next_power_of_two();
|
return false;
|
||||||
if allowed_bits == bit_depth {
|
}
|
||||||
// Not reducable
|
}
|
||||||
return false;
|
}
|
||||||
|
} else {
|
||||||
|
for byte in bit_vec.to_bytes() {
|
||||||
|
while allowed_bits < bit_depth {
|
||||||
|
let permutations: &[u8] = if allowed_bits == 1 {
|
||||||
|
&ONE_BIT_PERMUTATIONS
|
||||||
|
} else if allowed_bits == 2 {
|
||||||
|
&TWO_BIT_PERMUTATIONS
|
||||||
|
} else if allowed_bits == 4 {
|
||||||
|
&FOUR_BIT_PERMUTATIONS
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
if permutations.iter().any(|perm| *perm == byte) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
allowed_bits <<= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
tests/files/issue-140.png
Normal file
BIN
tests/files/issue-140.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 302 B |
|
|
@ -536,3 +536,15 @@ fn issue_133_left() {
|
||||||
BitDepth::Eight,
|
BitDepth::Eight,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_140() {
|
||||||
|
test_it_converts(
|
||||||
|
"tests/files/issue-140.png",
|
||||||
|
None,
|
||||||
|
ColorType::Grayscale,
|
||||||
|
BitDepth::Two,
|
||||||
|
ColorType::Grayscale,
|
||||||
|
BitDepth::Two,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue