diff --git a/src/lib.rs b/src/lib.rs index 9728245e..cd74186a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -726,6 +726,13 @@ fn perform_reductions( } if opts.color_type_reduction { + // Perform a black alpha reduction before color type reductions + // This can allow reductions from alpha to indexed which may not have been possible otherwise + if !opts.alphas.is_empty() { + if let Some(reduced) = filtered_alpha_channel(&png, AlphaOptim::Black) { + png = Arc::new(reduced); + } + } if let Some(reduced) = reduce_color_type(&png, opts.grayscale_reduction) { png = Arc::new(reduced); eval.try_image(png.clone()); diff --git a/src/reduction/color.rs b/src/reduction/color.rs index 5284c94e..2ada69de 100644 --- a/src/reduction/color.rs +++ b/src/reduction/color.rs @@ -3,7 +3,7 @@ use crate::headers::IhdrData; use crate::png::PngImage; use indexmap::IndexMap; use itertools::Itertools; -use rgb::{FromSlice, RGB8, RGBA8}; +use rgb::{FromSlice, RGB8, RGBA, RGBA8}; use rustc_hash::FxHasher; use std::hash::{BuildHasherDefault, Hash}; @@ -105,7 +105,7 @@ where } #[must_use] -pub fn reduced_color_to_palette(png: &PngImage) -> Option { +pub fn reduce_to_palette(png: &PngImage) -> Option { if png.ihdr.bit_depth != BitDepth::Eight { return None; } @@ -131,6 +131,17 @@ pub fn reduced_color_to_palette(png: &PngImage) -> Option { &mut palette, &mut raw_data, ) + } else if png.ihdr.color_type == ColorType::GrayscaleAlpha { + reduce_scanline_to_palette( + line.data.as_gray_alpha().iter().cloned().map(|px| RGBA { + r: px.0, + g: px.0, + b: px.0, + a: px.1, + }), + &mut palette, + &mut raw_data, + ) } else { debug_assert_eq!(png.ihdr.color_type, ColorType::RGBA); reduce_scanline_to_palette( diff --git a/src/reduction/mod.rs b/src/reduction/mod.rs index 0c56b89c..b775f753 100644 --- a/src/reduction/mod.rs +++ b/src/reduction/mod.rs @@ -12,7 +12,7 @@ use crate::bit_depth::reduce_bit_depth_8_or_less; pub mod color; use crate::color::*; -pub(crate) use crate::alpha::try_alpha_reductions; +pub(crate) use crate::alpha::{filtered_alpha_channel, try_alpha_reductions}; pub(crate) use crate::bit_depth::reduce_bit_depth; /// Attempt to reduce the number of colors in the palette @@ -206,14 +206,14 @@ pub fn reduce_color_type(png: &PngImage, grayscale_reduction: bool) -> Option Option