Reduce alpha in palette

This commit is contained in:
Andrew 2022-12-10 21:41:39 +13:00
parent 93d48d64e6
commit e842a0e2f3
3 changed files with 31 additions and 19 deletions

View file

@ -80,7 +80,7 @@ fn reductions_rgba_to_rgb_16(b: &mut Bencher) {
let input = test::black_box(PathBuf::from("tests/files/rgba_16_should_be_rgb_16.png"));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduce_color_type(&png.raw, true));
b.iter(|| reduce_color_type(&png.raw, true, false));
}
#[bench]
@ -88,7 +88,7 @@ fn reductions_rgba_to_rgb_8(b: &mut Bencher) {
let input = test::black_box(PathBuf::from("tests/files/rgba_8_should_be_rgb_8.png"));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduce_color_type(&png.raw, true));
b.iter(|| reduce_color_type(&png.raw, true, false));
}
#[bench]
@ -98,7 +98,7 @@ fn reductions_rgba_to_grayscale_alpha_16(b: &mut Bencher) {
));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduce_color_type(&png.raw, true));
b.iter(|| reduce_color_type(&png.raw, true, false));
}
#[bench]
@ -108,7 +108,7 @@ fn reductions_rgba_to_grayscale_alpha_8(b: &mut Bencher) {
));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduce_color_type(&png.raw, true));
b.iter(|| reduce_color_type(&png.raw, true, false));
}
#[bench]
@ -118,7 +118,7 @@ fn reductions_rgba_to_grayscale_16(b: &mut Bencher) {
));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduce_color_type(&png.raw, true));
b.iter(|| reduce_color_type(&png.raw, true, false));
}
#[bench]
@ -128,7 +128,7 @@ fn reductions_rgba_to_grayscale_8(b: &mut Bencher) {
));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduce_color_type(&png.raw, true));
b.iter(|| reduce_color_type(&png.raw, true, false));
}
#[bench]
@ -138,7 +138,7 @@ fn reductions_rgb_to_grayscale_16(b: &mut Bencher) {
));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduce_color_type(&png.raw, true));
b.iter(|| reduce_color_type(&png.raw, true, false));
}
#[bench]
@ -146,7 +146,7 @@ fn reductions_rgb_to_grayscale_8(b: &mut Bencher) {
let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_grayscale_8.png"));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduce_color_type(&png.raw, true));
b.iter(|| reduce_color_type(&png.raw, true, false));
}
#[bench]
@ -154,7 +154,7 @@ fn reductions_rgba_to_palette_8(b: &mut Bencher) {
let input = test::black_box(PathBuf::from("tests/files/rgba_8_should_be_palette_8.png"));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduce_color_type(&png.raw, true));
b.iter(|| reduce_color_type(&png.raw, true, false));
}
#[bench]
@ -162,7 +162,7 @@ fn reductions_rgb_to_palette_8(b: &mut Bencher) {
let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_palette_8.png"));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduce_color_type(&png.raw, true));
b.iter(|| reduce_color_type(&png.raw, true, false));
}
#[bench]
@ -172,7 +172,7 @@ fn reductions_palette_duplicate_reduction(b: &mut Bencher) {
));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduced_palette(&png.raw));
b.iter(|| reduced_palette(&png.raw, false));
}
#[bench]
@ -182,7 +182,7 @@ fn reductions_palette_unused_reduction(b: &mut Bencher) {
));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduced_palette(&png.raw));
b.iter(|| reduced_palette(&png.raw, false));
}
#[bench]
@ -192,7 +192,7 @@ fn reductions_palette_full_reduction(b: &mut Bencher) {
));
let png = PngData::new(&input, false).unwrap();
b.iter(|| reduced_palette(&png.raw));
b.iter(|| reduced_palette(&png.raw, false));
}
#[bench]

View file

@ -703,7 +703,7 @@ fn perform_reductions(
}
if opts.palette_reduction {
if let Some(reduced) = reduced_palette(&png) {
if let Some(reduced) = reduced_palette(&png, opts.optimize_alpha) {
png = Arc::new(reduced);
eval.try_image(png.clone());
report_reduction(&png);
@ -737,7 +737,9 @@ fn perform_reductions(
}
if opts.color_type_reduction {
if let Some(reduced) = reduce_color_type(&png, opts.grayscale_reduction) {
if let Some(reduced) =
reduce_color_type(&png, opts.grayscale_reduction, opts.optimize_alpha)
{
png = Arc::new(reduced);
eval.try_image(png.clone());
report_reduction(&png);

View file

@ -17,7 +17,7 @@ pub(crate) use crate::bit_depth::reduce_bit_depth;
/// Attempt to reduce the number of colors in the palette
/// Returns `None` if palette hasn't changed
pub fn reduced_palette(png: &PngImage) -> Option<PngImage> {
pub fn reduced_palette(png: &PngImage, optimize_alpha: bool) -> Option<PngImage> {
if png.ihdr.color_type != ColorType::Indexed {
// Can't reduce if there is no palette
return None;
@ -90,10 +90,16 @@ pub fn reduced_palette(png: &PngImage) -> Option<PngImage> {
continue;
}
// There are invalid files that use pixel indices beyond palette size
let color = palette
let mut color = palette
.get(i)
.cloned()
.unwrap_or_else(|| RGBA8::new(0, 0, 0, 255));
// If there are multiple fully transparent entries, reduce them into one
if optimize_alpha && color.a == 0 {
color.r = 0;
color.g = 0;
color.b = 0;
}
match seen.entry(color) {
Vacant(new) => {
palette_map[i] = Some(next_index as u8);
@ -191,7 +197,11 @@ fn reordered_palette(palette: &[RGBA8], palette_map: &[Option<u8>; 256]) -> Vec<
/// Attempt to reduce the color type of the image
/// Returns true if the color type was reduced, false otherwise
pub fn reduce_color_type(png: &PngImage, grayscale_reduction: bool) -> Option<PngImage> {
pub fn reduce_color_type(
png: &PngImage,
grayscale_reduction: bool,
optimize_alpha: bool,
) -> Option<PngImage> {
let mut should_reduce_bit_depth = false;
let mut reduced = Cow::Borrowed(png);
@ -234,7 +244,7 @@ pub fn reduce_color_type(png: &PngImage, grayscale_reduction: bool) -> Option<Pn
//Make sure that palette gets sorted. Ideally, this should be done within reduced_color_to_palette.
if should_reduce_bit_depth && reduced.ihdr.color_type == ColorType::Indexed {
if let Some(r) = reduced_palette(&reduced) {
if let Some(r) = reduced_palette(&reduced, optimize_alpha) {
reduced = Cow::Owned(r);
should_reduce_bit_depth = true;
}