Add bigrams filter

This commit is contained in:
Andrew 2022-11-05 14:19:54 +13:00
parent 5c25de48f1
commit fc32786498
4 changed files with 63 additions and 1 deletions

40
Cargo.lock generated
View file

@ -43,6 +43,18 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitvec"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
dependencies = [
"funty",
"radium",
"tap",
"wyz",
]
[[package]]
name = "bytemuck"
version = "1.12.1"
@ -194,6 +206,12 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "funty"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
[[package]]
name = "glob"
version = "0.3.0"
@ -363,6 +381,7 @@ name = "oxipng"
version = "6.0.1"
dependencies = [
"bit-vec",
"bitvec",
"clap",
"crossbeam-channel",
"filetime",
@ -391,6 +410,12 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "radium"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
[[package]]
name = "rayon"
version = "1.5.3"
@ -472,6 +497,12 @@ version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "tap"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
[[package]]
name = "termcolor"
version = "1.1.3"
@ -585,6 +616,15 @@ version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "wyz"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30b31594f29d27036c383b53b59ed3476874d518f0efb151b27a4c275141390e"
dependencies = [
"tap",
]
[[package]]
name = "zopfli"
version = "0.7.1"

View file

@ -32,6 +32,7 @@ libdeflater = "0.11.0"
log = "0.4.17"
stderrlog = { version = "0.5.3", optional = true, default-features = false }
crossbeam-channel = "0.5.6"
bitvec = "1.0.1"
[dependencies.filetime]
optional = true

View file

@ -14,6 +14,7 @@ pub enum RowFilter {
// Heuristic strategies
MinSum,
Entropy,
Bigrams,
}
impl TryFrom<u8> for RowFilter {
@ -40,13 +41,14 @@ impl Display for RowFilter {
Self::Paeth => "Paeth",
Self::MinSum => "MinSum",
Self::Entropy => "Entropy",
Self::Bigrams => "Bigrams",
}
)
}
}
impl RowFilter {
pub const LAST: u8 = Self::Entropy as u8;
pub const LAST: u8 = Self::Bigrams as u8;
pub const STANDARD: [Self; 5] = [Self::None, Self::Sub, Self::Up, Self::Average, Self::Paeth];
pub const SINGLE_LINE: [Self; 2] = [Self::None, Self::Sub];

View file

@ -4,6 +4,7 @@ use crate::error::PngError;
use crate::filters::*;
use crate::headers::*;
use crate::interlace::{deinterlace_image, interlace_image};
use bitvec::bitarr;
use indexmap::IndexMap;
use rgb::ComponentSlice;
use rgb::RGBA8;
@ -367,6 +368,24 @@ impl PngImage {
}
}
}
RowFilter::Bigrams => {
// Count distinct bigrams, from pngwolf
// https://bjoern.hoehrmann.de/pngwolf/
let mut best_size = usize::MAX;
for try_filter in try_filters {
try_filter.filter_line(bpp, line.data, last_line, &mut f_buf);
let mut set = bitarr![0; 0x10000];
for i in 1..f_buf.len() {
let bigram = (f_buf[i - 1] as usize) << 8 | f_buf[i] as usize;
set.set(bigram, true);
}
let size = set.count_ones();
if size < best_size {
best_size = size;
std::mem::swap(&mut best_line, &mut f_buf);
}
}
}
_ => unreachable!(),
}
filtered.extend_from_slice(&best_line);