parent
4ea310fa68
commit
71d0f6fa31
4 changed files with 228 additions and 5 deletions
|
|
@ -1,3 +1,6 @@
|
||||||
|
### Version 2.1.1
|
||||||
|
- More fixes for alpha optimization on interlaced images ([#133](https://github.com/shssoichiro/oxipng/issues/133))
|
||||||
|
|
||||||
### Version 2.1.0
|
### Version 2.1.0
|
||||||
- [SEMVER_MINOR] Bump minimum Rust version to 1.27.0
|
- [SEMVER_MINOR] Bump minimum Rust version to 1.27.0
|
||||||
- [SEMVER_MINOR] Reenable faster Cloudflare zlib compression on platforms that support it
|
- [SEMVER_MINOR] Reenable faster Cloudflare zlib compression on platforms that support it
|
||||||
|
|
|
||||||
|
|
@ -712,9 +712,12 @@ impl PngData {
|
||||||
let mut lines = Vec::new();
|
let mut lines = Vec::new();
|
||||||
let mut scan_lines = self.scan_lines().collect::<Vec<ScanLine>>();
|
let mut scan_lines = self.scan_lines().collect::<Vec<ScanLine>>();
|
||||||
scan_lines.reverse();
|
scan_lines.reverse();
|
||||||
let mut last_line = vec![0; scan_lines[0].data.len()];
|
let mut last_line = Vec::new();
|
||||||
let mut current_line = Vec::with_capacity(last_line.len());
|
let mut current_line = Vec::with_capacity(last_line.len());
|
||||||
for line in scan_lines {
|
for line in scan_lines {
|
||||||
|
if line.data.len() != last_line.len() {
|
||||||
|
last_line = vec![0; line.data.len()];
|
||||||
|
}
|
||||||
current_line.push(line.filter);
|
current_line.push(line.filter);
|
||||||
for (pixel, last_pixel) in line.data.chunks(bpp).zip(last_line.chunks(bpp)) {
|
for (pixel, last_pixel) in line.data.chunks(bpp).zip(last_line.chunks(bpp)) {
|
||||||
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
||||||
|
|
@ -735,8 +738,11 @@ impl PngData {
|
||||||
|
|
||||||
fn reduce_alpha_to_down(&self, bpc: usize, bpp: usize) -> Vec<u8> {
|
fn reduce_alpha_to_down(&self, bpc: usize, bpp: usize) -> Vec<u8> {
|
||||||
let mut reduced = Vec::with_capacity(self.raw_data.len());
|
let mut reduced = Vec::with_capacity(self.raw_data.len());
|
||||||
let mut last_line = vec![0; self.scan_lines().next().unwrap().data.len()];
|
let mut last_line = Vec::new();
|
||||||
for line in self.scan_lines() {
|
for line in self.scan_lines() {
|
||||||
|
if line.data.len() != last_line.len() {
|
||||||
|
last_line = vec![0; line.data.len()];
|
||||||
|
}
|
||||||
reduced.push(line.filter);
|
reduced.push(line.filter);
|
||||||
for (pixel, last_pixel) in line.data.chunks(bpp).zip(last_line.chunks(bpp)) {
|
for (pixel, last_pixel) in line.data.chunks(bpp).zip(last_line.chunks(bpp)) {
|
||||||
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
||||||
|
|
|
||||||
BIN
tests/files/issue-133.png
Normal file
BIN
tests/files/issue-133.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
|
|
@ -291,14 +291,14 @@ fn issue_92_filter_5() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn issue_113() {
|
fn issue_113_white() {
|
||||||
let input = "tests/files/issue-113.png";
|
let input = "tests/files/issue-113.png";
|
||||||
let (_, mut opts) = get_opts(Path::new(input));
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
opts.interlace = Some(1);
|
opts.interlace = Some(1);
|
||||||
opts.alphas = HashSet::new();
|
opts.alphas = HashSet::new();
|
||||||
opts.alphas.insert(AlphaOptim::Up);
|
opts.alphas.insert(AlphaOptim::Black);
|
||||||
let output = OutFile::Path(Some(
|
let output = OutFile::Path(Some(
|
||||||
Path::new(input).with_extension("-f5-out.png").to_owned(),
|
Path::new(input).with_extension("-white-out.png").to_owned(),
|
||||||
));
|
));
|
||||||
test_it_converts(
|
test_it_converts(
|
||||||
input,
|
input,
|
||||||
|
|
@ -309,3 +309,217 @@ fn issue_113() {
|
||||||
BitDepth::Eight,
|
BitDepth::Eight,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_113_black() {
|
||||||
|
let input = "tests/files/issue-113.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.interlace = Some(1);
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::Black);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-black-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::GrayscaleAlpha,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_113_right() {
|
||||||
|
let input = "tests/files/issue-113.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.interlace = Some(1);
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::Right);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-right-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::GrayscaleAlpha,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_113_left() {
|
||||||
|
let input = "tests/files/issue-113.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.interlace = Some(1);
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::Left);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-left-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::GrayscaleAlpha,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_113_up() {
|
||||||
|
let input = "tests/files/issue-113.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.interlace = Some(1);
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::Up);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-up-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::GrayscaleAlpha,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_113_down() {
|
||||||
|
let input = "tests/files/issue-113.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.interlace = Some(1);
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::Down);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-down-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::GrayscaleAlpha,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_133_black() {
|
||||||
|
let input = "tests/files/issue-133.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::Black);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-black-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_133_white() {
|
||||||
|
let input = "tests/files/issue-133.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::White);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-white-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_133_up() {
|
||||||
|
let input = "tests/files/issue-133.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::Up);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-up-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_133_down() {
|
||||||
|
let input = "tests/files/issue-133.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::Down);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-down-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_133_right() {
|
||||||
|
let input = "tests/files/issue-133.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::Right);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-right-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn issue_133_left() {
|
||||||
|
let input = "tests/files/issue-133.png";
|
||||||
|
let (_, mut opts) = get_opts(Path::new(input));
|
||||||
|
opts.alphas = HashSet::new();
|
||||||
|
opts.alphas.insert(AlphaOptim::Left);
|
||||||
|
let output = OutFile::Path(Some(
|
||||||
|
Path::new(input).with_extension("-left-out.png").to_owned(),
|
||||||
|
));
|
||||||
|
test_it_converts(
|
||||||
|
input,
|
||||||
|
Some((output, opts)),
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
ColorType::RGBA,
|
||||||
|
BitDepth::Eight,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue