Skip to content

Commit

Permalink
Try both gray and indexed low depths
Browse files Browse the repository at this point in the history
  • Loading branch information
andrews05 committed Feb 18, 2024
1 parent 4cb8296 commit 0c33cb3
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 19 deletions.
24 changes: 12 additions & 12 deletions benches/reductions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn reductions_8_to_4_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -41,7 +41,7 @@ fn reductions_8_to_2_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -51,7 +51,7 @@ fn reductions_8_to_1_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -61,7 +61,7 @@ fn reductions_4_to_2_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -71,7 +71,7 @@ fn reductions_4_to_1_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -81,7 +81,7 @@ fn reductions_2_to_1_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -91,7 +91,7 @@ fn reductions_grayscale_8_to_4_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -101,7 +101,7 @@ fn reductions_grayscale_8_to_2_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -111,7 +111,7 @@ fn reductions_grayscale_8_to_1_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -121,7 +121,7 @@ fn reductions_grayscale_4_to_2_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -131,7 +131,7 @@ fn reductions_grayscale_4_to_1_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand All @@ -141,7 +141,7 @@ fn reductions_grayscale_2_to_1_bits(b: &mut Bencher) {
));
let png = PngData::new(&input, &Options::default()).unwrap();

b.iter(|| bit_depth::reduced_bit_depth_8_or_less(&png.raw));
b.iter(|| bit_depth::reduced_bit_depth(&png.raw, 8));
}

#[bench]
Expand Down
10 changes: 7 additions & 3 deletions src/reduction/bit_depth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ pub fn scaled_bit_depth_16_to_8(png: &PngImage) -> Option<PngImage> {

/// Attempt to reduce an 8-bit image to a lower bit depth, returning the reduced image if successful
#[must_use]
pub fn reduced_bit_depth_8_or_less(png: &PngImage) -> Option<PngImage> {
if png.ihdr.bit_depth != BitDepth::Eight || png.channels_per_pixel() != 1 {
pub fn reduced_bit_depth(png: &PngImage, below_depth: usize) -> Option<PngImage> {
assert!(below_depth <= 8);
if below_depth <= 1 || png.ihdr.bit_depth != BitDepth::Eight || png.channels_per_pixel() != 1 {
return None;
}

Expand All @@ -78,6 +79,9 @@ pub fn reduced_bit_depth_8_or_less(png: &PngImage) -> Option<PngImage> {
5..=16 => 4,
_ => return None,
};
if minimum_bits >= below_depth {
return None;
}
} else {
// Finding minimum depth for grayscale is much more complicated
let mut mask = 1;
Expand All @@ -97,7 +101,7 @@ pub fn reduced_bit_depth_8_or_less(png: &PngImage) -> Option<PngImage> {
if byte & mask != compare {
// This depth is not possible, try the next one up
minimum_bits <<= 1;
if minimum_bits == 8 {
if minimum_bits >= below_depth {
return None;
}
mask = (1 << minimum_bits) - 1;
Expand Down
17 changes: 13 additions & 4 deletions src/reduction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,23 @@ pub(crate) fn perform_reductions(

// Attempt to reduce to a lower bit depth
if opts.bit_depth_reduction && !deadline.passed() {
// Try reducing the previous png, falling back to the indexed one if it exists
// This allows a grayscale depth reduction to be preferred over an indexed depth reduction
let reduced = reduced_bit_depth_8_or_less(&png)
.or_else(|| indexed.and_then(|png| reduced_bit_depth_8_or_less(&png)));
// First try reducing the `png` var (could be grayscale or indexed)
let reduced = reduced_bit_depth(&png, 8);
let mut indexed_depth_limit = 8;
if let Some(reduced) = reduced {
// For cheap evaluations, skip the `indexed` attempt (if it exists then this one is grayscale which is preferred)
// Otherwise require the indexed to reach a lower depth than what we've achieved here
indexed_depth_limit = if cheap { 0 } else { reduced.ihdr.bit_depth as usize };
eval.try_image(Arc::new(reduced));
evaluation_added = true;
}
// Now see if we can reduce the `indexed` var
if !deadline.passed() {
if let Some(reduced) = indexed.and_then(|png| reduced_bit_depth(&png, indexed_depth_limit)) {
eval.try_image(Arc::new(reduced));
evaluation_added = true;
}
}
}

if evaluation_added {
Expand Down

0 comments on commit 0c33cb3

Please sign in to comment.