diff --git a/benches/reductions.rs b/benches/reductions.rs index e94d8280..30eebe17 100644 --- a/benches/reductions.rs +++ b/benches/reductions.rs @@ -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)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[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)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[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)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[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)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[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)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[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)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[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)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[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)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[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)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[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)); + b.iter(|| reduce_color_type(&png.raw, true)); } #[bench] diff --git a/src/lib.rs b/src/lib.rs index 0b6fc479..239968de 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -169,6 +169,10 @@ pub struct Options { /// /// Default: `true` pub palette_reduction: bool, + /// Whether to attempt grayscale reduction + /// + /// Default: `true` + pub grayscale_reduction: bool, /// Whether to perform IDAT recoding /// /// If any type of reduction is performed, IDAT recoding will be performed @@ -305,6 +309,7 @@ impl Default for Options { bit_depth_reduction: true, color_type_reduction: true, palette_reduction: true, + grayscale_reduction: true, idat_recoding: true, strip: Headers::None, deflate: Deflaters::Zlib { @@ -741,7 +746,7 @@ fn perform_reductions( } if opts.color_type_reduction { - if let Some(reduced) = reduce_color_type(&png) { + if let Some(reduced) = reduce_color_type(&png, opts.grayscale_reduction) { png = Arc::new(reduced); eval.try_image(png.clone()); report_reduction(&png); diff --git a/src/main.rs b/src/main.rs index 20c8f16b..1a269dd4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -184,6 +184,9 @@ fn main() { .arg(Arg::with_name("no-palette-reduction") .help("No palette reduction") .long("np")) + .arg(Arg::with_name("no-grayscale-reduction") + .help("No grayscale reduction") + .long("ng")) .arg(Arg::with_name("no-reductions") .help("No reductions") .long("nx")) @@ -433,10 +436,15 @@ fn parse_opts_into_struct( opts.palette_reduction = false; } + if matches.is_present("no-grayscale-reduction") { + opts.grayscale_reduction = false; + } + if matches.is_present("no-reductions") { opts.bit_depth_reduction = false; opts.color_type_reduction = false; opts.palette_reduction = false; + opts.grayscale_reduction = false; } if matches.is_present("no-recoding") { diff --git a/src/reduction/mod.rs b/src/reduction/mod.rs index e6f4bf7d..6b89b839 100644 --- a/src/reduction/mod.rs +++ b/src/reduction/mod.rs @@ -185,15 +185,19 @@ fn reordered_palette(palette: &[RGBA8], palette_map: &[Option; 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) -> Option { +pub fn reduce_color_type(png: &PngImage, grayscale_reduction: bool) -> Option { let mut should_reduce_bit_depth = false; let mut reduced = Cow::Borrowed(png); // Go down one step at a time // Maybe not the most efficient, but it's safe if reduced.ihdr.color_type == ColorType::RGBA { - if let Some(r) = - reduce_rgba_to_grayscale_alpha(&reduced).or_else(|| reduced_alpha_channel(&reduced)) + if let Some(r) = if grayscale_reduction { + reduce_rgba_to_grayscale_alpha(&reduced) + } else { + None + } + .or_else(|| reduced_alpha_channel(&reduced)) { reduced = Cow::Owned(r); } else if let Some(r) = reduced_color_to_palette(&reduced) { @@ -210,8 +214,12 @@ pub fn reduce_color_type(png: &PngImage) -> Option { } if reduced.ihdr.color_type == ColorType::RGB { - if let Some(r) = - reduce_rgb_to_grayscale(&reduced).or_else(|| reduced_color_to_palette(&reduced)) + if let Some(r) = if grayscale_reduction { + reduce_rgb_to_grayscale(&reduced) + } else { + None + } + .or_else(|| reduced_color_to_palette(&reduced)) { reduced = Cow::Owned(r); should_reduce_bit_depth = true;