diff --git a/src/png/mod.rs b/src/png/mod.rs index df695973..455b96cc 100644 --- a/src/png/mod.rs +++ b/src/png/mod.rs @@ -341,9 +341,17 @@ impl PngImage { let mut prev_line = Vec::new(); let mut prev_pass: Option = None; let mut f_buf = Vec::new(); + let mut best_possible = 0; for line in self.scan_lines(false) { if prev_pass != line.pass || line.data.len() != prev_line.len() { prev_line = vec![0; line.data.len()]; + // Calculate the best possible result for this pass + best_possible = match filter { + RowFilter::Entropy => ilog2i(line.data.len() as u32 + 1) as i32, + RowFilter::Bigrams => 1, + RowFilter::BigEnt => ilog2i(line.data.len() as u32) as i32, + _ => 0, + } } // Alpha optimisation may alter the line data, so we need a mutable copy of it let mut line_data = line.data.to_vec(); @@ -372,17 +380,21 @@ impl PngImage { RowFilter::MinSum => { // MSAD algorithm mentioned in libpng reference docs // http://www.libpng.org/pub/png/book/chapter09.html - let mut best_size = usize::MAX; + let mut best_size = i32::MAX; for f in try_filters { f.filter_line(bpp, &mut line_data, &prev_line, &mut f_buf, alpha_bytes); let size = f_buf.iter().fold(0, |acc, &x| { let signed = x as i8; - acc + signed.unsigned_abs() as usize + acc + signed.unsigned_abs() as i32 }); if size < best_size { best_size = size; std::mem::swap(&mut best_line, &mut f_buf); best_line_raw.clone_from(&line_data); + if size == best_possible { + // Best possible result + break; + } } } } @@ -406,13 +418,17 @@ impl PngImage { best_size = size; std::mem::swap(&mut best_line, &mut f_buf); best_line_raw.clone_from(&line_data); + if size == best_possible { + // Best possible result + break; + } } } } RowFilter::Bigrams => { // Count distinct bigrams, from pngwolf // https://bjoern.hoehrmann.de/pngwolf/ - let mut best_size = usize::MAX; + let mut best_size = i32::MAX; for f in try_filters { f.filter_line(bpp, &mut line_data, &prev_line, &mut f_buf, alpha_bytes); let mut set = bitarr![0; 0x10000]; @@ -420,11 +436,15 @@ impl PngImage { let bigram = (pair[0] as usize) << 8 | pair[1] as usize; set.set(bigram, true); } - let size = set.count_ones(); + let size = set.count_ones() as i32; if size < best_size { best_size = size; std::mem::swap(&mut best_line, &mut f_buf); best_line_raw.clone_from(&line_data); + if size == best_possible { + // Best possible result + break; + } } } } @@ -445,6 +465,10 @@ impl PngImage { best_size = size; std::mem::swap(&mut best_line, &mut f_buf); best_line_raw.clone_from(&line_data); + if size == best_possible { + // Best possible result + break; + } } } }