More Reductions (#468)
* Add test for issue 195 * Reduce grayscale alpha to palette * Black alpha before color type reductions
This commit is contained in:
parent
1934587253
commit
bd5a0b526b
5 changed files with 36 additions and 6 deletions
|
|
@ -726,6 +726,13 @@ fn perform_reductions(
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.color_type_reduction {
|
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) {
|
if let Some(reduced) = reduce_color_type(&png, opts.grayscale_reduction) {
|
||||||
png = Arc::new(reduced);
|
png = Arc::new(reduced);
|
||||||
eval.try_image(png.clone());
|
eval.try_image(png.clone());
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ use crate::headers::IhdrData;
|
||||||
use crate::png::PngImage;
|
use crate::png::PngImage;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use rgb::{FromSlice, RGB8, RGBA8};
|
use rgb::{FromSlice, RGB8, RGBA, RGBA8};
|
||||||
use rustc_hash::FxHasher;
|
use rustc_hash::FxHasher;
|
||||||
use std::hash::{BuildHasherDefault, Hash};
|
use std::hash::{BuildHasherDefault, Hash};
|
||||||
|
|
||||||
|
|
@ -105,7 +105,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn reduced_color_to_palette(png: &PngImage) -> Option<PngImage> {
|
pub fn reduce_to_palette(png: &PngImage) -> Option<PngImage> {
|
||||||
if png.ihdr.bit_depth != BitDepth::Eight {
|
if png.ihdr.bit_depth != BitDepth::Eight {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
@ -131,6 +131,17 @@ pub fn reduced_color_to_palette(png: &PngImage) -> Option<PngImage> {
|
||||||
&mut palette,
|
&mut palette,
|
||||||
&mut raw_data,
|
&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 {
|
} else {
|
||||||
debug_assert_eq!(png.ihdr.color_type, ColorType::RGBA);
|
debug_assert_eq!(png.ihdr.color_type, ColorType::RGBA);
|
||||||
reduce_scanline_to_palette(
|
reduce_scanline_to_palette(
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use crate::bit_depth::reduce_bit_depth_8_or_less;
|
||||||
pub mod color;
|
pub mod color;
|
||||||
use crate::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;
|
pub(crate) use crate::bit_depth::reduce_bit_depth;
|
||||||
|
|
||||||
/// Attempt to reduce the number of colors in the palette
|
/// 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<Pn
|
||||||
.or_else(|| reduced_alpha_channel(&reduced))
|
.or_else(|| reduced_alpha_channel(&reduced))
|
||||||
{
|
{
|
||||||
reduced = Cow::Owned(r);
|
reduced = Cow::Owned(r);
|
||||||
} else if let Some(r) = reduced_color_to_palette(&reduced) {
|
} else if let Some(r) = reduce_to_palette(&reduced) {
|
||||||
reduced = Cow::Owned(r);
|
reduced = Cow::Owned(r);
|
||||||
should_reduce_bit_depth = true;
|
should_reduce_bit_depth = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if reduced.ihdr.color_type == ColorType::GrayscaleAlpha {
|
if reduced.ihdr.color_type == ColorType::GrayscaleAlpha {
|
||||||
if let Some(r) = reduced_alpha_channel(&reduced) {
|
if let Some(r) = reduced_alpha_channel(&reduced).or_else(|| reduce_to_palette(&reduced)) {
|
||||||
reduced = Cow::Owned(r);
|
reduced = Cow::Owned(r);
|
||||||
should_reduce_bit_depth = true;
|
should_reduce_bit_depth = true;
|
||||||
}
|
}
|
||||||
|
|
@ -225,7 +225,7 @@ pub fn reduce_color_type(png: &PngImage, grayscale_reduction: bool) -> Option<Pn
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
.or_else(|| reduced_color_to_palette(&reduced))
|
.or_else(|| reduce_to_palette(&reduced))
|
||||||
{
|
{
|
||||||
reduced = Cow::Owned(r);
|
reduced = Cow::Owned(r);
|
||||||
should_reduce_bit_depth = true;
|
should_reduce_bit_depth = true;
|
||||||
|
|
|
||||||
BIN
tests/files/issue-195.png
Normal file
BIN
tests/files/issue-195.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
|
|
@ -630,3 +630,15 @@ fn issue_182() {
|
||||||
BitDepth::One,
|
BitDepth::One,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_195() {
|
||||||
|
test_it_converts(
|
||||||
|
"tests/files/issue-195.png",
|
||||||
|
None,
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::Indexed,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue