Automatically change transparent pixels to black
This commit is contained in:
parent
ca657150ec
commit
413f1aac7c
26 changed files with 2637 additions and 1916 deletions
|
|
@ -11,7 +11,7 @@ matrix:
|
|||
env: TARGET=x86_64-apple-darwin
|
||||
cache: cargo
|
||||
- os: linux
|
||||
rust: 1.17.0
|
||||
rust: 1.19.0
|
||||
env: TARGET=x86_64-unknown-linux-gnu
|
||||
cache: cargo
|
||||
- os: linux
|
||||
|
|
|
|||
66
CHANGELOG.md
66
CHANGELOG.md
|
|
@ -1,129 +1,133 @@
|
|||
**Version 0.16.3**
|
||||
### Version 0.17.0 (unreleased)
|
||||
- [SEMVER_MAJOR] Bump minimum required rustc version to 1.19.0
|
||||
- Change all transparent pixels to `rgba(0, 0, 0, 0)` to improve compression
|
||||
|
||||
### Version 0.16.3
|
||||
- Fix command-line help text ([#70](https://github.com/shssoichiro/oxipng/issues/70))
|
||||
|
||||
**Version 0.16.2**
|
||||
### Version 0.16.2
|
||||
- Publicly export `error` module
|
||||
|
||||
**Version 0.16.1**
|
||||
### Version 0.16.1
|
||||
- Fix rayon's breaking changes that they made in a point release
|
||||
|
||||
**Version 0.16.0**
|
||||
### Version 0.16.0
|
||||
- [SEMVER_MAJOR] Bump minimum rustc version to 1.17.0
|
||||
- Bump `image` to 0.14
|
||||
- Bump `rayon` to 0.8
|
||||
|
||||
**Version 0.15.2**
|
||||
### Version 0.15.2
|
||||
- Bump `image` to 0.13 ([#65](https://github.com/shssoichiro/oxipng/pull/65))
|
||||
- Bump `rayon` to 0.7
|
||||
- Bump `itertools` to 0.6
|
||||
|
||||
**Version 0.15.1**
|
||||
### Version 0.15.1
|
||||
- Ignore color reductions that would increase file size ([#61](https://github.com/shssoichiro/oxipng/issues/61))
|
||||
|
||||
**Version 0.15.0**
|
||||
### Version 0.15.0
|
||||
- [SEMVER_MINOR] Check images for correctness before writing result ([#60](https://github.com/shssoichiro/oxipng/issues/60))
|
||||
- Fix invalid output when reducing image to a different color type but file size does not improve ([#60](https://github.com/shssoichiro/oxipng/issues/60))
|
||||
- Don't write new file if moving from interlaced to non-interlaced if new file would be larger
|
||||
|
||||
**Version 0.14.4**
|
||||
### Version 0.14.4
|
||||
- Fix bug when reducing RGBA to Indexed if image has 256 colors plus a background color
|
||||
|
||||
**Version 0.14.3**
|
||||
### Version 0.14.3
|
||||
- Fix multiple bugs when reducing transparency palettes
|
||||
|
||||
**Version 0.14.2**
|
||||
### Version 0.14.2
|
||||
- Fix a bug when reducing palette in images with bit depth less than 8
|
||||
- Fix a bug when reducing palette in images with transparency
|
||||
|
||||
**Version 0.14.1**
|
||||
### Version 0.14.1
|
||||
- Remove zlib dependency and switch entirely to miniz, since zlib 1.2.11 was not working with oxipng. This costs some performance, but is better than having a broken application.
|
||||
|
||||
**Version 0.14.0**
|
||||
### Version 0.14.0
|
||||
- Performance optimizations
|
||||
- [SEMVER_MAJOR] Bump minimum rustc version to 1.13.0
|
||||
- Add categories on crates.io
|
||||
|
||||
**Version 0.13.1**
|
||||
### Version 0.13.1
|
||||
- Bump regex dependency to 0.2
|
||||
- Bump byteorder dependency to 1.0
|
||||
- Bump rayon dependency to 0.6
|
||||
|
||||
**Version 0.13.0**
|
||||
### Version 0.13.0
|
||||
- Fix bug in certain PNG headers when reducing color type ([#52](https://github.com/shssoichiro/oxipng/issues/52))
|
||||
- [SEMVER_MAJOR] Reduction functions now take `&mut PngData` and return a `bool` indicating whether the image was reduced
|
||||
- [SMEVER_MAJOR] Bump minimum required rustc version to 1.12.0
|
||||
|
||||
**Version 0.12.0**
|
||||
### Version 0.12.0
|
||||
- Performance optimizations
|
||||
- Fix processing filenames that contain commas (@aliceatlas [#50](https://github.com/shssoichiro/oxipng/pull/50))
|
||||
- [SEMVER_MINOR] Add zopfli option (-Z), disabled by default. Gives about 10% better compression, but is currently 50-100x slower.
|
||||
|
||||
**Version 0.11.0**
|
||||
### Version 0.11.0
|
||||
- [SEMVER_MAJOR] Bump minimum rustc version to 1.9.0, required by dependencies
|
||||
- [SEMVER_MINOR] Allow calling optimization presets via crate using `Options::from_preset`
|
||||
- [SEMVER_MAJOR] Return proper `PngError` type which implements `std::error::Error` from `Result`s
|
||||
- [SEMVER_MAJOR] Rename module `deflate::deflate` to `deflate`
|
||||
- Performance optimizations
|
||||
|
||||
**Version 0.10.0**
|
||||
### Version 0.10.0
|
||||
- [SEMVER_MINOR] Make clap and regex dependencies optional
|
||||
- Enabled by default, needed for executable build; can be disabled for use in crates
|
||||
- Remove reduction from palette to grayscale, which was not working and provided minimal benefit
|
||||
|
||||
**Version 0.9.0**
|
||||
### Version 0.9.0
|
||||
- [SEMVER_MAJOR] Significant refactoring of modules
|
||||
- Use `itertools` to cleanup areas of code
|
||||
- Use multiple threads for filtering trials
|
||||
|
||||
**Version 0.8.2**
|
||||
### Version 0.8.2
|
||||
- Fix issue where images smaller than 4px width would crash on interlacing ([#42](https://github.com/shssoichiro/oxipng/issues/42))
|
||||
|
||||
**Version 0.8.1**
|
||||
### Version 0.8.1
|
||||
- Minor optimizations
|
||||
- Fix issue where interlaced images with certain widths would fail to optimize
|
||||
|
||||
**Version 0.8.0**
|
||||
### Version 0.8.0
|
||||
- [SEMVER_MINOR] Add support for optimizing PNGs already loaded into memory via library function
|
||||
|
||||
**Version 0.7.0**
|
||||
### Version 0.7.0
|
||||
- Minor compression improvement on interlaced images
|
||||
- Performance optimizations
|
||||
- [SEMVER_MINOR] Move default Options into a Default impl
|
||||
- [SEMVER_MINOR] Add option for setting number of threads ([#39](https://github.com/shssoichiro/oxipng/issues/39))
|
||||
|
||||
**Version 0.6.0**
|
||||
### Version 0.6.0
|
||||
- Fix issue where output directory would not be created if it did not exist
|
||||
- Use miniz for compression strategies where it outperforms zlib
|
||||
- [SEMVER_MINOR] Partially implement -p / --preserve, as far as stable Rust will allow for now
|
||||
- [SEMVER_MINOR] Implement --fix to ignore CRC errors and recalculate correct CRC in output
|
||||
|
||||
**Version 0.5.0**
|
||||
### Version 0.5.0
|
||||
- [SEMVER_MINOR] Palette entries can now reduced, on by default ([#11](https://github.com/shssoichiro/oxipng/issues/11))
|
||||
- Don't report that we are in pretend mode if verbosity is set to none
|
||||
- Add cargo bench suite ([#7](https://github.com/shssoichiro/oxipng/issues/7))
|
||||
|
||||
**Version 0.4.0**
|
||||
### Version 0.4.0
|
||||
- Performance optimizations
|
||||
- [SEMVER_MAJOR] `-s` automatically infers `--strip safe` ([#31](https://github.com/shssoichiro/oxipng/issues/31))
|
||||
- Update byteorder and clap crates
|
||||
- Fix issue where interlaced images incorrectly applied filters on the first line of a pass
|
||||
|
||||
**Version 0.3.0**
|
||||
### Version 0.3.0
|
||||
- Properly decode interlaced images
|
||||
- [SEMVER_MINOR] Allow converting between progressive and interlaced images ([#3](https://github.com/shssoichiro/oxipng/issues/3))
|
||||
- Fix a bug that would cause oxipng to crash on very small images
|
||||
|
||||
**Version 0.2.2**
|
||||
### Version 0.2.2
|
||||
- Limit number of threads to 1.5x number of cores
|
||||
- Significantly improve memory usage, especially with high optimization levels. ([#32](https://github.com/shssoichiro/oxipng/issues/32))
|
||||
- Refactor output code ([#19](https://github.com/shssoichiro/oxipng/issues/19))
|
||||
|
||||
**Version 0.2.1**
|
||||
### Version 0.2.1
|
||||
- Add rustdoc for public methods and structs
|
||||
- Improve filter mode 5 heuristic ([#16](https://github.com/shssoichiro/oxipng/issues/16))
|
||||
- Add tests for edge-case images with subtitles ([#29](https://github.com/shssoichiro/oxipng/issues/29))
|
||||
|
||||
**Version 0.2.0**
|
||||
### Version 0.2.0
|
||||
- Fix program version that is displayed when running `oxipng -V`
|
||||
- Ensure `--quiet` mode is actually quiet (@SethDusek [#20](https://github.com/shssoichiro/oxipng/pull/20))
|
||||
- Write status/debug information to stderr instead of stdout
|
||||
|
|
@ -131,10 +135,10 @@
|
|||
- [SEMVER_MAJOR] Allow 'safe', 'all', or comma-separated list as options for `--strip`
|
||||
- [SEMVER_MINOR] Add `-s` alias for `--strip`
|
||||
|
||||
**Version 0.1.1**
|
||||
### Version 0.1.1
|
||||
- Fix `oxipng *` writing all input files to one output file ([#15](https://github.com/shssoichiro/oxipng/issues/15))
|
||||
|
||||
**Version 0.1.0**
|
||||
### Version 0.1.0
|
||||
- Initial beta release
|
||||
- Reduce color type and bit depth
|
||||
- Recompress with zlib
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ cargo build --release
|
|||
cp target/release/oxipng /usr/local/bin
|
||||
```
|
||||
|
||||
The current minimum supported Rust version is **1.17.0**. Oxipng may compile on earlier versions of Rust,
|
||||
The current minimum supported Rust version is **1.19.0**. Oxipng may compile on earlier versions of Rust,
|
||||
but there is no guarantee.
|
||||
|
||||
Oxipng follows Semantic Versioning.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,9 @@ fn deflate_16_bits_strategy_0(b: &mut Bencher) {
|
|||
let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png"));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 0, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 0, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -21,31 +23,45 @@ fn deflate_8_bits_strategy_0(b: &mut Bencher) {
|
|||
let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png"));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 0, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 0, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_4_bits_strategy_0(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 0, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 0, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_2_bits_strategy_0(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 0, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 0, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_1_bits_strategy_0(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 0, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 0, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -53,7 +69,9 @@ fn deflate_16_bits_strategy_1(b: &mut Bencher) {
|
|||
let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png"));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 1, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 1, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -61,31 +79,45 @@ fn deflate_8_bits_strategy_1(b: &mut Bencher) {
|
|||
let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png"));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 1, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 1, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_4_bits_strategy_1(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 1, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 1, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_2_bits_strategy_1(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 1, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 1, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_1_bits_strategy_1(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 1, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 1, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -93,7 +125,9 @@ fn deflate_16_bits_strategy_2(b: &mut Bencher) {
|
|||
let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png"));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 2, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 2, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -101,31 +135,45 @@ fn deflate_8_bits_strategy_2(b: &mut Bencher) {
|
|||
let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png"));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 2, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 2, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_4_bits_strategy_2(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 2, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 2, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_2_bits_strategy_2(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 2, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 2, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_1_bits_strategy_2(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 2, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 2, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -133,7 +181,9 @@ fn deflate_16_bits_strategy_3(b: &mut Bencher) {
|
|||
let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_rgb_16.png"));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 3, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 3, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -141,31 +191,45 @@ fn deflate_8_bits_strategy_3(b: &mut Bencher) {
|
|||
let input = test::black_box(PathBuf::from("tests/files/rgb_8_should_be_rgb_8.png"));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 3, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 3, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_4_bits_strategy_3(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 3, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 3, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_2_bits_strategy_3(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 3, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 3, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deflate_1_bits_strategy_3(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::deflate(png.raw_data.as_ref(), 9, 9, 3, 15).ok(); });
|
||||
b.iter(|| {
|
||||
deflate::deflate(png.raw_data.as_ref(), 9, 9, 3, 15).ok();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ fn filters_8_bits_filter_0(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_4_bits_filter_0(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(0); });
|
||||
|
|
@ -33,7 +35,9 @@ fn filters_4_bits_filter_0(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_2_bits_filter_0(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(0); });
|
||||
|
|
@ -41,7 +45,9 @@ fn filters_2_bits_filter_0(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_1_bits_filter_0(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(0); });
|
||||
|
|
@ -65,7 +71,9 @@ fn filters_8_bits_filter_1(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_4_bits_filter_1(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(1); });
|
||||
|
|
@ -73,7 +81,9 @@ fn filters_4_bits_filter_1(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_2_bits_filter_1(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(1); });
|
||||
|
|
@ -81,7 +91,9 @@ fn filters_2_bits_filter_1(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_1_bits_filter_1(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(1); });
|
||||
|
|
@ -105,7 +117,9 @@ fn filters_8_bits_filter_2(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_4_bits_filter_2(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(2); });
|
||||
|
|
@ -113,7 +127,9 @@ fn filters_4_bits_filter_2(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_2_bits_filter_2(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(2); });
|
||||
|
|
@ -121,7 +137,9 @@ fn filters_2_bits_filter_2(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_1_bits_filter_2(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(2); });
|
||||
|
|
@ -145,7 +163,9 @@ fn filters_8_bits_filter_3(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_4_bits_filter_3(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(3); });
|
||||
|
|
@ -153,7 +173,9 @@ fn filters_4_bits_filter_3(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_2_bits_filter_3(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(3); });
|
||||
|
|
@ -161,7 +183,9 @@ fn filters_2_bits_filter_3(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_1_bits_filter_3(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(3); });
|
||||
|
|
@ -185,7 +209,9 @@ fn filters_8_bits_filter_4(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_4_bits_filter_4(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(4); });
|
||||
|
|
@ -193,7 +219,9 @@ fn filters_4_bits_filter_4(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_2_bits_filter_4(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(4); });
|
||||
|
|
@ -201,7 +229,9 @@ fn filters_2_bits_filter_4(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_1_bits_filter_4(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(4); });
|
||||
|
|
@ -225,7 +255,9 @@ fn filters_8_bits_filter_5(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_4_bits_filter_5(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(5); });
|
||||
|
|
@ -233,7 +265,9 @@ fn filters_4_bits_filter_5(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_2_bits_filter_5(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(5); });
|
||||
|
|
@ -241,7 +275,9 @@ fn filters_2_bits_filter_5(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn filters_1_bits_filter_5(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { png.filter_image(5); });
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@ fn interlacing_16_bits(b: &mut Bencher) {
|
|||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(1);
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(1);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -24,95 +24,111 @@ fn interlacing_8_bits(b: &mut Bencher) {
|
|||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(1);
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(1);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn interlacing_4_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(1);
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(1);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn interlacing_2_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(1);
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(1);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn interlacing_1_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(1);
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(1);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deinterlacing_16_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/interlaced_rgb_16_should_be_rgb_16.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/interlaced_rgb_16_should_be_rgb_16.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(0);
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(0);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deinterlacing_8_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/interlaced_rgb_8_should_be_rgb_8.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/interlaced_rgb_8_should_be_rgb_8.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(0);
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(0);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deinterlacing_4_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/interlaced_palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/interlaced_palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(0);
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(0);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deinterlacing_2_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/interlaced_palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/interlaced_palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(0);
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(0);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn deinterlacing_1_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/interlaced_palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/interlaced_palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(0);
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.change_interlacing(0);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,75 +13,87 @@ fn reductions_16_to_8_bits(b: &mut Bencher) {
|
|||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_8_to_4_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_8_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_8_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_8_to_2_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_8_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_8_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_8_to_1_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_8_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_8_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_4_to_2_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_4_to_1_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_2_to_1_bits(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_bit_depth();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -90,9 +102,9 @@ fn reductions_rgba_to_rgb_16(b: &mut Bencher) {
|
|||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -101,64 +113,74 @@ fn reductions_rgba_to_rgb_8(b: &mut Bencher) {
|
|||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_rgba_to_grayscale_alpha_16(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/rgba_16_should_be_grayscale_alpha_16.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/rgba_16_should_be_grayscale_alpha_16.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_rgba_to_grayscale_alpha_8(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/rgba_8_should_be_grayscale_alpha_8.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/rgba_8_should_be_grayscale_alpha_8.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_rgba_to_grayscale_16(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/rgba_16_should_be_grayscale_16.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/rgba_16_should_be_grayscale_16.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_rgba_to_grayscale_8(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/rgba_8_should_be_grayscale_8.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/rgba_8_should_be_grayscale_8.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_rgb_to_grayscale_16(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/rgb_16_should_be_grayscale_16.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/rgb_16_should_be_grayscale_16.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -167,9 +189,9 @@ fn reductions_rgb_to_grayscale_8(b: &mut Bencher) {
|
|||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -178,9 +200,9 @@ fn reductions_rgba_to_palette_8(b: &mut Bencher) {
|
|||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
|
|
@ -189,40 +211,46 @@ fn reductions_rgb_to_palette_8(b: &mut Bencher) {
|
|||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_color_type();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_palette_duplicate_reduction(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_should_be_reduced_with_dupes.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_should_be_reduced_with_dupes.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_palette();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_palette();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_palette_unused_reduction(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_should_be_reduced_with_unused.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_should_be_reduced_with_unused.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_palette();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_palette();
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn reductions_palette_full_reduction(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_should_be_reduced_with_both.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_should_be_reduced_with_both.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| {
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_palette();
|
||||
});
|
||||
let mut safe_png = png.clone();
|
||||
safe_png.reduce_palette();
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ fn zopfli_8_bits_strategy_0(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn zopfli_4_bits_strategy_0(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_4_should_be_palette_4.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_4_should_be_palette_4.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::zopfli_deflate(png.raw_data.as_ref()).ok(); });
|
||||
|
|
@ -34,7 +36,9 @@ fn zopfli_4_bits_strategy_0(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn zopfli_2_bits_strategy_0(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_2_should_be_palette_2.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_2_should_be_palette_2.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::zopfli_deflate(png.raw_data.as_ref()).ok(); });
|
||||
|
|
@ -42,7 +46,9 @@ fn zopfli_2_bits_strategy_0(b: &mut Bencher) {
|
|||
|
||||
#[bench]
|
||||
fn zopfli_1_bits_strategy_0(b: &mut Bencher) {
|
||||
let input = test::black_box(PathBuf::from("tests/files/palette_1_should_be_palette_1.png"));
|
||||
let input = test::black_box(PathBuf::from(
|
||||
"tests/files/palette_1_should_be_palette_1.png",
|
||||
));
|
||||
let png = png::PngData::new(&input, false).unwrap();
|
||||
|
||||
b.iter(|| { deflate::zopfli_deflate(png.raw_data.as_ref()).ok(); });
|
||||
|
|
|
|||
|
|
@ -18,13 +18,17 @@ pub enum ColorType {
|
|||
impl fmt::Display for ColorType {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", match *self {
|
||||
ColorType::Grayscale => "Grayscale",
|
||||
ColorType::RGB => "RGB",
|
||||
ColorType::Indexed => "Indexed",
|
||||
ColorType::GrayscaleAlpha => "Grayscale + Alpha",
|
||||
ColorType::RGBA => "RGB + Alpha",
|
||||
})
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
ColorType::Grayscale => "Grayscale",
|
||||
ColorType::RGB => "RGB",
|
||||
ColorType::Indexed => "Indexed",
|
||||
ColorType::GrayscaleAlpha => "Grayscale + Alpha",
|
||||
ColorType::RGBA => "RGB + Alpha",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -60,13 +64,17 @@ pub enum BitDepth {
|
|||
impl fmt::Display for BitDepth {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", match *self {
|
||||
BitDepth::One => "1",
|
||||
BitDepth::Two => "2",
|
||||
BitDepth::Four => "4",
|
||||
BitDepth::Eight => "8",
|
||||
BitDepth::Sixteen => "16",
|
||||
})
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match *self {
|
||||
BitDepth::One => "1",
|
||||
BitDepth::Two => "2",
|
||||
BitDepth::Four => "4",
|
||||
BitDepth::Eight => "8",
|
||||
BitDepth::Sixteen => "16",
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,19 +22,22 @@ pub trait Direction {
|
|||
}
|
||||
|
||||
impl Stream<Compress> {
|
||||
pub fn new_compress(lvl: c_int,
|
||||
window_bits: c_int,
|
||||
mem_size: c_int,
|
||||
strategy: c_int)
|
||||
-> Stream<Compress> {
|
||||
pub fn new_compress(
|
||||
lvl: c_int,
|
||||
window_bits: c_int,
|
||||
mem_size: c_int,
|
||||
strategy: c_int,
|
||||
) -> Stream<Compress> {
|
||||
unsafe {
|
||||
let mut state: miniz_sys::mz_stream = mem::zeroed();
|
||||
let ret = miniz_sys::mz_deflateInit2(&mut state,
|
||||
lvl,
|
||||
miniz_sys::MZ_DEFLATED,
|
||||
window_bits,
|
||||
mem_size,
|
||||
strategy);
|
||||
let ret = miniz_sys::mz_deflateInit2(
|
||||
&mut state,
|
||||
lvl,
|
||||
miniz_sys::MZ_DEFLATED,
|
||||
window_bits,
|
||||
mem_size,
|
||||
strategy,
|
||||
);
|
||||
debug_assert_eq!(ret, 0);
|
||||
Stream {
|
||||
raw: state,
|
||||
|
|
@ -91,12 +94,14 @@ impl Stream<Compress> {
|
|||
unsafe {
|
||||
self.raw.next_in = input.as_mut_ptr().offset(self.total_in() as isize);
|
||||
self.raw.next_out = output.as_mut_ptr().offset(self.total_out() as isize);
|
||||
let rc = miniz_sys::mz_deflate(&mut self.raw,
|
||||
if self.raw.avail_in > 0 {
|
||||
miniz_sys::MZ_NO_FLUSH
|
||||
} else {
|
||||
miniz_sys::MZ_FINISH
|
||||
});
|
||||
let rc = miniz_sys::mz_deflate(
|
||||
&mut self.raw,
|
||||
if self.raw.avail_in > 0 {
|
||||
miniz_sys::MZ_NO_FLUSH
|
||||
} else {
|
||||
miniz_sys::MZ_FINISH
|
||||
},
|
||||
);
|
||||
output.set_len(self.total_out() as usize);
|
||||
rc
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,37 +6,33 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> Vec
|
|||
}
|
||||
1 => {
|
||||
filtered.extend_from_slice(&data[0..bpp]);
|
||||
filtered.extend(data.iter()
|
||||
.skip(bpp)
|
||||
.zip(data.iter())
|
||||
.map(|(cur, last)| cur.wrapping_sub(*last)));
|
||||
filtered.extend(data.iter().skip(bpp).zip(data.iter()).map(|(cur, last)| {
|
||||
cur.wrapping_sub(*last)
|
||||
}));
|
||||
}
|
||||
2 => {
|
||||
if last_line.is_empty() {
|
||||
filtered.extend_from_slice(data);
|
||||
} else {
|
||||
filtered.extend(data.iter()
|
||||
.zip(last_line.iter())
|
||||
.map(|(cur, last)| cur.wrapping_sub(*last)));
|
||||
filtered.extend(data.iter().zip(last_line.iter()).map(|(cur, last)| {
|
||||
cur.wrapping_sub(*last)
|
||||
}));
|
||||
};
|
||||
}
|
||||
3 => {
|
||||
for (i, byte) in data.iter().enumerate() {
|
||||
if last_line.is_empty() {
|
||||
filtered.push(match i.checked_sub(bpp) {
|
||||
Some(x) => byte.wrapping_sub(data[x] >> 1),
|
||||
None => *byte,
|
||||
});
|
||||
Some(x) => byte.wrapping_sub(data[x] >> 1),
|
||||
None => *byte,
|
||||
});
|
||||
} else {
|
||||
filtered.push(match i.checked_sub(bpp) {
|
||||
Some(x) => {
|
||||
byte.wrapping_sub(((data[x] as u16 +
|
||||
last_line[i] as u16) >>
|
||||
1) as
|
||||
u8)
|
||||
}
|
||||
None => byte.wrapping_sub(last_line[i] >> 1),
|
||||
});
|
||||
Some(x) => {
|
||||
byte.wrapping_sub(((data[x] as u16 + last_line[i] as u16) >> 1) as u8)
|
||||
}
|
||||
None => byte.wrapping_sub(last_line[i] >> 1),
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -44,18 +40,16 @@ pub fn filter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> Vec
|
|||
for (i, byte) in data.iter().enumerate() {
|
||||
if last_line.is_empty() {
|
||||
filtered.push(match i.checked_sub(bpp) {
|
||||
Some(x) => byte.wrapping_sub(data[x]),
|
||||
None => *byte,
|
||||
});
|
||||
Some(x) => byte.wrapping_sub(data[x]),
|
||||
None => *byte,
|
||||
});
|
||||
} else {
|
||||
filtered.push(match i.checked_sub(bpp) {
|
||||
Some(x) => {
|
||||
byte.wrapping_sub(paeth_predictor(data[x],
|
||||
last_line[i],
|
||||
last_line[x]))
|
||||
}
|
||||
None => byte.wrapping_sub(last_line[i]),
|
||||
});
|
||||
Some(x) => {
|
||||
byte.wrapping_sub(paeth_predictor(data[x], last_line[i], last_line[x]))
|
||||
}
|
||||
None => byte.wrapping_sub(last_line[i]),
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -87,9 +81,9 @@ pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> V
|
|||
if last_line.is_empty() {
|
||||
unfiltered.extend_from_slice(data);
|
||||
} else {
|
||||
unfiltered.extend(data.iter()
|
||||
.zip(last_line.iter())
|
||||
.map(|(cur, last)| cur.wrapping_add(*last)));
|
||||
unfiltered.extend(data.iter().zip(last_line.iter()).map(|(cur, last)| {
|
||||
cur.wrapping_add(*last)
|
||||
}));
|
||||
};
|
||||
}
|
||||
3 => {
|
||||
|
|
@ -108,9 +102,9 @@ pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> V
|
|||
match i.checked_sub(bpp) {
|
||||
Some(x) => {
|
||||
let b = unfiltered[x];
|
||||
unfiltered
|
||||
.push(byte.wrapping_add(((b as u16 + last_line[i] as u16) >> 1) as
|
||||
u8));
|
||||
unfiltered.push(byte.wrapping_add(
|
||||
((b as u16 + last_line[i] as u16) >> 1) as u8,
|
||||
));
|
||||
}
|
||||
None => {
|
||||
unfiltered.push(byte.wrapping_add(last_line[i] >> 1));
|
||||
|
|
@ -135,9 +129,9 @@ pub fn unfilter_line(filter: u8, bpp: usize, data: &[u8], last_line: &[u8]) -> V
|
|||
match i.checked_sub(bpp) {
|
||||
Some(x) => {
|
||||
let b = unfiltered[x];
|
||||
unfiltered.push(byte.wrapping_add(paeth_predictor(b,
|
||||
last_line[i],
|
||||
last_line[x])));
|
||||
unfiltered.push(byte.wrapping_add(
|
||||
paeth_predictor(b, last_line[i], last_line[x]),
|
||||
));
|
||||
}
|
||||
None => {
|
||||
unfiltered.push(byte.wrapping_add(last_line[i]));
|
||||
|
|
|
|||
|
|
@ -43,16 +43,19 @@ pub fn file_header_is_valid(bytes: &[u8]) -> bool {
|
|||
*bytes == expected_header
|
||||
}
|
||||
|
||||
pub fn parse_next_header(byte_data: &[u8],
|
||||
byte_offset: &mut usize,
|
||||
fix_errors: bool)
|
||||
-> Result<Option<(String, Vec<u8>)>, PngError> {
|
||||
let mut rdr = Cursor::new(byte_data
|
||||
.iter()
|
||||
.skip(*byte_offset)
|
||||
.take(4)
|
||||
.cloned()
|
||||
.collect::<Vec<u8>>());
|
||||
pub fn parse_next_header(
|
||||
byte_data: &[u8],
|
||||
byte_offset: &mut usize,
|
||||
fix_errors: bool,
|
||||
) -> Result<Option<(String, Vec<u8>)>, PngError> {
|
||||
let mut rdr = Cursor::new(
|
||||
byte_data
|
||||
.iter()
|
||||
.skip(*byte_offset)
|
||||
.take(4)
|
||||
.cloned()
|
||||
.collect::<Vec<u8>>(),
|
||||
);
|
||||
let length: u32 = match rdr.read_u32::<BigEndian>() {
|
||||
Ok(x) => x,
|
||||
Err(_) => return Err(PngError::new("Invalid data found; unable to read PNG file")),
|
||||
|
|
@ -82,12 +85,14 @@ pub fn parse_next_header(byte_data: &[u8],
|
|||
.cloned()
|
||||
.collect();
|
||||
*byte_offset += length as usize;
|
||||
let mut rdr = Cursor::new(byte_data
|
||||
.iter()
|
||||
.skip(*byte_offset)
|
||||
.take(4)
|
||||
.cloned()
|
||||
.collect::<Vec<u8>>());
|
||||
let mut rdr = Cursor::new(
|
||||
byte_data
|
||||
.iter()
|
||||
.skip(*byte_offset)
|
||||
.take(4)
|
||||
.cloned()
|
||||
.collect::<Vec<u8>>(),
|
||||
);
|
||||
let crc: u32 = match rdr.read_u32::<BigEndian>() {
|
||||
Ok(x) => x,
|
||||
Err(_) => return Err(PngError::new("Invalid data found; unable to read PNG file")),
|
||||
|
|
@ -95,8 +100,10 @@ pub fn parse_next_header(byte_data: &[u8],
|
|||
*byte_offset += 4;
|
||||
header_bytes.extend_from_slice(&data);
|
||||
if !fix_errors && crc32::checksum_ieee(header_bytes.as_ref()) != crc {
|
||||
return Err(PngError::new(&format!("CRC Mismatch in {} header; May be recoverable by using --fix",
|
||||
header)));
|
||||
return Err(PngError::new(&format!(
|
||||
"CRC Mismatch in {} header; May be recoverable by using --fix",
|
||||
header
|
||||
)));
|
||||
}
|
||||
|
||||
Ok(Some((header, data)))
|
||||
|
|
@ -105,26 +112,26 @@ pub fn parse_next_header(byte_data: &[u8],
|
|||
pub fn parse_ihdr_header(byte_data: &[u8]) -> Result<IhdrData, PngError> {
|
||||
let mut rdr = Cursor::new(&byte_data[0..8]);
|
||||
Ok(IhdrData {
|
||||
color_type: match byte_data[9] {
|
||||
0 => ColorType::Grayscale,
|
||||
2 => ColorType::RGB,
|
||||
3 => ColorType::Indexed,
|
||||
4 => ColorType::GrayscaleAlpha,
|
||||
6 => ColorType::RGBA,
|
||||
_ => return Err(PngError::new("Unexpected color type in header")),
|
||||
},
|
||||
bit_depth: match byte_data[8] {
|
||||
1 => BitDepth::One,
|
||||
2 => BitDepth::Two,
|
||||
4 => BitDepth::Four,
|
||||
8 => BitDepth::Eight,
|
||||
16 => BitDepth::Sixteen,
|
||||
_ => return Err(PngError::new("Unexpected bit depth in header")),
|
||||
},
|
||||
width: rdr.read_u32::<BigEndian>().unwrap(),
|
||||
height: rdr.read_u32::<BigEndian>().unwrap(),
|
||||
compression: byte_data[10],
|
||||
filter: byte_data[11],
|
||||
interlaced: byte_data[12],
|
||||
})
|
||||
color_type: match byte_data[9] {
|
||||
0 => ColorType::Grayscale,
|
||||
2 => ColorType::RGB,
|
||||
3 => ColorType::Indexed,
|
||||
4 => ColorType::GrayscaleAlpha,
|
||||
6 => ColorType::RGBA,
|
||||
_ => return Err(PngError::new("Unexpected color type in header")),
|
||||
},
|
||||
bit_depth: match byte_data[8] {
|
||||
1 => BitDepth::One,
|
||||
2 => BitDepth::Two,
|
||||
4 => BitDepth::Four,
|
||||
8 => BitDepth::Eight,
|
||||
16 => BitDepth::Sixteen,
|
||||
_ => return Err(PngError::new("Unexpected bit depth in header")),
|
||||
},
|
||||
width: rdr.read_u32::<BigEndian>().unwrap(),
|
||||
height: rdr.read_u32::<BigEndian>().unwrap(),
|
||||
compression: byte_data[10],
|
||||
filter: byte_data[11],
|
||||
interlaced: byte_data[12],
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,15 +92,15 @@ pub fn deinterlace_image(png: &mut PngData) {
|
|||
let bits_per_line = 8 + bits_per_pixel as usize * png.ihdr_data.width as usize;
|
||||
// Initialize each output line with a starting filter byte of 0
|
||||
// as well as some blank data
|
||||
let mut lines: Vec<BitVec> = vec![BitVec::from_elem(bits_per_line, false);
|
||||
png.ihdr_data.height as usize];
|
||||
let mut lines: Vec<BitVec> =
|
||||
vec![BitVec::from_elem(bits_per_line, false); png.ihdr_data.height as usize];
|
||||
let mut current_pass = 1;
|
||||
let mut pass_constants = interlaced_constants(current_pass);
|
||||
let mut current_y: usize = pass_constants.y_shift as usize;
|
||||
for line in png.scan_lines() {
|
||||
let bit_vec = BitVec::from_bytes(&line.data);
|
||||
let bits_in_line = ((png.ihdr_data.width - pass_constants.x_shift as u32) as f32 /
|
||||
pass_constants.x_step as f32)
|
||||
pass_constants.x_step as f32)
|
||||
.ceil() as usize * bits_per_pixel as usize;
|
||||
for (i, bit) in bit_vec.iter().enumerate() {
|
||||
// Avoid moving padded 0's into new image
|
||||
|
|
@ -108,7 +108,7 @@ pub fn deinterlace_image(png: &mut PngData) {
|
|||
break;
|
||||
}
|
||||
let current_x: usize = pass_constants.x_shift as usize +
|
||||
(i / bits_per_pixel as usize) * pass_constants.x_step as usize;
|
||||
(i / bits_per_pixel as usize) * pass_constants.x_step as usize;
|
||||
// Copy this bit into the output line, offset by 8 because of filter byte
|
||||
let index = 8 + (i % bits_per_pixel as usize) + current_x * bits_per_pixel as usize;
|
||||
lines[current_y].set(index, bit);
|
||||
|
|
|
|||
259
src/lib.rs
259
src/lib.rs
|
|
@ -20,7 +20,7 @@ use png::PngData;
|
|||
use rayon::prelude::*;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::fs::{File, copy};
|
||||
use std::io::{BufWriter, Write, stderr, stdout};
|
||||
use std::io::{BufWriter, Write, stdout};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
pub mod colors;
|
||||
|
|
@ -281,11 +281,11 @@ impl Default for Options {
|
|||
pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
|
||||
// Initialize the thread pool with correct number of threads
|
||||
let thread_count = opts.threads;
|
||||
rayon::initialize(rayon::Configuration::new().num_threads(thread_count)).ok();
|
||||
let _ = rayon::initialize(rayon::Configuration::new().num_threads(thread_count));
|
||||
|
||||
// Read in the file and try to decode as PNG.
|
||||
if opts.verbosity.is_some() {
|
||||
writeln!(&mut stderr(), "Processing: {}", filepath.to_str().unwrap()).ok();
|
||||
eprintln!("Processing: {}", filepath.to_str().unwrap());
|
||||
}
|
||||
|
||||
let in_file = Path::new(filepath);
|
||||
|
|
@ -296,27 +296,29 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
|
|||
let optimized_output = optimize_png(&mut png, &in_data, opts)?;
|
||||
|
||||
if is_fully_optimized(in_data.len(), optimized_output.len(), opts) {
|
||||
writeln!(&mut stderr(), "File already optimized").ok();
|
||||
eprintln!("File already optimized");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if opts.pretend {
|
||||
if opts.verbosity.is_some() {
|
||||
writeln!(&mut stderr(), "Running in pretend mode, no output").ok();
|
||||
eprintln!("Running in pretend mode, no output");
|
||||
}
|
||||
} else {
|
||||
if opts.backup {
|
||||
match copy(in_file,
|
||||
in_file.with_extension(format!("bak.{}",
|
||||
in_file
|
||||
.extension()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()))) {
|
||||
match copy(
|
||||
in_file,
|
||||
in_file.with_extension(format!(
|
||||
"bak.{}",
|
||||
in_file.extension().unwrap().to_str().unwrap()
|
||||
)),
|
||||
) {
|
||||
Ok(x) => x,
|
||||
Err(_) => {
|
||||
return Err(PngError::new(&format!("Unable to write to backup file at {}",
|
||||
opts.out_file.display())))
|
||||
return Err(PngError::new(&format!(
|
||||
"Unable to write to backup file at {}",
|
||||
opts.out_file.display()
|
||||
)))
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -331,8 +333,10 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
|
|||
let out_file = match File::create(&opts.out_file) {
|
||||
Ok(x) => x,
|
||||
Err(_) => {
|
||||
return Err(PngError::new(&format!("Unable to write to file {}",
|
||||
opts.out_file.display())))
|
||||
return Err(PngError::new(&format!(
|
||||
"Unable to write to file {}",
|
||||
opts.out_file.display()
|
||||
)))
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -352,9 +356,9 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
|
|||
}
|
||||
Err(_) => {
|
||||
if opts.verbosity.is_some() {
|
||||
writeln!(&mut stderr(),
|
||||
"Failed to set permissions on output file")
|
||||
.ok();
|
||||
eprintln!(
|
||||
"Failed to set permissions on output file"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -362,17 +366,14 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
|
|||
}
|
||||
Err(_) => {
|
||||
if opts.verbosity.is_some() {
|
||||
writeln!(&mut stderr(),
|
||||
"Failed to read permissions on input file")
|
||||
.ok();
|
||||
eprintln!("Failed to read permissions on input file");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
if opts.verbosity.is_some() {
|
||||
writeln!(&mut stderr(), "Failed to read permissions on input file")
|
||||
.ok();
|
||||
eprintln!("Failed to read permissions on input file");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -382,12 +383,14 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
|
|||
match buffer.write_all(&optimized_output) {
|
||||
Ok(_) => {
|
||||
if opts.verbosity.is_some() {
|
||||
writeln!(&mut stderr(), "Output: {}", opts.out_file.display()).ok();
|
||||
eprintln!("Output: {}", opts.out_file.display());
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
return Err(PngError::new(&format!("Unable to write to file {}",
|
||||
opts.out_file.display())))
|
||||
return Err(PngError::new(&format!(
|
||||
"Unable to write to file {}",
|
||||
opts.out_file.display()
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -400,11 +403,11 @@ pub fn optimize(filepath: &Path, opts: &Options) -> Result<(), PngError> {
|
|||
pub fn optimize_from_memory(data: &[u8], opts: &Options) -> Result<Vec<u8>, PngError> {
|
||||
// Initialize the thread pool with correct number of threads
|
||||
let thread_count = opts.threads;
|
||||
rayon::initialize(rayon::Configuration::new().num_threads(thread_count)).ok();
|
||||
let _ = rayon::initialize(rayon::Configuration::new().num_threads(thread_count));
|
||||
|
||||
// Read in the file and try to decode as PNG.
|
||||
if opts.verbosity.is_some() {
|
||||
writeln!(&mut stderr(), "Processing from memory").ok();
|
||||
eprintln!("Processing from memory");
|
||||
}
|
||||
let original_size = data.len() as usize;
|
||||
let mut png = PngData::from_slice(data, opts.fix_errors)?;
|
||||
|
|
@ -413,7 +416,7 @@ pub fn optimize_from_memory(data: &[u8], opts: &Options) -> Result<Vec<u8>, PngE
|
|||
let optimized_output = optimize_png(&mut png, data, opts)?;
|
||||
|
||||
if is_fully_optimized(original_size, optimized_output.len(), opts) {
|
||||
writeln!(&mut stderr(), "Image already optimized").ok();
|
||||
eprintln!("Image already optimized");
|
||||
Ok(data.to_vec())
|
||||
} else {
|
||||
Ok(optimized_output)
|
||||
|
|
@ -421,10 +424,11 @@ pub fn optimize_from_memory(data: &[u8], opts: &Options) -> Result<Vec<u8>, PngE
|
|||
}
|
||||
|
||||
/// Perform optimization on the input PNG object using the options provided
|
||||
fn optimize_png(png: &mut PngData,
|
||||
original_data: &[u8],
|
||||
opts: &Options)
|
||||
-> Result<Vec<u8>, PngError> {
|
||||
fn optimize_png(
|
||||
png: &mut PngData,
|
||||
original_data: &[u8],
|
||||
opts: &Options,
|
||||
) -> Result<Vec<u8>, PngError> {
|
||||
type TrialWithData = (u8, u8, u8, u8, Vec<u8>);
|
||||
|
||||
let original_png = png.clone();
|
||||
|
|
@ -433,33 +437,27 @@ fn optimize_png(png: &mut PngData,
|
|||
let file_original_size = original_data.len();
|
||||
let idat_original_size = png.idat_data.len();
|
||||
if opts.verbosity.is_some() {
|
||||
writeln!(&mut stderr(),
|
||||
" {}x{} pixels, PNG format",
|
||||
png.ihdr_data.width,
|
||||
png.ihdr_data.height)
|
||||
.ok();
|
||||
eprintln!(
|
||||
" {}x{} pixels, PNG format",
|
||||
png.ihdr_data.width,
|
||||
png.ihdr_data.height
|
||||
);
|
||||
if let Some(ref palette) = png.palette {
|
||||
writeln!(&mut stderr(),
|
||||
" {} bits/pixel, {} colors in palette",
|
||||
png.ihdr_data.bit_depth,
|
||||
palette.len() / 3)
|
||||
.ok();
|
||||
eprintln!(
|
||||
" {} bits/pixel, {} colors in palette",
|
||||
png.ihdr_data.bit_depth,
|
||||
palette.len() / 3
|
||||
);
|
||||
} else {
|
||||
writeln!(&mut stderr(),
|
||||
" {}x{} bits/pixel, {:?}",
|
||||
png.channels_per_pixel(),
|
||||
png.ihdr_data.bit_depth,
|
||||
png.ihdr_data.color_type)
|
||||
.ok();
|
||||
eprintln!(
|
||||
" {}x{} bits/pixel, {:?}",
|
||||
png.channels_per_pixel(),
|
||||
png.ihdr_data.bit_depth,
|
||||
png.ihdr_data.color_type
|
||||
);
|
||||
}
|
||||
writeln!(&mut stderr(),
|
||||
" IDAT size = {} bytes",
|
||||
idat_original_size)
|
||||
.ok();
|
||||
writeln!(&mut stderr(),
|
||||
" File size = {} bytes",
|
||||
file_original_size)
|
||||
.ok();
|
||||
eprintln!(" IDAT size = {} bytes", idat_original_size);
|
||||
eprintln!(" File size = {} bytes", file_original_size);
|
||||
}
|
||||
|
||||
let mut filter = opts.filter.iter().cloned().collect::<Vec<u8>>();
|
||||
|
|
@ -470,7 +468,8 @@ fn optimize_png(png: &mut PngData,
|
|||
if opts.use_heuristics {
|
||||
// Heuristically determine which set of options to use
|
||||
if png.ihdr_data.bit_depth.as_u8() >= 8 &&
|
||||
png.ihdr_data.color_type != colors::ColorType::Indexed {
|
||||
png.ihdr_data.color_type != colors::ColorType::Indexed
|
||||
{
|
||||
if filter.is_empty() {
|
||||
filter.push(5);
|
||||
}
|
||||
|
|
@ -498,7 +497,7 @@ fn optimize_png(png: &mut PngData,
|
|||
};
|
||||
let mut results: Vec<(u8, u8, u8, u8)> = Vec::with_capacity(combinations);
|
||||
if opts.verbosity.is_some() {
|
||||
writeln!(&mut stderr(), "Trying: {} combinations", combinations).ok();
|
||||
eprintln!("Trying: {} combinations", combinations);
|
||||
}
|
||||
|
||||
for f in &filter {
|
||||
|
|
@ -541,14 +540,14 @@ fn optimize_png(png: &mut PngData,
|
|||
}.unwrap();
|
||||
|
||||
if opts.verbosity == Some(1) {
|
||||
writeln!(&mut stderr(),
|
||||
" zc = {} zm = {} zs = {} f = {} {} bytes",
|
||||
trial.1,
|
||||
trial.2,
|
||||
trial.3,
|
||||
trial.0,
|
||||
new_idat.len())
|
||||
.ok();
|
||||
eprintln!(
|
||||
" zc = {} zm = {} zs = {} f = {} {} bytes",
|
||||
trial.1,
|
||||
trial.2,
|
||||
trial.3,
|
||||
trial.0,
|
||||
new_idat.len()
|
||||
);
|
||||
}
|
||||
|
||||
if new_idat.len() < original_len || added_interlacing || opts.force {
|
||||
|
|
@ -562,18 +561,18 @@ fn optimize_png(png: &mut PngData,
|
|||
if let Some(better) = best {
|
||||
png.idat_data = better.4;
|
||||
if opts.verbosity.is_some() {
|
||||
writeln!(&mut stderr(), "Found better combination:").ok();
|
||||
writeln!(&mut stderr(),
|
||||
" zc = {} zm = {} zs = {} f = {} {} bytes",
|
||||
better.1,
|
||||
better.2,
|
||||
better.3,
|
||||
better.0,
|
||||
png.idat_data.len())
|
||||
.ok();
|
||||
eprintln!("Found better combination:");
|
||||
eprintln!(
|
||||
" zc = {} zm = {} zs = {} f = {} {} bytes",
|
||||
better.1,
|
||||
better.2,
|
||||
better.3,
|
||||
better.0,
|
||||
png.idat_data.len()
|
||||
);
|
||||
}
|
||||
} else if reduction_occurred {
|
||||
png.reset_from_original(original_png);
|
||||
png.reset_from_original(&original_png);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -583,34 +582,32 @@ fn optimize_png(png: &mut PngData,
|
|||
|
||||
if opts.verbosity.is_some() {
|
||||
if idat_original_size >= png.idat_data.len() {
|
||||
writeln!(&mut stderr(),
|
||||
" IDAT size = {} bytes ({} bytes decrease)",
|
||||
png.idat_data.len(),
|
||||
idat_original_size - png.idat_data.len())
|
||||
.ok();
|
||||
eprintln!(
|
||||
" IDAT size = {} bytes ({} bytes decrease)",
|
||||
png.idat_data.len(),
|
||||
idat_original_size - png.idat_data.len()
|
||||
);
|
||||
} else {
|
||||
writeln!(&mut stderr(),
|
||||
" IDAT size = {} bytes ({} bytes increase)",
|
||||
png.idat_data.len(),
|
||||
png.idat_data.len() - idat_original_size)
|
||||
.ok();
|
||||
eprintln!(
|
||||
" IDAT size = {} bytes ({} bytes increase)",
|
||||
png.idat_data.len(),
|
||||
png.idat_data.len() - idat_original_size
|
||||
);
|
||||
}
|
||||
if file_original_size >= output.len() {
|
||||
writeln!(&mut stderr(),
|
||||
" file size = {} bytes ({} bytes = {:.2}% decrease)",
|
||||
output.len(),
|
||||
file_original_size - output.len(),
|
||||
(file_original_size - output.len()) as f64 / file_original_size as f64 *
|
||||
100f64)
|
||||
.ok();
|
||||
eprintln!(
|
||||
" file size = {} bytes ({} bytes = {:.2}% decrease)",
|
||||
output.len(),
|
||||
file_original_size - output.len(),
|
||||
(file_original_size - output.len()) as f64 / file_original_size as f64 * 100f64
|
||||
);
|
||||
} else {
|
||||
writeln!(&mut stderr(),
|
||||
" file size = {} bytes ({} bytes = {:.2}% increase)",
|
||||
output.len(),
|
||||
output.len() - file_original_size,
|
||||
(output.len() - file_original_size) as f64 / file_original_size as f64 *
|
||||
100f64)
|
||||
.ok();
|
||||
eprintln!(
|
||||
" file size = {} bytes ({} bytes = {:.2}% increase)",
|
||||
output.len(),
|
||||
output.len() - file_original_size,
|
||||
(output.len() - file_original_size) as f64 / file_original_size as f64 * 100f64
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -620,13 +617,16 @@ fn optimize_png(png: &mut PngData,
|
|||
if let Ok(new_png) = new_png {
|
||||
if let Ok(old_png) = old_png {
|
||||
if old_png
|
||||
.pixels()
|
||||
.map(|x| x.2.channels().to_owned())
|
||||
.collect::<Vec<Vec<u8>>>() ==
|
||||
new_png
|
||||
.pixels()
|
||||
.map(|x| x.2.channels().to_owned())
|
||||
.collect::<Vec<Vec<u8>>>() {
|
||||
.pixels()
|
||||
.map(|x| x.2.channels().to_owned())
|
||||
.filter(|p| !(p.len() == 4 && p[3] == 0))
|
||||
.collect::<Vec<Vec<u8>>>() ==
|
||||
new_png
|
||||
.pixels()
|
||||
.map(|x| x.2.channels().to_owned())
|
||||
.filter(|p| !(p.len() == 4 && p[3] == 0))
|
||||
.collect::<Vec<Vec<u8>>>()
|
||||
{
|
||||
return Ok(output);
|
||||
}
|
||||
} else {
|
||||
|
|
@ -637,7 +637,9 @@ fn optimize_png(png: &mut PngData,
|
|||
}
|
||||
}
|
||||
|
||||
writeln!(&mut stderr(), "The resulting image is corrupted and will not be outputted.\nThis is a bug! Please report it at https://github.com/shssoichiro/oxipng/issues").ok();
|
||||
eprintln!(
|
||||
"The resulting image is corrupted and will not be outputted.\nThis is a bug! Please report it at https://github.com/shssoichiro/oxipng/issues"
|
||||
);
|
||||
Err(PngError::new("The resulting image is corrupted"))
|
||||
}
|
||||
|
||||
|
|
@ -671,6 +673,8 @@ fn perform_reductions(png: &mut png::PngData, opts: &Options) -> bool {
|
|||
report_reduction(png);
|
||||
}
|
||||
|
||||
png.reduce_alpha_channel();
|
||||
|
||||
if let Some(interlacing) = opts.interlace {
|
||||
if png.change_interlacing(interlacing) {
|
||||
png.ihdr_data.interlaced = interlacing;
|
||||
|
|
@ -685,18 +689,18 @@ fn perform_reductions(png: &mut png::PngData, opts: &Options) -> bool {
|
|||
#[inline]
|
||||
fn report_reduction(png: &png::PngData) {
|
||||
if let Some(ref palette) = png.palette {
|
||||
writeln!(&mut stderr(),
|
||||
"Reducing image to {} bits/pixel, {} colors in palette",
|
||||
png.ihdr_data.bit_depth,
|
||||
palette.len() / 3)
|
||||
.ok();
|
||||
eprintln!(
|
||||
"Reducing image to {} bits/pixel, {} colors in palette",
|
||||
png.ihdr_data.bit_depth,
|
||||
palette.len() / 3
|
||||
);
|
||||
} else {
|
||||
writeln!(&mut stderr(),
|
||||
"Reducing image to {}x{} bits/pixel, {}",
|
||||
png.channels_per_pixel(),
|
||||
png.ihdr_data.bit_depth,
|
||||
png.ihdr_data.color_type)
|
||||
.ok();
|
||||
eprintln!(
|
||||
"Reducing image to {}x{} bits/pixel, {}",
|
||||
png.channels_per_pixel(),
|
||||
png.ihdr_data.bit_depth,
|
||||
png.ihdr_data.color_type
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -711,8 +715,17 @@ fn perform_strip(png: &mut png::PngData, opts: &Options) {
|
|||
}
|
||||
}
|
||||
Headers::Safe => {
|
||||
const PRESERVED_HEADERS: [&'static str; 9] = ["cHRM", "gAMA", "iCCP", "sBIT", "sRGB",
|
||||
"bKGD", "hIST", "pHYs", "sPLT"];
|
||||
const PRESERVED_HEADERS: [&'static str; 9] = [
|
||||
"cHRM",
|
||||
"gAMA",
|
||||
"iCCP",
|
||||
"sBIT",
|
||||
"sRGB",
|
||||
"bKGD",
|
||||
"hIST",
|
||||
"pHYs",
|
||||
"sPLT",
|
||||
];
|
||||
let hdrs = png.aux_headers.keys().cloned().collect::<Vec<String>>();
|
||||
for hdr in hdrs {
|
||||
if !PRESERVED_HEADERS.contains(&hdr.as_ref()) {
|
||||
|
|
|
|||
75
src/main.rs
75
src/main.rs
|
|
@ -18,7 +18,6 @@ use oxipng::Options;
|
|||
use regex::Regex;
|
||||
use std::collections::HashSet;
|
||||
use std::fs::DirBuilder;
|
||||
use std::io::{Write, stderr};
|
||||
use std::path::PathBuf;
|
||||
|
||||
fn main() {
|
||||
|
|
@ -222,17 +221,19 @@ fn main() {
|
|||
let opts = match parse_opts_into_struct(&matches) {
|
||||
Ok(x) => x,
|
||||
Err(x) => {
|
||||
writeln!(&mut stderr(), "{}", x).ok();
|
||||
eprintln!("{}", x);
|
||||
return ();
|
||||
}
|
||||
};
|
||||
|
||||
handle_optimization(matches
|
||||
.values_of("files")
|
||||
.unwrap()
|
||||
.map(PathBuf::from)
|
||||
.collect(),
|
||||
&opts);
|
||||
handle_optimization(
|
||||
matches
|
||||
.values_of("files")
|
||||
.unwrap()
|
||||
.map(PathBuf::from)
|
||||
.collect(),
|
||||
&opts,
|
||||
);
|
||||
}
|
||||
|
||||
fn handle_optimization(inputs: Vec<PathBuf>, opts: &Options) {
|
||||
|
|
@ -240,17 +241,16 @@ fn handle_optimization(inputs: Vec<PathBuf>, opts: &Options) {
|
|||
let mut current_opts = opts.clone();
|
||||
if input.is_dir() {
|
||||
if current_opts.recursive {
|
||||
handle_optimization(input
|
||||
.read_dir()
|
||||
.unwrap()
|
||||
.map(|x| x.unwrap().path())
|
||||
.collect(),
|
||||
¤t_opts)
|
||||
handle_optimization(
|
||||
input
|
||||
.read_dir()
|
||||
.unwrap()
|
||||
.map(|x| x.unwrap().path())
|
||||
.collect(),
|
||||
¤t_opts,
|
||||
)
|
||||
} else {
|
||||
writeln!(&mut stderr(),
|
||||
"{} is a directory, skipping",
|
||||
input.display())
|
||||
.ok();
|
||||
eprintln!("{} is a directory, skipping", input.display());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -262,7 +262,7 @@ fn handle_optimization(inputs: Vec<PathBuf>, opts: &Options) {
|
|||
match oxipng::optimize(&input, ¤t_opts) {
|
||||
Ok(_) => (),
|
||||
Err(x) => {
|
||||
writeln!(&mut stderr(), "{}", x).ok();
|
||||
eprintln!("{}", x);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -320,8 +320,10 @@ fn parse_opts_into_struct(matches: &ArgMatches) -> Result<Options, String> {
|
|||
Err(x) => return Err(format!("Could not create output directory {}", x)),
|
||||
};
|
||||
} else if !path.is_dir() {
|
||||
return Err(format!("{} is an existing file (not a directory), cannot create directory",
|
||||
x));
|
||||
return Err(format!(
|
||||
"{} is an existing file (not a directory), cannot create directory",
|
||||
x
|
||||
));
|
||||
}
|
||||
opts.out_dir = Some(path);
|
||||
}
|
||||
|
|
@ -398,8 +400,10 @@ fn parse_opts_into_struct(matches: &ArgMatches) -> Result<Options, String> {
|
|||
.collect::<Vec<String>>();
|
||||
if hdrs.contains(&"safe".to_owned()) || hdrs.contains(&"all".to_owned()) {
|
||||
if hdrs.len() > 1 {
|
||||
return Err("'safe' or 'all' presets for --strip should be used by themselves"
|
||||
.to_owned());
|
||||
return Err(
|
||||
"'safe' or 'all' presets for --strip should be used by themselves"
|
||||
.to_owned(),
|
||||
);
|
||||
}
|
||||
if hdrs[0] == "safe" {
|
||||
opts.strip = Headers::Safe;
|
||||
|
|
@ -432,18 +436,21 @@ fn parse_opts_into_struct(matches: &ArgMatches) -> Result<Options, String> {
|
|||
Ok(opts)
|
||||
}
|
||||
|
||||
fn parse_numeric_range_opts(input: &str,
|
||||
min_value: u8,
|
||||
max_value: u8)
|
||||
-> Result<HashSet<u8>, String> {
|
||||
fn parse_numeric_range_opts(
|
||||
input: &str,
|
||||
min_value: u8,
|
||||
max_value: u8,
|
||||
) -> Result<HashSet<u8>, String> {
|
||||
let one_item = Regex::new(format!(r"^[{}-{}]$", min_value, max_value).as_ref()).unwrap();
|
||||
let multiple_items = Regex::new(format!(r"^([{}-{}])(,|-)([{}-{}])$",
|
||||
min_value,
|
||||
max_value,
|
||||
min_value,
|
||||
max_value)
|
||||
.as_ref())
|
||||
.unwrap();
|
||||
let multiple_items = Regex::new(
|
||||
format!(
|
||||
r"^([{}-{}])(,|-)([{}-{}])$",
|
||||
min_value,
|
||||
max_value,
|
||||
min_value,
|
||||
max_value
|
||||
).as_ref(),
|
||||
).unwrap();
|
||||
let mut items = HashSet::new();
|
||||
|
||||
if one_item.is_match(input) {
|
||||
|
|
|
|||
168
src/png.rs
168
src/png.rs
|
|
@ -51,7 +51,7 @@ impl<'a> Iterator for ScanLines<'a> {
|
|||
}
|
||||
}
|
||||
let bits_per_pixel = self.png.ihdr_data.bit_depth.as_u8() as u32 *
|
||||
self.png.channels_per_pixel() as u32;
|
||||
self.png.channels_per_pixel() as u32;
|
||||
let y_steps;
|
||||
let pixels_factor;
|
||||
match self.pass {
|
||||
|
|
@ -129,23 +129,23 @@ impl<'a> Iterator for ScanLines<'a> {
|
|||
}
|
||||
}
|
||||
Some(ScanLine {
|
||||
filter: self.png.raw_data[self.start],
|
||||
data: self.png.raw_data[(self.start + 1)..self.end].to_owned(),
|
||||
pass: current_pass,
|
||||
})
|
||||
filter: self.png.raw_data[self.start],
|
||||
data: self.png.raw_data[(self.start + 1)..self.end].to_owned(),
|
||||
pass: current_pass,
|
||||
})
|
||||
} else {
|
||||
// Standard, non-interlaced PNG scanlines
|
||||
let bits_per_line = self.png.ihdr_data.width as usize *
|
||||
self.png.ihdr_data.bit_depth.as_u8() as usize *
|
||||
self.png.channels_per_pixel() as usize;
|
||||
self.png.ihdr_data.bit_depth.as_u8() as usize *
|
||||
self.png.channels_per_pixel() as usize;
|
||||
let bytes_per_line = (bits_per_line as f32 / 8f32).ceil() as usize;
|
||||
self.start = self.end;
|
||||
self.end = self.start + bytes_per_line + 1;
|
||||
Some(ScanLine {
|
||||
filter: self.png.raw_data[self.start],
|
||||
data: self.png.raw_data[(self.start + 1)..self.end].to_owned(),
|
||||
pass: None,
|
||||
})
|
||||
filter: self.png.raw_data[self.start],
|
||||
data: self.png.raw_data[(self.start + 1)..self.end].to_owned(),
|
||||
pass: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -280,14 +280,14 @@ impl PngData {
|
|||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn reset_from_original(&mut self, original: PngData) {
|
||||
self.idat_data = original.idat_data;
|
||||
pub fn reset_from_original(&mut self, original: &PngData) {
|
||||
self.idat_data = original.idat_data.clone();
|
||||
self.ihdr_data = original.ihdr_data;
|
||||
self.raw_data = original.raw_data;
|
||||
self.palette = original.palette;
|
||||
self.transparency_pixel = original.transparency_pixel;
|
||||
self.transparency_palette = original.transparency_palette;
|
||||
self.aux_headers = original.aux_headers;
|
||||
self.raw_data = original.raw_data.clone();
|
||||
self.palette = original.palette.clone();
|
||||
self.transparency_pixel = original.transparency_pixel.clone();
|
||||
self.transparency_palette = original.transparency_palette.clone();
|
||||
self.aux_headers = original.aux_headers.clone();
|
||||
}
|
||||
|
||||
/// Return the number of channels in the image, based on color type
|
||||
|
|
@ -307,21 +307,19 @@ impl PngData {
|
|||
let mut output = vec![0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
|
||||
// IHDR
|
||||
let mut ihdr_data = Vec::with_capacity(13);
|
||||
ihdr_data.write_u32::<BigEndian>(self.ihdr_data.width).ok();
|
||||
ihdr_data.write_u32::<BigEndian>(self.ihdr_data.height).ok();
|
||||
ihdr_data.write_u8(self.ihdr_data.bit_depth.as_u8()).ok();
|
||||
ihdr_data
|
||||
.write_u8(self.ihdr_data.color_type.png_header_code())
|
||||
.ok();
|
||||
ihdr_data.write_u8(0).ok(); // Compression -- deflate
|
||||
ihdr_data.write_u8(0).ok(); // Filter method -- 5-way adaptive filtering
|
||||
ihdr_data.write_u8(self.ihdr_data.interlaced).ok();
|
||||
let _ = ihdr_data.write_u32::<BigEndian>(self.ihdr_data.width);
|
||||
let _ = ihdr_data.write_u32::<BigEndian>(self.ihdr_data.height);
|
||||
let _ = ihdr_data.write_u8(self.ihdr_data.bit_depth.as_u8());
|
||||
let _ = ihdr_data.write_u8(self.ihdr_data.color_type.png_header_code());
|
||||
let _ = ihdr_data.write_u8(0); // Compression -- deflate
|
||||
let _ = ihdr_data.write_u8(0); // Filter method -- 5-way adaptive filtering
|
||||
let _ = ihdr_data.write_u8(self.ihdr_data.interlaced);
|
||||
write_png_block(b"IHDR", &ihdr_data, &mut output);
|
||||
// Ancillary headers
|
||||
for (key, header) in
|
||||
self.aux_headers
|
||||
.iter()
|
||||
.filter(|&(key, _)| !(*key == "bKGD" || *key == "hIST" || *key == "tRNS")) {
|
||||
for (key, header) in self.aux_headers.iter().filter(|&(key, _)| {
|
||||
!(*key == "bKGD" || *key == "hIST" || *key == "tRNS")
|
||||
})
|
||||
{
|
||||
write_png_block(key.as_bytes(), header, &mut output);
|
||||
}
|
||||
// Palette
|
||||
|
|
@ -336,10 +334,10 @@ impl PngData {
|
|||
write_png_block(b"tRNS", transparency_pixel, &mut output);
|
||||
}
|
||||
// Special ancillary headers that need to come after PLTE but before IDAT
|
||||
for (key, header) in
|
||||
self.aux_headers
|
||||
.iter()
|
||||
.filter(|&(key, _)| *key == "bKGD" || *key == "hIST" || *key == "tRNS") {
|
||||
for (key, header) in self.aux_headers.iter().filter(|&(key, _)| {
|
||||
*key == "bKGD" || *key == "hIST" || *key == "tRNS"
|
||||
})
|
||||
{
|
||||
write_png_block(key.as_bytes(), header, &mut output);
|
||||
}
|
||||
// IDAT data
|
||||
|
|
@ -365,7 +363,7 @@ impl PngData {
|
|||
pub fn unfilter_image(&self) -> Vec<u8> {
|
||||
let mut unfiltered = Vec::with_capacity(self.raw_data.len());
|
||||
let bpp = (((self.ihdr_data.bit_depth.as_u8() * self.channels_per_pixel()) as f32) /
|
||||
8f32)
|
||||
8f32)
|
||||
.ceil() as usize;
|
||||
let mut last_line: Vec<u8> = Vec::new();
|
||||
for line in self.scan_lines() {
|
||||
|
|
@ -387,7 +385,7 @@ impl PngData {
|
|||
pub fn filter_image(&self, filter: u8) -> Vec<u8> {
|
||||
let mut filtered = Vec::with_capacity(self.raw_data.len());
|
||||
let bpp = (((self.ihdr_data.bit_depth.as_u8() * self.channels_per_pixel()) as f32) /
|
||||
8f32)
|
||||
8f32)
|
||||
.ceil() as usize;
|
||||
let mut last_line: Vec<u8> = Vec::new();
|
||||
let mut last_pass: Option<u8> = None;
|
||||
|
|
@ -396,8 +394,9 @@ impl PngData {
|
|||
0 | 1 | 2 | 3 | 4 => {
|
||||
if last_pass == line.pass || filter <= 1 {
|
||||
filtered.push(filter);
|
||||
filtered
|
||||
.extend_from_slice(&filter_line(filter, bpp, &line.data, &last_line));
|
||||
filtered.extend_from_slice(
|
||||
&filter_line(filter, bpp, &line.data, &last_line),
|
||||
);
|
||||
} else {
|
||||
// Avoid vertical filtering on first line of each interlacing pass
|
||||
filtered.push(0);
|
||||
|
|
@ -438,17 +437,18 @@ impl PngData {
|
|||
pub fn reduce_bit_depth(&mut self) -> bool {
|
||||
if self.ihdr_data.bit_depth != BitDepth::Sixteen {
|
||||
if self.ihdr_data.color_type == ColorType::Indexed ||
|
||||
self.ihdr_data.color_type == ColorType::Grayscale {
|
||||
self.ihdr_data.color_type == ColorType::Grayscale
|
||||
{
|
||||
return reduce_bit_depth_8_or_less(self);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reduce from 16 to 8 bits per channel per pixel
|
||||
let mut reduced = Vec::with_capacity((self.ihdr_data.width * self.ihdr_data.height *
|
||||
self.channels_per_pixel() as u32 +
|
||||
self.ihdr_data.height) as
|
||||
usize);
|
||||
let mut reduced = Vec::with_capacity(
|
||||
(self.ihdr_data.width * self.ihdr_data.height * self.channels_per_pixel() as u32 +
|
||||
self.ihdr_data.height) as usize,
|
||||
);
|
||||
let mut high_byte = 0;
|
||||
|
||||
for line in self.scan_lines() {
|
||||
|
|
@ -494,20 +494,20 @@ impl PngData {
|
|||
.chunks(3)
|
||||
.zip(trns.iter().chain([255].iter().cycle()))
|
||||
.flat_map(|(pixel, trns)| {
|
||||
let mut pixel = pixel.to_owned();
|
||||
pixel.push(*trns);
|
||||
pixel
|
||||
})
|
||||
let mut pixel = pixel.to_owned();
|
||||
pixel.push(*trns);
|
||||
pixel
|
||||
})
|
||||
.collect()
|
||||
} else {
|
||||
self.palette.clone().unwrap()
|
||||
};
|
||||
let mut indexed_palette: Vec<&[u8]> = palette
|
||||
.chunks(if self.transparency_palette.is_some() {
|
||||
4
|
||||
} else {
|
||||
3
|
||||
})
|
||||
4
|
||||
} else {
|
||||
3
|
||||
})
|
||||
.collect();
|
||||
// A map of old indexes to new ones, for any moved
|
||||
let mut index_map: HashMap<u8, u8> = HashMap::new();
|
||||
|
|
@ -591,10 +591,12 @@ impl PngData {
|
|||
true
|
||||
}
|
||||
|
||||
fn do_palette_reduction(&mut self,
|
||||
indices: &[u8],
|
||||
index_map: &mut HashMap<u8, u8>,
|
||||
indexed_palette: &mut Vec<&[u8]>) {
|
||||
fn do_palette_reduction(
|
||||
&mut self,
|
||||
indices: &[u8],
|
||||
index_map: &mut HashMap<u8, u8>,
|
||||
indexed_palette: &mut Vec<&[u8]>,
|
||||
) {
|
||||
let mut new_data = Vec::with_capacity(self.raw_data.len());
|
||||
let original_len = indexed_palette.len();
|
||||
for idx in indices.iter().sorted_by(|a, b| b.cmp(a)) {
|
||||
|
|
@ -687,7 +689,9 @@ impl PngData {
|
|||
.cloned()
|
||||
.flatten()
|
||||
.enumerate()
|
||||
.filter(|&(i, _)| !(self.transparency_palette.is_some() && i % 4 == 3))
|
||||
.filter(|&(i, _)| {
|
||||
!(self.transparency_palette.is_some() && i % 4 == 3)
|
||||
})
|
||||
.map(|(_, x)| *x)
|
||||
.collect::<Vec<u8>>();
|
||||
self.palette = Some(new_palette);
|
||||
|
|
@ -711,13 +715,15 @@ impl PngData {
|
|||
}
|
||||
|
||||
if self.ihdr_data.color_type == ColorType::GrayscaleAlpha &&
|
||||
reduce_grayscale_alpha_to_grayscale(self) {
|
||||
reduce_grayscale_alpha_to_grayscale(self)
|
||||
{
|
||||
changed = true;
|
||||
should_reduce_bit_depth = true;
|
||||
}
|
||||
|
||||
if self.ihdr_data.color_type == ColorType::RGB &&
|
||||
(reduce_rgb_to_grayscale(self) || reduce_rgb_to_palette(self)) {
|
||||
(reduce_rgb_to_grayscale(self) || reduce_rgb_to_palette(self))
|
||||
{
|
||||
changed = true;
|
||||
should_reduce_bit_depth = true;
|
||||
}
|
||||
|
|
@ -731,6 +737,44 @@ impl PngData {
|
|||
changed
|
||||
}
|
||||
|
||||
pub fn reduce_alpha_channel(&mut self) -> bool {
|
||||
let (bpc, bpp) = match self.ihdr_data.color_type {
|
||||
ColorType::RGBA => {
|
||||
match self.ihdr_data.bit_depth {
|
||||
BitDepth::Sixteen => (2, 8),
|
||||
BitDepth::Eight => (1, 4),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
ColorType::GrayscaleAlpha => {
|
||||
match self.ihdr_data.bit_depth {
|
||||
BitDepth::Sixteen => (2, 4),
|
||||
BitDepth::Eight => (1, 2),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
let mut reduced = Vec::with_capacity(self.raw_data.len());
|
||||
for line in self.scan_lines() {
|
||||
reduced.push(line.filter);
|
||||
for pixel in line.data.chunks(bpp) {
|
||||
if pixel.iter().skip(bpp - bpc).fold(0, |sum, i| sum | i) == 0 {
|
||||
for _ in 0..bpp {
|
||||
reduced.push(0);
|
||||
}
|
||||
} else {
|
||||
reduced.extend_from_slice(pixel);
|
||||
}
|
||||
}
|
||||
}
|
||||
self.raw_data = reduced;
|
||||
true
|
||||
}
|
||||
|
||||
/// Convert the image to the specified interlacing type
|
||||
/// Returns true if the interlacing was changed, false otherwise
|
||||
/// The `interlace` parameter specifies the *new* interlacing mode
|
||||
|
|
@ -758,10 +802,8 @@ fn write_png_block(key: &[u8], header: &[u8], output: &mut Vec<u8>) {
|
|||
header_data.extend_from_slice(key);
|
||||
header_data.extend_from_slice(header);
|
||||
output.reserve(header_data.len() + 8);
|
||||
output
|
||||
.write_u32::<BigEndian>(header_data.len() as u32 - 4)
|
||||
.ok();
|
||||
let _ = output.write_u32::<BigEndian>(header_data.len() as u32 - 4);
|
||||
let crc = crc32::checksum_ieee(&header_data);
|
||||
output.append(&mut header_data);
|
||||
output.write_u32::<BigEndian>(crc).ok();
|
||||
let _ = output.write_u32::<BigEndian>(crc);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,13 +134,14 @@ pub fn reduce_rgba_to_palette(png: &mut PngData) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
let mut color_palette = Vec::with_capacity(palette.len() * 3 +
|
||||
if png.aux_headers
|
||||
.contains_key(&"bKGD".to_string()) {
|
||||
6
|
||||
} else {
|
||||
0
|
||||
});
|
||||
let mut color_palette = Vec::with_capacity(
|
||||
palette.len() * 3 +
|
||||
if png.aux_headers.contains_key(&"bKGD".to_string()) {
|
||||
6
|
||||
} else {
|
||||
0
|
||||
},
|
||||
);
|
||||
let mut trans_palette = Vec::with_capacity(palette.len());
|
||||
for color in &palette {
|
||||
for (i, byte) in color.iter().enumerate() {
|
||||
|
|
@ -166,9 +167,10 @@ pub fn reduce_rgba_to_palette(png: &mut PngData) -> bool {
|
|||
.step(2)
|
||||
.cloned()
|
||||
.collect::<Vec<u8>>();
|
||||
if let Some(entry) = color_palette
|
||||
.chunks(3)
|
||||
.position(|x| x == header_pixels.as_slice()) {
|
||||
if let Some(entry) = color_palette.chunks(3).position(
|
||||
|x| x == header_pixels.as_slice(),
|
||||
)
|
||||
{
|
||||
*bkgd_header = vec![entry as u8];
|
||||
} else if color_palette.len() / 3 == 256 {
|
||||
return false;
|
||||
|
|
@ -244,9 +246,10 @@ pub fn reduce_rgb_to_palette(png: &mut PngData) -> bool {
|
|||
.step(2)
|
||||
.cloned()
|
||||
.collect::<Vec<u8>>();
|
||||
if let Some(entry) = color_palette
|
||||
.chunks(3)
|
||||
.position(|x| x == header_pixels.as_slice()) {
|
||||
if let Some(entry) = color_palette.chunks(3).position(
|
||||
|x| x == header_pixels.as_slice(),
|
||||
)
|
||||
{
|
||||
*bkgd_header = vec![entry as u8];
|
||||
} else if color_palette.len() == 255 {
|
||||
return false;
|
||||
|
|
|
|||
BIN
tests/files/grayscale_alpha_16_reduce_alpha_black.png
Normal file
BIN
tests/files/grayscale_alpha_16_reduce_alpha_black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
tests/files/grayscale_alpha_8_reduce_alpha_black.png
Normal file
BIN
tests/files/grayscale_alpha_8_reduce_alpha_black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
tests/files/rgba_16_reduce_alpha_black.png
Normal file
BIN
tests/files/rgba_16_reduce_alpha_black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 66 KiB |
BIN
tests/files/rgba_8_reduce_alpha_black.png
Normal file
BIN
tests/files/rgba_8_reduce_alpha_black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
1072
tests/filters.rs
1072
tests/filters.rs
File diff suppressed because it is too large
Load diff
|
|
@ -22,13 +22,15 @@ fn get_opts(input: &Path) -> oxipng::Options {
|
|||
options
|
||||
}
|
||||
|
||||
fn test_it_converts(input: &Path,
|
||||
output: &Path,
|
||||
opts: &oxipng::Options,
|
||||
color_type_in: ColorType,
|
||||
bit_depth_in: BitDepth,
|
||||
color_type_out: ColorType,
|
||||
bit_depth_out: BitDepth) {
|
||||
fn test_it_converts(
|
||||
input: &Path,
|
||||
output: &Path,
|
||||
opts: &oxipng::Options,
|
||||
color_type_in: ColorType,
|
||||
bit_depth_in: BitDepth,
|
||||
color_type_out: ColorType,
|
||||
bit_depth_out: BitDepth,
|
||||
) {
|
||||
let png = png::PngData::new(input, opts.fix_errors).unwrap();
|
||||
|
||||
assert_eq!(png.ihdr_data.color_type, color_type_in);
|
||||
|
|
@ -61,13 +63,15 @@ fn verbose_mode() {
|
|||
opts.verbosity = Some(1);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -374,13 +378,15 @@ fn preserve_attrs() {
|
|||
opts.preserve_attrs = true;
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
|
||||
// TODO: Actually check permissions
|
||||
}
|
||||
|
|
@ -425,11 +431,13 @@ fn zopfli_mode() {
|
|||
opts.deflate = Deflaters::Zopfli;
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -20,13 +20,15 @@ fn get_opts(input: &Path) -> oxipng::Options {
|
|||
options
|
||||
}
|
||||
|
||||
fn test_it_converts(input: &Path,
|
||||
output: &Path,
|
||||
opts: &oxipng::Options,
|
||||
color_type_in: ColorType,
|
||||
bit_depth_in: BitDepth,
|
||||
color_type_out: ColorType,
|
||||
bit_depth_out: BitDepth) {
|
||||
fn test_it_converts(
|
||||
input: &Path,
|
||||
output: &Path,
|
||||
opts: &oxipng::Options,
|
||||
color_type_in: ColorType,
|
||||
bit_depth_in: BitDepth,
|
||||
color_type_out: ColorType,
|
||||
bit_depth_out: BitDepth,
|
||||
) {
|
||||
let png = png::PngData::new(input, opts.fix_errors).unwrap();
|
||||
|
||||
assert_eq!(png.ihdr_data.color_type, color_type_in);
|
||||
|
|
@ -58,13 +60,15 @@ fn issue_29() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGB,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -107,13 +111,15 @@ fn issue_52_01() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Eight);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -122,13 +128,15 @@ fn issue_52_02() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Eight);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -137,13 +145,15 @@ fn issue_52_03() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Eight);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -152,13 +162,15 @@ fn issue_52_04() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::One);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::One,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -167,13 +179,15 @@ fn issue_52_05() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::One);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::One,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -182,13 +196,15 @@ fn issue_52_06() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Two);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Two,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -197,13 +213,15 @@ fn issue_56() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Four,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Four);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Four,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Four,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -212,13 +230,15 @@ fn issue_58() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Four,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Four);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Four,
|
||||
ColorType::Indexed,
|
||||
BitDepth::Four,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -227,13 +247,15 @@ fn issue_59() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -242,11 +264,13 @@ fn issue_60() {
|
|||
let opts = get_opts(&input);
|
||||
let output = opts.out_file.clone();
|
||||
|
||||
test_it_converts(&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::GrayscaleAlpha,
|
||||
BitDepth::Eight);
|
||||
test_it_converts(
|
||||
&input,
|
||||
&output,
|
||||
&opts,
|
||||
ColorType::RGBA,
|
||||
BitDepth::Eight,
|
||||
ColorType::GrayscaleAlpha,
|
||||
BitDepth::Eight,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue