Ensure palette is trimmed after depth reduction

Fixes #159
This commit is contained in:
Kornel Lesiński 2019-01-22 21:19:25 +00:00 committed by Kornel Lesiński
parent 2711bee317
commit 1f9ed834bd
5 changed files with 30 additions and 7 deletions

View file

@ -190,12 +190,13 @@ impl PngData {
// Palette
if let Some(ref palette) = self.raw.palette {
let mut palette_data = Vec::with_capacity(palette.len() * 3);
for px in palette {
let max_palette_size = 1 << (self.raw.ihdr.bit_depth.as_u8() as usize);
for px in palette.iter().take(max_palette_size) {
palette_data.extend_from_slice(px.rgb().as_slice());
}
write_png_block(b"PLTE", &palette_data, &mut output);
let num_transparent =
palette.iter().enumerate().fold(
palette.iter().take(max_palette_size).enumerate().fold(
0,
|prev, (index, px)| {
if px.a != 255 {

View file

@ -68,7 +68,7 @@ pub fn reduce_bit_depth(png: &PngImage, minimum_bits: usize) -> Option<PngImage>
bit_depth: BitDepth::Eight,
..png.ihdr
},
palette: png.palette.clone(),
palette: None,
transparency_pixel: png.transparency_pixel.clone(),
aux_headers: png.aux_headers.clone(),
})

BIN
tests/files/issue-159.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View file

@ -55,6 +55,11 @@ fn test_it_converts(
assert_eq!(png.raw.ihdr.color_type, color_type_out);
assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out);
if let Some(palette) = png.raw.palette.as_ref() {
assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth.as_u8() as usize));
} else {
assert!(png.raw.ihdr.color_type != ColorType::Indexed);
}
remove_file(output).ok();
}

View file

@ -33,8 +33,8 @@ fn test_it_converts(
let (output, opts) = custom.unwrap_or_else(|| get_opts(&input));
let png = PngData::new(&input, opts.fix_errors).unwrap();
assert_eq!(png.raw.ihdr.color_type, color_type_in);
assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in);
assert_eq!(png.raw.ihdr.color_type, color_type_in, "test file is broken");
assert_eq!(png.raw.ihdr.bit_depth, bit_depth_in, "test file is broken");
match oxipng::optimize(&InFile::Path(input), &output, &opts) {
Ok(_) => (),
@ -51,8 +51,13 @@ fn test_it_converts(
}
};
assert_eq!(png.raw.ihdr.color_type, color_type_out);
assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out);
assert_eq!(png.raw.ihdr.color_type, color_type_out, "optimized to wrong color type");
assert_eq!(png.raw.ihdr.bit_depth, bit_depth_out, "optimized to wrong bit depth");
if let Some(palette) = png.raw.palette.as_ref() {
assert!(palette.len() <= 1 << (png.raw.ihdr.bit_depth.as_u8() as usize));
} else {
assert!(png.raw.ihdr.color_type != ColorType::Indexed);
}
remove_file(output).ok();
}
@ -572,3 +577,15 @@ fn issue_153() {
BitDepth::Eight,
);
}
#[test]
fn issue_159() {
test_it_converts(
"tests/files/issue-159.png",
None,
ColorType::Indexed,
BitDepth::One,
ColorType::Indexed,
BitDepth::One,
);
}